Completed
Branch master (1d1574)
by Evgenij
18:38
created

SocketBag::setSocketMetaData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 17
ccs 13
cts 13
cp 1
rs 9.4285
cc 2
eloc 11
nc 2
nop 3
crap 2
1
<?php
2
/**
3
 * Async sockets
4
 *
5
 * @copyright Copyright (c) 2015-2016, Efimov Evgenij <[email protected]>
6
 *
7
 * This source file is subject to the MIT license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
namespace AsyncSockets\RequestExecutor\Metadata;
11
12
use AsyncSockets\Operation\OperationInterface;
13
use AsyncSockets\RequestExecutor\EventHandlerInterface;
14
use AsyncSockets\RequestExecutor\RequestExecutorInterface;
15
use AsyncSockets\RequestExecutor\SocketBagInterface;
16
use AsyncSockets\Socket\SocketInterface;
17
18
/**
19
 * Class SocketBag
20
 */
21
class SocketBag implements SocketBagInterface
22
{
23
    /**
24
     * RequestExecutorInterface
25
     *
26
     * @var RequestExecutorInterface
27
     */
28
    private $executor;
29
30
    /**
31
     * Target metadata items
32
     *
33
     * @var RequestDescriptor[]
34
     */
35
    private $items;
36
37
    /**
38
     * Default connection timeout
39
     *
40
     * @var double
41
     */
42
    private $connectTimeout;
43
44
    /**
45
     * Default I/O timeout
46
     *
47
     * @var double
48
     */
49
    private $ioTimeout;
50
51
    /**
52
     * SocketBag constructor.
53
     *
54
     * @param RequestExecutorInterface $executor Owner RequestExecutor
55
     * @param double                   $connectTimeout Default connection timeout
56
     * @param double                   $ioTimeout Default I/O timeout
57
     */
58 152
    public function __construct(RequestExecutorInterface $executor, $connectTimeout, $ioTimeout)
59
    {
60 152
        $this->executor       = $executor;
61 152
        $this->items          = [ ];
62 152
        $this->connectTimeout = $connectTimeout;
63 152
        $this->ioTimeout      = $ioTimeout;
64 152
    }
65
66
    /** {@inheritdoc} */
67 1
    public function count()
68
    {
69 1
        return count($this->items);
70
    }
71
72
73
    /** {@inheritdoc} */
74 141
    public function addSocket(
75
        SocketInterface $socket,
76
        OperationInterface $operation,
77
        array $metadata = null,
78
        EventHandlerInterface $eventHandlers = null
79
    ) {
80 141
        $hash = $this->getOperationStorageKey($socket);
81 141
        if (isset($this->items[$hash])) {
82 1
            throw new \LogicException('Can not add socket twice.');
83
        }
84
85 141
        $meta = array_merge(
86
            [
87 141
                RequestExecutorInterface::META_ADDRESS               => null,
88 141
                RequestExecutorInterface::META_USER_CONTEXT          => null,
89 141
                RequestExecutorInterface::META_SOCKET_STREAM_CONTEXT => null,
90 141
                RequestExecutorInterface::META_CONNECTION_TIMEOUT    => $this->connectTimeout,
91 141
                RequestExecutorInterface::META_IO_TIMEOUT            => $this->ioTimeout,
92 141
            ],
93 141
            $metadata ?: [],
94
            [
95 141
                RequestExecutorInterface::META_CONNECTION_START_TIME  => null,
96 141
                RequestExecutorInterface::META_CONNECTION_FINISH_TIME => null,
97 141
                RequestExecutorInterface::META_LAST_IO_START_TIME     => null,
98 141
                RequestExecutorInterface::META_REQUEST_COMPLETE       => false,
99
            ]
100 141
        );
101
102 141
        $this->items[$hash] = new RequestDescriptor($socket, $operation, $meta, $eventHandlers);
103 141
    }
104
105
    /** {@inheritdoc} */
106 1
    public function getSocketOperation(SocketInterface $socket)
107
    {
108 1
        return $this->requireDescriptor($socket)->getOperation();
109
    }
110
111
    /** {@inheritdoc} */
112 1
    public function setSocketOperation(SocketInterface $socket, OperationInterface $operation)
113
    {
114 1
        $this->requireDescriptor($socket)->setOperation($operation);
115 1
    }
116
117
118
    /** {@inheritdoc} */
119 3
    public function hasSocket(SocketInterface $socket)
120
    {
121 3
        $hash = $this->getOperationStorageKey($socket);
122 3
        return isset($this->items[$hash]);
123
    }
124
125
    /** {@inheritdoc} */
126 3
    public function removeSocket(SocketInterface $socket)
127
    {
128 3
        $key = $this->getOperationStorageKey($socket);
129 3
        if (!isset($this->items[$key])) {
130 1
            return;
131
        }
132
133 2
        $meta = $this->items[$key]->getMetadata();
134 2
        if (!$meta[RequestExecutorInterface::META_REQUEST_COMPLETE] && $this->executor->isExecuting()) {
135 1
            throw new \LogicException('Can not remove unprocessed socket during request processing.');
136
        }
137
138 1
        unset($this->items[$key]);
139 1
    }
140
141
    /** {@inheritdoc} */
142 1
    public function postponeSocket(SocketInterface $socket)
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...
143
    {
144 1
        $key = $this->getOperationStorageKey($socket);
145 1
        if (!isset($this->items[$key])) {
146 1
            return;
147
        }
148
149
        $this->items[$key]->postpone();
150
    }
151
152
    /** {@inheritdoc} */
153 84
    public function getSocketMetaData(SocketInterface $socket)
154
    {
155 84
        return $this->requireDescriptor($socket)->getMetadata();
156
    }
157
158
    /** {@inheritdoc} */
159 9
    public function setSocketMetaData(SocketInterface $socket, $key, $value = null)
160
    {
161
        $writableKeys = [
162 9
            RequestExecutorInterface::META_ADDRESS               => 1,
163 9
            RequestExecutorInterface::META_USER_CONTEXT          => 1,
164 9
            RequestExecutorInterface::META_CONNECTION_TIMEOUT    => 1,
165 9
            RequestExecutorInterface::META_IO_TIMEOUT            => 1,
166 9
            RequestExecutorInterface::META_SOCKET_STREAM_CONTEXT => 1,
167 9
        ];
168
169 9
        if (!is_array($key)) {
170 9
            $key = [ $key => $value ];
171 9
        }
172
173 9
        $key = array_intersect_key($key, $writableKeys);
174 9
        $this->requireDescriptor($socket)->setMetadata($key);
175 9
    }
176
177
    /**
178
     * Return socket key in internal storage
179
     *
180
     * @param SocketInterface $socket Socket object
181
     *
182
     * @return string
183
     */
184 143
    private function getOperationStorageKey(SocketInterface $socket)
185
    {
186 143
        return spl_object_hash($socket);
187
    }
188
189
    /**
190
     * Require operation descriptor for given socket
191
     *
192
     * @param SocketInterface $socket Socket object
193
     *
194
     * @return RequestDescriptor
195
     * @throws \OutOfBoundsException
196
     */
197 85
    private function requireDescriptor(SocketInterface $socket)
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...
198
    {
199 85
        $hash = $this->getOperationStorageKey($socket);
200 85
        if (!isset($this->items[$hash])) {
201 1
            throw new \OutOfBoundsException('Trying to perform operation on not added socket.');
202
        }
203
204 84
        return $this->items[$hash];
205
    }
206
207
    /**
208
     * Return metadata items
209
     *
210
     * @return RequestDescriptor[]
211
     */
212 125
    public function getItems()
213
    {
214 125
        return $this->items;
215
    }
216
}
217