Completed
Pull Request — master (#416)
by
unknown
01:24
created

PresenceChannel::unsubscribe()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.8337
c 0
b 0
f 0
cc 6
nc 7
nop 1
1
<?php
2
3
namespace BeyondCode\LaravelWebSockets\WebSockets\Channels;
4
5
use Ratchet\ConnectionInterface;
6
use stdClass;
7
8
class PresenceChannel extends Channel
9
{
10
    protected $users = [];
11
12
    public function getUsers(): array
13
    {
14
        return $this->users;
15
    }
16
17
    /*
18
     * @link https://pusher.com/docs/pusher_protocol#presence-channel-events
19
     */
20
    public function subscribe(ConnectionInterface $connection, stdClass $payload)
21
    {
22
        $this->verifySignature($connection, $payload);
23
24
        $this->saveConnection($connection);
25
26
        $channelData = json_decode($payload->channel_data);
27
        $this->users[$connection->socketId] = $channelData;
0 ignored issues
show
Bug introduced by
Accessing socketId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
28
29
        // Send the success event
30
        $connection->send(json_encode([
31
            'event' => 'pusher_internal:subscription_succeeded',
32
            'channel' => $this->channelName,
33
            'data' => json_encode($this->getChannelData()),
34
        ]));
35
36
        $this->broadcastToOthers($connection, [
37
            'event' => 'pusher_internal:member_added',
38
            'channel' => $this->channelName,
39
            'data' => json_encode($channelData),
40
        ]);
41
    }
42
43
    public function unsubscribe(ConnectionInterface $connection)
44
    {
45
        parent::unsubscribe($connection);
46
47
        if (! isset($this->users[$connection->socketId])) {
0 ignored issues
show
Bug introduced by
Accessing socketId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
48
            return;
49
        }
50
51
        $last_connection = true;
52
        foreach ($this->users as $socketId => $channelData) {
53
            if ($socketId !== $connection->socketId && $channelData->user_id === $this->users[$connection->socketId]->user_id) {
0 ignored issues
show
Bug introduced by
Accessing socketId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
54
                $last_connection = false;
55
                break;
56
            }
57
        }
58
59
        //fire the event only if is the user last connection
60
        if ($last_connection) {
61
            $this->broadcastToOthers($connection, [
62
                'event' => 'pusher_internal:member_removed',
63
                'channel' => $this->channelName,
64
                'data' => json_encode([
65
                    'user_id' => $this->users[$connection->socketId]->user_id,
0 ignored issues
show
Bug introduced by
Accessing socketId on the interface Ratchet\ConnectionInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
66
                ]),
67
            ]);
68
        }
69
70
        unset($this->users[$connection->socketId]);
71
    }
72
73
    protected function getChannelData(): array
74
    {
75
        return [
76
            'presence' => [
77
                'ids' => $this->getUserIds(),
78
                'hash' => $this->getHash(),
79
                'count' => count($this->users),
80
            ],
81
        ];
82
    }
83
84
    public function toArray(): array
85
    {
86
        return array_merge(parent::toArray(), [
87
            'user_count' => count($this->users),
88
        ]);
89
    }
90
91
    protected function getUserIds(): array
92
    {
93
        $userIds = array_map(function ($channelData) {
94
            return (string) $channelData->user_id;
95
        }, $this->users);
96
97
        return array_values($userIds);
98
    }
99
100
    protected function getHash(): array
101
    {
102
        $hash = [];
103
104
        foreach ($this->users as $socketId => $channelData) {
105
            $hash[$channelData->user_id] = $channelData->user_info;
106
        }
107
108
        return $hash;
109
    }
110
}
111