Completed
Push — master ( edcf20...3ec6c0 )
by Marcel
03:05 queued 01:22
created

src/WebSockets/Channels/Channel.php (5 issues)

property access on interfaces.

Bug Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace BeyondCode\LaravelWebSockets\WebSockets\Channels;
4
5
use stdClass;
6
use Illuminate\Support\Str;
7
use Ratchet\ConnectionInterface;
8
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
9
use BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature;
10
11
class Channel
12
{
13
    /** @var string */
14
    protected $channelName;
15
16
    /** @var \Ratchet\ConnectionInterface[] */
17
    protected $subscribedConnections = [];
18
19
    public function __construct(string $channelName)
20
    {
21
        $this->channelName = $channelName;
22
    }
23
24
    public function hasConnections(): bool
25
    {
26
        return count($this->subscribedConnections) > 0;
27
    }
28
29
    public function getSubscribedConnections(): array
30
    {
31
        return $this->subscribedConnections;
32
    }
33
34
    protected function verifySignature(ConnectionInterface $connection, stdClass $payload)
35
    {
36
        $signature = "{$connection->socketId}:{$this->channelName}";
0 ignored issues
show
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...
37
38
        if (isset($payload->channel_data)) {
39
            $signature .= ":{$payload->channel_data}";
40
        }
41
42
        if (Str::after($payload->auth, ':') !== hash_hmac('sha256', $signature, $connection->app->secret)) {
0 ignored issues
show
Accessing app 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...
43
            throw new InvalidSignature();
44
        }
45
    }
46
47
    /*
48
     * @link https://pusher.com/docs/pusher_protocol#presence-channel-events
49
     */
50
    public function subscribe(ConnectionInterface $connection, stdClass $payload)
51
    {
52
        $this->saveConnection($connection);
53
54
        $connection->send(json_encode([
55
            'event' => 'pusher_internal:subscription_succeeded',
56
            'channel' => $this->channelName,
57
        ]));
58
    }
59
60
    public function unsubscribe(ConnectionInterface $connection)
61
    {
62
        unset($this->subscribedConnections[$connection->socketId]);
63
64
        if (! $this->hasConnections()) {
65
            DashboardLogger::vacated($connection, $this->channelName);
66
        }
67
    }
68
69
    protected function saveConnection(ConnectionInterface $connection)
70
    {
71
        $hadConnectionsPreviously = $this->hasConnections();
72
73
        $this->subscribedConnections[$connection->socketId] = $connection;
0 ignored issues
show
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...
74
75
        if (! $hadConnectionsPreviously) {
76
            DashboardLogger::occupied($connection, $this->channelName);
77
        }
78
79
        DashboardLogger::subscribed($connection, $this->channelName);
80
    }
81
82
    public function broadcast($payload)
83
    {
84
        foreach ($this->subscribedConnections as $connection) {
85
            $connection->send(json_encode($payload));
86
        }
87
    }
88
89
    public function broadcastToOthers(ConnectionInterface $connection, $payload)
90
    {
91
        $this->broadcastToEveryoneExcept($payload, $connection->socketId);
0 ignored issues
show
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...
92
    }
93
94
    public function broadcastToEveryoneExcept($payload, ?string $socketId = null)
95
    {
96
        if (is_null($socketId)) {
97
            return $this->broadcast($payload);
98
        }
99
100
        foreach ($this->subscribedConnections as $connection) {
101
            if ($connection->socketId !== $socketId) {
0 ignored issues
show
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...
102
                $connection->send(json_encode($payload));
103
            }
104
        }
105
    }
106
107
    public function toArray(): array
108
    {
109
        return [
110
            'occupied' => count($this->subscribedConnections) > 0,
111
            'subscription_count' => count($this->subscribedConnections),
112
        ];
113
    }
114
}
115