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

UnrewindableIterator   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 116
Duplicated Lines 7.76 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 95.45%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 0
dl 9
loc 116
ccs 42
cts 44
cp 0.9545
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A toArray() 0 14 2
A current() 0 4 1
A key() 0 8 2
A next() 0 8 2
A rewind() 0 4 1
A valid() 0 4 1
A preventRewinding() 0 9 2
A getIterator() 0 8 2
A wrapTraversable() 9 9 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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