|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_View |
|
17 * @subpackage Helper |
|
18 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
19 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
20 * @version $Id: Links.php 20096 2010-01-06 02:05:09Z bkarwin $ |
|
21 */ |
|
22 |
|
23 /** |
|
24 * @see Zend_View_Helper_Navigation_HelperAbstract |
|
25 */ |
|
26 require_once 'Zend/View/Helper/Navigation/HelperAbstract.php'; |
|
27 |
|
28 /** |
|
29 * Helper for printing <link> elements |
|
30 * |
|
31 * @category Zend |
|
32 * @package Zend_View |
|
33 * @subpackage Helper |
|
34 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
35 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
36 */ |
|
37 class Zend_View_Helper_Navigation_Links |
|
38 extends Zend_View_Helper_Navigation_HelperAbstract |
|
39 { |
|
40 /**#@+ |
|
41 * Constants used for specifying which link types to find and render |
|
42 * |
|
43 * @var int |
|
44 */ |
|
45 const RENDER_ALTERNATE = 0x0001; |
|
46 const RENDER_STYLESHEET = 0x0002; |
|
47 const RENDER_START = 0x0004; |
|
48 const RENDER_NEXT = 0x0008; |
|
49 const RENDER_PREV = 0x0010; |
|
50 const RENDER_CONTENTS = 0x0020; |
|
51 const RENDER_INDEX = 0x0040; |
|
52 const RENDER_GLOSSARY = 0x0080; |
|
53 const RENDER_COPYRIGHT = 0x0100; |
|
54 const RENDER_CHAPTER = 0x0200; |
|
55 const RENDER_SECTION = 0x0400; |
|
56 const RENDER_SUBSECTION = 0x0800; |
|
57 const RENDER_APPENDIX = 0x1000; |
|
58 const RENDER_HELP = 0x2000; |
|
59 const RENDER_BOOKMARK = 0x4000; |
|
60 const RENDER_CUSTOM = 0x8000; |
|
61 const RENDER_ALL = 0xffff; |
|
62 /**#@+**/ |
|
63 |
|
64 /** |
|
65 * Maps render constants to W3C link types |
|
66 * |
|
67 * @var array |
|
68 */ |
|
69 protected static $_RELATIONS = array( |
|
70 self::RENDER_ALTERNATE => 'alternate', |
|
71 self::RENDER_STYLESHEET => 'stylesheet', |
|
72 self::RENDER_START => 'start', |
|
73 self::RENDER_NEXT => 'next', |
|
74 self::RENDER_PREV => 'prev', |
|
75 self::RENDER_CONTENTS => 'contents', |
|
76 self::RENDER_INDEX => 'index', |
|
77 self::RENDER_GLOSSARY => 'glossary', |
|
78 self::RENDER_COPYRIGHT => 'copyright', |
|
79 self::RENDER_CHAPTER => 'chapter', |
|
80 self::RENDER_SECTION => 'section', |
|
81 self::RENDER_SUBSECTION => 'subsection', |
|
82 self::RENDER_APPENDIX => 'appendix', |
|
83 self::RENDER_HELP => 'help', |
|
84 self::RENDER_BOOKMARK => 'bookmark' |
|
85 ); |
|
86 |
|
87 /** |
|
88 * The helper's render flag |
|
89 * |
|
90 * @see render() |
|
91 * @see setRenderFlag() |
|
92 * @var int |
|
93 */ |
|
94 protected $_renderFlag = self::RENDER_ALL; |
|
95 |
|
96 /** |
|
97 * Root container |
|
98 * |
|
99 * Used for preventing methods to traverse above the container given to |
|
100 * the {@link render()} method. |
|
101 * |
|
102 * @see _findRoot() |
|
103 * |
|
104 * @var Zend_Navigation_Container |
|
105 */ |
|
106 protected $_root; |
|
107 |
|
108 /** |
|
109 * View helper entry point: |
|
110 * Retrieves helper and optionally sets container to operate on |
|
111 * |
|
112 * @param Zend_Navigation_Container $container [optional] container to |
|
113 * operate on |
|
114 * @return Zend_View_Helper_Navigation_Links fluent interface, returns |
|
115 * self |
|
116 */ |
|
117 public function links(Zend_Navigation_Container $container = null) |
|
118 { |
|
119 if (null !== $container) { |
|
120 $this->setContainer($container); |
|
121 } |
|
122 |
|
123 return $this; |
|
124 } |
|
125 |
|
126 /** |
|
127 * Magic overload: Proxy calls to {@link findRelation()} or container |
|
128 * |
|
129 * Examples of finder calls: |
|
130 * <code> |
|
131 * // METHOD // SAME AS |
|
132 * $h->findRelNext($page); // $h->findRelation($page, 'rel', 'next') |
|
133 * $h->findRevSection($page); // $h->findRelation($page, 'rev', 'section'); |
|
134 * $h->findRelFoo($page); // $h->findRelation($page, 'rel', 'foo'); |
|
135 * </code> |
|
136 * |
|
137 * @param string $method method name |
|
138 * @param array $arguments method arguments |
|
139 * @throws Zend_Navigation_Exception if method does not exist in container |
|
140 */ |
|
141 public function __call($method, array $arguments = array()) |
|
142 { |
|
143 if (@preg_match('/find(Rel|Rev)(.+)/', $method, $match)) { |
|
144 return $this->findRelation($arguments[0], |
|
145 strtolower($match[1]), |
|
146 strtolower($match[2])); |
|
147 } |
|
148 |
|
149 return parent::__call($method, $arguments); |
|
150 } |
|
151 |
|
152 // Accessors: |
|
153 |
|
154 /** |
|
155 * Sets the helper's render flag |
|
156 * |
|
157 * The helper uses the bitwise '&' operator against the hex values of the |
|
158 * render constants. This means that the flag can is "bitwised" value of |
|
159 * the render constants. Examples: |
|
160 * <code> |
|
161 * // render all links except glossary |
|
162 * $flag = Zend_View_Helper_Navigation_Links:RENDER_ALL ^ |
|
163 * Zend_View_Helper_Navigation_Links:RENDER_GLOSSARY; |
|
164 * $helper->setRenderFlag($flag); |
|
165 * |
|
166 * // render only chapters and sections |
|
167 * $flag = Zend_View_Helper_Navigation_Links:RENDER_CHAPTER | |
|
168 * Zend_View_Helper_Navigation_Links:RENDER_SECTION; |
|
169 * $helper->setRenderFlag($flag); |
|
170 * |
|
171 * // render only relations that are not native W3C relations |
|
172 * $helper->setRenderFlag(Zend_View_Helper_Navigation_Links:RENDER_CUSTOM); |
|
173 * |
|
174 * // render all relations (default) |
|
175 * $helper->setRenderFlag(Zend_View_Helper_Navigation_Links:RENDER_ALL); |
|
176 * </code> |
|
177 * |
|
178 * Note that custom relations can also be rendered directly using the |
|
179 * {@link renderLink()} method. |
|
180 * |
|
181 * @param int $renderFlag render flag |
|
182 * @return Zend_View_Helper_Navigation_Links fluent interface, returns self |
|
183 */ |
|
184 public function setRenderFlag($renderFlag) |
|
185 { |
|
186 $this->_renderFlag = (int) $renderFlag; |
|
187 return $this; |
|
188 } |
|
189 |
|
190 /** |
|
191 * Returns the helper's render flag |
|
192 * |
|
193 * @return int render flag |
|
194 */ |
|
195 public function getRenderFlag() |
|
196 { |
|
197 return $this->_renderFlag; |
|
198 } |
|
199 |
|
200 // Finder methods: |
|
201 |
|
202 /** |
|
203 * Finds all relations (forward and reverse) for the given $page |
|
204 * |
|
205 * The form of the returned array: |
|
206 * <code> |
|
207 * // $page denotes an instance of Zend_Navigation_Page |
|
208 * $returned = array( |
|
209 * 'rel' => array( |
|
210 * 'alternate' => array($page, $page, $page), |
|
211 * 'start' => array($page), |
|
212 * 'next' => array($page), |
|
213 * 'prev' => array($page), |
|
214 * 'canonical' => array($page) |
|
215 * ), |
|
216 * 'rev' => array( |
|
217 * 'section' => array($page) |
|
218 * ) |
|
219 * ); |
|
220 * </code> |
|
221 * |
|
222 * @param Zend_Navigation_Page $page page to find links for |
|
223 * @return array related pages |
|
224 */ |
|
225 public function findAllRelations(Zend_Navigation_Page $page, |
|
226 $flag = null) |
|
227 { |
|
228 if (!is_int($flag)) { |
|
229 $flag = self::RENDER_ALL; |
|
230 } |
|
231 |
|
232 $result = array('rel' => array(), 'rev' => array()); |
|
233 $native = array_values(self::$_RELATIONS); |
|
234 |
|
235 foreach (array_keys($result) as $rel) { |
|
236 $meth = 'getDefined' . ucfirst($rel); |
|
237 $types = array_merge($native, array_diff($page->$meth(), $native)); |
|
238 |
|
239 foreach ($types as $type) { |
|
240 if (!$relFlag = array_search($type, self::$_RELATIONS)) { |
|
241 $relFlag = self::RENDER_CUSTOM; |
|
242 } |
|
243 if (!($flag & $relFlag)) { |
|
244 continue; |
|
245 } |
|
246 if ($found = $this->findRelation($page, $rel, $type)) { |
|
247 if (!is_array($found)) { |
|
248 $found = array($found); |
|
249 } |
|
250 $result[$rel][$type] = $found; |
|
251 } |
|
252 } |
|
253 } |
|
254 |
|
255 return $result; |
|
256 } |
|
257 |
|
258 /** |
|
259 * Finds relations of the given $rel=$type from $page |
|
260 * |
|
261 * This method will first look for relations in the page instance, then |
|
262 * by searching the root container if nothing was found in the page. |
|
263 * |
|
264 * @param Zend_Navigation_Page $page page to find relations for |
|
265 * @param string $rel relation, "rel" or "rev" |
|
266 * @param string $type link type, e.g. 'start', 'next' |
|
267 * @return Zend_Navigaiton_Page|array|null page(s), or null if not found |
|
268 * @throws Zend_View_Exception if $rel is not "rel" or "rev" |
|
269 */ |
|
270 public function findRelation(Zend_Navigation_Page $page, $rel, $type) |
|
271 { |
|
272 if (!in_array($rel, array('rel', 'rev'))) { |
|
273 require_once 'Zend/View/Exception.php'; |
|
274 $e = new Zend_View_Exception(sprintf( |
|
275 'Invalid argument: $rel must be "rel" or "rev"; "%s" given', |
|
276 $rel)); |
|
277 $e->setView($this->view); |
|
278 throw $e; |
|
279 } |
|
280 |
|
281 if (!$result = $this->_findFromProperty($page, $rel, $type)) { |
|
282 $result = $this->_findFromSearch($page, $rel, $type); |
|
283 } |
|
284 |
|
285 return $result; |
|
286 } |
|
287 |
|
288 /** |
|
289 * Finds relations of given $type for $page by checking if the |
|
290 * relation is specified as a property of $page |
|
291 * |
|
292 * @param Zend_Navigation_Page $page page to find relations for |
|
293 * @param string $rel relation, 'rel' or 'rev' |
|
294 * @param string $type link type, e.g. 'start', 'next' |
|
295 * @return Zend_Navigation_Page|array|null page(s), or null if not found |
|
296 */ |
|
297 protected function _findFromProperty(Zend_Navigation_Page $page, $rel, $type) |
|
298 { |
|
299 $method = 'get' . ucfirst($rel); |
|
300 if ($result = $page->$method($type)) { |
|
301 if ($result = $this->_convertToPages($result)) { |
|
302 if (!is_array($result)) { |
|
303 $result = array($result); |
|
304 } |
|
305 |
|
306 foreach ($result as $key => $page) { |
|
307 if (!$this->accept($page)) { |
|
308 unset($result[$key]); |
|
309 } |
|
310 } |
|
311 |
|
312 return count($result) == 1 ? $result[0] : $result; |
|
313 } |
|
314 } |
|
315 |
|
316 return null; |
|
317 } |
|
318 |
|
319 /** |
|
320 * Finds relations of given $rel=$type for $page by using the helper to |
|
321 * search for the relation in the root container |
|
322 * |
|
323 * @param Zend_Navigation_Page $page page to find relations for |
|
324 * @param string $rel relation, 'rel' or 'rev' |
|
325 * @param string $type link type, e.g. 'start', 'next', etc |
|
326 * @return array|null array of pages, or null if not found |
|
327 */ |
|
328 protected function _findFromSearch(Zend_Navigation_Page $page, $rel, $type) |
|
329 { |
|
330 $found = null; |
|
331 |
|
332 $method = 'search' . ucfirst($rel) . ucfirst($type); |
|
333 if (method_exists($this, $method)) { |
|
334 $found = $this->$method($page); |
|
335 } |
|
336 |
|
337 return $found; |
|
338 } |
|
339 |
|
340 // Search methods: |
|
341 |
|
342 /** |
|
343 * Searches the root container for the forward 'start' relation of the given |
|
344 * $page |
|
345 * |
|
346 * From {@link http://www.w3.org/TR/html4/types.html#type-links}: |
|
347 * Refers to the first document in a collection of documents. This link type |
|
348 * tells search engines which document is considered by the author to be the |
|
349 * starting point of the collection. |
|
350 * |
|
351 * @param Zend_Navigation_Page $page page to find relation for |
|
352 * @return Zend_Navigation_Page|null page or null |
|
353 */ |
|
354 public function searchRelStart(Zend_Navigation_Page $page) |
|
355 { |
|
356 $found = $this->_findRoot($page); |
|
357 if (!$found instanceof Zend_Navigation_Page) { |
|
358 $found->rewind(); |
|
359 $found = $found->current(); |
|
360 } |
|
361 |
|
362 if ($found === $page || !$this->accept($found)) { |
|
363 $found = null; |
|
364 } |
|
365 |
|
366 return $found; |
|
367 } |
|
368 |
|
369 /** |
|
370 * Searches the root container for the forward 'next' relation of the given |
|
371 * $page |
|
372 * |
|
373 * From {@link http://www.w3.org/TR/html4/types.html#type-links}: |
|
374 * Refers to the next document in a linear sequence of documents. User |
|
375 * agents may choose to preload the "next" document, to reduce the perceived |
|
376 * load time. |
|
377 * |
|
378 * @param Zend_Navigation_Page $page page to find relation for |
|
379 * @return Zend_Navigation_Page|null page(s) or null |
|
380 */ |
|
381 public function searchRelNext(Zend_Navigation_Page $page) |
|
382 { |
|
383 $found = null; |
|
384 $break = false; |
|
385 $iterator = new RecursiveIteratorIterator($this->_findRoot($page), |
|
386 RecursiveIteratorIterator::SELF_FIRST); |
|
387 foreach ($iterator as $intermediate) { |
|
388 if ($intermediate === $page) { |
|
389 // current page; break at next accepted page |
|
390 $break = true; |
|
391 continue; |
|
392 } |
|
393 |
|
394 if ($break && $this->accept($intermediate)) { |
|
395 $found = $intermediate; |
|
396 break; |
|
397 } |
|
398 } |
|
399 |
|
400 return $found; |
|
401 } |
|
402 |
|
403 /** |
|
404 * Searches the root container for the forward 'prev' relation of the given |
|
405 * $page |
|
406 * |
|
407 * From {@link http://www.w3.org/TR/html4/types.html#type-links}: |
|
408 * Refers to the previous document in an ordered series of documents. Some |
|
409 * user agents also support the synonym "Previous". |
|
410 * |
|
411 * @param Zend_Navigation_Page $page page to find relation for |
|
412 * @return Zend_Navigation_Page|null page or null |
|
413 */ |
|
414 public function searchRelPrev(Zend_Navigation_Page $page) |
|
415 { |
|
416 $found = null; |
|
417 $prev = null; |
|
418 $iterator = new RecursiveIteratorIterator( |
|
419 $this->_findRoot($page), |
|
420 RecursiveIteratorIterator::SELF_FIRST); |
|
421 foreach ($iterator as $intermediate) { |
|
422 if (!$this->accept($intermediate)) { |
|
423 continue; |
|
424 } |
|
425 if ($intermediate === $page) { |
|
426 $found = $prev; |
|
427 break; |
|
428 } |
|
429 |
|
430 $prev = $intermediate; |
|
431 } |
|
432 |
|
433 return $found; |
|
434 } |
|
435 |
|
436 /** |
|
437 * Searches the root container for forward 'chapter' relations of the given |
|
438 * $page |
|
439 * |
|
440 * From {@link http://www.w3.org/TR/html4/types.html#type-links}: |
|
441 * Refers to a document serving as a chapter in a collection of documents. |
|
442 * |
|
443 * @param Zend_Navigation_Page $page page to find relation for |
|
444 * @return Zend_Navigation_Page|array|null page(s) or null |
|
445 */ |
|
446 public function searchRelChapter(Zend_Navigation_Page $page) |
|
447 { |
|
448 $found = array(); |
|
449 |
|
450 // find first level of pages |
|
451 $root = $this->_findRoot($page); |
|
452 |
|
453 // find start page(s) |
|
454 $start = $this->findRelation($page, 'rel', 'start'); |
|
455 if (!is_array($start)) { |
|
456 $start = array($start); |
|
457 } |
|
458 |
|
459 foreach ($root as $chapter) { |
|
460 // exclude self and start page from chapters |
|
461 if ($chapter !== $page && |
|
462 !in_array($chapter, $start) && |
|
463 $this->accept($chapter)) { |
|
464 $found[] = $chapter; |
|
465 } |
|
466 } |
|
467 |
|
468 switch (count($found)) { |
|
469 case 0: |
|
470 return null; |
|
471 case 1: |
|
472 return $found[0]; |
|
473 default: |
|
474 return $found; |
|
475 } |
|
476 } |
|
477 |
|
478 /** |
|
479 * Searches the root container for forward 'section' relations of the given |
|
480 * $page |
|
481 * |
|
482 * From {@link http://www.w3.org/TR/html4/types.html#type-links}: |
|
483 * Refers to a document serving as a section in a collection of documents. |
|
484 * |
|
485 * @param Zend_Navigation_Page $page page to find relation for |
|
486 * @return Zend_Navigation_Page|array|null page(s) or null |
|
487 */ |
|
488 public function searchRelSection(Zend_Navigation_Page $page) |
|
489 { |
|
490 $found = array(); |
|
491 |
|
492 // check if given page has pages and is a chapter page |
|
493 if ($page->hasPages() && $this->_findRoot($page)->hasPage($page)) { |
|
494 foreach ($page as $section) { |
|
495 if ($this->accept($section)) { |
|
496 $found[] = $section; |
|
497 } |
|
498 } |
|
499 } |
|
500 |
|
501 switch (count($found)) { |
|
502 case 0: |
|
503 return null; |
|
504 case 1: |
|
505 return $found[0]; |
|
506 default: |
|
507 return $found; |
|
508 } |
|
509 } |
|
510 |
|
511 /** |
|
512 * Searches the root container for forward 'subsection' relations of the |
|
513 * given $page |
|
514 * |
|
515 * From {@link http://www.w3.org/TR/html4/types.html#type-links}: |
|
516 * Refers to a document serving as a subsection in a collection of |
|
517 * documents. |
|
518 * |
|
519 * @param Zend_Navigation_Page $page page to find relation for |
|
520 * @return Zend_Navigation_Page|array|null page(s) or null |
|
521 */ |
|
522 public function searchRelSubsection(Zend_Navigation_Page $page) |
|
523 { |
|
524 $found = array(); |
|
525 |
|
526 if ($page->hasPages()) { |
|
527 // given page has child pages, loop chapters |
|
528 foreach ($this->_findRoot($page) as $chapter) { |
|
529 // is page a section? |
|
530 if ($chapter->hasPage($page)) { |
|
531 foreach ($page as $subsection) { |
|
532 if ($this->accept($subsection)) { |
|
533 $found[] = $subsection; |
|
534 } |
|
535 } |
|
536 } |
|
537 } |
|
538 } |
|
539 |
|
540 switch (count($found)) { |
|
541 case 0: |
|
542 return null; |
|
543 case 1: |
|
544 return $found[0]; |
|
545 default: |
|
546 return $found; |
|
547 } |
|
548 } |
|
549 |
|
550 /** |
|
551 * Searches the root container for the reverse 'section' relation of the |
|
552 * given $page |
|
553 * |
|
554 * From {@link http://www.w3.org/TR/html4/types.html#type-links}: |
|
555 * Refers to a document serving as a section in a collection of documents. |
|
556 * |
|
557 * @param Zend_Navigation_Page $page page to find relation for |
|
558 * @return Zend_Navigation_Page|null page(s) or null |
|
559 */ |
|
560 public function searchRevSection(Zend_Navigation_Page $page) |
|
561 { |
|
562 $found = null; |
|
563 |
|
564 if ($parent = $page->getParent()) { |
|
565 if ($parent instanceof Zend_Navigation_Page && |
|
566 $this->_findRoot($page)->hasPage($parent)) { |
|
567 $found = $parent; |
|
568 } |
|
569 } |
|
570 |
|
571 return $found; |
|
572 } |
|
573 |
|
574 /** |
|
575 * Searches the root container for the reverse 'section' relation of the |
|
576 * given $page |
|
577 * |
|
578 * From {@link http://www.w3.org/TR/html4/types.html#type-links}: |
|
579 * Refers to a document serving as a subsection in a collection of |
|
580 * documents. |
|
581 * |
|
582 * @param Zend_Navigation_Page $page page to find relation for |
|
583 * @return Zend_Navigation_Page|null page(s) or null |
|
584 */ |
|
585 public function searchRevSubsection(Zend_Navigation_Page $page) |
|
586 { |
|
587 $found = null; |
|
588 |
|
589 if ($parent = $page->getParent()) { |
|
590 if ($parent instanceof Zend_Navigation_Page) { |
|
591 $root = $this->_findRoot($page); |
|
592 foreach ($root as $chapter) { |
|
593 if ($chapter->hasPage($parent)) { |
|
594 $found = $parent; |
|
595 break; |
|
596 } |
|
597 } |
|
598 } |
|
599 } |
|
600 |
|
601 return $found; |
|
602 } |
|
603 |
|
604 // Util methods: |
|
605 |
|
606 /** |
|
607 * Returns the root container of the given page |
|
608 * |
|
609 * When rendering a container, the render method still store the given |
|
610 * container as the root container, and unset it when done rendering. This |
|
611 * makes sure finder methods will not traverse above the container given |
|
612 * to the render method. |
|
613 * |
|
614 * @param Zend_Navigaiton_Page $page page to find root for |
|
615 * @return Zend_Navigation_Container the root container of the given page |
|
616 */ |
|
617 protected function _findRoot(Zend_Navigation_Page $page) |
|
618 { |
|
619 if ($this->_root) { |
|
620 return $this->_root; |
|
621 } |
|
622 |
|
623 $root = $page; |
|
624 |
|
625 while ($parent = $page->getParent()) { |
|
626 $root = $parent; |
|
627 if ($parent instanceof Zend_Navigation_Page) { |
|
628 $page = $parent; |
|
629 } else { |
|
630 break; |
|
631 } |
|
632 } |
|
633 |
|
634 return $root; |
|
635 } |
|
636 |
|
637 /** |
|
638 * Converts a $mixed value to an array of pages |
|
639 * |
|
640 * @param mixed $mixed mixed value to get page(s) from |
|
641 * @param bool $recursive whether $value should be looped |
|
642 * if it is an array or a config |
|
643 * @return Zend_Navigation_Page|array|null empty if unable to convert |
|
644 */ |
|
645 protected function _convertToPages($mixed, $recursive = true) |
|
646 { |
|
647 if (is_object($mixed)) { |
|
648 if ($mixed instanceof Zend_Navigation_Page) { |
|
649 // value is a page instance; return directly |
|
650 return $mixed; |
|
651 } elseif ($mixed instanceof Zend_Navigation_Container) { |
|
652 // value is a container; return pages in it |
|
653 $pages = array(); |
|
654 foreach ($mixed as $page) { |
|
655 $pages[] = $page; |
|
656 } |
|
657 return $pages; |
|
658 } elseif ($mixed instanceof Zend_Config) { |
|
659 // convert config object to array and extract |
|
660 return $this->_convertToPages($mixed->toArray(), $recursive); |
|
661 } |
|
662 } elseif (is_string($mixed)) { |
|
663 // value is a string; make an URI page |
|
664 return Zend_Navigation_Page::factory(array( |
|
665 'type' => 'uri', |
|
666 'uri' => $mixed |
|
667 )); |
|
668 } elseif (is_array($mixed) && !empty($mixed)) { |
|
669 if ($recursive && is_numeric(key($mixed))) { |
|
670 // first key is numeric; assume several pages |
|
671 $pages = array(); |
|
672 foreach ($mixed as $value) { |
|
673 if ($value = $this->_convertToPages($value, false)) { |
|
674 $pages[] = $value; |
|
675 } |
|
676 } |
|
677 return $pages; |
|
678 } else { |
|
679 // pass array to factory directly |
|
680 try { |
|
681 $page = Zend_Navigation_Page::factory($mixed); |
|
682 return $page; |
|
683 } catch (Exception $e) { |
|
684 } |
|
685 } |
|
686 } |
|
687 |
|
688 // nothing found |
|
689 return null; |
|
690 } |
|
691 |
|
692 // Render methods: |
|
693 |
|
694 /** |
|
695 * Renders the given $page as a link element, with $attrib = $relation |
|
696 * |
|
697 * @param Zend_Navigation_Page $page the page to render the link for |
|
698 * @param string $attrib the attribute to use for $type, |
|
699 * either 'rel' or 'rev' |
|
700 * @param string $relation relation type, muse be one of; |
|
701 * alternate, appendix, bookmark, |
|
702 * chapter, contents, copyright, |
|
703 * glossary, help, home, index, next, |
|
704 * prev, section, start, stylesheet, |
|
705 * subsection |
|
706 * @return string rendered link element |
|
707 * @throws Zend_View_Exception if $attrib is invalid |
|
708 */ |
|
709 public function renderLink(Zend_Navigation_Page $page, $attrib, $relation) |
|
710 { |
|
711 if (!in_array($attrib, array('rel', 'rev'))) { |
|
712 require_once 'Zend/View/Exception.php'; |
|
713 $e = new Zend_View_Exception(sprintf( |
|
714 'Invalid relation attribute "%s", must be "rel" or "rev"', |
|
715 $attrib)); |
|
716 $e->setView($this->view); |
|
717 throw $e; |
|
718 } |
|
719 |
|
720 if (!$href = $page->getHref()) { |
|
721 return ''; |
|
722 } |
|
723 |
|
724 // TODO: add more attribs |
|
725 // http://www.w3.org/TR/html401/struct/links.html#h-12.2 |
|
726 $attribs = array( |
|
727 $attrib => $relation, |
|
728 'href' => $href, |
|
729 'title' => $page->getLabel() |
|
730 ); |
|
731 |
|
732 return '<link' . |
|
733 $this->_htmlAttribs($attribs) . |
|
734 $this->getClosingBracket(); |
|
735 } |
|
736 |
|
737 // Zend_View_Helper_Navigation_Helper: |
|
738 |
|
739 /** |
|
740 * Renders helper |
|
741 * |
|
742 * Implements {@link Zend_View_Helper_Navigation_Helper::render()}. |
|
743 * |
|
744 * @param Zend_Navigation_Container $container [optional] container to |
|
745 * render. Default is to |
|
746 * render the container |
|
747 * registered in the helper. |
|
748 * @return string helper output |
|
749 */ |
|
750 public function render(Zend_Navigation_Container $container = null) |
|
751 { |
|
752 if (null === $container) { |
|
753 $container = $this->getContainer(); |
|
754 } |
|
755 |
|
756 if ($active = $this->findActive($container)) { |
|
757 $active = $active['page']; |
|
758 } else { |
|
759 // no active page |
|
760 return ''; |
|
761 } |
|
762 |
|
763 $output = ''; |
|
764 $indent = $this->getIndent(); |
|
765 $this->_root = $container; |
|
766 |
|
767 $result = $this->findAllRelations($active, $this->getRenderFlag()); |
|
768 foreach ($result as $attrib => $types) { |
|
769 foreach ($types as $relation => $pages) { |
|
770 foreach ($pages as $page) { |
|
771 if ($r = $this->renderLink($page, $attrib, $relation)) { |
|
772 $output .= $indent . $r . self::EOL; |
|
773 } |
|
774 } |
|
775 } |
|
776 } |
|
777 |
|
778 $this->_root = null; |
|
779 |
|
780 // return output (trim last newline by spec) |
|
781 return strlen($output) ? rtrim($output, self::EOL) : ''; |
|
782 } |
|
783 } |