Passed
Push — master ( 805156...f7bb18 )
by Alec
02:23
created

Circular::refineData()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 6
nc 4
nop 1
dl 0
loc 11
ccs 7
cts 7
cp 1
crap 5
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AlecRabbit\Accessories;
6
7
use function AlecRabbit\typeOf;
8
use Countable;
9
10
/**
11
 * Class Circular
12
 */
13
class Circular implements \Iterator
14
{
15
    /** @var Rewindable */
16
    protected $data;
17
18
    /** @var bool */
19
    protected $oneElement = false;
20
21
    /**
22
     * Circular constructor.
23
     * @param array|callable|Rewindable $data accepts array, callable which returns \Generator or Rewindable
24
     */
25 11
    public function __construct($data)
26
    {
27 11
        $this->data = $this->refineData($data);
28 9
    }
29
30
    /**
31
     * @param $data
32
     * @return mixed
33
     */
34 11
    protected function refineData($data)
35
    {
36 11
        if (\is_array($data) || $data instanceof Countable) {
37 7
            if (1 === $count = count($data)) {
38 2
                return $this->setOneElementData(reset($data));
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type Countable; however, parameter $array of reset() does only seem to accept array, 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

38
                return $this->setOneElementData(reset(/** @scrutinizer ignore-type */ $data));
Loading history...
39
            }
40 5
            if (0 === $count) {
41 1
                return $this->setOneElementData(null);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->setOneElementData(null) targeting AlecRabbit\Accessories\C...ar::setOneElementData() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
42
            }
43
        }
44 8
        return $this->convert($data);
45
    }
46
47
    /**
48
     * @param mixed $data
49
     * @return mixed
50
     */
51 3
    protected function setOneElementData($data)
52
    {
53 3
        $this->oneElement = true;
54 3
        return $data;
55
    }
56
57
    /**
58
     * @param mixed $arg
59
     * @return Rewindable
60
     */
61 8
    private function convert(&$arg): Rewindable
62
    {
63 8
        if (\is_array($arg)) {
64
            return
65 4
                new Rewindable(
66
                    static function () use (&$arg): \Generator {
67 4
                        yield from $arg;
68 4
                    }
69
                );
70
        }
71 4
        if (\is_callable($arg)) {
72
            return
73 2
                new Rewindable($arg);
74
        }
75 2
        if ($arg instanceof Rewindable) {
76 1
            return $arg;
77
        }
78 1
        throw new \InvalidArgumentException('Unexpected argument type: ' . typeOf($arg) . ' for ' . Caller::get());
79
    }
80
81
    /**
82
     * @return mixed
83
     */
84 2
    public function __invoke()
85
    {
86 2
        return $this->value();
87
    }
88
89
    /**
90
     * @return mixed
91
     */
92 5
    public function value()
93
    {
94 5
        if ($this->oneElement) {
95 3
            return $this->data;
96
        }
97 2
        if (null === $value = $this->current()) {
98 2
            $this->rewind();
99 2
            $value = $this->current();
100
        }
101 2
        $this->next();
102 2
        return $value;
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108 6
    public function current()
109
    {
110 6
        return $this->data->current();
111
    }
112
113
    /**
114
     * {@inheritdoc}
115
     */
116 6
    public function rewind(): void
117
    {
118 6
        $this->data->rewind();
119 6
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124 6
    public function next(): void
125
    {
126 6
        $this->data->next();
127 6
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132 4
    public function valid(): bool
133
    {
134
        return
135 4
            $this->data->valid();
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141 4
    public function key()
142
    {
143 4
        return $this->data->key();
144
    }
145
}
146