-
Notifications
You must be signed in to change notification settings - Fork 194
Expand file tree
/
Copy pathPageArray.php
More file actions
368 lines (324 loc) · 8.58 KB
/
PageArray.php
File metadata and controls
368 lines (324 loc) · 8.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
<?php
/**
* ProcessWire PageArray
*
* PageArray provides an array-like means for storing PageReferences and is utilized throughout ProcessWire.
*
* ProcessWire 2.x
* Copyright (C) 2015 by Ryan Cramer
* This file licensed under Mozilla Public License v2.0 http://mozilla.org/MPL/2.0/
*
* https://processwire.com
*
* @method string getMarkup($key = null) Render a simple/default markup value for each item
*
*/
class PageArray extends PaginatedArray implements WirePaginatable {
/**
* Reference to the selectors that led to this PageArray, if applicable
*
* @var Selectors
*
*/
protected $selectors = null;
/**
* Template mehod that descendant classes may use to validate items added to this WireArray
*
* @param mixed $item Item to add
* @return bool True if item is valid and may be added, false if not
*
*/
public function isValidItem($item) {
return is_object($item) && $item instanceof Page;
}
/**
* Validate the key used to add a Page
*
* PageArrays are keyed by an incremental number that does NOT relate to the Page ID.
*
* @param string|int $key
* @return bool True if key is valid and may be used, false if not
*
*/
public function isValidKey($key) {
return ctype_digit("$key");
}
/**
* Does this PageArray use numeric keys only? (yes it does)
*
* Defined here to override the slower check in WireArray
*
* @return bool
*
*/
protected function usesNumericKeys() {
return true;
}
/**
* Per WireArray interface, return a blank Page
*
*/
public function makeBlankItem() {
return new Page();
}
/**
* Import the provided pages into this PageArray.
*
* @param array|PageArray|Page $pages Pages to import.
* @return PageArray reference to current instance.
*
*/
public function import($pages) {
if(is_object($pages) && $pages instanceof Page) $pages = array($pages);
if(!self::iterable($pages)) return $this;
foreach($pages as $page) $this->add($page);
if($pages instanceof PageArray) {
if(count($pages) < $pages->getTotal()) $this->setTotal($this->getTotal() + ($pages->getTotal() - count($pages)));
}
return $this;
}
/*
public function get($key) {
if(ctype_digit("$key")) return parent::get($key);
@todo check if selector, then call findOne(). If it returns null, return a NullPage instead.
return null;
}
*/
/**
* Does this PageArray contain the given index or Page?
*
* @param Page|int $key Page Array index or Page object.
* @return bool True if the index or Page exists here, false if not.
*/
public function has($key) {
if(is_int($key) || is_string($key)) return parent::has($key);
$has = false;
if(is_object($key) && $key instanceof Page) {
foreach($this as $k => $pg) {
$has = ($pg->id == $key->id);
if($has) break;
}
}
return $has;
}
/**
* Add a Page to this PageArray.
*
* @param Page|PageArray|int $page Page object, PageArray object, or Page ID.
* If Page, the Page will be added.
* If PageArray, it will do the same thing as the import() function: import all the pages.
* If Page ID, it will be loaded and added.
* @return PageArray reference to current instance.
*/
public function add($page) {
if($this->isValidItem($page)) {
parent::add($page);
$this->numTotal++;
} else if($page instanceof PageArray || is_array($page)) {
return $this->import($page);
} else if(ctype_digit("$page")) {
if($page = $this->getFuel('pages')->findOne("id=$page")) {
parent::add($page);
$this->numTotal++;
}
}
return $this;
}
/**
* Sets an index in the PageArray.
*
* @param int $key Key of item to set.
* @param Page $value Value of item.
* @return $this
*
*/
public function set($key, $value) {
$has = $this->has($key);
parent::set($key, $value);
if(!$has) $this->numTotal++;
return $this;
}
/**
* Prepend a Page to the beginning of the PageArray.
*
* @param Page|PageArray $item
* @return WireArray This instance.
*
*/
public function prepend($item) {
parent::prepend($item);
// note that WireArray::prepend does a recursive call to prepend with each item,
// so it's only necessary to increase numTotal if the given item is Page (vs. PageArray)
if($item instanceof Page) $this->numTotal++;
return $this;
}
/**
* Remove the given Page or key from the PageArray.
*
* @param int|Page $key
* @return bool true if removed, false if not
*
*/
public function remove($key) {
// if a Page object has been passed, determine it's key
if($this->isValidItem($key)) {
foreach($this->data as $k => $pg) {
if($pg->id == $key->id) {
$key = $k;
break;
}
}
}
if($this->has($key)) {
parent::remove($key);
$this->numTotal--;
}
return $this;
}
/**
* Shift the first Page off of the PageArray and return it.
*
* @return Page|NULL
*
*/
public function shift() {
if($this->numTotal) $this->numTotal--;
return parent::shift();
}
/**
* Pop the last page off of the PageArray and return it.
*
* @return Page|NULL
*
*/
public function pop() {
if($this->numTotal) $this->numTotal--;
return parent::pop();
}
/**
* Set the Selectors that led to this PageArray, if applicable
*
* @param Selectors $selectors
* @return $this
*
*/
public function setSelectors(Selectors $selectors) {
$this->selectors = $selectors;
return $this;
}
/**
* Return the Selectors that led to this PageArray, or null if not set/applicable
*
* @return Selectors|null
*
*/
public function getSelectors() {
return $this->selectors;
}
/**
* Filter out Pages that don't match the selector.
*
* This is applicable to and destructive to the WireArray.
*
* @param string|Selectors $selectors AttributeSelector string to use as the filter.
* @param bool $not Make this a "not" filter? (default is false)
* @return WireArray reference to current [filtered] instance
*
*/
protected function filterData($selectors, $not = false) {
if(is_string($selectors) && $selectors[0] === '/') $selectors = "path=$selectors";
return parent::filterData($selectors, $not);
}
/**
* Prepare selectors for filtering
*
* Template method for descending classes to modify selectors if needed
*
* @param Selectors $selectors
*
*/
protected function filterDataSelectors(Selectors $selectors) {
// @todo make it remove references to include= statements since not applicable in-memory
parent::filterDataSelectors($selectors);
}
/**
* Get the value of $property from $item
*
* Used by the WireArray::sort method to retrieve a value from a Wire object.
* If output formatting is on, we turn it off to ensure that the sorting
* is performed without output formatting.
*
* @param Wire $item
* @param string $property
* @return mixed
*
*/
protected function getItemPropertyValue(Wire $item, $property) {
if($item instanceof Page) {
$value = $item->getUnformatted($property);
} else if(strpos($property, '.') !== false) {
$value = WireData::_getDot($property, $item);
} else if($item instanceof WireArray) {
$value = $item->getProperty($property);
if(is_null($value)) {
$value = $item->first();
$value = $this->getItemPropertyValue($value, $property);
}
} else {
$value = $item->$property;
}
if(is_array($value)) $value = implode('|', $value);
return $value;
}
/**
* PageArrays always return a string of the Page IDs separated by pipe "|" characters
*
* Pipe charactesr are used for compatibility with Selector OR statements
*
*/
public function __toString() {
$s = '';
foreach($this as $key => $page) $s .= "$page|";
$s = rtrim($s, "|");
return $s;
}
/**
* Render a simple/default markup value for each item
*
* Primarily for testing/debugging purposes.
*
* @param string|callable|function $key
* @return string
*
*/
public function ___getMarkup($key = null) {
if($key && !is_string($key)) {
$out = $this->each($key);
} else if(strpos($key, '{') !== false && strpos($key, '}')) {
$out = $this->each($key);
} else {
if(empty($key)) $key = "<li>{title|name}</li>";
$out = $this->each($key);
if($out) {
$out = "<ul>$out</ul>";
if($this->getLimit() && $this->getTotal() > $this->getLimit()) {
$pager = $this->wire('modules')->get('MarkupPagerNav');
$out .= $pager->render($this);
}
}
}
return $out;
}
/**
* debugInfo PHP 5.6+ magic method
*
* @return array
*
*/
public function __debugInfo() {
$info = parent::__debugInfo();
$info['selectors'] = (string) $this->selectors;
if(!count($info['selectors'])) unset($info['selectors']);
return $info;
}
}