Completed
Pull Request — master (#14)
by
unknown
04:08
created
src/Client.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -66,7 +66,7 @@  discard block
 block discarded – undo
66 66
 	 * Get some parameter from config
67 67
 	 *
68 68
 	 * @param string $parameter Name of required parameter
69
-	 * @return mixed
69
+	 * @return integer
70 70
 	 * @throws \RouterOS\Exceptions\ConfigException
71 71
 	 */
72 72
 	private function config(string $parameter) 
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
 	/**
100 100
 	 * Send write query to RouterOS (with or without tag)
101 101
 	 *
102
-	 * @param string|array|\RouterOS\Query $query
102
+	 * @param Query $query
103 103
 	 * @return \RouterOS\Interfaces\ClientInterface
104 104
 	 * @throws \RouterOS\Exceptions\QueryException
105 105
 	 */
Please login to merge, or discard this patch.
Indentation   +368 added lines, -368 removed lines patch added patch discarded remove patch
@@ -16,372 +16,372 @@
 block discarded – undo
16 16
  */
17 17
 class Client implements Interfaces\ClientInterface 
18 18
 {
19
-	use SocketTrait, ShortsTrait;
20
-
21
-	/**
22
-	 * Configuration of connection
23
-	 *
24
-	 * @var \RouterOS\Config
25
-	 */
26
-	private $_config;
27
-
28
-	/**
29
-	 * API communication object
30
-	 *
31
-	 * @var \RouterOS\APIConnector
32
-	 */
33
-
34
-	private $_connector;
35
-
36
-	/**
37
-	 * Client constructor.
38
-	 *
39
-	 * @param array|\RouterOS\Config $config
40
-	 * @throws \RouterOS\Exceptions\ClientException
41
-	 * @throws \RouterOS\Exceptions\ConfigException
42
-	 * @throws \RouterOS\Exceptions\QueryException
43
-	 */
44
-	public function __construct($config) 
45
-	{
46
-		// If array then need create object
47
-		if (\is_array($config)) {
48
-			$config = new Config($config);
49
-		}
50
-
51
-		// Check for important keys
52
-		if (true !== $key = ArrayHelper::checkIfKeysNotExist(['host', 'user', 'pass'], $config->getParameters())) {
53
-			throw new ConfigException("One or few parameters '$key' of Config is not set or empty");
54
-		}
55
-
56
-		// Save config if everything is okay
57
-		$this->setConfig($config);
58
-
59
-		// Throw error if cannot to connect
60
-		if (false === $this->connect()) {
61
-			throw new ClientException('Unable to connect to ' . $config->get('host') . ':' . $config->get('port'));
62
-		}
63
-	}
64
-
65
-	/**
66
-	 * Get some parameter from config
67
-	 *
68
-	 * @param string $parameter Name of required parameter
69
-	 * @return mixed
70
-	 * @throws \RouterOS\Exceptions\ConfigException
71
-	 */
72
-	private function config(string $parameter) 
73
-	{
74
-		return $this->_config->get($parameter);
75
-	}
76
-
77
-	/**
78
-	 * Return socket resource if is exist
79
-	 *
80
-	 * @return \RouterOS\Config
81
-	 * @since 0.6
82
-	 */
83
-	public function getConfig(): Config 
84
-	{
85
-		return $this->_config;
86
-	}
87
-
88
-	/**
89
-	 * Set configuration of client
90
-	 *
91
-	 * @param \RouterOS\Config $config
92
-	 * @since 0.7
93
-	 */
94
-	public function setConfig(Config $config) 
95
-	{
96
-		$this->_config = $config;
97
-	}
98
-
99
-	/**
100
-	 * Send write query to RouterOS (with or without tag)
101
-	 *
102
-	 * @param string|array|\RouterOS\Query $query
103
-	 * @return \RouterOS\Interfaces\ClientInterface
104
-	 * @throws \RouterOS\Exceptions\QueryException
105
-	 */
106
-	public function write($query): ClientInterface 
107
-	{
108
-		if (\is_string($query)) {
109
-			$query = new Query($query);
110
-		} elseif (\is_array($query)) {
111
-			$endpoint = array_shift($query);
112
-			$query = new Query($endpoint, $query);
113
-		}
114
-
115
-		if (!$query instanceof Query) {
116
-			throw new QueryException('Parameters cannot be processed');
117
-		}
118
-
119
-		// Send commands via loop to router
120
-		foreach ($query->getQuery() as $command) {
121
-			$this->_connector->writeWord(trim($command));
122
-		}
123
-
124
-		// Write zero-terminator (empty string)
125
-		$this->_connector->writeWord('');
126
-
127
-		return $this;
128
-	}
129
-
130
-	/**
131
-	 * Read answer from server after query was executed
132
-	 *
133
-	 * A Mikrotik reply is formed of blocks
134
-	 * Each block starts with a word, one of ('!re', '!trap', '!done', '!fatal')
135
-	 * Each block end with an zero byte (empty line)
136
-	 * Reply ends with a complete !done or !fatal block (ended with 'empty line')
137
-	 * A !fatal block precedes TCP connexion close
138
-	 *
139
-	 * @param bool $parse
140
-	 * @return mixed
141
-	 */
142
-	public function read(bool $parse = true) 
143
-	{
144
-		// By default response is empty
145
-		$response = [];
146
-		// We have to wait a !done or !fatal
147
-		$lastReply = false;
148
-
149
-		// Read answer from socket in loop
150
-		while (true) {
151
-			$word = $this->_connector->readWord();
152
-
153
-			if ('' === $word) {
154
-				if ($lastReply) {
155
-					// We received a !done or !fatal message in a precedent loop
156
-					// response is complete
157
-					break;
158
-				}
159
-				// We did not receive the !done or !fatal message
160
-				// This 0 length message is the end of a reply !re or !trap
161
-				// We have to wait the router to send a !done or !fatal reply followed by optionals values and a 0 length message
162
-				continue;
163
-			}
164
-
165
-			// Save output line to response array
166
-			$response[] = $word;
167
-
168
-			// If we get a !done or !fatal line in response, we are now ready to finish the read
169
-			// but we need to wait a 0 length message, switch the flag
170
-			if ('!done' === $word || '!fatal' === $word) {
171
-				$lastReply = true;
172
-			}
173
-		}
174
-
175
-		// Parse results and return
176
-		return $parse ? $this->rosario($response) : $response;
177
-	}
178
-
179
-	/**
180
-	 * Read using Iterators to improve performance on large dataset
181
-	 *
182
-	 * @return Iterators\ResponseIterator
183
-	 */
184
-	public function readAsIterator() 
185
-	{
186
-		return new Iterators\ResponseIterator($this->read(false));
187
-	}
188
-
189
-	/**
190
-	 * This method was created by memory save reasons, it convert response
191
-	 * from RouterOS to readable array in safe way.
192
-	 *
193
-	 * @param array $raw Array RAW response from server
194
-	 * @return mixed
195
-	 *
196
-	 * Based on RouterOSResponseArray solution by @arily
197
-	 *
198
-	 * @link    https://github.com/arily/RouterOSResponseArray
199
-	 * @since   0.10
200
-	 */
201
-	private function rosario(array $raw): array
202
-	{
203
-		// This RAW should't be an error
204
-		$positions = array_keys($raw, '!re');
205
-		$count = count($raw);
206
-		$result = [];
207
-
208
-		if (isset($positions[1])) {
209
-
210
-			foreach ($positions as $key => $position) {
211
-				// Get length of future block
212
-				$length = isset($positions[$key + 1])
213
-				? $positions[$key + 1] - $position + 1
214
-				: $count - $position;
215
-
216
-				// Convert array to simple items
217
-				$item = [];
218
-				for ($i = 1; $i < $length; $i++) {
219
-					$item[] = array_shift($raw);
220
-				}
221
-
222
-				// Save as result
223
-				$result[] = $this->parseResponse($item)[0];
224
-			}
225
-
226
-		} else {
227
-			$result = $this->parseResponse($raw);
228
-		}
229
-
230
-		return $result;
231
-	}
232
-
233
-	/**
234
-	 * Parse response from Router OS
235
-	 *
236
-	 * @param array $response Response data
237
-	 * @return array Array with parsed data
238
-	 */
239
-	protected function parseResponse(array $response): array
240
-	{
241
-		$result = [];
242
-		$i = -1;
243
-		$lines = \count($response);
244
-		foreach ($response as $key => $value) {
245
-			switch ($value) {
246
-			case '!re':
247
-				$i++;
248
-				break;
249
-			case '!fatal':
250
-				$result = $response;
251
-				break 2;
252
-			case '!trap':
253
-			case '!done':
254
-				// Check for =ret=, .tag and any other following messages
255
-				for ($j = $key + 1; $j <= $lines; $j++) {
256
-					// If we have lines after current one
257
-					if (isset($response[$j])) {
258
-						$this->pregResponse($response[$j], $matches);
259
-						if (isset($matches[1][0], $matches[2][0])) {
260
-							$result['after'][$matches[1][0]] = $matches[2][0];
261
-						}
262
-					}
263
-				}
264
-				break 2;
265
-			default:
266
-				$this->pregResponse($value, $matches);
267
-				if (isset($matches[1][0], $matches[2][0])) {
268
-					$result[$i][$matches[1][0]] = $matches[2][0];
269
-				}
270
-				break;
271
-			}
272
-		}
273
-		return $result;
274
-	}
275
-
276
-	/**
277
-	 * Parse result from RouterOS by regular expression
278
-	 *
279
-	 * @param string $value
280
-	 * @param array  $matches
281
-	 */
282
-	private function pregResponse(string $value, &$matches) 
283
-	{
284
-		preg_match_all('/^[=|\.](.*)=(.*)/', $value, $matches);
285
-	}
286
-
287
-	/**
288
-	 * Authorization logic
289
-	 *
290
-	 * @param bool $legacyRetry Retry login if we detect legacy version of RouterOS
291
-	 * @return bool
292
-	 * @throws \RouterOS\Exceptions\ClientException
293
-	 * @throws \RouterOS\Exceptions\ConfigException
294
-	 * @throws \RouterOS\Exceptions\QueryException
295
-	 */
296
-	private function login(bool $legacyRetry = false): bool 
297
-	{
298
-		// If legacy login scheme is enabled
299
-		if ($this->config('legacy')) {
300
-			// For the first we need get hash with salt
301
-			$query = new Query('/login');
302
-			$response = $this->write($query)->read();
303
-
304
-			// Now need use this hash for authorization
305
-			$query = (new Query('/login'))
306
-				->add('=name=' . $this->config('user'))
307
-				->add('=response=00' . md5(\chr(0) . $this->config('pass') . pack('H*', $response['after']['ret'])));
308
-		} else {
309
-			// Just login with our credentials
310
-			$query = (new Query('/login'))
311
-				->add('=name=' . $this->config('user'))
312
-				->add('=password=' . $this->config('pass'));
313
-
314
-			// If we set modern auth scheme but router with legacy firmware then need to retry query,
315
-			// but need to prevent endless loop
316
-			$legacyRetry = true;
317
-		}
318
-
319
-		// Execute query and get response
320
-		$response = $this->write($query)->read(false);
321
-
322
-		// if:
323
-		//  - we have more than one response
324
-		//  - response is '!done'
325
-		// => problem with legacy version, swap it and retry
326
-		// Only tested with ROS pre 6.43, will test with post 6.43 => this could make legacy parameter obsolete?
327
-		if ($legacyRetry && $this->isLegacy($response)) {
328
-			$this->_config->set('legacy', true);
329
-			return $this->login();
330
-		}
331
-
332
-		// Return true if we have only one line from server and this line is !done
333
-		return (1 === count($response)) && isset($response[0]) && ($response[0] === '!done');
334
-	}
335
-
336
-	/**
337
-	 * Detect by login request if firmware is legacy
338
-	 *
339
-	 * @param array $response
340
-	 * @return bool
341
-	 * @throws ConfigException
342
-	 */
343
-	private function isLegacy(array &$response): bool 
344
-	{
345
-		return \count($response) > 1 && $response[0] === '!done' && !$this->config('legacy');
346
-	}
347
-
348
-	/**
349
-	 * Connect to socket server
350
-	 *
351
-	 * @return bool
352
-	 * @throws \RouterOS\Exceptions\ClientException
353
-	 * @throws \RouterOS\Exceptions\ConfigException
354
-	 * @throws \RouterOS\Exceptions\QueryException
355
-	 */
356
-	private function connect(): bool
357
-	{
358
-		// By default we not connected
359
-		$connected = false;
360
-
361
-		// Few attempts in loop
362
-		for ($attempt = 1; $attempt <= $this->config('attempts'); $attempt++) {
363
-
364
-			// Initiate socket session
365
-			$this->openSocket();
366
-
367
-			// If socket is active
368
-			if (null !== $this->getSocket()) {
369
-				$this->_connector = new APIConnector(new Streams\ResourceStream($this->getSocket()));
370
-				// If we logged in then exit from loop
371
-				if (true === $this->login()) {
372
-					$connected = true;
373
-					break;
374
-				}
375
-
376
-				// Else close socket and start from begin
377
-				$this->closeSocket();
378
-			}
379
-
380
-			// Sleep some time between tries
381
-			sleep($this->config('delay'));
382
-		}
383
-
384
-		// Return status of connection
385
-		return $connected;
386
-	}
19
+    use SocketTrait, ShortsTrait;
20
+
21
+    /**
22
+     * Configuration of connection
23
+     *
24
+     * @var \RouterOS\Config
25
+     */
26
+    private $_config;
27
+
28
+    /**
29
+     * API communication object
30
+     *
31
+     * @var \RouterOS\APIConnector
32
+     */
33
+
34
+    private $_connector;
35
+
36
+    /**
37
+     * Client constructor.
38
+     *
39
+     * @param array|\RouterOS\Config $config
40
+     * @throws \RouterOS\Exceptions\ClientException
41
+     * @throws \RouterOS\Exceptions\ConfigException
42
+     * @throws \RouterOS\Exceptions\QueryException
43
+     */
44
+    public function __construct($config) 
45
+    {
46
+        // If array then need create object
47
+        if (\is_array($config)) {
48
+            $config = new Config($config);
49
+        }
50
+
51
+        // Check for important keys
52
+        if (true !== $key = ArrayHelper::checkIfKeysNotExist(['host', 'user', 'pass'], $config->getParameters())) {
53
+            throw new ConfigException("One or few parameters '$key' of Config is not set or empty");
54
+        }
55
+
56
+        // Save config if everything is okay
57
+        $this->setConfig($config);
58
+
59
+        // Throw error if cannot to connect
60
+        if (false === $this->connect()) {
61
+            throw new ClientException('Unable to connect to ' . $config->get('host') . ':' . $config->get('port'));
62
+        }
63
+    }
64
+
65
+    /**
66
+     * Get some parameter from config
67
+     *
68
+     * @param string $parameter Name of required parameter
69
+     * @return mixed
70
+     * @throws \RouterOS\Exceptions\ConfigException
71
+     */
72
+    private function config(string $parameter) 
73
+    {
74
+        return $this->_config->get($parameter);
75
+    }
76
+
77
+    /**
78
+     * Return socket resource if is exist
79
+     *
80
+     * @return \RouterOS\Config
81
+     * @since 0.6
82
+     */
83
+    public function getConfig(): Config 
84
+    {
85
+        return $this->_config;
86
+    }
87
+
88
+    /**
89
+     * Set configuration of client
90
+     *
91
+     * @param \RouterOS\Config $config
92
+     * @since 0.7
93
+     */
94
+    public function setConfig(Config $config) 
95
+    {
96
+        $this->_config = $config;
97
+    }
98
+
99
+    /**
100
+     * Send write query to RouterOS (with or without tag)
101
+     *
102
+     * @param string|array|\RouterOS\Query $query
103
+     * @return \RouterOS\Interfaces\ClientInterface
104
+     * @throws \RouterOS\Exceptions\QueryException
105
+     */
106
+    public function write($query): ClientInterface 
107
+    {
108
+        if (\is_string($query)) {
109
+            $query = new Query($query);
110
+        } elseif (\is_array($query)) {
111
+            $endpoint = array_shift($query);
112
+            $query = new Query($endpoint, $query);
113
+        }
114
+
115
+        if (!$query instanceof Query) {
116
+            throw new QueryException('Parameters cannot be processed');
117
+        }
118
+
119
+        // Send commands via loop to router
120
+        foreach ($query->getQuery() as $command) {
121
+            $this->_connector->writeWord(trim($command));
122
+        }
123
+
124
+        // Write zero-terminator (empty string)
125
+        $this->_connector->writeWord('');
126
+
127
+        return $this;
128
+    }
129
+
130
+    /**
131
+     * Read answer from server after query was executed
132
+     *
133
+     * A Mikrotik reply is formed of blocks
134
+     * Each block starts with a word, one of ('!re', '!trap', '!done', '!fatal')
135
+     * Each block end with an zero byte (empty line)
136
+     * Reply ends with a complete !done or !fatal block (ended with 'empty line')
137
+     * A !fatal block precedes TCP connexion close
138
+     *
139
+     * @param bool $parse
140
+     * @return mixed
141
+     */
142
+    public function read(bool $parse = true) 
143
+    {
144
+        // By default response is empty
145
+        $response = [];
146
+        // We have to wait a !done or !fatal
147
+        $lastReply = false;
148
+
149
+        // Read answer from socket in loop
150
+        while (true) {
151
+            $word = $this->_connector->readWord();
152
+
153
+            if ('' === $word) {
154
+                if ($lastReply) {
155
+                    // We received a !done or !fatal message in a precedent loop
156
+                    // response is complete
157
+                    break;
158
+                }
159
+                // We did not receive the !done or !fatal message
160
+                // This 0 length message is the end of a reply !re or !trap
161
+                // We have to wait the router to send a !done or !fatal reply followed by optionals values and a 0 length message
162
+                continue;
163
+            }
164
+
165
+            // Save output line to response array
166
+            $response[] = $word;
167
+
168
+            // If we get a !done or !fatal line in response, we are now ready to finish the read
169
+            // but we need to wait a 0 length message, switch the flag
170
+            if ('!done' === $word || '!fatal' === $word) {
171
+                $lastReply = true;
172
+            }
173
+        }
174
+
175
+        // Parse results and return
176
+        return $parse ? $this->rosario($response) : $response;
177
+    }
178
+
179
+    /**
180
+     * Read using Iterators to improve performance on large dataset
181
+     *
182
+     * @return Iterators\ResponseIterator
183
+     */
184
+    public function readAsIterator() 
185
+    {
186
+        return new Iterators\ResponseIterator($this->read(false));
187
+    }
188
+
189
+    /**
190
+     * This method was created by memory save reasons, it convert response
191
+     * from RouterOS to readable array in safe way.
192
+     *
193
+     * @param array $raw Array RAW response from server
194
+     * @return mixed
195
+     *
196
+     * Based on RouterOSResponseArray solution by @arily
197
+     *
198
+     * @link    https://github.com/arily/RouterOSResponseArray
199
+     * @since   0.10
200
+     */
201
+    private function rosario(array $raw): array
202
+    {
203
+        // This RAW should't be an error
204
+        $positions = array_keys($raw, '!re');
205
+        $count = count($raw);
206
+        $result = [];
207
+
208
+        if (isset($positions[1])) {
209
+
210
+            foreach ($positions as $key => $position) {
211
+                // Get length of future block
212
+                $length = isset($positions[$key + 1])
213
+                ? $positions[$key + 1] - $position + 1
214
+                : $count - $position;
215
+
216
+                // Convert array to simple items
217
+                $item = [];
218
+                for ($i = 1; $i < $length; $i++) {
219
+                    $item[] = array_shift($raw);
220
+                }
221
+
222
+                // Save as result
223
+                $result[] = $this->parseResponse($item)[0];
224
+            }
225
+
226
+        } else {
227
+            $result = $this->parseResponse($raw);
228
+        }
229
+
230
+        return $result;
231
+    }
232
+
233
+    /**
234
+     * Parse response from Router OS
235
+     *
236
+     * @param array $response Response data
237
+     * @return array Array with parsed data
238
+     */
239
+    protected function parseResponse(array $response): array
240
+    {
241
+        $result = [];
242
+        $i = -1;
243
+        $lines = \count($response);
244
+        foreach ($response as $key => $value) {
245
+            switch ($value) {
246
+            case '!re':
247
+                $i++;
248
+                break;
249
+            case '!fatal':
250
+                $result = $response;
251
+                break 2;
252
+            case '!trap':
253
+            case '!done':
254
+                // Check for =ret=, .tag and any other following messages
255
+                for ($j = $key + 1; $j <= $lines; $j++) {
256
+                    // If we have lines after current one
257
+                    if (isset($response[$j])) {
258
+                        $this->pregResponse($response[$j], $matches);
259
+                        if (isset($matches[1][0], $matches[2][0])) {
260
+                            $result['after'][$matches[1][0]] = $matches[2][0];
261
+                        }
262
+                    }
263
+                }
264
+                break 2;
265
+            default:
266
+                $this->pregResponse($value, $matches);
267
+                if (isset($matches[1][0], $matches[2][0])) {
268
+                    $result[$i][$matches[1][0]] = $matches[2][0];
269
+                }
270
+                break;
271
+            }
272
+        }
273
+        return $result;
274
+    }
275
+
276
+    /**
277
+     * Parse result from RouterOS by regular expression
278
+     *
279
+     * @param string $value
280
+     * @param array  $matches
281
+     */
282
+    private function pregResponse(string $value, &$matches) 
283
+    {
284
+        preg_match_all('/^[=|\.](.*)=(.*)/', $value, $matches);
285
+    }
286
+
287
+    /**
288
+     * Authorization logic
289
+     *
290
+     * @param bool $legacyRetry Retry login if we detect legacy version of RouterOS
291
+     * @return bool
292
+     * @throws \RouterOS\Exceptions\ClientException
293
+     * @throws \RouterOS\Exceptions\ConfigException
294
+     * @throws \RouterOS\Exceptions\QueryException
295
+     */
296
+    private function login(bool $legacyRetry = false): bool 
297
+    {
298
+        // If legacy login scheme is enabled
299
+        if ($this->config('legacy')) {
300
+            // For the first we need get hash with salt
301
+            $query = new Query('/login');
302
+            $response = $this->write($query)->read();
303
+
304
+            // Now need use this hash for authorization
305
+            $query = (new Query('/login'))
306
+                ->add('=name=' . $this->config('user'))
307
+                ->add('=response=00' . md5(\chr(0) . $this->config('pass') . pack('H*', $response['after']['ret'])));
308
+        } else {
309
+            // Just login with our credentials
310
+            $query = (new Query('/login'))
311
+                ->add('=name=' . $this->config('user'))
312
+                ->add('=password=' . $this->config('pass'));
313
+
314
+            // If we set modern auth scheme but router with legacy firmware then need to retry query,
315
+            // but need to prevent endless loop
316
+            $legacyRetry = true;
317
+        }
318
+
319
+        // Execute query and get response
320
+        $response = $this->write($query)->read(false);
321
+
322
+        // if:
323
+        //  - we have more than one response
324
+        //  - response is '!done'
325
+        // => problem with legacy version, swap it and retry
326
+        // Only tested with ROS pre 6.43, will test with post 6.43 => this could make legacy parameter obsolete?
327
+        if ($legacyRetry && $this->isLegacy($response)) {
328
+            $this->_config->set('legacy', true);
329
+            return $this->login();
330
+        }
331
+
332
+        // Return true if we have only one line from server and this line is !done
333
+        return (1 === count($response)) && isset($response[0]) && ($response[0] === '!done');
334
+    }
335
+
336
+    /**
337
+     * Detect by login request if firmware is legacy
338
+     *
339
+     * @param array $response
340
+     * @return bool
341
+     * @throws ConfigException
342
+     */
343
+    private function isLegacy(array &$response): bool 
344
+    {
345
+        return \count($response) > 1 && $response[0] === '!done' && !$this->config('legacy');
346
+    }
347
+
348
+    /**
349
+     * Connect to socket server
350
+     *
351
+     * @return bool
352
+     * @throws \RouterOS\Exceptions\ClientException
353
+     * @throws \RouterOS\Exceptions\ConfigException
354
+     * @throws \RouterOS\Exceptions\QueryException
355
+     */
356
+    private function connect(): bool
357
+    {
358
+        // By default we not connected
359
+        $connected = false;
360
+
361
+        // Few attempts in loop
362
+        for ($attempt = 1; $attempt <= $this->config('attempts'); $attempt++) {
363
+
364
+            // Initiate socket session
365
+            $this->openSocket();
366
+
367
+            // If socket is active
368
+            if (null !== $this->getSocket()) {
369
+                $this->_connector = new APIConnector(new Streams\ResourceStream($this->getSocket()));
370
+                // If we logged in then exit from loop
371
+                if (true === $this->login()) {
372
+                    $connected = true;
373
+                    break;
374
+                }
375
+
376
+                // Else close socket and start from begin
377
+                $this->closeSocket();
378
+            }
379
+
380
+            // Sleep some time between tries
381
+            sleep($this->config('delay'));
382
+        }
383
+
384
+        // Return status of connection
385
+        return $connected;
386
+    }
387 387
 }
Please login to merge, or discard this patch.
Switch Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -243,31 +243,31 @@
 block discarded – undo
243 243
 		$lines = \count($response);
244 244
 		foreach ($response as $key => $value) {
245 245
 			switch ($value) {
246
-			case '!re':
247
-				$i++;
248
-				break;
249
-			case '!fatal':
250
-				$result = $response;
251
-				break 2;
252
-			case '!trap':
253
-			case '!done':
254
-				// Check for =ret=, .tag and any other following messages
255
-				for ($j = $key + 1; $j <= $lines; $j++) {
256
-					// If we have lines after current one
257
-					if (isset($response[$j])) {
258
-						$this->pregResponse($response[$j], $matches);
259
-						if (isset($matches[1][0], $matches[2][0])) {
260
-							$result['after'][$matches[1][0]] = $matches[2][0];
261
-						}
262
-					}
263
-				}
264
-				break 2;
265
-			default:
266
-				$this->pregResponse($value, $matches);
267
-				if (isset($matches[1][0], $matches[2][0])) {
268
-					$result[$i][$matches[1][0]] = $matches[2][0];
269
-				}
270
-				break;
246
+			    case '!re':
247
+				    $i++;
248
+				    break;
249
+			    case '!fatal':
250
+				    $result = $response;
251
+				    break 2;
252
+			    case '!trap':
253
+			    case '!done':
254
+				    // Check for =ret=, .tag and any other following messages
255
+				    for ($j = $key + 1; $j <= $lines; $j++) {
256
+					    // If we have lines after current one
257
+					    if (isset($response[$j])) {
258
+						    $this->pregResponse($response[$j], $matches);
259
+						    if (isset($matches[1][0], $matches[2][0])) {
260
+							    $result['after'][$matches[1][0]] = $matches[2][0];
261
+						    }
262
+					    }
263
+				    }
264
+				    break 2;
265
+			    default:
266
+				    $this->pregResponse($value, $matches);
267
+				    if (isset($matches[1][0], $matches[2][0])) {
268
+					    $result[$i][$matches[1][0]] = $matches[2][0];
269
+				    }
270
+				    break;
271 271
 			}
272 272
 		}
273 273
 		return $result;
Please login to merge, or discard this patch.
src/Iterators/ResponseIterator.php 2 patches
Indentation   +121 added lines, -121 removed lines patch added patch discarded remove patch
@@ -15,131 +15,131 @@
 block discarded – undo
15 15
 
16 16
 class ResponseIterator implements \Iterator, \ArrayAccess, \Countable {
17 17
 
18
-	public $parsed = [];
19
-	public $raw = [];
20
-	public $current;
21
-	public $length;
18
+    public $parsed = [];
19
+    public $raw = [];
20
+    public $current;
21
+    public $length;
22 22
 
23
-	public function __construct($raw) {
24
-		$this->current = 0;
25
-		// This RAW should't be an error
26
-		$positions = array_keys($raw, '!re');
27
-		$this->length = count($positions);
28
-		$count = count($raw);
29
-		$result = [];
23
+    public function __construct($raw) {
24
+        $this->current = 0;
25
+        // This RAW should't be an error
26
+        $positions = array_keys($raw, '!re');
27
+        $this->length = count($positions);
28
+        $count = count($raw);
29
+        $result = [];
30 30
 
31
-		if (isset($positions[1])) {
31
+        if (isset($positions[1])) {
32 32
 
33
-			foreach ($positions as $key => $position) {
34
-				// Get length of future block
35
-				$length = isset($positions[$key + 1])
36
-				? $positions[$key + 1] - $position + 1
37
-				: $count - $position;
33
+            foreach ($positions as $key => $position) {
34
+                // Get length of future block
35
+                $length = isset($positions[$key + 1])
36
+                ? $positions[$key + 1] - $position + 1
37
+                : $count - $position;
38 38
 
39
-				// Convert array to simple items
40
-				// Save as result
41
-				$result[] = array_slice($raw, $position, $length);
42
-			}
39
+                // Convert array to simple items
40
+                // Save as result
41
+                $result[] = array_slice($raw, $position, $length);
42
+            }
43 43
 
44
-		} else {
45
-			$result = [$raw];
46
-		}
44
+        } else {
45
+            $result = [$raw];
46
+        }
47 47
 
48
-		$this->raw = $result;
49
-	}
50
-	public function next() {
51
-		++$this->current;
52
-	}
53
-	public function current() {
54
-		if (isset($this->parsed[$this->current])) {
55
-			return $this->parsed[$this->current];
56
-		} elseif (isset($this->raw[$this->current])) {
57
-			return $this->parseResponse($this->raw[$this->current])[0];
58
-		} else {
59
-			return FALSE;
60
-		}
61
-	}
62
-	public function key() {
63
-		return $this->current;
64
-	}
65
-	public function valid() {
66
-		return isset($this->raw[$this->current]);
67
-	}
68
-	public function count() {
69
-		return count($this->raw);
70
-	}
71
-	public function rewind() {
72
-		$this->current = 0;
73
-	}
74
-	public function offsetSet($offset, $value) {
75
-		if (is_null($offset)) {
76
-			$this->parsed[] = $value;
77
-			throw new \RuntimeException('don\'t append to me It will cause a Bug sometime I PROMISE');
78
-		} else {
79
-			$this->parsed[$offset] = $value;
80
-		}
81
-	}
82
-	public function offsetExists($offset) {
83
-		return isset($this->raw[$offset]) && $this->raw[$offset] !== ['!re'];
84
-	}
85
-	public function offsetUnset($offset) {
86
-		unset($this->parsed[$offset]);
87
-		unset($this->raw[$offset]);
88
-	}
89
-	public function offsetGet($offset) {
90
-		if (isset($this->parsed[$offset])) {
91
-			return $this->parsed[$offset];
92
-		} elseif (isset($this->raw[$offset]) && $this->raw[$offset] !== NULL) {
93
-			$f = $this->parseResponse($this->raw[$offset]);
94
-			if ($f !== []) {
95
-				$r = $this->parsed[$offset] = $f[0];
96
-				return $r;
97
-			}
98
-		} else {
99
-			return FALSE;
100
-		}
101
-	}
102
-	public function flush() {
103
-		$this->raw = [];
104
-		$this->parsed = [];
105
-	}
106
-	private function parseResponse(array $response): array
107
-	{
108
-		$result = [];
109
-		$i = -1;
110
-		$lines = \count($response);
111
-		foreach ($response as $key => $value) {
112
-			switch ($value) {
113
-			case '!re':
114
-				$i++;
115
-				break;
116
-			case '!fatal':
117
-				$result = $response;
118
-				break 2;
119
-			case '!trap':
120
-			case '!done':
121
-				// Check for =ret=, .tag and any other following messages
122
-				for ($j = $key + 1; $j <= $lines; $j++) {
123
-					// If we have lines after current one
124
-					if (isset($response[$j])) {
125
-						$this->pregResponse($response[$j], $matches);
126
-						if (isset($matches[1][0], $matches[2][0])) {
127
-							$result['after'][$matches[1][0]] = $matches[2][0];
128
-						}
129
-					}
130
-				}
131
-				break 2;
132
-			default:
133
-				$this->pregResponse($value, $matches);
134
-				if (isset($matches[1][0], $matches[2][0])) {
135
-					$result[$i][$matches[1][0]] = $matches[2][0];
136
-				}
137
-				break;
138
-			}
139
-		}
140
-		return $result;
141
-	}
142
-	private function pregResponse(string $value, &$matches) {
143
-		preg_match_all('/^[=|\.](.*)=(.*)/', $value, $matches);
144
-	}
48
+        $this->raw = $result;
49
+    }
50
+    public function next() {
51
+        ++$this->current;
52
+    }
53
+    public function current() {
54
+        if (isset($this->parsed[$this->current])) {
55
+            return $this->parsed[$this->current];
56
+        } elseif (isset($this->raw[$this->current])) {
57
+            return $this->parseResponse($this->raw[$this->current])[0];
58
+        } else {
59
+            return FALSE;
60
+        }
61
+    }
62
+    public function key() {
63
+        return $this->current;
64
+    }
65
+    public function valid() {
66
+        return isset($this->raw[$this->current]);
67
+    }
68
+    public function count() {
69
+        return count($this->raw);
70
+    }
71
+    public function rewind() {
72
+        $this->current = 0;
73
+    }
74
+    public function offsetSet($offset, $value) {
75
+        if (is_null($offset)) {
76
+            $this->parsed[] = $value;
77
+            throw new \RuntimeException('don\'t append to me It will cause a Bug sometime I PROMISE');
78
+        } else {
79
+            $this->parsed[$offset] = $value;
80
+        }
81
+    }
82
+    public function offsetExists($offset) {
83
+        return isset($this->raw[$offset]) && $this->raw[$offset] !== ['!re'];
84
+    }
85
+    public function offsetUnset($offset) {
86
+        unset($this->parsed[$offset]);
87
+        unset($this->raw[$offset]);
88
+    }
89
+    public function offsetGet($offset) {
90
+        if (isset($this->parsed[$offset])) {
91
+            return $this->parsed[$offset];
92
+        } elseif (isset($this->raw[$offset]) && $this->raw[$offset] !== NULL) {
93
+            $f = $this->parseResponse($this->raw[$offset]);
94
+            if ($f !== []) {
95
+                $r = $this->parsed[$offset] = $f[0];
96
+                return $r;
97
+            }
98
+        } else {
99
+            return FALSE;
100
+        }
101
+    }
102
+    public function flush() {
103
+        $this->raw = [];
104
+        $this->parsed = [];
105
+    }
106
+    private function parseResponse(array $response): array
107
+    {
108
+        $result = [];
109
+        $i = -1;
110
+        $lines = \count($response);
111
+        foreach ($response as $key => $value) {
112
+            switch ($value) {
113
+            case '!re':
114
+                $i++;
115
+                break;
116
+            case '!fatal':
117
+                $result = $response;
118
+                break 2;
119
+            case '!trap':
120
+            case '!done':
121
+                // Check for =ret=, .tag and any other following messages
122
+                for ($j = $key + 1; $j <= $lines; $j++) {
123
+                    // If we have lines after current one
124
+                    if (isset($response[$j])) {
125
+                        $this->pregResponse($response[$j], $matches);
126
+                        if (isset($matches[1][0], $matches[2][0])) {
127
+                            $result['after'][$matches[1][0]] = $matches[2][0];
128
+                        }
129
+                    }
130
+                }
131
+                break 2;
132
+            default:
133
+                $this->pregResponse($value, $matches);
134
+                if (isset($matches[1][0], $matches[2][0])) {
135
+                    $result[$i][$matches[1][0]] = $matches[2][0];
136
+                }
137
+                break;
138
+            }
139
+        }
140
+        return $result;
141
+    }
142
+    private function pregResponse(string $value, &$matches) {
143
+        preg_match_all('/^[=|\.](.*)=(.*)/', $value, $matches);
144
+    }
145 145
 }
Please login to merge, or discard this patch.
Switch Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -110,31 +110,31 @@
 block discarded – undo
110 110
 		$lines = \count($response);
111 111
 		foreach ($response as $key => $value) {
112 112
 			switch ($value) {
113
-			case '!re':
114
-				$i++;
115
-				break;
116
-			case '!fatal':
117
-				$result = $response;
118
-				break 2;
119
-			case '!trap':
120
-			case '!done':
121
-				// Check for =ret=, .tag and any other following messages
122
-				for ($j = $key + 1; $j <= $lines; $j++) {
123
-					// If we have lines after current one
124
-					if (isset($response[$j])) {
125
-						$this->pregResponse($response[$j], $matches);
126
-						if (isset($matches[1][0], $matches[2][0])) {
127
-							$result['after'][$matches[1][0]] = $matches[2][0];
128
-						}
129
-					}
130
-				}
131
-				break 2;
132
-			default:
133
-				$this->pregResponse($value, $matches);
134
-				if (isset($matches[1][0], $matches[2][0])) {
135
-					$result[$i][$matches[1][0]] = $matches[2][0];
136
-				}
137
-				break;
113
+			    case '!re':
114
+				    $i++;
115
+				    break;
116
+			    case '!fatal':
117
+				    $result = $response;
118
+				    break 2;
119
+			    case '!trap':
120
+			    case '!done':
121
+				    // Check for =ret=, .tag and any other following messages
122
+				    for ($j = $key + 1; $j <= $lines; $j++) {
123
+					    // If we have lines after current one
124
+					    if (isset($response[$j])) {
125
+						    $this->pregResponse($response[$j], $matches);
126
+						    if (isset($matches[1][0], $matches[2][0])) {
127
+							    $result['after'][$matches[1][0]] = $matches[2][0];
128
+						    }
129
+					    }
130
+				    }
131
+				    break 2;
132
+			    default:
133
+				    $this->pregResponse($value, $matches);
134
+				    if (isset($matches[1][0], $matches[2][0])) {
135
+					    $result[$i][$matches[1][0]] = $matches[2][0];
136
+				    }
137
+				    break;
138 138
 			}
139 139
 		}
140 140
 		return $result;
Please login to merge, or discard this patch.