Completed
Pull Request — master (#12)
by Timo
03:52
created

ClientSessionStub   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 273
Duplicated Lines 16.85 %

Coupling/Cohesion

Components 5
Dependencies 6

Importance

Changes 7
Bugs 0 Features 4
Metric Value
wmc 20
c 7
b 0
f 4
lcom 5
cbo 6
dl 46
loc 273
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A subscribe() 0 10 1
A completeSubscription() 13 13 2
A publish() 0 8 1
A confirmPublication() 11 11 2
A register() 0 13 1
A confirmRegistration() 0 11 2
A callRegistration() 0 10 2
A unregister() 0 11 1
A confirmUnregistration() 11 11 2
A call() 0 10 1
A respondToCall() 11 11 2
A setSessionId() 0 4 1
A getSessionId() 0 4 1
A getUniqueId() 0 8 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
namespace Tidal\WampWatch\Stub;
3
4
5
use Thruway\Message\SubscribedMessage;
6
use Thruway\Message\PublishedMessage;
7
use Thruway\Message\RegisteredMessage;
8
use Thruway\Message\UnregisteredMessage;
9
use Evenement\EventEmitterInterface;
10
use Evenement\EventEmitterTrait;
11
use React\Promise\Deferred;
12
13
use Tidal\WampWatch\ClientSessionInterface;
14
15
/**
16
 *
17
 * !!! WARNING !!!!
18
 * This Class should only be used for testing or demos.
19
 * It allows for testing client method calls but behaves differently to
20
 * real client session implementation in that it only stores one (the last)
21
 * subscription, registration etc. for a specific topic/procedure.
22
 *
23
 */
24
25
/**
26
 * Class ClientSessionStub
27
 */
28
class ClientSessionStub implements ClientSessionInterface, EventEmitterInterface
29
{
30
31
    use EventEmitterTrait;
32
33
    protected $sessionId;
34
35
    protected $subscriptions = [];
36
37
    protected $publications = [];
38
39
    protected $registrations = [];
40
41
    protected $unregistrations = [];
42
43
    protected $calls = [];
44
45
    protected $procedures = [];
46
47
48
49
    /**
50
     * Subscribe.
51
     *
52
     * @param string   $topicName
53
     * @param callable $callback
54
     * @param          $options array
55
     * @return \React\Promise\Promise
56
     */
57
    public function subscribe($topicName, callable $callback, $options = null)
58
    {
59
        $this->on($topicName, $callback);
60
61
        $futureResult = new Deferred();
62
63
        $this->subscriptions[$topicName] = $futureResult;
64
65
        return $futureResult->promise();
66
    }
67
68
    /**
69
     * Trigger a SUBSCRIBED message for given topic.
70
     *
71
     * @param $topicName
72
     * @param $requestId
73
     * @param $sessionId
74
     * @throws \RuntimeException if the topic is unknown.
75
     */
76 View Code Duplication
    public function completeSubscription($topicName, $requestId = 1, $sessionId = 1)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
77
    {
78
        if (!isset($this->subscriptions[$topicName])) {
79
            throw new \RuntimeException("No subscription to topic '$topicName' initiated.");
80
        }
81
82
        /* @var $futureResult Deferred */
83
        $futureResult = $this->subscriptions[$topicName];
84
        $result = new SubscribedMessage($requestId, $sessionId);
85
86
        $futureResult->resolve($result);
87
88
    }
89
90
91
    /**
92
     * Publish.
93
     *
94
     * @param string      $topicName
95
     * @param array|mixed $arguments
96
     * @param array|mixed $argumentsKw
97
     * @param array|mixed $options
98
     * @return \React\Promise\Promise
99
     */
100
    public function publish($topicName, $arguments = null, $argumentsKw = null, $options = null)
101
    {
102
        $futureResult = new Deferred();
103
104
        $this->publications[$topicName] = $futureResult;
105
106
        return $futureResult->promise();
107
    }
108
109
    /**
110
     * Trigger a PUBLISHED message for given topic.
111
     *
112
     * @param string $topicName
113
     * @param int    $requestId
114
     * @param int    $publicationId
115
     * @throws \RuntimeException if the topic is unknown.
116
     */
117 View Code Duplication
    public function confirmPublication($topicName, $requestId = 1, $publicationId = 1)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
118
    {
119
        if (!isset($this->publications[$topicName])) {
120
            throw new \RuntimeException("No publication to topic '$topicName' initiated.");
121
        }
122
123
        $futureResult = $this->publications[$topicName];
124
        $result = new PublishedMessage($requestId, $publicationId);
125
126
        $futureResult->resolve($result);
127
    }
128
129
130
    /**
131
     * Register.
132
     *
133
     * @param string      $procedureName
134
     * @param callable    $callback
135
     * @param array|mixed $options
136
     * @return \React\Promise\Promise
137
     */
138
    public function register($procedureName, callable $callback, $options = null)
139
    {
140
141
        $this->procedures[$procedureName] = $callback;
142
143
        $futureResult = new Deferred();
144
145
        $this->registrations[$procedureName] = $futureResult;
146
147
148
        return $futureResult->promise();
149
150
    }
151
152
    /**
153
     * Trigger a REGISTERED message for given procedure.
154
     *
155
     * @param string $procedureName
156
     * @param int    $requestId
157
     * @param int    $registrationId
158
     * @throws \RuntimeException if the procedure is unknown.
159
     */
160
    public function confirmRegistration($procedureName, $requestId = 1, $registrationId = 1)
161
    {
162
        if (!isset($this->registrations[$procedureName])) {
163
            throw new \RuntimeException("No registration to procedure '$procedureName' initiated.");
164
        }
165
166
        $futureResult = $this->registrations[$procedureName];
167
        $result = new RegisteredMessage($requestId, $registrationId);
168
169
        $futureResult->resolve($result);
170
    }
171
172
    /**
173
     * Triggers a call to a registered procedure and returns its result.
174
     *
175
     * @param string $procedureName
176
     * @param array  $args
177
     * @return mixed    the procedure result
178
     * @throws \RuntimeException if the procedure is unknown.
179
     */
180
    public function callRegistration($procedureName, array $args = [])
181
    {
182
        if (!isset($this->procedures[$procedureName])) {
183
            throw new \RuntimeException("No registration for procedure '$procedureName'.");
184
        }
185
186
        $procedure = $this->procedures[$procedureName];
187
188
        return $procedure($args);
189
    }
190
191
192
    /**
193
     * Unregister.
194
     *
195
     * @param string $procedureName
196
     *
197
     * @return \React\Promise\Promise|false
198
     */
199
    public function unregister($procedureName)
200
    {
201
202
        $futureResult = new Deferred();
203
204
        $this->unregistrations[$procedureName] = $futureResult;
205
206
207
        return $futureResult->promise();
208
209
    }
210
211
    /**
212
     * Triggers a UNREGISTERED message for given procedure.
213
     *
214
     * @param string $procedureName
215
     * @param int    $requestId
216
     */
217 View Code Duplication
    public function confirmUnregistration($procedureName, $requestId = 1)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
218
    {
219
        if (!isset($this->unregistrations[$procedureName])) {
220
            throw new \RuntimeException("No registration to procedure '$procedureName' initiated.");
221
        }
222
223
        $futureResult = $this->unregistrations[$procedureName];
224
        $result = new UnregisteredMessage($requestId);
225
226
        $futureResult->resolve($result);
227
    }
228
229
    /**
230
     * Call.
231
     *
232
     * @param string      $procedureName
233
     * @param array|mixed $arguments
234
     * @param array|mixed $argumentsKw
235
     * @param array|mixed $options
236
     * @return \React\Promise\Promise
237
     */
238
    public function call($procedureName, $arguments = null, $argumentsKw = null, $options = null)
239
    {
240
241
        $futureResult = new Deferred();
242
243
        $this->calls[$procedureName] = $futureResult;
244
245
        return $futureResult->promise();
246
247
    }
248
249
250
    /**
251
     * Process ResultMessage
252
     *
253
     * @param string    $procedureName
254
     * @param \stdClass $result
255
     */
256 View Code Duplication
    public function respondToCall($procedureName, $result)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
257
    {
258
        if (!isset($this->calls[$procedureName])) {
259
            throw new \RuntimeException("No call to topic '$procedureName' initiated.");
260
        }
261
262
        /* @var $futureResult Deferred */
263
        $futureResult = $this->calls[$procedureName];
264
265
        $futureResult->resolve($result);
266
    }
267
268
269
    /**
270
     * @param int $sessionId
271
     */
272
    public function setSessionId($sessionId)
273
    {
274
        $this->sessionId = $sessionId;
275
    }
276
277
    /**
278
     * @return int the Session Id
279
     */
280
    public function getSessionId()
281
    {
282
        return $this->sessionId;
283
    }
284
285
    /**
286
     * Generate a unique id for sessions and requests
287
     *
288
     * @return mixed
289
     */
290
    public static function getUniqueId()
291
    {
292
        $filter = 0x1fffffffffffff; // 53 bits
293
        $randomBytes = openssl_random_pseudo_bytes(8);
294
        list($high, $low) = array_values(unpack("N2", $randomBytes));
295
296
        return abs(($high << 32 | $low) & $filter);
297
    }
298
299
300
}