File indexing completed on 2024-12-29 05:28:12

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_View
0017  * @subpackage Helper
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 /**
0024  * @see Zend_View_Helper_Navigation_HelperAbstract
0025  */
0026 // require_once 'Zend/View/Helper/Navigation/HelperAbstract.php';
0027 
0028 /**
0029  * Helper for printing <link> elements
0030  *
0031  * @category   Zend
0032  * @package    Zend_View
0033  * @subpackage Helper
0034  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0035  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0036  */
0037 class Zend_View_Helper_Navigation_Links
0038     extends Zend_View_Helper_Navigation_HelperAbstract
0039 {
0040     /**#@+
0041      * Constants used for specifying which link types to find and render
0042      *
0043      * @var int
0044      */
0045     const RENDER_ALTERNATE  = 0x0001;
0046     const RENDER_STYLESHEET = 0x0002;
0047     const RENDER_START      = 0x0004;
0048     const RENDER_NEXT       = 0x0008;
0049     const RENDER_PREV       = 0x0010;
0050     const RENDER_CONTENTS   = 0x0020;
0051     const RENDER_INDEX      = 0x0040;
0052     const RENDER_GLOSSARY   = 0x0080;
0053     const RENDER_COPYRIGHT  = 0x0100;
0054     const RENDER_CHAPTER    = 0x0200;
0055     const RENDER_SECTION    = 0x0400;
0056     const RENDER_SUBSECTION = 0x0800;
0057     const RENDER_APPENDIX   = 0x1000;
0058     const RENDER_HELP       = 0x2000;
0059     const RENDER_BOOKMARK   = 0x4000;
0060     const RENDER_CUSTOM     = 0x8000;
0061     const RENDER_ALL        = 0xffff;
0062     /**#@+**/
0063 
0064     /**
0065      * Maps render constants to W3C link types
0066      *
0067      * @var array
0068      */
0069     protected static $_RELATIONS = array(
0070         self::RENDER_ALTERNATE  => 'alternate',
0071         self::RENDER_STYLESHEET => 'stylesheet',
0072         self::RENDER_START      => 'start',
0073         self::RENDER_NEXT       => 'next',
0074         self::RENDER_PREV       => 'prev',
0075         self::RENDER_CONTENTS   => 'contents',
0076         self::RENDER_INDEX      => 'index',
0077         self::RENDER_GLOSSARY   => 'glossary',
0078         self::RENDER_COPYRIGHT  => 'copyright',
0079         self::RENDER_CHAPTER    => 'chapter',
0080         self::RENDER_SECTION    => 'section',
0081         self::RENDER_SUBSECTION => 'subsection',
0082         self::RENDER_APPENDIX   => 'appendix',
0083         self::RENDER_HELP       => 'help',
0084         self::RENDER_BOOKMARK   => 'bookmark'
0085     );
0086 
0087     /**
0088      * The helper's render flag
0089      *
0090      * @see render()
0091      * @see setRenderFlag()
0092      * @var int
0093      */
0094     protected $_renderFlag = self::RENDER_ALL;
0095 
0096     /**
0097      * Root container
0098      *
0099      * Used for preventing methods to traverse above the container given to
0100      * the {@link render()} method.
0101      *
0102      * @see _findRoot()
0103      *
0104      * @var Zend_Navigation_Container
0105      */
0106     protected $_root;
0107 
0108     /**
0109      * View helper entry point:
0110      * Retrieves helper and optionally sets container to operate on
0111      *
0112      * @param  Zend_Navigation_Container $container  [optional] container to
0113      *                                               operate on
0114      * @return Zend_View_Helper_Navigation_Links     fluent interface, returns
0115      *                                               self
0116      */
0117     public function links(Zend_Navigation_Container $container = null)
0118     {
0119         if (null !== $container) {
0120             $this->setContainer($container);
0121         }
0122 
0123         return $this;
0124     }
0125 
0126     /**
0127      * Magic overload: Proxy calls to {@link findRelation()} or container
0128      *
0129      * Examples of finder calls:
0130      * <code>
0131      * // METHOD                  // SAME AS
0132      * $h->findRelNext($page);    // $h->findRelation($page, 'rel', 'next')
0133      * $h->findRevSection($page); // $h->findRelation($page, 'rev', 'section');
0134      * $h->findRelFoo($page);     // $h->findRelation($page, 'rel', 'foo');
0135      * </code>
0136      *
0137      * @param  string $method             method name
0138      * @param  array  $arguments          method arguments
0139      * @throws Zend_Navigation_Exception  if method does not exist in container
0140      */
0141     public function __call($method, array $arguments = array())
0142     {
0143         if (@preg_match('/find(Rel|Rev)(.+)/', $method, $match)) {
0144             return $this->findRelation($arguments[0],
0145                                        strtolower($match[1]),
0146                                        strtolower($match[2]));
0147         }
0148 
0149         return parent::__call($method, $arguments);
0150     }
0151 
0152     // Accessors:
0153 
0154     /**
0155      * Sets the helper's render flag
0156      *
0157      * The helper uses the bitwise '&' operator against the hex values of the
0158      * render constants. This means that the flag can is "bitwised" value of
0159      * the render constants. Examples:
0160      * <code>
0161      * // render all links except glossary
0162      * $flag = Zend_View_Helper_Navigation_Links:RENDER_ALL ^
0163      *         Zend_View_Helper_Navigation_Links:RENDER_GLOSSARY;
0164      * $helper->setRenderFlag($flag);
0165      *
0166      * // render only chapters and sections
0167      * $flag = Zend_View_Helper_Navigation_Links:RENDER_CHAPTER |
0168      *         Zend_View_Helper_Navigation_Links:RENDER_SECTION;
0169      * $helper->setRenderFlag($flag);
0170      *
0171      * // render only relations that are not native W3C relations
0172      * $helper->setRenderFlag(Zend_View_Helper_Navigation_Links:RENDER_CUSTOM);
0173      *
0174      * // render all relations (default)
0175      * $helper->setRenderFlag(Zend_View_Helper_Navigation_Links:RENDER_ALL);
0176      * </code>
0177      *
0178      * Note that custom relations can also be rendered directly using the
0179      * {@link renderLink()} method.
0180      *
0181      * @param  int $renderFlag                    render flag
0182      * @return Zend_View_Helper_Navigation_Links  fluent interface, returns self
0183      */
0184     public function setRenderFlag($renderFlag)
0185     {
0186         $this->_renderFlag = (int) $renderFlag;
0187         return $this;
0188     }
0189 
0190     /**
0191      * Returns the helper's render flag
0192      *
0193      * @return int  render flag
0194      */
0195     public function getRenderFlag()
0196     {
0197         return $this->_renderFlag;
0198     }
0199 
0200     // Finder methods:
0201 
0202     /**
0203      * Finds all relations (forward and reverse) for the given $page
0204      *
0205      * The form of the returned array:
0206      * <code>
0207      * // $page denotes an instance of Zend_Navigation_Page
0208      * $returned = array(
0209      *     'rel' => array(
0210      *         'alternate' => array($page, $page, $page),
0211      *         'start'     => array($page),
0212      *         'next'      => array($page),
0213      *         'prev'      => array($page),
0214      *         'canonical' => array($page)
0215      *     ),
0216      *     'rev' => array(
0217      *         'section'   => array($page)
0218      *     )
0219      * );
0220      * </code>
0221      *
0222      * @param  Zend_Navigation_Page $page  page to find links for
0223      * @return array                       related pages
0224      */
0225     public function findAllRelations(Zend_Navigation_Page $page,
0226                                      $flag = null)
0227     {
0228         if (!is_int($flag)) {
0229             $flag = self::RENDER_ALL;
0230         }
0231 
0232         $result = array('rel' => array(), 'rev' => array());
0233         $native = array_values(self::$_RELATIONS);
0234 
0235         foreach (array_keys($result) as $rel) {
0236             $meth = 'getDefined' . ucfirst($rel);
0237             $types = array_merge($native, array_diff($page->$meth(), $native));
0238 
0239             foreach ($types as $type) {
0240                 if (!$relFlag = array_search($type, self::$_RELATIONS)) {
0241                     $relFlag = self::RENDER_CUSTOM;
0242                 }
0243                 if (!($flag & $relFlag)) {
0244                     continue;
0245                 }
0246                 if ($found = $this->findRelation($page, $rel, $type)) {
0247                     if (!is_array($found)) {
0248                         $found = array($found);
0249                     }
0250                     $result[$rel][$type] = $found;
0251                 }
0252             }
0253         }
0254 
0255         return $result;
0256     }
0257 
0258     /**
0259      * Finds relations of the given $rel=$type from $page
0260      *
0261      * This method will first look for relations in the page instance, then
0262      * by searching the root container if nothing was found in the page.
0263      *
0264      * @param  Zend_Navigation_Page $page       page to find relations for
0265      * @param  string              $rel         relation, "rel" or "rev"
0266      * @param  string              $type        link type, e.g. 'start', 'next'
0267      * @return Zend_Navigaiton_Page|array|null  page(s), or null if not found
0268      * @throws Zend_View_Exception              if $rel is not "rel" or "rev"
0269      */
0270     public function findRelation(Zend_Navigation_Page $page, $rel, $type)
0271     {
0272         if (!in_array($rel, array('rel', 'rev'))) {
0273             // require_once 'Zend/View/Exception.php';
0274             $e = new Zend_View_Exception(sprintf(
0275                 'Invalid argument: $rel must be "rel" or "rev"; "%s" given',
0276                 $rel));
0277             $e->setView($this->view);
0278             throw $e;
0279         }
0280 
0281         if (!$result = $this->_findFromProperty($page, $rel, $type)) {
0282             $result = $this->_findFromSearch($page, $rel, $type);
0283         }
0284 
0285         return $result;
0286     }
0287 
0288     /**
0289      * Finds relations of given $type for $page by checking if the
0290      * relation is specified as a property of $page
0291      *
0292      * @param  Zend_Navigation_Page $page       page to find relations for
0293      * @param  string              $rel         relation, 'rel' or 'rev'
0294      * @param  string              $type        link type, e.g. 'start', 'next'
0295      * @return Zend_Navigation_Page|array|null  page(s), or null if not found
0296      */
0297     protected function _findFromProperty(Zend_Navigation_Page $page, $rel, $type)
0298     {
0299         $method = 'get' . ucfirst($rel);
0300         if ($result = $page->$method($type)) {
0301             if ($result = $this->_convertToPages($result)) {
0302                 if (!is_array($result)) {
0303                     $result = array($result);
0304                 }
0305 
0306                 foreach ($result as $key => $page) {
0307                     if (!$this->accept($page)) {
0308                         unset($result[$key]);
0309                     }
0310                 }
0311 
0312                 return count($result) == 1 ? $result[0] : $result;
0313             }
0314         }
0315 
0316         return null;
0317     }
0318 
0319     /**
0320      * Finds relations of given $rel=$type for $page by using the helper to
0321      * search for the relation in the root container
0322      *
0323      * @param  Zend_Navigation_Page $page  page to find relations for
0324      * @param  string              $rel    relation, 'rel' or 'rev'
0325      * @param  string              $type   link type, e.g. 'start', 'next', etc
0326      * @return array|null                  array of pages, or null if not found
0327      */
0328     protected function _findFromSearch(Zend_Navigation_Page $page, $rel, $type)
0329     {
0330         $found = null;
0331 
0332         $method = 'search' . ucfirst($rel) . ucfirst($type);
0333         if (method_exists($this, $method)) {
0334             $found = $this->$method($page);
0335         }
0336 
0337         return $found;
0338     }
0339 
0340     // Search methods:
0341 
0342     /**
0343      * Searches the root container for the forward 'start' relation of the given
0344      * $page
0345      *
0346      * From {@link http://www.w3.org/TR/html4/types.html#type-links}:
0347      * Refers to the first document in a collection of documents. This link type
0348      * tells search engines which document is considered by the author to be the
0349      * starting point of the collection.
0350      *
0351      * @param  Zend_Navigation_Page $page  page to find relation for
0352      * @return Zend_Navigation_Page|null   page or null
0353      */
0354     public function searchRelStart(Zend_Navigation_Page $page)
0355     {
0356         $found = $this->_findRoot($page);
0357         if (!$found instanceof Zend_Navigation_Page) {
0358             $found->rewind();
0359             $found = $found->current();
0360         }
0361 
0362         if ($found === $page || !$this->accept($found)) {
0363             $found = null;
0364         }
0365 
0366         return $found;
0367     }
0368 
0369     /**
0370      * Searches the root container for the forward 'next' relation of the given
0371      * $page
0372      *
0373      * From {@link http://www.w3.org/TR/html4/types.html#type-links}:
0374      * Refers to the next document in a linear sequence of documents. User
0375      * agents may choose to preload the "next" document, to reduce the perceived
0376      * load time.
0377      *
0378      * @param  Zend_Navigation_Page $page  page to find relation for
0379      * @return Zend_Navigation_Page|null   page(s) or null
0380      */
0381     public function searchRelNext(Zend_Navigation_Page $page)
0382     {
0383         $found = null;
0384         $break = false;
0385         $iterator = new RecursiveIteratorIterator($this->_findRoot($page),
0386                 RecursiveIteratorIterator::SELF_FIRST);
0387         foreach ($iterator as $intermediate) {
0388             if ($intermediate === $page) {
0389                 // current page; break at next accepted page
0390                 $break = true;
0391                 continue;
0392             }
0393 
0394             if ($break && $this->accept($intermediate)) {
0395                 $found = $intermediate;
0396                 break;
0397             }
0398         }
0399 
0400         return $found;
0401     }
0402 
0403     /**
0404      * Searches the root container for the forward 'prev' relation of the given
0405      * $page
0406      *
0407      * From {@link http://www.w3.org/TR/html4/types.html#type-links}:
0408      * Refers to the previous document in an ordered series of documents. Some
0409      * user agents also support the synonym "Previous".
0410      *
0411      * @param  Zend_Navigation_Page $page  page to find relation for
0412      * @return Zend_Navigation_Page|null   page or null
0413      */
0414     public function searchRelPrev(Zend_Navigation_Page $page)
0415     {
0416         $found = null;
0417         $prev = null;
0418         $iterator = new RecursiveIteratorIterator(
0419                 $this->_findRoot($page),
0420                 RecursiveIteratorIterator::SELF_FIRST);
0421         foreach ($iterator as $intermediate) {
0422             if (!$this->accept($intermediate)) {
0423                 continue;
0424             }
0425             if ($intermediate === $page) {
0426                 $found = $prev;
0427                 break;
0428             }
0429 
0430             $prev = $intermediate;
0431         }
0432 
0433         return $found;
0434     }
0435 
0436     /**
0437      * Searches the root container for forward 'chapter' relations of the given
0438      * $page
0439      *
0440      * From {@link http://www.w3.org/TR/html4/types.html#type-links}:
0441      * Refers to a document serving as a chapter in a collection of documents.
0442      *
0443      * @param  Zend_Navigation_Page $page       page to find relation for
0444      * @return Zend_Navigation_Page|array|null  page(s) or null
0445      */
0446     public function searchRelChapter(Zend_Navigation_Page $page)
0447     {
0448         $found = array();
0449 
0450         // find first level of pages
0451         $root = $this->_findRoot($page);
0452 
0453         // find start page(s)
0454         $start = $this->findRelation($page, 'rel', 'start');
0455         if (!is_array($start)) {
0456             $start = array($start);
0457         }
0458 
0459         foreach ($root as $chapter) {
0460             // exclude self and start page from chapters
0461             if ($chapter !== $page &&
0462                 !in_array($chapter, $start) &&
0463                 $this->accept($chapter)) {
0464                 $found[] = $chapter;
0465             }
0466         }
0467 
0468         switch (count($found)) {
0469             case 0:
0470                 return null;
0471             case 1:
0472                 return $found[0];
0473             default:
0474                 return $found;
0475         }
0476     }
0477 
0478     /**
0479      * Searches the root container for forward 'section' relations of the given
0480      * $page
0481      *
0482      * From {@link http://www.w3.org/TR/html4/types.html#type-links}:
0483      * Refers to a document serving as a section in a collection of documents.
0484      *
0485      * @param  Zend_Navigation_Page $page       page to find relation for
0486      * @return Zend_Navigation_Page|array|null  page(s) or null
0487      */
0488     public function searchRelSection(Zend_Navigation_Page $page)
0489     {
0490         $found = array();
0491 
0492         // check if given page has pages and is a chapter page
0493         if ($page->hasPages() && $this->_findRoot($page)->hasPage($page)) {
0494             foreach ($page as $section) {
0495                 if ($this->accept($section)) {
0496                     $found[] = $section;
0497                 }
0498             }
0499         }
0500 
0501         switch (count($found)) {
0502             case 0:
0503                 return null;
0504             case 1:
0505                 return $found[0];
0506             default:
0507                 return $found;
0508         }
0509     }
0510 
0511     /**
0512      * Searches the root container for forward 'subsection' relations of the
0513      * given $page
0514      *
0515      * From {@link http://www.w3.org/TR/html4/types.html#type-links}:
0516      * Refers to a document serving as a subsection in a collection of
0517      * documents.
0518      *
0519      * @param  Zend_Navigation_Page $page       page to find relation for
0520      * @return Zend_Navigation_Page|array|null  page(s) or null
0521      */
0522     public function searchRelSubsection(Zend_Navigation_Page $page)
0523     {
0524         $found = array();
0525 
0526         if ($page->hasPages()) {
0527             // given page has child pages, loop chapters
0528             foreach ($this->_findRoot($page) as $chapter) {
0529                 // is page a section?
0530                 if ($chapter->hasPage($page)) {
0531                     foreach ($page as $subsection) {
0532                         if ($this->accept($subsection)) {
0533                             $found[] = $subsection;
0534                         }
0535                     }
0536                 }
0537             }
0538         }
0539 
0540         switch (count($found)) {
0541             case 0:
0542                 return null;
0543             case 1:
0544                 return $found[0];
0545             default:
0546                 return $found;
0547         }
0548     }
0549 
0550     /**
0551      * Searches the root container for the reverse 'section' relation of the
0552      * given $page
0553      *
0554      * From {@link http://www.w3.org/TR/html4/types.html#type-links}:
0555      * Refers to a document serving as a section in a collection of documents.
0556      *
0557      * @param  Zend_Navigation_Page $page  page to find relation for
0558      * @return Zend_Navigation_Page|null   page(s) or null
0559      */
0560     public function searchRevSection(Zend_Navigation_Page $page)
0561     {
0562         $found = null;
0563 
0564         if ($parent = $page->getParent()) {
0565             if ($parent instanceof Zend_Navigation_Page &&
0566                 $this->_findRoot($page)->hasPage($parent)) {
0567                 $found = $parent;
0568             }
0569         }
0570 
0571         return $found;
0572     }
0573 
0574     /**
0575      * Searches the root container for the reverse 'section' relation of the
0576      * given $page
0577      *
0578      * From {@link http://www.w3.org/TR/html4/types.html#type-links}:
0579      * Refers to a document serving as a subsection in a collection of
0580      * documents.
0581      *
0582      * @param  Zend_Navigation_Page $page  page to find relation for
0583      * @return Zend_Navigation_Page|null   page(s) or null
0584      */
0585     public function searchRevSubsection(Zend_Navigation_Page $page)
0586     {
0587         $found = null;
0588 
0589         if ($parent = $page->getParent()) {
0590             if ($parent instanceof Zend_Navigation_Page) {
0591                 $root = $this->_findRoot($page);
0592                 foreach ($root as $chapter) {
0593                     if ($chapter->hasPage($parent)) {
0594                         $found = $parent;
0595                         break;
0596                     }
0597                 }
0598             }
0599         }
0600 
0601         return $found;
0602     }
0603 
0604     // Util methods:
0605 
0606     /**
0607      * Returns the root container of the given page
0608      *
0609      * When rendering a container, the render method still store the given
0610      * container as the root container, and unset it when done rendering. This
0611      * makes sure finder methods will not traverse above the container given
0612      * to the render method.
0613      *
0614      * @param  Zend_Navigaiton_Page $page  page to find root for
0615      * @return Zend_Navigation_Container   the root container of the given page
0616      */
0617     protected function _findRoot(Zend_Navigation_Page $page)
0618     {
0619         if ($this->_root) {
0620             return $this->_root;
0621         }
0622 
0623         $root = $page;
0624 
0625         while ($parent = $page->getParent()) {
0626             $root = $parent;
0627             if ($parent instanceof Zend_Navigation_Page) {
0628                 $page = $parent;
0629             } else {
0630                 break;
0631             }
0632         }
0633 
0634         return $root;
0635     }
0636 
0637     /**
0638      * Converts a $mixed value to an array of pages
0639      *
0640      * @param  mixed $mixed                     mixed value to get page(s) from
0641      * @param  bool  $recursive                 whether $value should be looped
0642      *                                          if it is an array or a config
0643      * @return Zend_Navigation_Page|array|null  empty if unable to convert
0644      */
0645     protected function _convertToPages($mixed, $recursive = true)
0646     {
0647         if (is_object($mixed)) {
0648             if ($mixed instanceof Zend_Navigation_Page) {
0649                 // value is a page instance; return directly
0650                 return $mixed;
0651             } elseif ($mixed instanceof Zend_Navigation_Container) {
0652                 // value is a container; return pages in it
0653                 $pages = array();
0654                 foreach ($mixed as $page) {
0655                     $pages[] = $page;
0656                 }
0657                 return $pages;
0658             } elseif ($mixed instanceof Zend_Config) {
0659                 // convert config object to array and extract
0660                 return $this->_convertToPages($mixed->toArray(), $recursive);
0661             }
0662         } elseif (is_string($mixed)) {
0663             // value is a string; make an URI page
0664             return Zend_Navigation_Page::factory(array(
0665                 'type' => 'uri',
0666                 'uri'  => $mixed
0667             ));
0668         } elseif (is_array($mixed) && !empty($mixed)) {
0669             if ($recursive && is_numeric(key($mixed))) {
0670                 // first key is numeric; assume several pages
0671                 $pages = array();
0672                 foreach ($mixed as $value) {
0673                     if ($value = $this->_convertToPages($value, false)) {
0674                         $pages[] = $value;
0675                     }
0676                 }
0677                 return $pages;
0678             } else {
0679                 // pass array to factory directly
0680                 try {
0681                     $page = Zend_Navigation_Page::factory($mixed);
0682                     return $page;
0683                 } catch (Exception $e) {
0684                 }
0685             }
0686         }
0687 
0688         // nothing found
0689         return null;
0690     }
0691 
0692     // Render methods:
0693 
0694     /**
0695      * Renders the given $page as a link element, with $attrib = $relation
0696      *
0697      * @param  Zend_Navigation_Page $page      the page to render the link for
0698      * @param  string               $attrib    the attribute to use for $type,
0699      *                                         either 'rel' or 'rev'
0700      * @param  string               $relation  relation type, muse be one of;
0701      *                                         alternate, appendix, bookmark,
0702      *                                         chapter, contents, copyright,
0703      *                                         glossary, help, home, index, next,
0704      *                                         prev, section, start, stylesheet,
0705      *                                         subsection
0706      * @return string                          rendered link element
0707      * @throws Zend_View_Exception             if $attrib is invalid
0708      */
0709     public function renderLink(Zend_Navigation_Page $page, $attrib, $relation)
0710     {
0711         if (!in_array($attrib, array('rel', 'rev'))) {
0712             // require_once 'Zend/View/Exception.php';
0713             $e = new Zend_View_Exception(sprintf(
0714                     'Invalid relation attribute "%s", must be "rel" or "rev"',
0715                     $attrib));
0716             $e->setView($this->view);
0717             throw $e;
0718         }
0719 
0720         if (!$href = $page->getHref()) {
0721             return '';
0722         }
0723 
0724         // TODO: add more attribs
0725         // http://www.w3.org/TR/html401/struct/links.html#h-12.2
0726         $attribs = array(
0727             $attrib  => $relation,
0728             'href'   => $href,
0729             'title'  => $page->getLabel()
0730         );
0731 
0732         return '<link' .
0733                $this->_htmlAttribs($attribs) .
0734                $this->getClosingBracket();
0735     }
0736 
0737     // Zend_View_Helper_Navigation_Helper:
0738 
0739     /**
0740      * Renders helper
0741      *
0742      * Implements {@link Zend_View_Helper_Navigation_Helper::render()}.
0743      *
0744      * @param  Zend_Navigation_Container $container  [optional] container to
0745      *                                               render. Default is to
0746      *                                               render the container
0747      *                                               registered in the helper.
0748      * @return string                                helper output
0749      */
0750     public function render(Zend_Navigation_Container $container = null)
0751     {
0752         if (null === $container) {
0753             $container = $this->getContainer();
0754         }
0755 
0756         if ($active = $this->findActive($container)) {
0757             $active = $active['page'];
0758         } else {
0759             // no active page
0760             return '';
0761         }
0762 
0763         $output = '';
0764         $indent = $this->getIndent();
0765         $this->_root = $container;
0766 
0767         $result = $this->findAllRelations($active, $this->getRenderFlag());
0768         foreach ($result as $attrib => $types) {
0769             foreach ($types as $relation => $pages) {
0770                 foreach ($pages as $page) {
0771                     if ($r = $this->renderLink($page, $attrib, $relation)) {
0772                         $output .= $indent . $r . $this->getEOL();
0773                     }
0774                 }
0775             }
0776         }
0777 
0778         $this->_root = null;
0779 
0780         // return output (trim last newline by spec)
0781         return strlen($output) ? rtrim($output, self::EOL) : '';
0782     }
0783 }