Result   B
last analyzed

Complexity

Total Complexity 52

Size/Duplication

Total Lines 414
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 82
dl 0
loc 414
rs 7.44
c 2
b 1
f 0
wmc 52

34 Methods

Rating   Name   Duplication   Size   Complexity  
A seek() 0 10 3
A offsetUnset() 0 2 1
A magic_get_length() 0 2 1
A __map() 0 13 3
A offsetSet() 0 7 2
A offsetGet() 0 2 1
A __set() 0 2 1
A __chunk() 0 2 1
A __reverse() 0 5 1
A __column() 0 2 1
A __EnumerableToArray() 0 2 1
A __clear() 0 4 1
A __first() 0 2 1
A __findAll() 0 17 4
A valid() 0 2 1
A __toJSON() 0 2 2
A __toArray() 0 8 2
A __values() 0 2 2
A next() 0 2 1
A set() 0 5 2
A key() 0 2 1
A __inspect() 0 2 1
A rewind() 0 2 1
A __last() 0 2 1
A offsetExists() 0 2 1
A __fields() 0 2 1
A get() 0 4 2
A __construct() 0 13 3
A __merge() 0 4 1
A current() 0 2 1
A __each() 0 4 1
A count() 0 2 1
A __reject() 0 17 4
A __get() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like Result often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Result, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Class Result
4
 *
5
 * @filesource   Result.php
6
 * @created      28.06.2017
7
 * @package      chillerlan\Database
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2017 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\Database;
14
use ArrayAccess, Countable, SeekableIterator;
15
16
/**
17
 * @property int                              $length
18
 * @property \chillerlan\Database\ResultRow[] $array
19
 */
20
class Result implements ResultInterface, SeekableIterator, ArrayAccess, Countable{
21
22
	/**
23
	 * @var null|string
24
	 */
25
	protected $sourceEncoding;
26
27
	/**
28
	 * @var string
29
	 */
30
	protected $destEncoding;
31
32
	/**
33
	 * @todo
34
	 * @var bool
35
	 */
36
	protected $isBool;
37
38
	/**
39
	 * @todo
40
	 * @var bool
41
	 */
42
	protected $success = false;
43
44
	/**
45
	 * @todo
46
	 * @var array
47
	 */
48
	protected $metadata = [];
49
50
	/** @inheritdoc */
51
	public function __construct(iterable $data = null, string $sourceEncoding = null, string $destEncoding = null){
52
		$this->sourceEncoding = $sourceEncoding;
53
		$this->destEncoding   = $destEncoding ?? 'UTF-8';
54
55
		if($data !== null){
56
57
			foreach($data as $k => $v){
58
				$this->offsetSet($k, $v);
59
			}
60
61
		}
62
63
		$this->offset = 0;
64
	}
65
66
67
	/**
68
	 * @var array
69
	 */
70
	protected $array = [];
71
72
	/**
73
	 * @var int
74
	 */
75
	protected $offset = 0;
76
77
	/**
78
	 * @link http://api.prototypejs.org/language/Enumerable/prototype/toArray/
79
	 *
80
	 * @return array
81
	 *
82
	 * @codeCoverageIgnore
83
	 */
84
	public function __EnumerableToArray():array {
85
		return $this->array;
86
	}
87
88
	/**
89
	 * @link http://api.prototypejs.org/language/Enumerable/prototype/each/
90
	 *
91
	 * @param callable $callback
92
	 *
93
	 * @return $this
94
	 */
95
	public function __each($callback){
96
		$this->__map($callback);
97
98
		return $this;
99
	}
100
101
	/**
102
	 * @link http://api.prototypejs.org/language/Enumerable/prototype/collect/
103
	 * @link http://api.prototypejs.org/language/Enumerable/prototype/map/
104
	 *
105
	 * @param callable $callback
106
	 *
107
	 * @return array
108
	 * @throws \chillerlan\Database\DatabaseException
109
	 */
110
	public function __map($callback):array {
111
112
		if(!\is_callable($callback)){
113
			throw new DatabaseException('invalid callback');
114
		}
115
116
		$return = [];
117
118
		foreach($this->array as $index => $element){
119
			$return[$index] = \call_user_func_array($callback, [$element, $index]);
120
		}
121
122
		return $return;
123
	}
124
125
	/**
126
	 * @link http://api.prototypejs.org/language/Array/prototype/reverse/
127
	 */
128
	public function __reverse():ResultInterface{
129
		$this->array  = \array_reverse($this->array);
130
		$this->offset = 0;
131
132
		return $this;
133
	}
134
135
	/**
136
	 * @return mixed
137
	 */
138
	public function __first(){
139
		return $this->array[0] ?? null;
140
	}
141
142
	/**
143
	 * @return mixed
144
	 */
145
	public function __last(){
146
		return $this->array[\count($this->array) - 1] ?? null;
147
	}
148
149
	/**
150
	 *
151
	 */
152
	public function __clear():ResultInterface{
153
		$this->array = [];
154
155
		return $this;
156
	}
157
158
	/**
159
	 * @link http://api.prototypejs.org/language/Array/prototype/inspect/
160
	 *
161
	 * @return string
162
	 */
163
	public function __inspect():string {
164
		return \print_r($this->array, true);
165
	}
166
167
	/**
168
	 * @link http://api.prototypejs.org/language/Enumerable/prototype/findAll/
169
	 *
170
	 * @param callable $callback
171
	 *
172
	 * @return array
173
	 * @throws \chillerlan\Database\DatabaseException
174
	 */
175
	public function __findAll($callback):array{
176
177
		if(!\is_callable($callback)){
178
			throw new DatabaseException('invalid callback');
179
		}
180
181
		$return = [];
182
183
		foreach($this->array as $index => $element){
184
185
			if(\call_user_func_array($callback, [$element, $index]) === true){
186
				$return[] = $element;
187
			}
188
189
		}
190
191
		return $return;
192
	}
193
194
	/**
195
	 * @link http://api.prototypejs.org/language/Enumerable/prototype/reject/
196
	 *
197
	 * @param callable $callback
198
	 *
199
	 * @return array
200
	 * @throws \chillerlan\Database\DatabaseException
201
	 */
202
	public function __reject($callback):array{
203
204
		if(!\is_callable($callback)){
205
			throw new DatabaseException('invalid callback');
206
		}
207
208
		$return = [];
209
210
		foreach($this->array as $index => $element){
211
212
			if(\call_user_func_array($callback, [$element, $index]) !== true){
213
				$return[] = $element;
214
			}
215
216
		}
217
218
		return $return;
219
	}
220
221
	/**
222
	 * @param string $name
223
	 *
224
	 * @return mixed|null
225
	 */
226
	public function __get(string $name){
227
		return $this->get($name);
228
	}
229
230
	/**
231
	 * @param string $name
232
	 * @param mixed  $value
233
	 *
234
	 * @return void
235
	 */
236
	public function __set(string $name, $value):void{
237
		$this->set($name, $value);
238
	}
239
240
	/**
241
	 * @param string $name
242
	 *
243
	 * @return mixed|null
244
	 */
245
	private function get(string $name){
246
		$method = 'magic_get_'.$name;
247
248
		return \method_exists($this, $method) ? $this->$method() : null;
249
	}
250
251
	/**
252
	 * @param string $name
253
	 * @param        $value
254
	 *
255
	 * @return void
256
	 */
257
	private function set(string $name, $value):void{
258
		$method = 'magic_set_'.$name;
259
260
		if(\method_exists($this, $method)){
261
			$this->$method($value);
262
		}
263
264
	}
265
266
	/**
267
	 * @link  http://php.net/manual/arrayaccess.offsetexists.php
268
	 * @inheritdoc
269
	 */
270
	public function offsetExists($offset):bool{
271
		return \array_key_exists($offset, $this->array);
272
	}
273
274
	/**
275
	 * @link  http://php.net/manual/arrayaccess.offsetget.php
276
	 * @inheritdoc
277
	 */
278
	public function offsetGet($offset){
279
		return $this->array[$offset] ?? null;
280
	}
281
282
	/**
283
	 * @link  http://php.net/manual/arrayaccess.offsetunset.php
284
	 * @inheritdoc
285
	 */
286
	public function offsetUnset($offset):void{
287
		unset($this->array[$offset]);
288
	}
289
290
291
	/**
292
	 * @link http://php.net/manual/countable.count.php
293
	 * @inheritdoc
294
	 */
295
	public function count():int{
296
		return \count($this->array);
297
	}
298
299
	/**
300
	 * @link  http://php.net/manual/iterator.current.php
301
	 * @inheritdoc
302
	 */
303
	public function current(){
304
		return $this->array[$this->offset] ?? null;
305
	}
306
307
	/**
308
	 * @link  http://php.net/manual/iterator.next.php
309
	 * @inheritdoc
310
	 */
311
	public function next():void{
312
		$this->offset++;
313
	}
314
315
	/**
316
	 * @link  http://php.net/manual/iterator.key.php
317
	 * @inheritdoc
318
	 */
319
	public function key(){
320
		return $this->offset;
321
	}
322
323
	/**
324
	 * @link  http://php.net/manual/iterator.valid.php
325
	 * @inheritdoc
326
	 */
327
	public function valid():bool{
328
		return \array_key_exists($this->offset, $this->array);
329
	}
330
331
	/**
332
	 * @link  http://php.net/manual/iterator.rewind.php
333
	 * @inheritdoc
334
	 */
335
	public function rewind():void{
336
		$this->offset = 0;
337
	}
338
339
	/**
340
	 * @link  http://php.net/manual/seekableiterator.seek.php
341
	 * @inheritdoc
342
	 */
343
	public function seek($pos):void{
344
		$this->rewind();
345
346
		for( ; $this->offset < $pos; ){
347
348
			if(!\next($this->array)) {
349
				throw new \OutOfBoundsException('invalid seek position: '.$pos);
350
			}
351
352
			$this->offset++;
353
		}
354
355
	}
356
	/** @inheritdoc */
357
	public function __toJSON(bool $prettyprint = null):string{
358
		return json_encode($this->__toArray(), $prettyprint === true ? JSON_PRETTY_PRINT : null);
0 ignored issues
show
Bug introduced by
It seems like $prettyprint === true ? ...SON_PRETTY_PRINT : null can also be of type null; however, parameter $flags of json_encode() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

358
		return json_encode($this->__toArray(), /** @scrutinizer ignore-type */ $prettyprint === true ? JSON_PRETTY_PRINT : null);
Loading history...
359
	}
360
361
	/** @inheritdoc */
362
	public function __merge(Result $DBResult):Result{
363
		$this->array = array_merge($this->array, $DBResult->__EnumerableToArray());
364
365
		return $this;
366
	}
367
368
	/** @inheritdoc */
369
	public function __chunk(int $size):array{
370
		return array_chunk($this->__toArray(), $size, true);
371
	}
372
373
	/** @inheritdoc */
374
	public function __toArray():array{
375
		$arr = [];
376
377
		foreach($this->array as $key => $item){
378
			$arr[$key] = $item->__toArray();
379
		}
380
381
		return $arr;
382
	}
383
384
	/**
385
	 * @return array
386
	 */
387
	public function __fields():array{
388
		return array_keys($this->array);
389
	}
390
391
	/**
392
	 * @param bool|null $to_array
393
	 *
394
	 * @return array
395
	 */
396
	public function __values(bool $to_array = null):array{
397
		return array_values($to_array === true ? $this->__toArray() : $this->array);
398
	}
399
400
	/**
401
	 * @param string      $column
402
	 * @param string|null $index_key
403
	 *
404
	 * @return array
405
	 */
406
	public function __column(string $column, string $index_key = null):array{
407
		return array_column($this->__toArray(), $column, $index_key);
408
	}
409
410
	/*********
411
	 * magic *
412
	 *********/
413
414
	/**
415
	 * @return int
416
	 */
417
	protected function magic_get_length():int{
418
		return $this->count();
419
	}
420
421
422
	/***************
423
	 * ArrayAccess *
424
	 ***************/
425
426
	/** @inheritdoc */
427
	public function offsetSet($offset, $value):void{
428
429
		$row = new ResultRow($value, $this->sourceEncoding, $this->destEncoding);
430
431
		$offset !== null
432
			? $this->array[$offset] = $row
433
			: $this->array[] = $row;
434
	}
435
436
}
437