Kohana_Jam_Array::next()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php defined('SYSPATH') OR die('No direct script access.');
2
3
/**
4
 * A base iterator class, execute _load_contnet on any interaction with the array. Can be serialized properly
5
 *
6
 * @package    Jam
7
 * @category   Associations
8
 * @author     Ivan Kerin
9
 * @copyright  (c) 2011-2012 Despark Ltd.
10
 * @license    http://www.opensource.org/licenses/isc-license.txt
11
 */
12
abstract class Kohana_Jam_Array implements Countable, ArrayAccess, Iterator, Serializable {
13
14
	public static function factory()
15
	{
16
		return new Jam_Array();
17
	}
18
19
	/**
20
	 * An array of booleans that flags which entries have been changed
21
	 * @var array
22
	 */
23
	protected $_changed = array();
24
25
	/**
26
	 * This is set to true when any entries are removed
27
	 * @var boolean
28
	 */
29
	protected $_removed = FALSE;
30
31
	/**
32
	 * The content loaded with _load_content. The main store of this iterator
33
	 * @var array
34
	 */
35
	protected $_content = NULL;
36
37
	/**
38
	 * Iterator implementation
39
	 * @var integer
40
	 */
41
	protected $_current = 0;
42
43
	/**
44
	 * Load the _content variable. This is used to lazy load the content of this iterator
45
	 */
46 5
	protected function _load_content()
47
	{
48 5
		if ( ! $this->_content)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_content of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
49 1
			throw new Kohana_Exception('Content has not been loaded');
50 4
	}
51
52
	/**
53
	 * Load each of the entries of this iterator. Called everytime an entry is requested. Use it to lazy load each item
54
	 * @param  mixed    $value
55
	 * @param  boolean  $is_changed
56
	 * @param  int      $offset
57
	 * @return mixed
58
	 */
59 2
	protected function _load_item($value, $is_changed, $offset)
60
	{
61 2
		return $value;
62
	}
63
64
	/**
65
	 * Getter / Setter of the content. Lazy loads with _load_content();
66
	 * @param  array $content
67
	 * @return array
68
	 */
69 9
	public function content(array $content = NULL)
70
	{
71 9
		if ($content !== NULL)
72
		{
73 4
			$this->_content = $content;
74 4
			return $this;
75
		}
76
77 7
		$this->_load_content();
78
79 6
		return $this->_content;
80
	}
81
82
	/**
83
	 * Getter for the changed array - check if any or a particular item has been changed
84
	 * @param  int $offset
85
	 * @return bool
86
	 */
87 8
	public function changed($offset = NULL)
88
	{
89 8
		if ($offset !== NULL)
90 4
			return isset($this->_changed[$offset]);
91
92 7
		return ( (bool) $this->_changed OR $this->_removed);
93
	}
94
95
	/**
96
	 * Reset the content so it can be loaded again
97
	 * @return Jam_Array
98
	 */
99
	public function reload()
100
	{
101
		$this->_changed = array();
102
		$this->_removed = FALSE;
103
		$this->_current = 0;
104
		$this->_content = NULL;
0 ignored issues
show
Documentation Bug introduced by
It seems like NULL of type null is incompatible with the declared type array of property $_content.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
105
106
		return $this;
107
	}
108
109
	/**
110
	 * Implement Countable
111
	 * @return int
112
	 */
113 5
	public function count()
114
	{
115 5
		$this->_load_content();
116
117 5
		if ($this->_content === NULL)
118
			return 0;
119
120 5
		return count($this->_content);
121
	}
122
123
	/**
124
	 * Implement ArrayAccess. Lazy load with _load_content, and the item with _load_item
125
	 *
126
	 * @param  int $offset
127
	 * @return Jam_Model
128
	 */
129 14
	public function offsetGet($offset)
130
	{
131 14
		$this->_load_content();
132
133 14
		if (is_array($this->_content) AND ! array_key_exists($offset, $this->_content))
134 1
			return NULL;
135
136 14
		return $this->_load_item($this->_content[$offset] ?? null, isset($this->_changed[$offset]), $offset);
137
	}
138
139
	/**
140
	 * Implement ArrayAccess. Lazy load with _load_content
141
	 *
142
	 * @param  int $offset
143
	 * @return boolean
144
	 */
145
	public function offsetExists($offset)
146
	{
147
		$this->_load_content();
148
149
		return isset($this->_content[$offset]);
150
	}
151
152
	/**
153
	 * Implement ArrayAccess. Lazy load with _load_content
154
	 */
155 13
	public function offsetSet($offset, $value)
156
	{
157 13
		$this->_load_content();
158
159 13
		if ($offset === NULL)
160
		{
161 12
			$this->_content[] = $value;
162 12
			$this->_changed[count($this->_content) - 1] = TRUE;
163
		}
164 5
		elseif ($this->_content !== NULL)
165
		{
166 5
			$this->_content[$offset] = $value;
167 5
			$this->_changed[$offset] = TRUE;
168
		}
169 13
	}
170
171
	/**
172
	 * Implement ArrayAccess. Lazy load with _load_content
173
	 */
174 6
	public function offsetUnset($offset)
175
	{
176 6
		$this->_load_content();
177 6
		if ($this->_content)
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_content of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
178
		{
179 6
			array_splice($this->_content, $offset, 1);
180 6
			array_splice($this->_changed, $offset, 1);
181
182 6
			$this->_removed = TRUE;
183
		}
184
185 6
	}
186
187
	/**
188
	 * Implement Iterator
189
	 */
190 16
	public function rewind()
191
	{
192 16
		$this->_current = 0;
193 16
	}
194
195
	/**
196
	 * Implement Iterator. Lazy load with _load_content and the item with _load_item
197
	 * @return  Jam_Model
198
	 */
199 11
	public function current()
200
	{
201 11
		$this->_load_content();
202 11
		if ( ! $this->valid())
203
			return NULL;
204
205 11
		return $this->_load_item($this->_content[$this->_current] ?? null, isset($this->_changed[$this->_current]), $this->_current);
206
	}
207
208
	/**
209
	 * Implement Iterator
210
	 * @return  int
211
	 */
212 11
	public function key()
213
	{
214 11
		return $this->_current;
215
	}
216
217
	/**
218
	 * Implement Iterator
219
	 */
220 12
	public function next()
221
	{
222 12
		$this->_current ++;
223 12
	}
224
225
	/**
226
	 * Implement Iterator. Lazy load with _load_content
227
	 * @return  bool
228
	 */
229 15
	public function valid()
230
	{
231 15
		$this->_load_content();
232 15
		return is_array($this->_content) AND array_key_exists($this->_current, $this->_content);
233
	}
234
235
	/**
236
	 * Implement Serializable. Lazy load with _load_content
237
	 * @return string
238
	 */
239 1
	public function serialize()
240
	{
241 1
		$this->_load_content();
242
243 1
		return serialize(array(
244 1
			'changed' => $this->_changed,
245 1
			'content' => $this->_content,
246 1
			'removed' => $this->_removed,
247 1
			'current' => $this->_current,
248
		));
249
	}
250
251
	/**
252
	 * Implement Serializable.
253
	 * @param  string $data [description]
254
	 */
255 1
	public function unserialize($data)
256
	{
257 1
		$data = unserialize($data);
258
259 1
		$this->_changed = $data['changed'];
260 1
		$this->_content = $data['content'];
261 1
		$this->_removed = $data['removed'];
262 1
		$this->_current = $data['current'];
263 1
	}
264
}
265