784 Zeilen
26 KiB
PHP
784 Zeilen
26 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Zend Framework
|
||
|
*
|
||
|
* LICENSE
|
||
|
*
|
||
|
* This source file is subject to the new BSD license that is bundled
|
||
|
* with this package in the file LICENSE.txt.
|
||
|
* It is also available through the world-wide-web at this URL:
|
||
|
* http://framework.zend.com/license/new-bsd
|
||
|
* If you did not receive a copy of the license and are unable to
|
||
|
* obtain it through the world-wide-web, please send an email
|
||
|
* to license@zend.com so we can send you a copy immediately.
|
||
|
*
|
||
|
* @category Zend
|
||
|
* @package Zend_View
|
||
|
* @subpackage Helper
|
||
|
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||
|
* @version $Id$
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @see Zend_View_Helper_Navigation_HelperAbstract
|
||
|
*/
|
||
|
require_once 'Zend/View/Helper/Navigation/HelperAbstract.php';
|
||
|
|
||
|
/**
|
||
|
* Helper for printing <link> elements
|
||
|
*
|
||
|
* @category Zend
|
||
|
* @package Zend_View
|
||
|
* @subpackage Helper
|
||
|
* @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
|
||
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||
|
*/
|
||
|
class Zend_View_Helper_Navigation_Links
|
||
|
extends Zend_View_Helper_Navigation_HelperAbstract
|
||
|
{
|
||
|
/**#@+
|
||
|
* Constants used for specifying which link types to find and render
|
||
|
*
|
||
|
* @var int
|
||
|
*/
|
||
|
const RENDER_ALTERNATE = 0x0001;
|
||
|
const RENDER_STYLESHEET = 0x0002;
|
||
|
const RENDER_START = 0x0004;
|
||
|
const RENDER_NEXT = 0x0008;
|
||
|
const RENDER_PREV = 0x0010;
|
||
|
const RENDER_CONTENTS = 0x0020;
|
||
|
const RENDER_INDEX = 0x0040;
|
||
|
const RENDER_GLOSSARY = 0x0080;
|
||
|
const RENDER_COPYRIGHT = 0x0100;
|
||
|
const RENDER_CHAPTER = 0x0200;
|
||
|
const RENDER_SECTION = 0x0400;
|
||
|
const RENDER_SUBSECTION = 0x0800;
|
||
|
const RENDER_APPENDIX = 0x1000;
|
||
|
const RENDER_HELP = 0x2000;
|
||
|
const RENDER_BOOKMARK = 0x4000;
|
||
|
const RENDER_CUSTOM = 0x8000;
|
||
|
const RENDER_ALL = 0xffff;
|
||
|
/**#@+**/
|
||
|
|
||
|
/**
|
||
|
* Maps render constants to W3C link types
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected static $_RELATIONS = array(
|
||
|
self::RENDER_ALTERNATE => 'alternate',
|
||
|
self::RENDER_STYLESHEET => 'stylesheet',
|
||
|
self::RENDER_START => 'start',
|
||
|
self::RENDER_NEXT => 'next',
|
||
|
self::RENDER_PREV => 'prev',
|
||
|
self::RENDER_CONTENTS => 'contents',
|
||
|
self::RENDER_INDEX => 'index',
|
||
|
self::RENDER_GLOSSARY => 'glossary',
|
||
|
self::RENDER_COPYRIGHT => 'copyright',
|
||
|
self::RENDER_CHAPTER => 'chapter',
|
||
|
self::RENDER_SECTION => 'section',
|
||
|
self::RENDER_SUBSECTION => 'subsection',
|
||
|
self::RENDER_APPENDIX => 'appendix',
|
||
|
self::RENDER_HELP => 'help',
|
||
|
self::RENDER_BOOKMARK => 'bookmark'
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* The helper's render flag
|
||
|
*
|
||
|
* @see render()
|
||
|
* @see setRenderFlag()
|
||
|
* @var int
|
||
|
*/
|
||
|
protected $_renderFlag = self::RENDER_ALL;
|
||
|
|
||
|
/**
|
||
|
* Root container
|
||
|
*
|
||
|
* Used for preventing methods to traverse above the container given to
|
||
|
* the {@link render()} method.
|
||
|
*
|
||
|
* @see _findRoot()
|
||
|
*
|
||
|
* @var Zend_Navigation_Container
|
||
|
*/
|
||
|
protected $_root;
|
||
|
|
||
|
/**
|
||
|
* View helper entry point:
|
||
|
* Retrieves helper and optionally sets container to operate on
|
||
|
*
|
||
|
* @param Zend_Navigation_Container $container [optional] container to
|
||
|
* operate on
|
||
|
* @return Zend_View_Helper_Navigation_Links fluent interface, returns
|
||
|
* self
|
||
|
*/
|
||
|
public function links(Zend_Navigation_Container $container = null)
|
||
|
{
|
||
|
if (null !== $container) {
|
||
|
$this->setContainer($container);
|
||
|
}
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Magic overload: Proxy calls to {@link findRelation()} or container
|
||
|
*
|
||
|
* Examples of finder calls:
|
||
|
* <code>
|
||
|
* // METHOD // SAME AS
|
||
|
* $h->findRelNext($page); // $h->findRelation($page, 'rel', 'next')
|
||
|
* $h->findRevSection($page); // $h->findRelation($page, 'rev', 'section');
|
||
|
* $h->findRelFoo($page); // $h->findRelation($page, 'rel', 'foo');
|
||
|
* </code>
|
||
|
*
|
||
|
* @param string $method method name
|
||
|
* @param array $arguments method arguments
|
||
|
* @throws Zend_Navigation_Exception if method does not exist in container
|
||
|
*/
|
||
|
public function __call($method, array $arguments = array())
|
||
|
{
|
||
|
if (@preg_match('/find(Rel|Rev)(.+)/', $method, $match)) {
|
||
|
return $this->findRelation($arguments[0],
|
||
|
strtolower($match[1]),
|
||
|
strtolower($match[2]));
|
||
|
}
|
||
|
|
||
|
return parent::__call($method, $arguments);
|
||
|
}
|
||
|
|
||
|
// Accessors:
|
||
|
|
||
|
/**
|
||
|
* Sets the helper's render flag
|
||
|
*
|
||
|
* The helper uses the bitwise '&' operator against the hex values of the
|
||
|
* render constants. This means that the flag can is "bitwised" value of
|
||
|
* the render constants. Examples:
|
||
|
* <code>
|
||
|
* // render all links except glossary
|
||
|
* $flag = Zend_View_Helper_Navigation_Links:RENDER_ALL ^
|
||
|
* Zend_View_Helper_Navigation_Links:RENDER_GLOSSARY;
|
||
|
* $helper->setRenderFlag($flag);
|
||
|
*
|
||
|
* // render only chapters and sections
|
||
|
* $flag = Zend_View_Helper_Navigation_Links:RENDER_CHAPTER |
|
||
|
* Zend_View_Helper_Navigation_Links:RENDER_SECTION;
|
||
|
* $helper->setRenderFlag($flag);
|
||
|
*
|
||
|
* // render only relations that are not native W3C relations
|
||
|
* $helper->setRenderFlag(Zend_View_Helper_Navigation_Links:RENDER_CUSTOM);
|
||
|
*
|
||
|
* // render all relations (default)
|
||
|
* $helper->setRenderFlag(Zend_View_Helper_Navigation_Links:RENDER_ALL);
|
||
|
* </code>
|
||
|
*
|
||
|
* Note that custom relations can also be rendered directly using the
|
||
|
* {@link renderLink()} method.
|
||
|
*
|
||
|
* @param int $renderFlag render flag
|
||
|
* @return Zend_View_Helper_Navigation_Links fluent interface, returns self
|
||
|
*/
|
||
|
public function setRenderFlag($renderFlag)
|
||
|
{
|
||
|
$this->_renderFlag = (int) $renderFlag;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the helper's render flag
|
||
|
*
|
||
|
* @return int render flag
|
||
|
*/
|
||
|
public function getRenderFlag()
|
||
|
{
|
||
|
return $this->_renderFlag;
|
||
|
}
|
||
|
|
||
|
// Finder methods:
|
||
|
|
||
|
/**
|
||
|
* Finds all relations (forward and reverse) for the given $page
|
||
|
*
|
||
|
* The form of the returned array:
|
||
|
* <code>
|
||
|
* // $page denotes an instance of Zend_Navigation_Page
|
||
|
* $returned = array(
|
||
|
* 'rel' => array(
|
||
|
* 'alternate' => array($page, $page, $page),
|
||
|
* 'start' => array($page),
|
||
|
* 'next' => array($page),
|
||
|
* 'prev' => array($page),
|
||
|
* 'canonical' => array($page)
|
||
|
* ),
|
||
|
* 'rev' => array(
|
||
|
* 'section' => array($page)
|
||
|
* )
|
||
|
* );
|
||
|
* </code>
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find links for
|
||
|
* @return array related pages
|
||
|
*/
|
||
|
public function findAllRelations(Zend_Navigation_Page $page,
|
||
|
$flag = null)
|
||
|
{
|
||
|
if (!is_int($flag)) {
|
||
|
$flag = self::RENDER_ALL;
|
||
|
}
|
||
|
|
||
|
$result = array('rel' => array(), 'rev' => array());
|
||
|
$native = array_values(self::$_RELATIONS);
|
||
|
|
||
|
foreach (array_keys($result) as $rel) {
|
||
|
$meth = 'getDefined' . ucfirst($rel);
|
||
|
$types = array_merge($native, array_diff($page->$meth(), $native));
|
||
|
|
||
|
foreach ($types as $type) {
|
||
|
if (!$relFlag = array_search($type, self::$_RELATIONS)) {
|
||
|
$relFlag = self::RENDER_CUSTOM;
|
||
|
}
|
||
|
if (!($flag & $relFlag)) {
|
||
|
continue;
|
||
|
}
|
||
|
if ($found = $this->findRelation($page, $rel, $type)) {
|
||
|
if (!is_array($found)) {
|
||
|
$found = array($found);
|
||
|
}
|
||
|
$result[$rel][$type] = $found;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Finds relations of the given $rel=$type from $page
|
||
|
*
|
||
|
* This method will first look for relations in the page instance, then
|
||
|
* by searching the root container if nothing was found in the page.
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relations for
|
||
|
* @param string $rel relation, "rel" or "rev"
|
||
|
* @param string $type link type, e.g. 'start', 'next'
|
||
|
* @return Zend_Navigaiton_Page|array|null page(s), or null if not found
|
||
|
* @throws Zend_View_Exception if $rel is not "rel" or "rev"
|
||
|
*/
|
||
|
public function findRelation(Zend_Navigation_Page $page, $rel, $type)
|
||
|
{
|
||
|
if (!in_array($rel, array('rel', 'rev'))) {
|
||
|
require_once 'Zend/View/Exception.php';
|
||
|
$e = new Zend_View_Exception(sprintf(
|
||
|
'Invalid argument: $rel must be "rel" or "rev"; "%s" given',
|
||
|
$rel));
|
||
|
$e->setView($this->view);
|
||
|
throw $e;
|
||
|
}
|
||
|
|
||
|
if (!$result = $this->_findFromProperty($page, $rel, $type)) {
|
||
|
$result = $this->_findFromSearch($page, $rel, $type);
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Finds relations of given $type for $page by checking if the
|
||
|
* relation is specified as a property of $page
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relations for
|
||
|
* @param string $rel relation, 'rel' or 'rev'
|
||
|
* @param string $type link type, e.g. 'start', 'next'
|
||
|
* @return Zend_Navigation_Page|array|null page(s), or null if not found
|
||
|
*/
|
||
|
protected function _findFromProperty(Zend_Navigation_Page $page, $rel, $type)
|
||
|
{
|
||
|
$method = 'get' . ucfirst($rel);
|
||
|
if ($result = $page->$method($type)) {
|
||
|
if ($result = $this->_convertToPages($result)) {
|
||
|
if (!is_array($result)) {
|
||
|
$result = array($result);
|
||
|
}
|
||
|
|
||
|
foreach ($result as $key => $page) {
|
||
|
if (!$this->accept($page)) {
|
||
|
unset($result[$key]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return count($result) == 1 ? $result[0] : $result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Finds relations of given $rel=$type for $page by using the helper to
|
||
|
* search for the relation in the root container
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relations for
|
||
|
* @param string $rel relation, 'rel' or 'rev'
|
||
|
* @param string $type link type, e.g. 'start', 'next', etc
|
||
|
* @return array|null array of pages, or null if not found
|
||
|
*/
|
||
|
protected function _findFromSearch(Zend_Navigation_Page $page, $rel, $type)
|
||
|
{
|
||
|
$found = null;
|
||
|
|
||
|
$method = 'search' . ucfirst($rel) . ucfirst($type);
|
||
|
if (method_exists($this, $method)) {
|
||
|
$found = $this->$method($page);
|
||
|
}
|
||
|
|
||
|
return $found;
|
||
|
}
|
||
|
|
||
|
// Search methods:
|
||
|
|
||
|
/**
|
||
|
* Searches the root container for the forward 'start' relation of the given
|
||
|
* $page
|
||
|
*
|
||
|
* From {@link http://www.w3.org/TR/html4/types.html#type-links}:
|
||
|
* Refers to the first document in a collection of documents. This link type
|
||
|
* tells search engines which document is considered by the author to be the
|
||
|
* starting point of the collection.
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relation for
|
||
|
* @return Zend_Navigation_Page|null page or null
|
||
|
*/
|
||
|
public function searchRelStart(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
$found = $this->_findRoot($page);
|
||
|
if (!$found instanceof Zend_Navigation_Page) {
|
||
|
$found->rewind();
|
||
|
$found = $found->current();
|
||
|
}
|
||
|
|
||
|
if ($found === $page || !$this->accept($found)) {
|
||
|
$found = null;
|
||
|
}
|
||
|
|
||
|
return $found;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Searches the root container for the forward 'next' relation of the given
|
||
|
* $page
|
||
|
*
|
||
|
* From {@link http://www.w3.org/TR/html4/types.html#type-links}:
|
||
|
* Refers to the next document in a linear sequence of documents. User
|
||
|
* agents may choose to preload the "next" document, to reduce the perceived
|
||
|
* load time.
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relation for
|
||
|
* @return Zend_Navigation_Page|null page(s) or null
|
||
|
*/
|
||
|
public function searchRelNext(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
$found = null;
|
||
|
$break = false;
|
||
|
$iterator = new RecursiveIteratorIterator($this->_findRoot($page),
|
||
|
RecursiveIteratorIterator::SELF_FIRST);
|
||
|
foreach ($iterator as $intermediate) {
|
||
|
if ($intermediate === $page) {
|
||
|
// current page; break at next accepted page
|
||
|
$break = true;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ($break && $this->accept($intermediate)) {
|
||
|
$found = $intermediate;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $found;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Searches the root container for the forward 'prev' relation of the given
|
||
|
* $page
|
||
|
*
|
||
|
* From {@link http://www.w3.org/TR/html4/types.html#type-links}:
|
||
|
* Refers to the previous document in an ordered series of documents. Some
|
||
|
* user agents also support the synonym "Previous".
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relation for
|
||
|
* @return Zend_Navigation_Page|null page or null
|
||
|
*/
|
||
|
public function searchRelPrev(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
$found = null;
|
||
|
$prev = null;
|
||
|
$iterator = new RecursiveIteratorIterator(
|
||
|
$this->_findRoot($page),
|
||
|
RecursiveIteratorIterator::SELF_FIRST);
|
||
|
foreach ($iterator as $intermediate) {
|
||
|
if (!$this->accept($intermediate)) {
|
||
|
continue;
|
||
|
}
|
||
|
if ($intermediate === $page) {
|
||
|
$found = $prev;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
$prev = $intermediate;
|
||
|
}
|
||
|
|
||
|
return $found;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Searches the root container for forward 'chapter' relations of the given
|
||
|
* $page
|
||
|
*
|
||
|
* From {@link http://www.w3.org/TR/html4/types.html#type-links}:
|
||
|
* Refers to a document serving as a chapter in a collection of documents.
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relation for
|
||
|
* @return Zend_Navigation_Page|array|null page(s) or null
|
||
|
*/
|
||
|
public function searchRelChapter(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
$found = array();
|
||
|
|
||
|
// find first level of pages
|
||
|
$root = $this->_findRoot($page);
|
||
|
|
||
|
// find start page(s)
|
||
|
$start = $this->findRelation($page, 'rel', 'start');
|
||
|
if (!is_array($start)) {
|
||
|
$start = array($start);
|
||
|
}
|
||
|
|
||
|
foreach ($root as $chapter) {
|
||
|
// exclude self and start page from chapters
|
||
|
if ($chapter !== $page &&
|
||
|
!in_array($chapter, $start) &&
|
||
|
$this->accept($chapter)) {
|
||
|
$found[] = $chapter;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch (count($found)) {
|
||
|
case 0:
|
||
|
return null;
|
||
|
case 1:
|
||
|
return $found[0];
|
||
|
default:
|
||
|
return $found;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Searches the root container for forward 'section' relations of the given
|
||
|
* $page
|
||
|
*
|
||
|
* From {@link http://www.w3.org/TR/html4/types.html#type-links}:
|
||
|
* Refers to a document serving as a section in a collection of documents.
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relation for
|
||
|
* @return Zend_Navigation_Page|array|null page(s) or null
|
||
|
*/
|
||
|
public function searchRelSection(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
$found = array();
|
||
|
|
||
|
// check if given page has pages and is a chapter page
|
||
|
if ($page->hasPages() && $this->_findRoot($page)->hasPage($page)) {
|
||
|
foreach ($page as $section) {
|
||
|
if ($this->accept($section)) {
|
||
|
$found[] = $section;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch (count($found)) {
|
||
|
case 0:
|
||
|
return null;
|
||
|
case 1:
|
||
|
return $found[0];
|
||
|
default:
|
||
|
return $found;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Searches the root container for forward 'subsection' relations of the
|
||
|
* given $page
|
||
|
*
|
||
|
* From {@link http://www.w3.org/TR/html4/types.html#type-links}:
|
||
|
* Refers to a document serving as a subsection in a collection of
|
||
|
* documents.
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relation for
|
||
|
* @return Zend_Navigation_Page|array|null page(s) or null
|
||
|
*/
|
||
|
public function searchRelSubsection(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
$found = array();
|
||
|
|
||
|
if ($page->hasPages()) {
|
||
|
// given page has child pages, loop chapters
|
||
|
foreach ($this->_findRoot($page) as $chapter) {
|
||
|
// is page a section?
|
||
|
if ($chapter->hasPage($page)) {
|
||
|
foreach ($page as $subsection) {
|
||
|
if ($this->accept($subsection)) {
|
||
|
$found[] = $subsection;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch (count($found)) {
|
||
|
case 0:
|
||
|
return null;
|
||
|
case 1:
|
||
|
return $found[0];
|
||
|
default:
|
||
|
return $found;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Searches the root container for the reverse 'section' relation of the
|
||
|
* given $page
|
||
|
*
|
||
|
* From {@link http://www.w3.org/TR/html4/types.html#type-links}:
|
||
|
* Refers to a document serving as a section in a collection of documents.
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relation for
|
||
|
* @return Zend_Navigation_Page|null page(s) or null
|
||
|
*/
|
||
|
public function searchRevSection(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
$found = null;
|
||
|
|
||
|
if ($parent = $page->getParent()) {
|
||
|
if ($parent instanceof Zend_Navigation_Page &&
|
||
|
$this->_findRoot($page)->hasPage($parent)) {
|
||
|
$found = $parent;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $found;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Searches the root container for the reverse 'section' relation of the
|
||
|
* given $page
|
||
|
*
|
||
|
* From {@link http://www.w3.org/TR/html4/types.html#type-links}:
|
||
|
* Refers to a document serving as a subsection in a collection of
|
||
|
* documents.
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page page to find relation for
|
||
|
* @return Zend_Navigation_Page|null page(s) or null
|
||
|
*/
|
||
|
public function searchRevSubsection(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
$found = null;
|
||
|
|
||
|
if ($parent = $page->getParent()) {
|
||
|
if ($parent instanceof Zend_Navigation_Page) {
|
||
|
$root = $this->_findRoot($page);
|
||
|
foreach ($root as $chapter) {
|
||
|
if ($chapter->hasPage($parent)) {
|
||
|
$found = $parent;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $found;
|
||
|
}
|
||
|
|
||
|
// Util methods:
|
||
|
|
||
|
/**
|
||
|
* Returns the root container of the given page
|
||
|
*
|
||
|
* When rendering a container, the render method still store the given
|
||
|
* container as the root container, and unset it when done rendering. This
|
||
|
* makes sure finder methods will not traverse above the container given
|
||
|
* to the render method.
|
||
|
*
|
||
|
* @param Zend_Navigaiton_Page $page page to find root for
|
||
|
* @return Zend_Navigation_Container the root container of the given page
|
||
|
*/
|
||
|
protected function _findRoot(Zend_Navigation_Page $page)
|
||
|
{
|
||
|
if ($this->_root) {
|
||
|
return $this->_root;
|
||
|
}
|
||
|
|
||
|
$root = $page;
|
||
|
|
||
|
while ($parent = $page->getParent()) {
|
||
|
$root = $parent;
|
||
|
if ($parent instanceof Zend_Navigation_Page) {
|
||
|
$page = $parent;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $root;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Converts a $mixed value to an array of pages
|
||
|
*
|
||
|
* @param mixed $mixed mixed value to get page(s) from
|
||
|
* @param bool $recursive whether $value should be looped
|
||
|
* if it is an array or a config
|
||
|
* @return Zend_Navigation_Page|array|null empty if unable to convert
|
||
|
*/
|
||
|
protected function _convertToPages($mixed, $recursive = true)
|
||
|
{
|
||
|
if (is_object($mixed)) {
|
||
|
if ($mixed instanceof Zend_Navigation_Page) {
|
||
|
// value is a page instance; return directly
|
||
|
return $mixed;
|
||
|
} elseif ($mixed instanceof Zend_Navigation_Container) {
|
||
|
// value is a container; return pages in it
|
||
|
$pages = array();
|
||
|
foreach ($mixed as $page) {
|
||
|
$pages[] = $page;
|
||
|
}
|
||
|
return $pages;
|
||
|
} elseif ($mixed instanceof Zend_Config) {
|
||
|
// convert config object to array and extract
|
||
|
return $this->_convertToPages($mixed->toArray(), $recursive);
|
||
|
}
|
||
|
} elseif (is_string($mixed)) {
|
||
|
// value is a string; make an URI page
|
||
|
return Zend_Navigation_Page::factory(array(
|
||
|
'type' => 'uri',
|
||
|
'uri' => $mixed
|
||
|
));
|
||
|
} elseif (is_array($mixed) && !empty($mixed)) {
|
||
|
if ($recursive && is_numeric(key($mixed))) {
|
||
|
// first key is numeric; assume several pages
|
||
|
$pages = array();
|
||
|
foreach ($mixed as $value) {
|
||
|
if ($value = $this->_convertToPages($value, false)) {
|
||
|
$pages[] = $value;
|
||
|
}
|
||
|
}
|
||
|
return $pages;
|
||
|
} else {
|
||
|
// pass array to factory directly
|
||
|
try {
|
||
|
$page = Zend_Navigation_Page::factory($mixed);
|
||
|
return $page;
|
||
|
} catch (Exception $e) {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// nothing found
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// Render methods:
|
||
|
|
||
|
/**
|
||
|
* Renders the given $page as a link element, with $attrib = $relation
|
||
|
*
|
||
|
* @param Zend_Navigation_Page $page the page to render the link for
|
||
|
* @param string $attrib the attribute to use for $type,
|
||
|
* either 'rel' or 'rev'
|
||
|
* @param string $relation relation type, muse be one of;
|
||
|
* alternate, appendix, bookmark,
|
||
|
* chapter, contents, copyright,
|
||
|
* glossary, help, home, index, next,
|
||
|
* prev, section, start, stylesheet,
|
||
|
* subsection
|
||
|
* @return string rendered link element
|
||
|
* @throws Zend_View_Exception if $attrib is invalid
|
||
|
*/
|
||
|
public function renderLink(Zend_Navigation_Page $page, $attrib, $relation)
|
||
|
{
|
||
|
if (!in_array($attrib, array('rel', 'rev'))) {
|
||
|
require_once 'Zend/View/Exception.php';
|
||
|
$e = new Zend_View_Exception(sprintf(
|
||
|
'Invalid relation attribute "%s", must be "rel" or "rev"',
|
||
|
$attrib));
|
||
|
$e->setView($this->view);
|
||
|
throw $e;
|
||
|
}
|
||
|
|
||
|
if (!$href = $page->getHref()) {
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
// TODO: add more attribs
|
||
|
// http://www.w3.org/TR/html401/struct/links.html#h-12.2
|
||
|
$attribs = array(
|
||
|
$attrib => $relation,
|
||
|
'href' => $href,
|
||
|
'title' => $page->getLabel()
|
||
|
);
|
||
|
|
||
|
return '<link' .
|
||
|
$this->_htmlAttribs($attribs) .
|
||
|
$this->getClosingBracket();
|
||
|
}
|
||
|
|
||
|
// Zend_View_Helper_Navigation_Helper:
|
||
|
|
||
|
/**
|
||
|
* Renders helper
|
||
|
*
|
||
|
* Implements {@link Zend_View_Helper_Navigation_Helper::render()}.
|
||
|
*
|
||
|
* @param Zend_Navigation_Container $container [optional] container to
|
||
|
* render. Default is to
|
||
|
* render the container
|
||
|
* registered in the helper.
|
||
|
* @return string helper output
|
||
|
*/
|
||
|
public function render(Zend_Navigation_Container $container = null)
|
||
|
{
|
||
|
if (null === $container) {
|
||
|
$container = $this->getContainer();
|
||
|
}
|
||
|
|
||
|
if ($active = $this->findActive($container)) {
|
||
|
$active = $active['page'];
|
||
|
} else {
|
||
|
// no active page
|
||
|
return '';
|
||
|
}
|
||
|
|
||
|
$output = '';
|
||
|
$indent = $this->getIndent();
|
||
|
$this->_root = $container;
|
||
|
|
||
|
$result = $this->findAllRelations($active, $this->getRenderFlag());
|
||
|
foreach ($result as $attrib => $types) {
|
||
|
foreach ($types as $relation => $pages) {
|
||
|
foreach ($pages as $page) {
|
||
|
if ($r = $this->renderLink($page, $attrib, $relation)) {
|
||
|
$output .= $indent . $r . self::EOL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$this->_root = null;
|
||
|
|
||
|
// return output (trim last newline by spec)
|
||
|
return strlen($output) ? rtrim($output, self::EOL) : '';
|
||
|
}
|
||
|
}
|