diff --git a/src/HttpApi/Controllers/FetchChannelsController.php b/src/HttpApi/Controllers/FetchChannelsController.php index 192a52c..c57efe7 100644 --- a/src/HttpApi/Controllers/FetchChannelsController.php +++ b/src/HttpApi/Controllers/FetchChannelsController.php @@ -5,15 +5,23 @@ namespace BeyondCode\LaravelWebSockets\HttpApi\Controllers; use Illuminate\Support\Str; use Illuminate\Http\Request; use Illuminate\Support\Collection; -use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel; +use Symfony\Component\HttpKernel\Exception\HttpException; class FetchChannelsController extends Controller { public function __invoke(Request $request) { - $channels = Collection::make($this->channelManager->getChannels($request->appId))->filter(function ($channel) { - return $channel instanceof PresenceChannel; - }); + $attributes = []; + + if ($request->has('info')) { + $attributes = explode(',', trim($request->info)); + + if (in_array('user_count', $attributes) && ! Str::startsWith($request->filter_by_prefix, 'presence-')) { + throw new HttpException(400, 'Request must be limited to presence channels in order to fetch user_count'); + } + } + + $channels = Collection::make($this->channelManager->getChannels($request->appId)); if ($request->has('filter_by_prefix')) { $channels = $channels->filter(function ($channel, $channelName) use ($request) { @@ -22,10 +30,13 @@ class FetchChannelsController extends Controller } return [ - 'channels' => $channels->map(function ($channel) { - return [ - 'user_count' => count($channel->getUsers()), - ]; + 'channels' => $channels->map(function ($channel) use ($attributes) { + $info = new \stdClass; + if (in_array('user_count', $attributes)) { + $info->user_count = count($channel->getUsers()); + } + + return $info; })->toArray() ?: new \stdClass, ]; } diff --git a/tests/HttpApi/FetchChannelsTest.php b/tests/HttpApi/FetchChannelsTest.php index 8092507..9d750e4 100644 --- a/tests/HttpApi/FetchChannelsTest.php +++ b/tests/HttpApi/FetchChannelsTest.php @@ -38,8 +38,6 @@ class FetchChannelsTest extends TestCase public function it_returns_the_channel_information() { $this->joinPresenceChannel('presence-channel'); - $this->joinPresenceChannel('presence-channel'); - $this->joinPresenceChannel('presence-channel'); $connection = new Connection(); @@ -61,9 +59,7 @@ class FetchChannelsTest extends TestCase $this->assertSame([ 'channels' => [ - 'presence-channel' => [ - 'user_count' => 3, - ], + 'presence-channel' => [], ], ], json_decode($response->getContent(), true)); } @@ -96,6 +92,43 @@ class FetchChannelsTest extends TestCase /** @var JsonResponse $response */ $response = array_pop($connection->sentRawData); + $this->assertSame([ + 'channels' => [ + 'presence-global.1' => [], + 'presence-global.2' => [], + ], + ], json_decode($response->getContent(), true)); + } + + /** @test */ + public function it_returns_the_channel_information_for_prefix_with_user_count() + { + $this->joinPresenceChannel('presence-global.1'); + $this->joinPresenceChannel('presence-global.1'); + $this->joinPresenceChannel('presence-global.2'); + $this->joinPresenceChannel('presence-notglobal.2'); + + $connection = new Connection(); + + $requestPath = '/apps/1234/channels'; + $routeParams = [ + 'appId' => '1234', + ]; + + $queryString = Pusher::build_auth_query_string('TestKey', 'TestSecret', 'GET', $requestPath, [ + 'filter_by_prefix' => 'presence-global', + 'info' => 'user_count', + ]); + + $request = new Request('GET', "{$requestPath}?{$queryString}&".http_build_query($routeParams)); + + $controller = app(FetchChannelsController::class); + + $controller->onOpen($connection, $request); + + /** @var JsonResponse $response */ + $response = array_pop($connection->sentRawData); + $this->assertSame([ 'channels' => [ 'presence-global.1' => [ @@ -108,6 +141,33 @@ class FetchChannelsTest extends TestCase ], json_decode($response->getContent(), true)); } + /** @test */ + public function can_not_get_non_presence_channel_user_count() + { + $this->expectException(HttpException::class); + $this->expectExceptionMessage('Request must be limited to presence channels in order to fetch user_count'); + + $connection = new Connection(); + + $requestPath = '/apps/1234/channels'; + $routeParams = [ + 'appId' => '1234', + ]; + + $queryString = Pusher::build_auth_query_string('TestKey', 'TestSecret', 'GET', $requestPath, [ + 'info' => 'user_count', + ]); + + $request = new Request('GET', "{$requestPath}?{$queryString}&".http_build_query($routeParams)); + + $controller = app(FetchChannelsController::class); + + $controller->onOpen($connection, $request); + + /** @var JsonResponse $response */ + $response = array_pop($connection->sentRawData); + } + /** @test */ public function it_returns_empty_object_for_no_channels_found() {