BatchMapIterator::ensureBatchPresent()   B
last analyzed

Complexity

Conditions 9
Paths 16

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 8.0555
c 0
b 0
f 0
cc 9
nc 16
nop 0
1
<?php
2
3
namespace itertools;
4
5
use InvalidArgumentException;
6
use IteratorIterator;
7
8
/**
9
 * Maps iterator values using a callback function but in batches.
10
 */
11
class BatchMapIterator extends IteratorIterator
12
{
13
	const DONT_SPLIT_KEY_VALUES = 0;
14
	const SPLIT_KEY_VALUES = 1;
15
16
	const DONT_ADD_KEY_LIST = 0;
17
	const ADD_KEY_LIST = 2;
18
19
	const ALLOW_MERGE = 0;
20
	const DONT_ALLOW_MERGE = 4;
21
22
	protected $mapCallbacks;
23
	protected $type;
24
	protected $batchSize;
25
    protected $batch;
26
    protected $batchKeys;
27
28
	public function __construct($innerItererator, $mapCallback, $batchSize = 100, $type = 0)
29
	{
30
		if (! is_callable($mapCallback)) {
31
			throw new InvalidArgumentException('The callback must be callable');
32
		}
33
		if(($type & self::DONT_ALLOW_MERGE) == 0 && $innerItererator instanceof self && $batchSize == $innerItererator->getBatchSize() && $type == $innerItererator->getType()) {
34
			parent::__construct(IterUtil::asTraversable($innerItererator->getInnerIterator()));
35
			$this->mapCallbacks = array_merge($innerItererator->getMapCallbacks(), array($mapCallback));
36
		} else {
37
			parent::__construct(IterUtil::asTraversable($innerItererator));
38
			$this->mapCallbacks = array($mapCallback);
39
		}
40
		$this->type = $type;
41
		$this->batchSize = $batchSize;
42
	}
43
44
	public function getType()
45
	{
46
		return $this->type;
47
	}
48
49
	public function getMapCallbacks()
50
	{
51
		return $this->mapCallbacks;
52
	}
53
54
	public function getBatchSize()
55
	{
56
		return $this->batchSize;
57
	}
58
59
	protected function ensureBatchPresent()
60
	{
61
		$batch = array();
62
		$batchKeys = array();
63
        $inner = $this->getInnerIterator();
64
		if(self::SPLIT_KEY_VALUES & $this->type) {
65
			for($i = 0; $i < $this->batchSize && $inner->valid(); $i++, $inner->next()) {
66
				$batch[] = array($inner->key(), $inner->current());
67
			}
68
		} else {
69
			for($i = 0; $i < $this->batchSize && $inner->valid(); $i++, $inner->next()) {
70
				$batch[] = $inner->current();
71
				$batchKeys[] = $inner->key();
72
			}
73
		}
74
75
		if((self::ADD_KEY_LIST & $this->type) != 0) {
76
			foreach($this->mapCallbacks as $mapCallback) {
77
				list($batchKeys, $batch) = call_user_func($mapCallback, $batchKeys, $batch);
78
			}
79
		} else {
80
			foreach($this->mapCallbacks as $mapCallback) {
81
				$batch = call_user_func($mapCallback, $batch);
82
			}
83
		}
84
85
		$this->batch = $batch;
86
		reset($this->batch);
87
88
		$this->batchKeys = $batchKeys;
89
		reset($this->batchKeys);
90
	}
91
92
    public function rewind()
93
	{
94
		$this->getInnerIterator()->rewind();
95
		$this->batch = array();
96
		$this->batchKeys = array();
97
    }
98
99
    public function valid()
100
	{
101
		while(null === key($this->batch) && $this->getInnerIterator()->valid()) {
102
			$this->ensureBatchPresent();
103
		}
104
        return null !== key($this->batch);
105
    }
106
107
    public function next()
108
	{
109
		next($this->batch);
110
		next($this->batchKeys);
111
    }
112
113
    public function key()
114
	{
115
		if(self::SPLIT_KEY_VALUES & $this->type) {
116
			$result = current($this->batch);
117
			return $result[0];
118
		} else {
119
			return current($this->batchKeys);
120
		}
121
    }
122
123
    public function current()
124
	{
125
		if(self::SPLIT_KEY_VALUES & $this->type) {
126
			$result = current($this->batch);
127
			return $result[1];
128
		} else {
129
			return current($this->batch);
130
		}
131
    }
132
}
133
 
134