Automad
 All Classes Functions Variables Pages
selection.php
1 <?php
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  * AUTOMAD
29  *
30  * Copyright (c) 2014 by Marc Anton Dahmen
31  * http://marcdahmen.de
32  *
33  * Licensed under the MIT license.
34  * http://automad.org/license
35  */
36 
37 
38 namespace Automad\Core;
39 
40 
41 defined('AUTOMAD') or die('Direct access not permitted!');
42 
43 
59 class Selection {
60 
61 
69  private $selection = array();
70 
71 
78  public function __construct($pages) {
79 
80  $this->selection = $pages;
81 
82  }
83 
84 
89  private function excludeHidden() {
90 
91  foreach ($this->selection as $url => $Page) {
92 
93  if ($Page->hidden) {
94  unset($this->selection[$url]);
95  }
96 
97  }
98 
99  }
100 
101 
108  public function excludePage($url) {
109 
110  if (array_key_exists($url, $this->selection)) {
111  unset($this->selection[$url]);
112  }
113 
114  }
115 
116 
126  public function getSelection($excludeHidden = true, $offset = 0, $limit = NULL) {
127 
128  if ($excludeHidden) {
129  $this->excludeHidden();
130  }
131 
132  return array_slice($this->selection, $offset, $limit);
133 
134  }
135 
136 
143  public function filterBreadcrumbs($url) {
144 
145  // Test wheter $url is the URL of a real page.
146  // "Real" pages have a URL (not like search or error pages) and they exist in the selection array (not hidden).
147  // For all other $url, just the home page will be returned.
148  if (strpos($url, '/') === 0 && array_key_exists($url, $this->selection)) {
149 
150  $pages = array();
151 
152  // While $url is not the home page, strip each segement one by one and
153  // add the corresponding Page object to $pages.
154  while ($url != '/') {
155 
156  $pages[$url] = $this->selection[$url];
157  $url = '/' . trim(substr($url, 0, strrpos($url, '/')), '/');
158 
159  }
160 
161  // Add home page
162  $pages['/'] = $this->selection['/'];
163 
164  // Reverse the $pages array and pass it to $this->selection.
165  $this->selection = array_reverse($pages);
166 
167  } else {
168 
169  // If $url is not a valid URL, only add the home page to the selection.
170  // This might be the case for "virtual pages", like the "error" or "search results" pages,
171  // which don't have a $page->url.
172  $this->selection = array($this->selection['/']);
173 
174  }
175 
176  }
177 
178 
185  public function filterByParentUrl($parent) {
186 
187  $filtered = array();
188 
189  foreach ($this->selection as $key => $Page) {
190  if ($Page->parentUrl == $parent) {
191  $filtered[$key] = $Page;
192  }
193  }
194 
195  $this->selection = $filtered;
196 
197  }
198 
199 
206  public function filterByTag($tag) {
207 
208  if ($tag) {
209 
210  $filtered = array();
211 
212  foreach ($this->selection as $key => $Page) {
213 
214  if (in_array($tag, $Page->tags)) {
215  $filtered[$key] = $Page;
216  }
217 
218  }
219 
220  $this->selection = $filtered;
221 
222  }
223 
224  }
225 
226 
233  public function filterByTemplate($template) {
234 
235  if ($template) {
236 
237  $filtered = array();
238 
239  foreach ($this->selection as $key => $Page) {
240  if ($Page->template == $template) {
241  $filtered[$key] = $Page;
242  }
243  }
244 
245  $this->selection = $filtered;
246 
247  }
248 
249  }
250 
251 
258  public function filterByKeywords($str) {
259 
260  if ($str) {
261 
262  $filtered = array();
263 
264  // Explode keywords and also remove any tags and - most important - all "/", since they will be used as regex delimiters!
265  $keywords = explode(' ', str_replace('/', ' ', strip_tags($str)));
266 
267  // generate pattern
268  $pattern = '/^';
269  foreach ($keywords as $keyword) {
270  $pattern .= '(?=.*' . preg_quote($keyword) . ')';
271  }
272  // case-insensitive and multiline
273  $pattern .= '/is';
274 
275  // loop elements in $this->selection
276  foreach ($this->selection as $key => $Page) {
277 
278  // All the page's data get combined in on single string ($dataAsString), to make sure that a page gets returned,
279  // even if the keywords are distributed over different variables in $Page[data].
280  $dataAsString = strip_tags(implode(' ', $Page->data));
281 
282  // search
283  if (preg_match($pattern, $dataAsString) == 1) {
284  $filtered[$key] = $Page;
285  }
286 
287  }
288 
289  $this->selection = $filtered;
290 
291  }
292 
293  }
294 
295 
306  public function filterPrevAndNextToUrl($url) {
307 
308  // To be able to hide the hidden pages as neighbors and jump directly to the closest non-hidden pages (both sides),
309  // in case one or both neigbors is/are hidden, $this->excludeHidden() has to be called here already, because only excluding the hidden pages
310  // later, when calling getSelection(), will cause a "gap" in the neighbors-array, which will lead to a missing link, for a hidden neighbor.
311  // To handle hidden pages correctly, the current page has to be temporary stored in $current, in case the current page itself is hidden, because the
312  // curretn page is needed, even when hidden, to determine the closest neighbors.
313  $current = $this->selection[$url];
314  $this->excludeHidden();
315  $this->selection[$url] = $current;
316 
317  // Narrow down selection to pages with the same parentUrl
318  $this->filterByParentUrl($this->selection[$url]->parentUrl);
319  $this->sortPagesByBasename();
320 
321  $keys = array_keys($this->selection);
322  $keyIndexes = array_flip($keys);
323 
324  $neighbors = array();
325 
326  // Check number of pages
327  if (sizeof($keys) > 1) {
328 
329  if (sizeof($keys) > 2) {
330 
331  // Previous
332  if (isset($keys[$keyIndexes[$url]-1])) {
333  $neighbors['prev'] = $this->selection[$keys[$keyIndexes[$url]-1]];
334  } else {
335  $neighbors['prev'] = $this->selection[$keys[sizeof($keys)-1]];
336  }
337 
338  }
339 
340  // Next
341  if (isset($keys[$keyIndexes[$url]+1])) {
342  $neighbors['next'] = $this->selection[$keys[$keyIndexes[$url]+1]];
343  } else {
344  $neighbors['next'] = $this->selection[$keys[0]];
345  }
346 
347  }
348 
349  $this->selection = $neighbors;
350 
351  }
352 
353 
361  public function filterRelated($Page) {
362 
363  $tags = $Page->tags;
364 
365  $filtered = array();
366 
367  if ($tags) {
368 
369  foreach ($tags as $tag) {
370 
371  foreach($this->selection as $key => $p) {
372 
373  if (in_array($tag, $p->tags)) {
374  $filtered[$key] = $p;
375  }
376 
377  }
378 
379  }
380 
381  }
382 
383  $this->selection = $filtered;
384  $this->excludePage($Page->url);
385 
386  }
387 
388 
395  public function sortPagesByBasename($order = SORT_ASC) {
396 
397  $arrayToSortBy = array();
398 
399  foreach ($this->selection as $key => $Page) {
400 
401  $arrayToSortBy[$key] = basename($Page->path);
402 
403  }
404 
405  array_multisort($arrayToSortBy, $order, $this->selection);
406 
407  }
408 
409 
420  public function sortPages($var, $order = SORT_ASC) {
421 
422  if ($var) {
423 
424  // If $var is set, the selections is sorted by data[$var]
425  $arrayToSortBy = array();
426 
427  foreach ($this->selection as $key => $Page) {
428 
429  if (isset($Page->data[$var])) {
430  $arrayToSortBy[$key] = strtolower(strip_tags($Page->data[$var]));
431  } else {
432  // If data[$var] doesn't exists, the page's path's basename will be used.
433  // That way it is possible to order by basename with simply passing a non-existing var (for example "orig" or something else).
434  $arrayToSortBy[$key] = basename($Page->path);
435  }
436 
437  }
438 
439  array_multisort($arrayToSortBy, $order, $this->selection);
440 
441  } else {
442 
443  // else the selection is sorted by the file system path's basename
444  $this->sortPagesByBasename($order);
445 
446  }
447 
448  }
449 
450 
451 }
452 
453 
454 ?>
filterByParentUrl($parent)
Definition: selection.php:185
getSelection($excludeHidden=true, $offset=0, $limit=NULL)
Definition: selection.php:126
sortPagesByBasename($order=SORT_ASC)
Definition: selection.php:395
sortPages($var, $order=SORT_ASC)
Definition: selection.php:420
filterByTemplate($template)
Definition: selection.php:233