SessionMonitor::initSetupCalls()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
cc 3
eloc 11
nc 1
nop 0
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;
13
14
use Evenement\EventEmitterInterface;
15
use Thruway\Message\ErrorMessage;
16
use Tidal\WampWatch\ClientSessionInterface as ClientSession;
17
use Tidal\WampWatch\Adapter\React\PromiseAdapter;
18
use Tidal\WampWatch\Async\PromiseInterface;
19
20
/**
21
 * Class SessionMonitor.
22
 */
23
class SessionMonitor implements MonitorInterface, EventEmitterInterface
24
{
25
    use MonitorTrait;
26
27
    const SESSION_JOIN_TOPIC = 'wamp.session.on_join';
28
    const SESSION_LEAVE_TOPIC = 'wamp.session.on_leave';
29
    const SESSION_COUNT_TOPIC = 'wamp.session.count';
30
    const SESSION_LIST_TOPIC = 'wamp.session.list';
31
    const SESSION_INFO_TOPIC = 'wamp.session.get';
32
33
    /**
34
     * @var array monitored session ids
35
     */
36
    protected $sessionIds = [];
37
38
    /**
39
     * @var int subscription id for on_join
40
     */
41
    protected $joinSubscriptionId = 0;
42
43
    /**
44
     * @var int subscription id for on_leave
45
     */
46
    protected $leaveSubscriptionId = 0;
47
48
    /**
49
     * Constructor.
50
     *
51
     * @param ClientSession $session
52
     */
53
    public function __construct(ClientSession $session)
54
    {
55
        $this->setClientSession($session);
56
        $this->initSetupCalls();
57
    }
58
59
    /**
60
     * Retrieves the session-info for given sessionId
61
     * and populates it in via given callback.
62
     *
63
     * @param   $sessionId
64
     *
65
     * @return PromiseInterface
66
     */
67
    public function getSessionInfo($sessionId)
68
    {
69
        return $this->session->call(self::SESSION_INFO_TOPIC, [$sessionId])->then(
70
            function ($res) {
71
                $this->emit('info', [$res]);
72
73
                return $res;
74
            },
75
            function (ErrorMessage $error) use ($sessionId) {
76
                $this->emit('error', [$error, $sessionId]);
77
            }
78
        );
79
    }
80
81
    /**
82
     * Retrieves the Ids of the sessions currently
83
     * registered on the wamp-router in the monitor's realm
84
     * and populates the data via given callback,.
85
     *
86
     * @return PromiseInterface
87
     */
88
    public function getSessionIds()
89
    {
90
        if (!count($this->sessionIds)) {
91
            return $this->retrieveSessionIds();
92
        }
93
94
        return $this->createPromise(
95
            function (callable $resolve) {
96
                $resolve($this->getList());
97
            }
98
        );
99
    }
100
101
    /**
102
     * Checks if a session id is known.
103
     *
104
     * @param $sessionId
105
     *
106
     * @return bool
107
     */
108
    public function hasSessionId($sessionId)
109
    {
110
        return array_search($sessionId, $this->sessionIds) !== false;
111
    }
112
113
    /**
114
     * Removes a session id.
115
     *
116
     * @param int $sessionId
117
     */
118
    protected function removeSessionId($sessionId)
119
    {
120
        if (!$this->hasSessionId($sessionId)) {
121
            return;
122
        }
123
        $key = array_search($sessionId, $this->sessionIds);
124
        unset($this->sessionIds[$key]);
125
        $this->sessionIds = array_values($this->sessionIds);
126
        $this->emit('leave', [$sessionId]);
127
    }
128
129
    /**
130
     * Checks if a session is known by extracting its id.
131
     *
132
     * @param $sessionInfo
133
     *
134
     * @return bool
135
     */
136
    protected function hasSession($sessionInfo)
137
    {
138
        return $this->hasSessionId($sessionInfo->session);
139
    }
140
141
    /**
142
     * Adds and publishes a joined session.
143
     *
144
     * @param $sessionInfo
145
     */
146
    protected function addSession($sessionInfo)
147
    {
148
        $this->sessionIds[] = $sessionInfo->session;
149
        $this->emit('join', [$sessionInfo]);
150
    }
151
152
    /**
153
     * Validates the sessionInfo sent from the router.
154
     *
155
     * @param string $sessionInfo
156
     *
157
     * @return bool
158
     */
159
    protected function validateSessionInfo($sessionInfo)
160
    {
161
        return is_object($sessionInfo) && property_exists($sessionInfo, 'session');
162
    }
163
164
    /**
165
     * Initializes the subscription to the meta-events.
166
     */
167
    protected function initSetupCalls()
168
    {
169
        // @var \Tidal\WampWatch\Subscription\Collection
170
        $collection = $this->getMetaSubscriptionCollection();
171
172
        $collection->addSubscription(self::SESSION_JOIN_TOPIC, function (array $res) {
173
            $sessionInfo = $res[0];
174
            if (!$this->validateSessionInfo($sessionInfo) || $this->hasSession($sessionInfo)) {
175
                return;
176
            }
177
            $this->addSession($sessionInfo);
178
        });
179
180
        $collection->addSubscription(self::SESSION_LEAVE_TOPIC, function (array $res) {
181
            // @bug : wamp.session.on_leave is bugged as of crossbar.io 0.11.0
182
            // will provide sessionID when Browser closes/reloads,
183
            // but not when calling connection.close();
184
            $sessionId = (int) $res[0];
185
            $this->removeSessionId($sessionId);
186
        });
187
188
        $this->setInitialCall(self::SESSION_LIST_TOPIC, $this->getSessionIdRetrievalCallback());
189
    }
190
191
    /**
192
     * Retrieves the list of current sessionIds on the router.
193
     *
194
     * @return PromiseAdapter
195
     */
196
    protected function retrieveSessionIds()
197
    {
198
        return $this->retrieveCallData(
199
            self::SESSION_LIST_TOPIC,
200
            $this->getSessionIdRetrievalCallback(),
201
            []
202
        );
203
    }
204
205
    /**
206
     * @return \Closure
207
     */
208
    protected function getSessionIdRetrievalCallback()
209
    {
210
        return function ($res) {
211
            $this->setList($res[0]);
212
            $sessionIds = $this->getList();
213
            $this->emit('list', [$sessionIds]);
214
215
            return $sessionIds;
216
        };
217
    }
218
219
    /**
220
     * @param $list
221
     */
222
    protected function setList($list)
223
    {
224
        $this->sessionIds = $this->removeOwnSessionId($list);
225
    }
226
227
    /**
228
     * @return array
229
     */
230
    protected function getList()
231
    {
232
        return $this->sessionIds;
233
    }
234
235
    /**
236
     * remove the sessionID of the Monitor from the list.
237
     *
238
     * @param array $sessionsIds
239
     *
240
     * @return mixed
241
     */
242
    protected function removeOwnSessionId(array $sessionsIds)
243
    {
244
        $key = array_search($this->session->getSessionId(), $sessionsIds);
245
246
        if ($key !== false && $key >= 0) {
247
            unset($sessionsIds[$key]);
248
            $sessionsIds = array_values($sessionsIds);
249
        }
250
251
        return $sessionsIds;
252
    }
253
254
    public static function create(ClientSession $session)
255
    {
256
        return new self($session);
257
    }
258
}
259