Completed
Pull Request — master (#20)
by Haralan
11:12 queued 09:14
created

Nodelist   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 248
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 74.29%

Importance

Changes 3
Bugs 0 Features 2
Metric Value
wmc 31
c 3
b 0
f 2
lcom 1
cbo 2
dl 0
loc 248
ccs 26
cts 35
cp 0.7429
rs 9.8

20 Methods

Rating   Name   Duplication   Size   Complexity  
A rewind() 0 5 1
A locator() 0 4 1
A driver() 0 4 1
A __construct() 0 7 1
A __toString() 0 9 2
A current() 0 5 1
A key() 0 4 1
A next() 0 5 1
A valid() 0 4 1
A count() 0 4 1
A seek() 0 9 2
A offsetExists() 0 4 2
A offsetGet() 0 7 2
A offsetSet() 0 4 1
A offsetUnset() 0 4 1
A _load() 0 4 1
B list_ids() 0 20 5
A first() 0 9 2
A last() 0 9 2
A as_array() 0 9 2
1
<?php
2
3
namespace Openbuildings\Spiderling;
4
5
/**
6
 * NodeList represents a list of dom nodes. Has lazy loading
7
 *
8
 * @package    Openbuildings\Spiderling
9
 * @author     Ivan Kerin
10
 * @copyright  (c) 2013 OpenBuildings Ltd.
11
 * @license    http://spdx.org/licenses/BSD-3-Clause
12
 */
13
class Nodelist implements \Iterator, \Countable, \SeekableIterator, \ArrayAccess {
14
15
	/**
16
	 * The driver for traversing this node and its children
17
	 * @var Driver
18
	 */
19
	protected $_driver;
20
21
	/**
22
	 * The parent node, NULL if root
23
	 * @var Node
24
	 */
25
	protected $_parent;
26
27
	/**
28
	 * Cache for the ids of this node list
29
	 * @var array
30
	 */
31
	protected $_list_ids;
32
33
	/**
34
	 * Single node object to be used during iteration
35
	 * @var Node
36
	 */
37
	protected $_node;
38
39
	/**
40
	 * Implementing Iterator
41
	 * @var integer
42
	 */
43
	protected $_current = 0;
44
45 10
	function __construct(Driver $driver, Locator $locator, Node $parent)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
46
	{
47 10
		$this->_driver  = $driver;
48 10
		$this->_locator = $locator;
0 ignored issues
show
Bug introduced by
The property _locator does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
49 10
		$this->_parent  = $parent;
50
		$this->_node = new Node($driver, $parent);
51
	}
52
53
	/**
54
	 * Returns a string representation of the collection.
55
	 *
56
	 * @return  string
57
	 */
58 1
	public function __toString()
59
	{
60 1
		$nodes = array();
61 1
		foreach($this as $node)
62
		{
63
			$nodes[] = $node->html();
64
		}
65
		return "Nodelist: \nLocator: {$this->locator()} \nContent: [\n".join("\n", $nodes)."\n]\n";
66
	}
67
68
	/**
69
	 * Implementation of the Iterator interface
70
	 * @return  Nodelist
71
	 */
72 2
	public function rewind()
73
	{
74 2
		$this->_current = 0;
75 2
		return $this;
76
	}
77
78
	/**
79
	 * Implementation of the Iterator interface
80
	 *
81
	 * @return  Node
82
	 */
83
	public function current()
84
	{
85
		$ids = $this->list_ids();
86
		return $this->_load($ids[$this->_current]);
87
	}
88
89
	/**
90
	 * Implementation of the Iterator interface
91
	 * @return  int
92
	 */
93
	public function key()
94
	{
95
		return $this->_current;
96
	}
97
98
	/**
99
	 * Implementation of the Iterator interface
100
	 * @return  Nodelist
101
	 */
102
	public function next()
103
	{
104
		++$this->_current;
105
		return $this;
106
	}
107
108
	/**
109
	 * Implementation of the Iterator interface
110
	 *
111
	 * @return  boolean
112
	 */
113
	public function valid()
114
	{
115
		return $this->offsetExists($this->_current);
116
	}
117
118
	/**
119
	 * Implementation of the Countable interface
120
	 *
121
	 * @return  int
122
	 */
123
	public function count()
124
	{
125
		return count($this->list_ids());
126
	}
127
128
	/**
129
	 * Implementation of SeekableIterator
130
	 *
131
	 * @param   mixed  $offset
132
	 * @return  boolean
133
	 */
134 1
	public function seek($offset)
135
	{
136
		if ($this->offsetExists($offset))
137
		{
138
			$this->_current = $offset;
139
			return TRUE;
140
		}
141 1
		return FALSE;
142
	}
143
144
	/**
145
	 * ArrayAccess: offsetExists
146
	 *
147
	 * @param   mixed  $offset
148
	 * @return  boolean
149
	 */
150
	public function offsetExists($offset)
151
	{
152
		return ($offset >= 0 AND $offset < $this->count());
153
	}
154
155
	/**
156
	 * ArrayAccess: offsetGet
157
	 *
158
	 * @param   mixed  $offset
159
	 * @return  Node
160
	 */
161
	public function offsetGet($offset)
162
	{
163
		if ( ! $this->offsetExists($offset))
164
			return NULL;
165
		$ids = $this->list_ids();
166
		return $this->_load($ids[$offset]);
167
	}
168
169
	/**
170
	 * ArrayAccess: offsetSet
171
	 *
172
	 * @throws  Kohana_Exception
173
	 * @param   mixed  $offset
174
	 * @param   mixed  $value
175
	 * @return  void
176
	 */
177
	public function offsetSet($offset, $value)
178
	{
179
		throw new Exception('Cannot modify Nodelist');
180
	}
181
182
	/**
183
	 * ArrayAccess: offsetUnset
184
	 *
185
	 * @throws  Kohana_Exception
186
	 * @param   mixed  $offset
187
	 * @return  void
188
	 */
189
	public function offsetUnset($offset)
190
	{
191
		throw new Exception('Cannot modify Nodelist');
192
	}
193
194
	protected function _load($id)
195
	{
196
		return $this->_node->load_new_id($id);
197
	}
198
199 4
	protected function list_ids()
200
	{
201 4
		if ($this->_list_ids === NULL)
202
		{
203
			$this->_list_ids = (array) $this->_driver->all($this->_locator->xpath(), $this->_parent->id());
204
205
			if ($this->_locator->filters())
206
			{
207 1
				foreach ($this->_list_ids as $offset => $id)
208
				{
209
					if ( ! $this->_locator->is_filtered($this->_load($id), $offset))
210
					{
211
						unset($this->_list_ids[$offset]);
212
					}
213
				}
214
			}
215
		}
216
217 4
		return $this->_list_ids;
218
	}
219
220 1
	public function locator()
221
	{
222 1
		return $this->_locator;
223
	}
224
225 1
	public function driver()
226
	{
227 1
		return $this->_driver;
228
	}
229
230 3
	public function first()
231
	{
232
		$ids = $this->list_ids();
233
234
		if (count($ids) <= 0)
235 3
			return NULL;
236
237
		return $this->_load(reset($ids));
238
	}
239
240
	public function last()
241
	{
242
		$ids = $this->list_ids();
243
244
		if (count($ids) <= 0)
245
			return NULL;
246
247
		return $this->_load(end($ids));
248
	}
249
250 1
	public function as_array()
251
	{
252 1
		$nodes = array();
253 1
		foreach ($this->list_ids() as $i => $id)
254
		{
255
			$nodes[] = new Node($this->_driver, $this->_parent, $id);
256
		}
257 1
		return $nodes;
258
	}
259
260
}
261