ClientSessionStub::setSessionId()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Tidal/WampWatch package.
5
 *   (c) 2016 Timo Michna <timomichna/yahoo.de>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 *
10
 */
11
12
namespace Tidal\WampWatch\Stub;
13
14
use Evenement\EventEmitterInterface;
15
use Evenement\EventEmitterTrait;
16
use React\Promise\Deferred;
17
use Thruway\Message\PublishedMessage;
18
use Thruway\Message\PublishMessage;
19
use Thruway\Message\SubscribedMessage;
20
use Thruway\Message\SubscribeMessage;
21
use Thruway\Message\RegisteredMessage;
22
use Thruway\Message\RegisterMessage;
23
use Thruway\Message\UnregisteredMessage;
24
use Thruway\Message\CallMessage;
25
use Thruway\Message\ErrorMessage;
26
use Tidal\WampWatch\ClientSessionInterface;
27
use Tidal\WampWatch\Exception\UnknownProcedureException;
28
use Tidal\WampWatch\Exception\UnknownTopicException;
29
use Tidal\WampWatch\Adapter\React\PromiseAdapter;
30
use Tidal\WampWatch\Behavior\Async\MakesDeferredPromisesTrait;
31
use Tidal\WampWatch\Behavior\Async\MakesPromisesTrait;
32
use Tidal\WampWatch\Async\DeferredInterface;
33
34
/**
35
 * !!! WARNING !!!!
36
 * This Class should only be used for testing or demos.
37
 * It allows for testing client method calls but behaves differently to
38
 * real client session implementation in that it only stores one (the last)
39
 * subscription, registration etc. for a specific topic/procedure.
40
 */
41
42
/**
43
 * Class ClientSessionStub.
44
 */
45
class ClientSessionStub implements ClientSessionInterface, EventEmitterInterface
46
{
47
    use EventEmitterTrait,
48
        MakesPromisesTrait,
49
        MakesDeferredPromisesTrait;
50
51
    /**
52
     * @var int
53
     */
54
    protected $sessionId;
55
56
    /**
57
     * @var array
58
     */
59
    protected $subscriptions = [];
60
61
    /**
62
     * @var array
63
     */
64
    protected $subscribing = [];
65
66
    /**
67
     * @var array
68
     */
69
    protected $publications = [];
70
71
    /**
72
     * @var array
73
     */
74
    protected $publishing = [];
75
76
    /**
77
     * @var array
78
     */
79
    protected $registrations = [];
80
81
    /**
82
     * @var array
83
     */
84
    protected $registering = [];
85
86
    /**
87
     * @var array
88
     */
89
    protected $unregistrations = [];
90
91
    /**
92
     * @var array
93
     */
94
    protected $calls = [];
95
96
    /**
97
     * @var array
98
     */
99
    protected $calling = [];
100
101
    /**
102
     * @var array
103
     */
104
    protected $procedures = [];
105
106
    /**
107
     * Subscribe.
108
     *
109
     * @param string   $topicName
110
     * @param callable $callback
111
     * @param          $options   array
112
     *
113
     * @return PromiseAdapter
114
     */
115 View Code Duplication
    public function subscribe($topicName, callable $callback, $options = null)
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...
116
    {
117
        $this->on($topicName, $callback);
118
119
        $this->subscriptions[$topicName] = static::createDeferredAdapter();
0 ignored issues
show
Bug introduced by
Since createDeferredAdapter() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of createDeferredAdapter() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
120
        $this->subscribing[$topicName] = new SubscribeMessage(
121
            count($this->subscriptions),
122
            (object) $options,
123
            $topicName
124
        );
125
126
        return $this->subscriptions[$topicName]->promise();
127
    }
128
129
    /**
130
     * Trigger a SUBSCRIBED message for given topic.
131
     *
132
     * @param $topicName
133
     * @param $requestId
134
     * @param $subscriptionId
135
     *
136
     * @throws UnknownTopicException if the topic is unknown
137
     */
138 View Code Duplication
    public function completeSubscription($topicName, $requestId = 1, $subscriptionId = 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...
139
    {
140
        if (!isset($this->subscriptions[$topicName])) {
141
            throw new UnknownTopicException($topicName);
142
        }
143
144
        /* @var $futureResult Deferred */
145
        $futureResult = $this->subscriptions[$topicName];
146
        $result = new SubscribedMessage($requestId, $subscriptionId);
147
148
        $futureResult->resolve($result);
149
    }
150
151
    public function hasSubscription($topicName)
152
    {
153
        return isset($this->subscriptions[$topicName]);
154
    }
155
156
    /**
157
     * Publish.
158
     *
159
     * @param string      $topicName
160
     * @param array|mixed $arguments
161
     * @param array|mixed $argumentsKw
162
     * @param array|mixed $options
163
     *
164
     * @return PromiseAdapter
165
     */
166
    public function publish($topicName, $arguments = null, $argumentsKw = null, $options = null)
167
    {
168
        $this->publications[$topicName] = static::createDeferredAdapter();
0 ignored issues
show
Bug introduced by
Since createDeferredAdapter() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of createDeferredAdapter() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
169
        $this->publishing[$topicName] = new PublishMessage(
170
            count($this->publishing),
171
            $options,
172
            $topicName,
173
            $arguments,
174
            $argumentsKw
175
        );
176
177
        return $this->publications[$topicName]->promise();
178
    }
179
180
    /**
181
     * Trigger a PUBLISHED message for given topic.
182
     *
183
     * @param string $topicName
184
     * @param int    $requestId
185
     * @param int    $publicationId
186
     *
187
     * @throws UnknownTopicException if the topic is unknown
188
     */
189 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...
190
    {
191
        if (!isset($this->publications[$topicName])) {
192
            throw new UnknownTopicException($topicName);
193
        }
194
195
        $futureResult = $this->publications[$topicName];
196
        $result = new PublishedMessage($requestId, $publicationId);
197
198
        $futureResult->resolve($result);
199
    }
200
201
    /**
202
     * @param string $topicName
203
     * @param mixed  $error
204
     * @param int    $requestId
205
     */
206
    public function failPublication($topicName, $error, $requestId = 1)
207
    {
208
        if (!isset($this->publications[$topicName])) {
209
            throw new UnknownTopicException($topicName);
210
        }
211
212
        $futureResult = $this->publications[$topicName];
213
        $result = new ErrorMessage($error, $requestId, new \stdClass(), $topicName);
214
215
        $futureResult->reject($result);
216
    }
217
218
    /**
219
     * Register.
220
     *
221
     * @param string      $procedureName
222
     * @param callable    $callback
223
     * @param array|mixed $options
224
     *
225
     * @return PromiseAdapter
226
     */
227 View Code Duplication
    public function register($procedureName, callable $callback, $options = null)
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...
228
    {
229
        $this->procedures[$procedureName] = $callback;
230
231
        $this->registrations[$procedureName] = static::createDeferredAdapter();
0 ignored issues
show
Bug introduced by
Since createDeferredAdapter() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of createDeferredAdapter() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
232
        $this->registering[$procedureName] = new RegisterMessage(
233
            count($this->registering),
234
            $options,
235
            $procedureName
236
        );
237
238
        return $this->registrations[$procedureName]->promise();
239
    }
240
241
    /**
242
     * Trigger a REGISTERED message for given procedure.
243
     *
244
     * @param string $procedureName
245
     * @param int    $requestId
246
     * @param int    $registrationId
247
     *
248
     * @throws UnknownProcedureException if the procedure is unknown
249
     */
250 View Code Duplication
    public function confirmRegistration($procedureName, $requestId = 1, $registrationId = 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...
251
    {
252
        if (!isset($this->registrations[$procedureName])) {
253
            throw new UnknownProcedureException($procedureName);
254
        }
255
256
        $futureResult = $this->registrations[$procedureName];
257
        $result = new RegisteredMessage($requestId, $registrationId);
258
259
        $futureResult->resolve($result);
260
    }
261
262
    /**
263
     * Triggers a call to a registered procedure and returns its result.
264
     *
265
     * @param string $procedureName
266
     * @param array  $args
267
     *
268
     * @throws UnknownProcedureException if the procedure is unknown
269
     *
270
     * @return mixed the procedure result
271
     */
272
    public function callRegistration($procedureName, array $args = [])
273
    {
274
        if (!isset($this->procedures[$procedureName])) {
275
            throw new UnknownProcedureException($procedureName);
276
        }
277
278
        $procedure = $this->procedures[$procedureName];
279
280
        return $procedure($args);
281
    }
282
283
    /**
284
     * Unregister.
285
     *
286
     * @param string $procedureName
287
     *
288
     * @return PromiseAdapter
289
     */
290
    public function unregister($procedureName)
291
    {
292
        $this->unregistrations[$procedureName] = static::createDeferredAdapter();
0 ignored issues
show
Bug introduced by
Since createDeferredAdapter() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of createDeferredAdapter() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
293
294
        return $this->unregistrations[$procedureName]->promise();
295
    }
296
297
    /**
298
     * Triggers a UNREGISTERED message for given procedure.
299
     *
300
     * @param string $procedureName
301
     * @param int    $requestId
302
     *
303
     * @throws UnknownProcedureException
304
     */
305 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...
306
    {
307
        if (!isset($this->unregistrations[$procedureName])) {
308
            throw new UnknownProcedureException($procedureName);
309
        }
310
311
        $futureResult = $this->unregistrations[$procedureName];
312
        $result = new UnregisteredMessage($requestId);
313
314
        $futureResult->resolve($result);
315
    }
316
317
    /**
318
     * Call.
319
     *
320
     * @param string      $procedureName
321
     * @param array|mixed $arguments
322
     * @param array|mixed $argumentsKw
323
     * @param array|mixed $options
324
     *
325
     * @return PromiseAdapter
326
     */
327
    public function call($procedureName, $arguments = null, $argumentsKw = null, $options = null)
328
    {
329
        $this->calls[$procedureName] = $this->createDeferredAdapter();
330
        $this->calling[$procedureName] = new CallMessage(
331
            count($this->calling),
332
            $options,
333
            $procedureName,
334
            $arguments,
335
            $argumentsKw
336
        );
337
338
        return $this->calls[$procedureName]->promise();
339
    }
340
341
    /**
342
     * Process ResultMessage.
343
     *
344
     * @param string $procedureName
345
     * @param mixed  $result
346
     */
347 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...
348
    {
349
        if (!isset($this->calls[$procedureName])) {
350
            throw new UnknownProcedureException($procedureName);
351
        }
352
353
        /* @var $futureResult Deferred */
354
        $futureResult = $this->calls[$procedureName];
355
        unset($this->calls[$procedureName]);
356
357
        $futureResult->resolve($result);
358
    }
359
360
    /**
361
     * @param string $procedureName
362
     * @param mixed  $error
363
     */
364 View Code Duplication
    public function failCall($procedureName, $error)
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...
365
    {
366
        if (!isset($this->calls[$procedureName])) {
367
            throw new UnknownProcedureException($procedureName);
368
        }
369
370
        /* @var $futureResult Deferred */
371
        $futureResult = $this->calls[$procedureName];
372
        unset($this->calls[$procedureName]);
373
374
        $futureResult->reject($error);
375
    }
376
377
    /**
378
     * @param string $procedureName
379
     *
380
     * @return bool
381
     */
382
    public function hasCall($procedureName)
383
    {
384
        return isset($this->calls[$procedureName]);
385
    }
386
387
    /**
388
     * @param int $sessionId
389
     */
390
    public function setSessionId($sessionId)
391
    {
392
        $this->sessionId = $sessionId;
393
    }
394
395
    /**
396
     * @return int the Session Id
397
     */
398
    public function getSessionId()
399
    {
400
        return $this->sessionId;
401
    }
402
403
    /**
404
     * Generate a unique id for sessions and requests.
405
     *
406
     * @return mixed
407
     */
408
    public static function getUniqueId()
409
    {
410
        $filter = 0x1fffffffffffff; // 53 bits
411
        $randomBytes = openssl_random_pseudo_bytes(8);
412
        list($high, $low) = array_values(unpack('N2', $randomBytes));
413
414
        return abs(($high << 32 | $low) & $filter);
415
    }
416
417
    /**
418
     * @param $msg
419
     *
420
     * @return mixed
421
     */
422
    public function sendMessage($msg)
423
    {
424
        return $msg;
425
    }
426
427
    /**
428
     * @param callable $canceller
429
     *
430
     * @return DeferredInterface
431
     */
432
    private function createDeferredAdapter(callable $canceller = null)
433
    {
434
        $canceller = $canceller ?: function () {
435
        };
436
437
        return $this->getDeferredFactory()->create($canceller);
438
    }
439
}
440