Passed
Push — master ( 6ac744...48d05f )
by Mohammad
07:18
created

Receiver   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 0
Metric Value
wmc 17
lcom 2
cbo 3
dl 0
loc 152
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A onOpen() 0 8 1
B onMessage() 0 47 6
A onClose() 0 6 1
A onError() 0 8 1
A checkForRequiredInMessage() 0 10 4
A cloneProperties() 0 6 2
A mainRoutes() 0 8 1
1
<?php
2
/** @noinspection PhpUndefinedFieldInspection */
3
4
/**
5
 * Created by PhpStorm.
6
 * User: shanmaseen
7
 * Date: 23/03/19
8
 * Time: 07:40 م
9
 */
10
11
namespace Shamaseen\Laravel\Ratchet;
12
13
use Illuminate\Validation\ValidationException;
14
use Shamaseen\Laravel\Ratchet\Exceptions\WebSocketException;
15
use Shamaseen\Laravel\Ratchet\Facades\WsRoute;
16
use Shamaseen\Laravel\Ratchet\Objects\Clients\Client;
17
use Ratchet\ConnectionInterface;
18
use Ratchet\MessageComponentInterface;
19
use Shamaseen\Laravel\Ratchet\Traits\WebSocketMessagesManager;
20
21
/**
22
 * Class WebSocket
23
 * @package App\WebSockets
24
 */
25
class Receiver implements MessageComponentInterface
26
{
27
    use WebSocketMessagesManager;
28
29
    /**
30
     * @var Client[]
31
     */
32
    public $clients;
33
    private $routes;
34
    public $userAuthSocketMapper;
35
    public $rooms = [];
36
37
    /**
38
     * WebSocket constructor.
39
     */
40
    public function __construct()
41
    {
42
        $this->clients = [];
43
        /**
44
         * The key will be auth id, the value will be resourceId
45
         */
46
        $this->userAuthSocketMapper = [];
47
48
        $this->mainRoutes();
49
        include base_path().'/routes/websocket.php';
50
        $this->routes = WsRoute::getRoutes();
51
    }
52
53
    /**
54
     * @param ConnectionInterface $conn
55
     */
56
    public function onOpen(ConnectionInterface $conn) {
57
58
        $this->clients[$conn->resourceId] = new Client();
0 ignored issues
show
Bug introduced by
Accessing resourceId 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...
59
        $this->clients[$conn->resourceId]->conn = $conn;
0 ignored issues
show
Bug introduced by
Accessing resourceId 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...
60
//        $this->clients[$conn->resourceId]->resourceId = $conn->resourceId;
61
62
        echo "New connection! ({$conn->resourceId})\n";
0 ignored issues
show
Bug introduced by
Accessing resourceId 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...
63
    }
64
65
    /**
66
     * @param ConnectionInterface $from
67
     * @param string $msg
68
     * @throws \Exception
69
     */
70
    public function onMessage(ConnectionInterface $from, $msg) {
71
        try
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after TRY keyword; newline found
Loading history...
72
        {
73
            $msg = json_decode($msg);
74
75
            $this->checkForRequiredInMessage($msg,$from);
76
77
            \Session::setId($msg->session);
78
79
            \Session::start();
80
81
            $route = $this->routes[$msg->route];
82
            if($route->auth && !\Auth::check())
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after IF keyword; 0 found
Loading history...
83
                $this->error($msg,$from,'Unauthenticated.');
84
            else
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after ELSE keyword; newline found
Loading history...
85
                $this->userAuthSocketMapper[\Auth::id()] = $from->resourceId;
0 ignored issues
show
Bug introduced by
Accessing resourceId 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...
86
87
            $class = $route->controller;
88
            $method = $route->method;
89
            $controller = new $class;
90
91
            $this->cloneProperties($this,$controller);
92
93
            $controller->conn = $from;
94
            $controller->receiver = $this;
95
            $controller->request = $msg;
96
            $controller->route = $route;
97
98
            if(!method_exists($controller,$method))
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after IF keyword; 0 found
Loading history...
99
            {
100
                $this->error($msg,$from,'Method doesnt\'t exist !');
101
            }
102
103
            $controller->$method();
104
        }
105
        catch (WebSocketException $exception)
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
106
        {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
107
108
        }
109
        catch(ValidationException $exception)
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after CATCH keyword; 0 found
Loading history...
Bug introduced by
The class Illuminate\Validation\ValidationException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
110
        {
111
            $this->sendToWebSocketUser($from,[
112
                'message'=>$exception->getMessage(),
113
                'errors'=> $exception->errors()
114
            ]);
115
        }
116
    }
117
118
    /**
119
     * @param ConnectionInterface $conn
120
     */
121
    public function onClose(ConnectionInterface $conn) {
122
        // The connection is closed, remove it, as we can no longer send it messages
123
        unset($this->clients[$conn->resourceId]);
124
125
        echo "Connection {$conn->resourceId} has disconnected\n";
0 ignored issues
show
Bug introduced by
Accessing resourceId 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...
126
    }
127
128
    /**
129
     * @param ConnectionInterface $conn
130
     * @param \Exception $e
131
     */
132
    public function onError(ConnectionInterface $conn, \Exception $e) {
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $e. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
133
        echo "An error has occurred: {$e->getMessage()}\n";
134
        echo "In {$e->getFile()} line {$e->getLine()}\n";
135
136
        $conn->close();
137
        echo 'end';
138
        die;
0 ignored issues
show
Coding Style Compatibility introduced by
The method onError() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
139
    }
140
141
    /**
142
     * @param $msg
143
     * @param $from
144
     * @throws WebSocketException
145
     */
146
    function checkForRequiredInMessage($msg,$from)
0 ignored issues
show
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for checkForRequiredInMessage.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Coding Style introduced by
Expected 1 space between comma and argument "$from"; 0 found
Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
147
    {
148
        if(!isset($msg->route) || !isset($msg->session))
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after IF keyword; 0 found
Loading history...
149
        {
150
            $this->error($msg,$from,'You can\'t send a request without the route and the session id !');
151
        }
152
153
        if(!isset($this->routes[$msg->route]))
0 ignored issues
show
Coding Style introduced by
Expected 1 space(s) after IF keyword; 0 found
Loading history...
154
            $this->error($msg,$from,'No such route !');
155
    }
156
157
    /**
158
     * @param $clonedObject
159
     * @param $clone
160
     */
161
    function cloneProperties($clonedObject, $clone)
0 ignored issues
show
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for cloneProperties.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
162
    {
163
        foreach (get_object_vars($clonedObject) as $key => $value) {
164
            $clone->$key = $value;
165
        }
166
    }
167
168
    function mainRoutes()
0 ignored issues
show
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for mainRoutes.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
169
    {
170
        WsRoute::make('initializeWebsocket','Shamaseen\Laravel\Ratchet\Controllers\InitializeController','index');
171
        WsRoute::make('room-enter','Shamaseen\Laravel\Ratchet\Controllers\RoomController','enterRoom');
172
        WsRoute::make('room-exit','Shamaseen\Laravel\Ratchet\Controllers\RoomController','exitRoom');
173
        WsRoute::make('send-to-user','Shamaseen\Laravel\Ratchet\Controllers\ChatController','sendMessageToUser');
174
        WsRoute::make('send-to-room','Shamaseen\Laravel\Ratchet\Controllers\ChatController','sendMessageToRoom');
175
    }
176
}