1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace AlecRabbit\Accessories; |
6
|
|
|
|
7
|
|
|
use function AlecRabbit\typeOf; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Class Circular |
11
|
|
|
*/ |
12
|
|
|
class Circular implements \Iterator |
13
|
|
|
{ |
14
|
|
|
/** @var Rewindable */ |
15
|
|
|
protected $data; |
16
|
|
|
|
17
|
|
|
/** @var bool */ |
18
|
|
|
protected $oneElement = false; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Circular constructor. |
22
|
|
|
* @param array|callable|Rewindable $data accepts array, callable which returns \Generator or Rewindable |
23
|
|
|
*/ |
24
|
11 |
|
public function __construct($data) |
25
|
|
|
{ |
26
|
11 |
|
$this->data = $this->refineData($data); |
27
|
9 |
|
} |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @param mixed $data |
31
|
|
|
* @return mixed |
32
|
|
|
*/ |
33
|
11 |
|
protected function refineData($data) |
34
|
|
|
{ |
35
|
11 |
|
if (\is_array($data)) { |
36
|
7 |
|
if (1 === $count = count($data)) { |
37
|
2 |
|
return $this->setOneElement(reset($data)); |
38
|
|
|
} |
39
|
5 |
|
if (0 === $count) { |
40
|
1 |
|
return $this->setOneElement(); |
|
|
|
|
41
|
|
|
} |
42
|
|
|
} |
43
|
8 |
|
return $this->convert($data); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @param mixed $data |
48
|
|
|
* @return mixed |
49
|
|
|
*/ |
50
|
3 |
|
protected function setOneElement($data = null) |
51
|
|
|
{ |
52
|
3 |
|
$this->oneElement = true; |
53
|
3 |
|
return $data; |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* @param mixed $arg |
58
|
|
|
* @return Rewindable |
59
|
|
|
*/ |
60
|
8 |
|
private function convert(&$arg): Rewindable |
61
|
|
|
{ |
62
|
8 |
|
if (\is_array($arg)) { |
63
|
|
|
return |
64
|
4 |
|
new Rewindable( |
65
|
|
|
static function () use (&$arg): \Generator { |
66
|
4 |
|
yield from $arg; |
67
|
4 |
|
} |
68
|
|
|
); |
69
|
|
|
} |
70
|
4 |
|
if (\is_callable($arg)) { |
71
|
|
|
return |
72
|
2 |
|
new Rewindable($arg); |
73
|
|
|
} |
74
|
2 |
|
if ($arg instanceof Rewindable) { |
75
|
1 |
|
return $arg; |
76
|
|
|
} |
77
|
1 |
|
throw new \InvalidArgumentException('Unexpected argument type: ' . typeOf($arg) . ' for ' . Caller::get()); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* @return mixed |
82
|
|
|
*/ |
83
|
2 |
|
public function __invoke() |
84
|
|
|
{ |
85
|
2 |
|
return $this->value(); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @return mixed |
90
|
|
|
*/ |
91
|
5 |
|
public function value() |
92
|
|
|
{ |
93
|
5 |
|
if ($this->oneElement) { |
94
|
3 |
|
return $this->data; |
95
|
|
|
} |
96
|
2 |
|
if (null === $value = $this->current()) { |
97
|
2 |
|
$this->rewind(); |
98
|
2 |
|
$value = $this->current(); |
99
|
|
|
} |
100
|
2 |
|
$this->next(); |
101
|
2 |
|
return $value; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* {@inheritdoc} |
106
|
|
|
*/ |
107
|
6 |
|
public function current() |
108
|
|
|
{ |
109
|
6 |
|
return $this->data->current(); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* {@inheritdoc} |
114
|
|
|
*/ |
115
|
6 |
|
public function rewind(): void |
116
|
|
|
{ |
117
|
6 |
|
$this->data->rewind(); |
118
|
6 |
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* {@inheritdoc} |
122
|
|
|
*/ |
123
|
6 |
|
public function next(): void |
124
|
|
|
{ |
125
|
6 |
|
$this->data->next(); |
126
|
6 |
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* {@inheritdoc} |
130
|
|
|
*/ |
131
|
4 |
|
public function valid(): bool |
132
|
|
|
{ |
133
|
|
|
return |
134
|
4 |
|
$this->data->valid(); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* {@inheritdoc} |
139
|
|
|
*/ |
140
|
4 |
|
public function key() |
141
|
|
|
{ |
142
|
4 |
|
return $this->data->key(); |
143
|
|
|
} |
144
|
|
|
} |
145
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.