RewindableGenerator   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 96.77%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 0
dl 0
loc 111
ccs 30
cts 31
cp 0.9677
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A generateGenerator() 0 7 2
A current() 0 3 1
A next() 0 3 1
A key() 0 3 1
A valid() 0 3 1
A rewind() 0 11 3
A onRewind() 0 7 2
1
<?php
2
3
declare( strict_types = 1 );
4
5
/**
6
 * @licence GNU GPL v2+
7
 * @author Jeroen De Dauw < [email protected] >
8
 */
9
class RewindableGenerator implements Iterator {
10
11
	/**
12
	 * @var callable
13
	 */
14
	private $generatorFunction;
15
16
	/**
17
	 * @var Generator
18
	 */
19
	private $generator;
20
21
	/**
22
	 * @var callable|null
23
	 */
24
	private $onRewind;
25
26
	/**
27
	 * @param callable $generatorConstructionFunction A callable that should return a Generator
28
	 * @param callable $onRewind callable that gets invoked with 0 arguments after the iterator was rewinded
29
	 *
30
	 * @throws InvalidArgumentException
31
	 */
32 9
	public function __construct( callable $generatorConstructionFunction, callable $onRewind = null ) {
33 9
		$this->generatorFunction = $generatorConstructionFunction;
34 9
		$this->onRewind = $onRewind;
35 9
		$this->generateGenerator();
36 8
	}
37
38 9
	private function generateGenerator() {
39 9
		$this->generator = call_user_func( $this->generatorFunction );
40
41 9
		if ( !( $this->generator instanceof Generator ) ) {
42 1
			throw new InvalidArgumentException( 'The callable needs to return a Generator' );
43
		}
44 8
	}
45
46
	/**
47
	 * Return the current element
48
	 * @see Iterator::current
49
	 * @link http://php.net/manual/en/iterator.current.php
50
	 * @return mixed
51
	 */
52 4
	public function current() {
53 4
		return $this->generator->current();
54
	}
55
56
	/**
57
	 * Move forward to next element
58
	 * @see Iterator::next
59
	 * @link http://php.net/manual/en/iterator.next.php
60
	 */
61 4
	public function next() {
62 4
		$this->generator->next();
63 4
	}
64
65
	/**
66
	 * Return the key of the current element
67
	 * @see Iterator::key
68
	 * @link http://php.net/manual/en/iterator.key.php
69
	 * @return mixed scalar on success, or null on failure.
70
	 */
71 3
	public function key() {
72 3
		return $this->generator->key();
73
	}
74
75
	/**
76
	 * Checks if current position is valid
77
	 * @see Iterator::rewind
78
	 * @link http://php.net/manual/en/iterator.valid.php
79
	 * @return boolean
80
	 */
81 4
	public function valid() {
82 4
		return $this->generator->valid();
83
	}
84
85
	/**
86
	 * Rewind the Iterator to the first element
87
	 * @see Iterator::rewind
88
	 * @link http://php.net/manual/en/iterator.rewind.php
89
	 */
90 6
	public function rewind() {
91 6
		$this->generateGenerator();
92
93 6
		if ( is_callable( $this->onRewind ) ) {
94 2
			call_user_func( $this->onRewind );
95
		}
96
97 6
		if ( defined( 'HHVM_VERSION' ) ) {
98
			$this->generator->next();
99
		}
100 6
	}
101
102
	/**
103
	 * Sets a callable that gets invoked with 0 arguments after the iterator was rewinded.
104
	 * If a callable has been set already, an exception will be thrown.
105
	 *
106
	 * @since 1.1.0
107
	 *
108
	 * @param callable $onRewind
109
	 * @throws InvalidArgumentException
110
	 */
111 2
	public function onRewind( callable $onRewind ) {
112 2
		if ( $this->onRewind !== null ) {
113 2
			throw new InvalidArgumentException( 'Can only bind a onRewind handler once' );
114
		}
115
116 1
		$this->onRewind = $onRewind;
117 1
	}
118
119
}
120
121