Completed
Push — master ( 8fc9bf...b852d4 )
by Andreas
17s queued 12s
created

UnrewindableIterator::key()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\ODM\MongoDB\Iterator;
6
7
use Generator;
8
use LogicException;
9
use RuntimeException;
10
use Traversable;
11
use function iterator_to_array;
12
use function sprintf;
13
14
/**
15
 * Iterator for wrapping a Traversable/Cursor.
16
 *
17
 * @internal
18
 */
19
final class UnrewindableIterator implements Iterator
20
{
21
    /** @var Generator|null */
22
    private $iterator;
23
24
    /** @var bool */
25
    private $iteratorAdvanced = false;
26
27
    /**
28
     * Initialize the iterator. This effectively rewinds the Traversable and
29
     * the wrapping Generator, which will execute up to its first yield statement.
30
     * Additionally, this mimics behavior of the SPL iterators and allows users
31
     * to omit an explicit call to rewind() before using the other methods.
32
     */
33 11
    public function __construct(Traversable $iterator)
34
    {
35 11
        $this->iterator = $this->wrapTraversable($iterator);
36 11
        $this->iterator->key();
37 11
    }
38
39 3
    public function toArray() : array
40
    {
41 3
        $this->preventRewinding(__METHOD__);
42
43
        $toArray = function () {
44 2
            if (! $this->valid()) {
45 1
                return;
46
            }
47 1
            yield $this->key() => $this->current();
48 1
            yield from $this->getIterator();
49 2
        };
50
51 2
        return iterator_to_array($toArray());
52
    }
53
54
    /**
55
     * @see http://php.net/iterator.current
56
     *
57
     * @return mixed
58
     */
59 7
    public function current()
60
    {
61 7
        return $this->getIterator()->current();
62
    }
63
64
    /**
65
     * @see http://php.net/iterator.mixed
66
     *
67
     * @return mixed
68
     */
69 9
    public function key()
70
    {
71 9
        if ($this->iterator) {
72 7
            return $this->iterator->key();
73
        }
74
75 4
        return null;
76
    }
77
78
    /**
79
     * @see http://php.net/iterator.next
80
     */
81 5
    public function next() : void
82
    {
83 5
        if (! $this->iterator) {
84
            return;
85
        }
86
87 5
        $this->iterator->next();
88 5
    }
89
90
    /**
91
     * @see http://php.net/iterator.rewind
92
     */
93 6
    public function rewind() : void
94
    {
95 6
        $this->preventRewinding(__METHOD__);
96 6
    }
97
98
    /**
99
     * @see http://php.net/iterator.valid
100
     */
101 9
    public function valid() : bool
102
    {
103 9
        return $this->key() !== null;
104
    }
105
106 8
    private function preventRewinding(string $method) : void
107
    {
108 8
        if ($this->iteratorAdvanced) {
109 3
            throw new LogicException(sprintf(
110 3
                'Cannot call %s for iterator that already yielded results',
111 3
                $method
112
            ));
113
        }
114 8
    }
115
116 7
    private function getIterator() : Generator
117
    {
118 7
        if ($this->iterator === null) {
119
            throw new RuntimeException('Iterator has already been destroyed');
120
        }
121
122 7
        return $this->iterator;
123
    }
124
125 11 View Code Duplication
    private function wrapTraversable(Traversable $traversable) : Generator
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...
126
    {
127 11
        foreach ($traversable as $key => $value) {
128 7
            yield $key => $value;
129 6
            $this->iteratorAdvanced = true;
130
        }
131
132 7
        $this->iterator = null;
133 7
    }
134
}
135