Completed
Pull Request — master (#447)
by Marcel
02:52 queued 01:28
created

FetchChannelsController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
namespace BeyondCode\LaravelWebSockets\HttpApi\Controllers;
4
5
use BeyondCode\LaravelWebSockets\PubSub\ReplicationInterface;
6
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
7
use BeyondCode\LaravelWebSockets\WebSockets\Channels\PresenceChannel;
8
use Illuminate\Http\Request;
9
use Illuminate\Support\Collection;
10
use Illuminate\Support\Str;
11
use Symfony\Component\HttpKernel\Exception\HttpException;
12
13
class FetchChannelsController extends Controller
14
{
15
    /** @var ReplicationInterface */
16
    protected $replication;
17
18
    public function __construct(ChannelManager $channelManager, ReplicationInterface $replication)
19
    {
20
        parent::__construct($channelManager);
21
22
        $this->replication = $replication;
23
    }
24
25
    public function __invoke(Request $request)
26
    {
27
        $attributes = [];
28
29
        if ($request->has('info')) {
30
            $attributes = explode(',', trim($request->info));
31
32
            if (in_array('user_count', $attributes) && ! Str::startsWith($request->filter_by_prefix, 'presence-')) {
33
                throw new HttpException(400, 'Request must be limited to presence channels in order to fetch user_count');
34
            }
35
        }
36
37
        $channels = Collection::make($this->channelManager->getChannels($request->appId));
38
39
        if ($request->has('filter_by_prefix')) {
40
            $channels = $channels->filter(function ($channel, $channelName) use ($request) {
41
                return Str::startsWith($channelName, $request->filter_by_prefix);
42
            });
43
        }
44
45
        // We want to get the channel user count all in one shot when
46
        // using a replication backend rather than doing individual queries.
47
        // To do so, we first collect the list of channel names.
48
        $channelNames = $channels->map(function (PresenceChannel $channel) {
49
            return $channel->getChannelName();
50
        })->toArray();
51
52
        // We ask the replication backend to get us the member count per channel.
53
        // We get $counts back as a key-value array of channel names and their member count.
54
        return $this->replication
55
            ->channelMemberCounts($request->appId, $channelNames)
56
            ->then(function (array $counts) use ($channels, $attributes) {
57
                return [
58
                    'channels' => $channels->map(function (PresenceChannel $channel) use ($counts, $attributes) {
59
                        $info = new \stdClass;
60
                        if (in_array('user_count', $attributes)) {
61
                            $info->user_count = $counts[$channel->getChannelName()];
62
                        }
63
64
                        return $info;
65
                    })->toArray() ?: new \stdClass,
66
                ];
67
            });
68
    }
69
}
70