Completed
Pull Request — master (#2116)
by
unknown
19:57
created

BaseIterator::valid()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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