adding zend project folders into old campcaster.
This commit is contained in:
parent
56abfaf28e
commit
7ef0c18b26
4045 changed files with 1054952 additions and 0 deletions
331
library/Zend/View/Helper/Navigation/Breadcrumbs.php
Normal file
331
library/Zend/View/Helper/Navigation/Breadcrumbs.php
Normal file
|
@ -0,0 +1,331 @@
|
|||
<?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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id: Breadcrumbs.php 20096 2010-01-06 02:05:09Z bkarwin $
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Zend_View_Helper_Navigation_HelperAbstract
|
||||
*/
|
||||
require_once 'Zend/View/Helper/Navigation/HelperAbstract.php';
|
||||
|
||||
/**
|
||||
* Helper for printing breadcrumbs
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_View
|
||||
* @subpackage Helper
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_View_Helper_Navigation_Breadcrumbs
|
||||
extends Zend_View_Helper_Navigation_HelperAbstract
|
||||
{
|
||||
/**
|
||||
* Breadcrumbs separator string
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_separator = ' > ';
|
||||
|
||||
/**
|
||||
* The minimum depth a page must have to be included when rendering
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_minDepth = 1;
|
||||
|
||||
/**
|
||||
* Whether last page in breadcrumb should be hyperlinked
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_linkLast = false;
|
||||
|
||||
/**
|
||||
* Partial view script to use for rendering menu
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $_partial;
|
||||
|
||||
/**
|
||||
* 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_Breadcrumbs fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function breadcrumbs(Zend_Navigation_Container $container = null)
|
||||
{
|
||||
if (null !== $container) {
|
||||
$this->setContainer($container);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Accessors:
|
||||
|
||||
/**
|
||||
* Sets breadcrumb separator
|
||||
*
|
||||
* @param string $separator separator string
|
||||
* @return Zend_View_Helper_Navigation_Breadcrumbs fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setSeparator($separator)
|
||||
{
|
||||
if (is_string($separator)) {
|
||||
$this->_separator = $separator;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns breadcrumb separator
|
||||
*
|
||||
* @return string breadcrumb separator
|
||||
*/
|
||||
public function getSeparator()
|
||||
{
|
||||
return $this->_separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether last page in breadcrumbs should be hyperlinked
|
||||
*
|
||||
* @param bool $linkLast whether last page should
|
||||
* be hyperlinked
|
||||
* @return Zend_View_Helper_Navigation_Breadcrumbs fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setLinkLast($linkLast)
|
||||
{
|
||||
$this->_linkLast = (bool) $linkLast;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether last page in breadcrumbs should be hyperlinked
|
||||
*
|
||||
* @return bool whether last page in breadcrumbs should be hyperlinked
|
||||
*/
|
||||
public function getLinkLast()
|
||||
{
|
||||
return $this->_linkLast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets which partial view script to use for rendering menu
|
||||
*
|
||||
* @param string|array $partial partial view script or
|
||||
* null. If an array is
|
||||
* given, it is expected to
|
||||
* contain two values;
|
||||
* the partial view script
|
||||
* to use, and the module
|
||||
* where the script can be
|
||||
* found.
|
||||
* @return Zend_View_Helper_Navigation_Breadcrumbs fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setPartial($partial)
|
||||
{
|
||||
if (null === $partial || is_string($partial) || is_array($partial)) {
|
||||
$this->_partial = $partial;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns partial view script to use for rendering menu
|
||||
*
|
||||
* @return string|array|null
|
||||
*/
|
||||
public function getPartial()
|
||||
{
|
||||
return $this->_partial;
|
||||
}
|
||||
|
||||
// Render methods:
|
||||
|
||||
/**
|
||||
* Renders breadcrumbs by chaining 'a' elements with the separator
|
||||
* registered in the helper
|
||||
*
|
||||
* @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 renderStraight(Zend_Navigation_Container $container = null)
|
||||
{
|
||||
if (null === $container) {
|
||||
$container = $this->getContainer();
|
||||
}
|
||||
|
||||
// find deepest active
|
||||
if (!$active = $this->findActive($container)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$active = $active['page'];
|
||||
|
||||
// put the deepest active page last in breadcrumbs
|
||||
if ($this->getLinkLast()) {
|
||||
$html = $this->htmlify($active);
|
||||
} else {
|
||||
$html = $active->getLabel();
|
||||
if ($this->getUseTranslator() && $t = $this->getTranslator()) {
|
||||
$html = $t->translate($html);
|
||||
}
|
||||
$html = $this->view->escape($html);
|
||||
}
|
||||
|
||||
// walk back to root
|
||||
while ($parent = $active->getParent()) {
|
||||
if ($parent instanceof Zend_Navigation_Page) {
|
||||
// prepend crumb to html
|
||||
$html = $this->htmlify($parent)
|
||||
. $this->getSeparator()
|
||||
. $html;
|
||||
}
|
||||
|
||||
if ($parent === $container) {
|
||||
// at the root of the given container
|
||||
break;
|
||||
}
|
||||
|
||||
$active = $parent;
|
||||
}
|
||||
|
||||
return strlen($html) ? $this->getIndent() . $html : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the given $container by invoking the partial view helper
|
||||
*
|
||||
* The container will simply be passed on as a model to the view script,
|
||||
* so in the script it will be available in <code>$this->container</code>.
|
||||
*
|
||||
* @param Zend_Navigation_Container $container [optional] container to
|
||||
* pass to view script.
|
||||
* Default is to use the
|
||||
* container registered in the
|
||||
* helper.
|
||||
* @param string|array $partial [optional] partial view
|
||||
* script to use. Default is
|
||||
* to use the partial
|
||||
* registered in the helper.
|
||||
* If an array is given, it is
|
||||
* expected to contain two
|
||||
* values; the partial view
|
||||
* script to use, and the
|
||||
* module where the script can
|
||||
* be found.
|
||||
* @return string helper output
|
||||
*/
|
||||
public function renderPartial(Zend_Navigation_Container $container = null,
|
||||
$partial = null)
|
||||
{
|
||||
if (null === $container) {
|
||||
$container = $this->getContainer();
|
||||
}
|
||||
|
||||
if (null === $partial) {
|
||||
$partial = $this->getPartial();
|
||||
}
|
||||
|
||||
if (empty($partial)) {
|
||||
require_once 'Zend/View/Exception.php';
|
||||
$e = new Zend_View_Exception(
|
||||
'Unable to render menu: No partial view script provided'
|
||||
);
|
||||
$e->setView($this->view);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// put breadcrumb pages in model
|
||||
$model = array('pages' => array());
|
||||
if ($active = $this->findActive($container)) {
|
||||
$active = $active['page'];
|
||||
$model['pages'][] = $active;
|
||||
while ($parent = $active->getParent()) {
|
||||
if ($parent instanceof Zend_Navigation_Page) {
|
||||
$model['pages'][] = $parent;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($parent === $container) {
|
||||
// break if at the root of the given container
|
||||
break;
|
||||
}
|
||||
|
||||
$active = $parent;
|
||||
}
|
||||
$model['pages'] = array_reverse($model['pages']);
|
||||
}
|
||||
|
||||
if (is_array($partial)) {
|
||||
if (count($partial) != 2) {
|
||||
require_once 'Zend/View/Exception.php';
|
||||
$e = new Zend_View_Exception(
|
||||
'Unable to render menu: A view partial supplied as '
|
||||
. 'an array must contain two values: partial view '
|
||||
. 'script and module where script can be found'
|
||||
);
|
||||
$e->setView($this->view);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this->view->partial($partial[0], $partial[1], $model);
|
||||
}
|
||||
|
||||
return $this->view->partial($partial, null, $model);
|
||||
}
|
||||
|
||||
// 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 ($partial = $this->getPartial()) {
|
||||
return $this->renderPartial($container, $partial);
|
||||
} else {
|
||||
return $this->renderStraight($container);
|
||||
}
|
||||
}
|
||||
}
|
212
library/Zend/View/Helper/Navigation/Helper.php
Normal file
212
library/Zend/View/Helper/Navigation/Helper.php
Normal file
|
@ -0,0 +1,212 @@
|
|||
<?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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id: Helper.php 20096 2010-01-06 02:05:09Z bkarwin $
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for navigational helpers
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_View
|
||||
* @subpackage Helper
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
interface Zend_View_Helper_Navigation_Helper
|
||||
{
|
||||
/**
|
||||
* Sets navigation container the helper should operate on by default
|
||||
*
|
||||
* @param Zend_Navigation_Container $container [optional] container to
|
||||
* operate on. Default is
|
||||
* null, which indicates that
|
||||
* the container should be
|
||||
* reset.
|
||||
* @return Zend_View_Helper_Navigation_Helper fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setContainer(Zend_Navigation_Container $container = null);
|
||||
|
||||
/**
|
||||
* Returns the navigation container the helper operates on by default
|
||||
*
|
||||
* @return Zend_Navigation_Container navigation container
|
||||
*/
|
||||
public function getContainer();
|
||||
|
||||
/**
|
||||
* Sets translator to use in helper
|
||||
*
|
||||
* @param mixed $translator [optional] translator.
|
||||
* Expects an object of type
|
||||
* {@link Zend_Translate_Adapter}
|
||||
* or {@link Zend_Translate},
|
||||
* or null. Default is null.
|
||||
* @return Zend_View_Helper_Navigation_Helper fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setTranslator($translator = null);
|
||||
|
||||
/**
|
||||
* Returns translator used in helper
|
||||
*
|
||||
* @return Zend_Translate_Adapter|null translator or null
|
||||
*/
|
||||
public function getTranslator();
|
||||
|
||||
/**
|
||||
* Sets ACL to use when iterating pages
|
||||
*
|
||||
* @param Zend_Acl $acl [optional] ACL instance
|
||||
* @return Zend_View_Helper_Navigation_Helper fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setAcl(Zend_Acl $acl = null);
|
||||
|
||||
/**
|
||||
* Returns ACL or null if it isn't set using {@link setAcl()} or
|
||||
* {@link setDefaultAcl()}
|
||||
*
|
||||
* @return Zend_Acl|null ACL object or null
|
||||
*/
|
||||
public function getAcl();
|
||||
|
||||
/**
|
||||
* Sets ACL role to use when iterating pages
|
||||
*
|
||||
* @param mixed $role [optional] role to set.
|
||||
* Expects a string, an
|
||||
* instance of type
|
||||
* {@link Zend_Acl_Role_Interface},
|
||||
* or null. Default is null.
|
||||
* @throws Zend_View_Exception if $role is invalid
|
||||
* @return Zend_View_Helper_Navigation_Helper fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setRole($role = null);
|
||||
|
||||
/**
|
||||
* Returns ACL role to use when iterating pages, or null if it isn't set
|
||||
*
|
||||
* @return string|Zend_Acl_Role_Interface|null role or null
|
||||
*/
|
||||
public function getRole();
|
||||
|
||||
/**
|
||||
* Sets whether ACL should be used
|
||||
*
|
||||
* @param bool $useAcl [optional] whether ACL
|
||||
* should be used. Default is
|
||||
* true.
|
||||
* @return Zend_View_Helper_Navigation_Helper fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setUseAcl($useAcl = true);
|
||||
|
||||
/**
|
||||
* Returns whether ACL should be used
|
||||
*
|
||||
* @return bool whether ACL should be used
|
||||
*/
|
||||
public function getUseAcl();
|
||||
|
||||
/**
|
||||
* Return renderInvisible flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getRenderInvisible();
|
||||
|
||||
/**
|
||||
* Render invisible items?
|
||||
*
|
||||
* @param bool $renderInvisible [optional] boolean flag
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface
|
||||
* returns self
|
||||
*/
|
||||
public function setRenderInvisible($renderInvisible = true);
|
||||
|
||||
/**
|
||||
* Sets whether translator should be used
|
||||
*
|
||||
* @param bool $useTranslator [optional] whether
|
||||
* translator should be used.
|
||||
* Default is true.
|
||||
* @return Zend_View_Helper_Navigation_Helper fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setUseTranslator($useTranslator = true);
|
||||
|
||||
/**
|
||||
* Returns whether translator should be used
|
||||
*
|
||||
* @return bool whether translator should be used
|
||||
*/
|
||||
public function getUseTranslator();
|
||||
|
||||
/**
|
||||
* Checks if the helper has a container
|
||||
*
|
||||
* @return bool whether the helper has a container or not
|
||||
*/
|
||||
public function hasContainer();
|
||||
|
||||
/**
|
||||
* Checks if the helper has an ACL instance
|
||||
*
|
||||
* @return bool whether the helper has a an ACL instance or not
|
||||
*/
|
||||
public function hasAcl();
|
||||
|
||||
/**
|
||||
* Checks if the helper has an ACL role
|
||||
*
|
||||
* @return bool whether the helper has a an ACL role or not
|
||||
*/
|
||||
public function hasRole();
|
||||
|
||||
/**
|
||||
* Checks if the helper has a translator
|
||||
*
|
||||
* @return bool whether the helper has a translator or not
|
||||
*/
|
||||
public function hasTranslator();
|
||||
|
||||
/**
|
||||
* Magic overload: Should proxy to {@link render()}.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
|
||||
/**
|
||||
* Renders helper
|
||||
*
|
||||
* @param Zend_Navigation_Container $container [optional] container to
|
||||
* render. Default is null,
|
||||
* which indicates that the
|
||||
* helper should render the
|
||||
* container returned by
|
||||
* {@link getContainer()}.
|
||||
* @return string helper output
|
||||
* @throws Zend_View_Exception if unable to render
|
||||
*/
|
||||
public function render(Zend_Navigation_Container $container = null);
|
||||
}
|
855
library/Zend/View/Helper/Navigation/HelperAbstract.php
Normal file
855
library/Zend/View/Helper/Navigation/HelperAbstract.php
Normal file
|
@ -0,0 +1,855 @@
|
|||
<?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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id: HelperAbstract.php 20096 2010-01-06 02:05:09Z bkarwin $
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Zend_View_Helper_Navigation_Helper
|
||||
*/
|
||||
require_once 'Zend/View/Helper/Navigation/Helper.php';
|
||||
|
||||
/**
|
||||
* @see Zend_View_Helper_HtmlElement
|
||||
*/
|
||||
require_once 'Zend/View/Helper/HtmlElement.php';
|
||||
|
||||
/**
|
||||
* Base class for navigational helpers
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_View
|
||||
* @subpackage Helper
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Zend_View_Helper_Navigation_HelperAbstract
|
||||
extends Zend_View_Helper_HtmlElement
|
||||
implements Zend_View_Helper_Navigation_Helper
|
||||
{
|
||||
/**
|
||||
* Container to operate on by default
|
||||
*
|
||||
* @var Zend_Navigation_Container
|
||||
*/
|
||||
protected $_container;
|
||||
|
||||
/**
|
||||
* The minimum depth a page must have to be included when rendering
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_minDepth;
|
||||
|
||||
/**
|
||||
* The maximum depth a page can have to be included when rendering
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $_maxDepth;
|
||||
|
||||
/**
|
||||
* Indentation string
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_indent = '';
|
||||
|
||||
/**
|
||||
* Translator
|
||||
*
|
||||
* @var Zend_Translate_Adapter
|
||||
*/
|
||||
protected $_translator;
|
||||
|
||||
/**
|
||||
* ACL to use when iterating pages
|
||||
*
|
||||
* @var Zend_Acl
|
||||
*/
|
||||
protected $_acl;
|
||||
|
||||
/**
|
||||
* Wheter invisible items should be rendered by this helper
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_renderInvisible = false;
|
||||
|
||||
/**
|
||||
* ACL role to use when iterating pages
|
||||
*
|
||||
* @var string|Zend_Acl_Role_Interface
|
||||
*/
|
||||
protected $_role;
|
||||
|
||||
/**
|
||||
* Whether translator should be used for page labels and titles
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_useTranslator = true;
|
||||
|
||||
/**
|
||||
* Whether ACL should be used for filtering out pages
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_useAcl = true;
|
||||
|
||||
/**
|
||||
* Default ACL to use when iterating pages if not explicitly set in the
|
||||
* instance by calling {@link setAcl()}
|
||||
*
|
||||
* @var Zend_Acl
|
||||
*/
|
||||
protected static $_defaultAcl;
|
||||
|
||||
/**
|
||||
* Default ACL role to use when iterating pages if not explicitly set in the
|
||||
* instance by calling {@link setRole()}
|
||||
*
|
||||
* @var string|Zend_Acl_Role_Interface
|
||||
*/
|
||||
protected static $_defaultRole;
|
||||
|
||||
// Accessors:
|
||||
|
||||
/**
|
||||
* Sets navigation container the helper operates on by default
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Interface::setContainer()}.
|
||||
*
|
||||
* @param Zend_Navigation_Container $container [optional] container
|
||||
* to operate on.
|
||||
* Default is null,
|
||||
* meaning container
|
||||
* will be reset.
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setContainer(Zend_Navigation_Container $container = null)
|
||||
{
|
||||
$this->_container = $container;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the navigation container helper operates on by default
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Interface::getContainer()}.
|
||||
*
|
||||
* If a helper is not explicitly set in this helper instance by calling
|
||||
* {@link setContainer()} or by passing it through the helper entry point,
|
||||
* this method will look in {@link Zend_Registry} for a container by using
|
||||
* the key 'Zend_Navigation'.
|
||||
*
|
||||
* If no container is set, and nothing is found in Zend_Registry, a new
|
||||
* container will be instantiated and stored in the helper.
|
||||
*
|
||||
* @return Zend_Navigation_Container navigation container
|
||||
*/
|
||||
public function getContainer()
|
||||
{
|
||||
if (null === $this->_container) {
|
||||
// try to fetch from registry first
|
||||
require_once 'Zend/Registry.php';
|
||||
if (Zend_Registry::isRegistered('Zend_Navigation')) {
|
||||
$nav = Zend_Registry::get('Zend_Navigation');
|
||||
if ($nav instanceof Zend_Navigation_Container) {
|
||||
return $this->_container = $nav;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing found in registry, create new container
|
||||
require_once 'Zend/Navigation.php';
|
||||
$this->_container = new Zend_Navigation();
|
||||
}
|
||||
|
||||
return $this->_container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum depth a page must have to be included when rendering
|
||||
*
|
||||
* @param int $minDepth [optional] minimum
|
||||
* depth. Default is
|
||||
* null, which sets
|
||||
* no minimum depth.
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setMinDepth($minDepth = null)
|
||||
{
|
||||
if (null === $minDepth || is_int($minDepth)) {
|
||||
$this->_minDepth = $minDepth;
|
||||
} else {
|
||||
$this->_minDepth = (int) $minDepth;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns minimum depth a page must have to be included when rendering
|
||||
*
|
||||
* @return int|null minimum depth or null
|
||||
*/
|
||||
public function getMinDepth()
|
||||
{
|
||||
if (!is_int($this->_minDepth) || $this->_minDepth < 0) {
|
||||
return 0;
|
||||
}
|
||||
return $this->_minDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum depth a page can have to be included when rendering
|
||||
*
|
||||
* @param int $maxDepth [optional] maximum
|
||||
* depth. Default is
|
||||
* null, which sets no
|
||||
* maximum depth.
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setMaxDepth($maxDepth = null)
|
||||
{
|
||||
if (null === $maxDepth || is_int($maxDepth)) {
|
||||
$this->_maxDepth = $maxDepth;
|
||||
} else {
|
||||
$this->_maxDepth = (int) $maxDepth;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns maximum depth a page can have to be included when rendering
|
||||
*
|
||||
* @return int|null maximum depth or null
|
||||
*/
|
||||
public function getMaxDepth()
|
||||
{
|
||||
return $this->_maxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the indentation string for using in {@link render()}, optionally a
|
||||
* number of spaces to indent with
|
||||
*
|
||||
* @param string|int $indent indentation string or
|
||||
* number of spaces
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setIndent($indent)
|
||||
{
|
||||
$this->_indent = $this->_getWhitespace($indent);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns indentation
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIndent()
|
||||
{
|
||||
return $this->_indent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets translator to use in helper
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::setTranslator()}.
|
||||
*
|
||||
* @param mixed $translator [optional] translator.
|
||||
* Expects an object of
|
||||
* type
|
||||
* {@link Zend_Translate_Adapter}
|
||||
* or {@link Zend_Translate},
|
||||
* or null. Default is
|
||||
* null, which sets no
|
||||
* translator.
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setTranslator($translator = null)
|
||||
{
|
||||
if (null == $translator ||
|
||||
$translator instanceof Zend_Translate_Adapter) {
|
||||
$this->_translator = $translator;
|
||||
} elseif ($translator instanceof Zend_Translate) {
|
||||
$this->_translator = $translator->getAdapter();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns translator used in helper
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::getTranslator()}.
|
||||
*
|
||||
* @return Zend_Translate_Adapter|null translator or null
|
||||
*/
|
||||
public function getTranslator()
|
||||
{
|
||||
if (null === $this->_translator) {
|
||||
require_once 'Zend/Registry.php';
|
||||
if (Zend_Registry::isRegistered('Zend_Translate')) {
|
||||
$this->setTranslator(Zend_Registry::get('Zend_Translate'));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets ACL to use when iterating pages
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::setAcl()}.
|
||||
*
|
||||
* @param Zend_Acl $acl [optional] ACL object.
|
||||
* Default is null.
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setAcl(Zend_Acl $acl = null)
|
||||
{
|
||||
$this->_acl = $acl;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ACL or null if it isn't set using {@link setAcl()} or
|
||||
* {@link setDefaultAcl()}
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::getAcl()}.
|
||||
*
|
||||
* @return Zend_Acl|null ACL object or null
|
||||
*/
|
||||
public function getAcl()
|
||||
{
|
||||
if ($this->_acl === null && self::$_defaultAcl !== null) {
|
||||
return self::$_defaultAcl;
|
||||
}
|
||||
|
||||
return $this->_acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets ACL role(s) to use when iterating pages
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::setRole()}.
|
||||
*
|
||||
* @param mixed $role [optional] role to
|
||||
* set. Expects a string,
|
||||
* an instance of type
|
||||
* {@link Zend_Acl_Role_Interface},
|
||||
* or null. Default is
|
||||
* null, which will set
|
||||
* no role.
|
||||
* @throws Zend_View_Exception if $role is invalid
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setRole($role = null)
|
||||
{
|
||||
if (null === $role || is_string($role) ||
|
||||
$role instanceof Zend_Acl_Role_Interface) {
|
||||
$this->_role = $role;
|
||||
} else {
|
||||
require_once 'Zend/View/Exception.php';
|
||||
$e = new Zend_View_Exception(sprintf(
|
||||
'$role must be a string, null, or an instance of '
|
||||
. 'Zend_Acl_Role_Interface; %s given',
|
||||
gettype($role)
|
||||
));
|
||||
$e->setView($this->view);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ACL role to use when iterating pages, or null if it isn't set
|
||||
* using {@link setRole()} or {@link setDefaultRole()}
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::getRole()}.
|
||||
*
|
||||
* @return string|Zend_Acl_Role_Interface|null role or null
|
||||
*/
|
||||
public function getRole()
|
||||
{
|
||||
if ($this->_role === null && self::$_defaultRole !== null) {
|
||||
return self::$_defaultRole;
|
||||
}
|
||||
|
||||
return $this->_role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether ACL should be used
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::setUseAcl()}.
|
||||
*
|
||||
* @param bool $useAcl [optional] whether ACL
|
||||
* should be used.
|
||||
* Default is true.
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setUseAcl($useAcl = true)
|
||||
{
|
||||
$this->_useAcl = (bool) $useAcl;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether ACL should be used
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::getUseAcl()}.
|
||||
*
|
||||
* @return bool whether ACL should be used
|
||||
*/
|
||||
public function getUseAcl()
|
||||
{
|
||||
return $this->_useAcl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return renderInvisible flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getRenderInvisible()
|
||||
{
|
||||
return $this->_renderInvisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render invisible items?
|
||||
*
|
||||
* @param bool $renderInvisible [optional] boolean flag
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface
|
||||
* returns self
|
||||
*/
|
||||
public function setRenderInvisible($renderInvisible = true)
|
||||
{
|
||||
$this->_renderInvisible = (bool) $renderInvisible;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether translator should be used
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::setUseTranslator()}.
|
||||
*
|
||||
* @param bool $useTranslator [optional] whether
|
||||
* translator should be
|
||||
* used. Default is true.
|
||||
* @return Zend_View_Helper_Navigation_HelperAbstract fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function setUseTranslator($useTranslator = true)
|
||||
{
|
||||
$this->_useTranslator = (bool) $useTranslator;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether translator should be used
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::getUseTranslator()}.
|
||||
*
|
||||
* @return bool whether translator should be used
|
||||
*/
|
||||
public function getUseTranslator()
|
||||
{
|
||||
return $this->_useTranslator;
|
||||
}
|
||||
|
||||
// Magic overloads:
|
||||
|
||||
/**
|
||||
* Magic overload: Proxy calls to the navigation container
|
||||
*
|
||||
* @param string $method method name in container
|
||||
* @param array $arguments [optional] arguments to pass
|
||||
* @return mixed returns what the container returns
|
||||
* @throws Zend_Navigation_Exception if method does not exist in container
|
||||
*/
|
||||
public function __call($method, array $arguments = array())
|
||||
{
|
||||
return call_user_func_array(
|
||||
array($this->getContainer(), $method),
|
||||
$arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic overload: Proxy to {@link render()}.
|
||||
*
|
||||
* This method will trigger an E_USER_ERROR if rendering the helper causes
|
||||
* an exception to be thrown.
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::__toString()}.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
try {
|
||||
return $this->render();
|
||||
} catch (Exception $e) {
|
||||
$msg = get_class($e) . ': ' . $e->getMessage();
|
||||
trigger_error($msg, E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// Public methods:
|
||||
|
||||
/**
|
||||
* Finds the deepest active page in the given container
|
||||
*
|
||||
* @param Zend_Navigation_Container $container container to search
|
||||
* @param int|null $minDepth [optional] minimum depth
|
||||
* required for page to be
|
||||
* valid. Default is to use
|
||||
* {@link getMinDepth()}. A
|
||||
* null value means no minimum
|
||||
* depth required.
|
||||
* @param int|null $minDepth [optional] maximum depth
|
||||
* a page can have to be
|
||||
* valid. Default is to use
|
||||
* {@link getMaxDepth()}. A
|
||||
* null value means no maximum
|
||||
* depth required.
|
||||
* @return array an associative array with
|
||||
* the values 'depth' and
|
||||
* 'page', or an empty array
|
||||
* if not found
|
||||
*/
|
||||
public function findActive(Zend_Navigation_Container $container,
|
||||
$minDepth = null,
|
||||
$maxDepth = -1)
|
||||
{
|
||||
if (!is_int($minDepth)) {
|
||||
$minDepth = $this->getMinDepth();
|
||||
}
|
||||
if ((!is_int($maxDepth) || $maxDepth < 0) && null !== $maxDepth) {
|
||||
$maxDepth = $this->getMaxDepth();
|
||||
}
|
||||
|
||||
$found = null;
|
||||
$foundDepth = -1;
|
||||
$iterator = new RecursiveIteratorIterator($container,
|
||||
RecursiveIteratorIterator::CHILD_FIRST);
|
||||
|
||||
foreach ($iterator as $page) {
|
||||
$currDepth = $iterator->getDepth();
|
||||
if ($currDepth < $minDepth || !$this->accept($page)) {
|
||||
// page is not accepted
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($page->isActive(false) && $currDepth > $foundDepth) {
|
||||
// found an active page at a deeper level than before
|
||||
$found = $page;
|
||||
$foundDepth = $currDepth;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_int($maxDepth) && $foundDepth > $maxDepth) {
|
||||
while ($foundDepth > $maxDepth) {
|
||||
if (--$foundDepth < $minDepth) {
|
||||
$found = null;
|
||||
break;
|
||||
}
|
||||
|
||||
$found = $found->getParent();
|
||||
if (!$found instanceof Zend_Navigation_Page) {
|
||||
$found = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($found) {
|
||||
return array('page' => $found, 'depth' => $foundDepth);
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the helper has a container
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::hasContainer()}.
|
||||
*
|
||||
* @return bool whether the helper has a container or not
|
||||
*/
|
||||
public function hasContainer()
|
||||
{
|
||||
return null !== $this->_container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the helper has an ACL instance
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::hasAcl()}.
|
||||
*
|
||||
* @return bool whether the helper has a an ACL instance or not
|
||||
*/
|
||||
public function hasAcl()
|
||||
{
|
||||
return null !== $this->_acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the helper has an ACL role
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::hasRole()}.
|
||||
*
|
||||
* @return bool whether the helper has a an ACL role or not
|
||||
*/
|
||||
public function hasRole()
|
||||
{
|
||||
return null !== $this->_role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the helper has a translator
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::hasTranslator()}.
|
||||
*
|
||||
* @return bool whether the helper has a translator or not
|
||||
*/
|
||||
public function hasTranslator()
|
||||
{
|
||||
return null !== $this->_translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTML string containing an 'a' element for the given page
|
||||
*
|
||||
* @param Zend_Navigation_Page $page page to generate HTML for
|
||||
* @return string HTML string for the given page
|
||||
*/
|
||||
public function htmlify(Zend_Navigation_Page $page)
|
||||
{
|
||||
// get label and title for translating
|
||||
$label = $page->getLabel();
|
||||
$title = $page->getTitle();
|
||||
|
||||
if ($this->getUseTranslator() && $t = $this->getTranslator()) {
|
||||
if (is_string($label) && !empty($label)) {
|
||||
$label = $t->translate($label);
|
||||
}
|
||||
if (is_string($title) && !empty($title)) {
|
||||
$title = $t->translate($title);
|
||||
}
|
||||
}
|
||||
|
||||
// get attribs for anchor element
|
||||
$attribs = array(
|
||||
'id' => $page->getId(),
|
||||
'title' => $title,
|
||||
'class' => $page->getClass(),
|
||||
'href' => $page->getHref(),
|
||||
'target' => $page->getTarget()
|
||||
);
|
||||
|
||||
return '<a' . $this->_htmlAttribs($attribs) . '>'
|
||||
. $this->view->escape($label)
|
||||
. '</a>';
|
||||
}
|
||||
|
||||
// Iterator filter methods:
|
||||
|
||||
/**
|
||||
* Determines whether a page should be accepted when iterating
|
||||
*
|
||||
* Rules:
|
||||
* - If a page is not visible it is not accepted, unless RenderInvisible has
|
||||
* been set to true.
|
||||
* - If helper has no ACL, page is accepted
|
||||
* - If helper has ACL, but no role, page is not accepted
|
||||
* - If helper has ACL and role:
|
||||
* - Page is accepted if it has no resource or privilege
|
||||
* - Page is accepted if ACL allows page's resource or privilege
|
||||
* - If page is accepted by the rules above and $recursive is true, the page
|
||||
* will not be accepted if it is the descendant of a non-accepted page.
|
||||
*
|
||||
* @param Zend_Navigation_Page $page page to check
|
||||
* @param bool $recursive [optional] if true, page will not
|
||||
* be accepted if it is the
|
||||
* descendant of a page that is not
|
||||
* accepted. Default is true.
|
||||
* @return bool whether page should be accepted
|
||||
*/
|
||||
public function accept(Zend_Navigation_Page $page, $recursive = true)
|
||||
{
|
||||
// accept by default
|
||||
$accept = true;
|
||||
|
||||
if (!$page->isVisible(false) && !$this->getRenderInvisible()) {
|
||||
// don't accept invisible pages
|
||||
$accept = false;
|
||||
} elseif ($this->getUseAcl() && !$this->_acceptAcl($page)) {
|
||||
// acl is not amused
|
||||
$accept = false;
|
||||
}
|
||||
|
||||
if ($accept && $recursive) {
|
||||
$parent = $page->getParent();
|
||||
if ($parent instanceof Zend_Navigation_Page) {
|
||||
$accept = $this->accept($parent, true);
|
||||
}
|
||||
}
|
||||
|
||||
return $accept;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a page should be accepted by ACL when iterating
|
||||
*
|
||||
* Rules:
|
||||
* - If helper has no ACL, page is accepted
|
||||
* - If page has a resource or privilege defined, page is accepted
|
||||
* if the ACL allows access to it using the helper's role
|
||||
* - If page has no resource or privilege, page is accepted
|
||||
*
|
||||
* @param Zend_Navigation_Page $page page to check
|
||||
* @return bool whether page is accepted by ACL
|
||||
*/
|
||||
protected function _acceptAcl(Zend_Navigation_Page $page)
|
||||
{
|
||||
if (!$acl = $this->getAcl()) {
|
||||
// no acl registered means don't use acl
|
||||
return true;
|
||||
}
|
||||
|
||||
$role = $this->getRole();
|
||||
$resource = $page->getResource();
|
||||
$privilege = $page->getPrivilege();
|
||||
|
||||
if ($resource || $privilege) {
|
||||
// determine using helper role and page resource/privilege
|
||||
return $acl->isAllowed($role, $resource, $privilege);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Util methods:
|
||||
|
||||
/**
|
||||
* Retrieve whitespace representation of $indent
|
||||
*
|
||||
* @param int|string $indent
|
||||
* @return string
|
||||
*/
|
||||
protected function _getWhitespace($indent)
|
||||
{
|
||||
if (is_int($indent)) {
|
||||
$indent = str_repeat(' ', $indent);
|
||||
}
|
||||
|
||||
return (string) $indent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an associative array to a string of tag attributes.
|
||||
*
|
||||
* Overloads {@link Zend_View_Helper_HtmlElement::_htmlAttribs()}.
|
||||
*
|
||||
* @param array $attribs an array where each key-value pair is converted
|
||||
* to an attribute name and value
|
||||
* @return string an attribute string
|
||||
*/
|
||||
protected function _htmlAttribs($attribs)
|
||||
{
|
||||
// filter out null values and empty string values
|
||||
foreach ($attribs as $key => $value) {
|
||||
if ($value === null || (is_string($value) && !strlen($value))) {
|
||||
unset($attribs[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::_htmlAttribs($attribs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize an ID
|
||||
*
|
||||
* Overrides {@link Zend_View_Helper_HtmlElement::_normalizeId()}.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function _normalizeId($value)
|
||||
{
|
||||
$prefix = get_class($this);
|
||||
$prefix = strtolower(trim(substr($prefix, strrpos($prefix, '_')), '_'));
|
||||
|
||||
return $prefix . '-' . $value;
|
||||
}
|
||||
|
||||
// Static methods:
|
||||
|
||||
/**
|
||||
* Sets default ACL to use if another ACL is not explicitly set
|
||||
*
|
||||
* @param Zend_Acl $acl [optional] ACL object. Default is null, which
|
||||
* sets no ACL object.
|
||||
* @return void
|
||||
*/
|
||||
public static function setDefaultAcl(Zend_Acl $acl = null)
|
||||
{
|
||||
self::$_defaultAcl = $acl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default ACL role(s) to use when iterating pages if not explicitly
|
||||
* set later with {@link setRole()}
|
||||
*
|
||||
* @param midex $role [optional] role to set. Expects null,
|
||||
* string, or an instance of
|
||||
* {@link Zend_Acl_Role_Interface}.
|
||||
* Default is null, which sets no default
|
||||
* role.
|
||||
* @throws Zend_View_Exception if role is invalid
|
||||
* @return void
|
||||
*/
|
||||
public static function setDefaultRole($role = null)
|
||||
{
|
||||
if (null === $role ||
|
||||
is_string($role) ||
|
||||
$role instanceof Zend_Acl_Role_Interface) {
|
||||
self::$_defaultRole = $role;
|
||||
} else {
|
||||
require_once 'Zend/View/Exception.php';
|
||||
throw new Zend_View_Exception(
|
||||
'$role must be null|string|Zend_Acl_Role_Interface'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
783
library/Zend/View/Helper/Navigation/Links.php
Normal file
783
library/Zend/View/Helper/Navigation/Links.php
Normal file
|
@ -0,0 +1,783 @@
|
|||
<?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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id: Links.php 20096 2010-01-06 02:05:09Z bkarwin $
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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-2010 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) : '';
|
||||
}
|
||||
}
|
647
library/Zend/View/Helper/Navigation/Menu.php
Normal file
647
library/Zend/View/Helper/Navigation/Menu.php
Normal file
|
@ -0,0 +1,647 @@
|
|||
<?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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id: Menu.php 20096 2010-01-06 02:05:09Z bkarwin $
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Zend_View_Helper_Navigation_HelperAbstract
|
||||
*/
|
||||
require_once 'Zend/View/Helper/Navigation/HelperAbstract.php';
|
||||
|
||||
/**
|
||||
* Helper for rendering menus from navigation containers
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_View
|
||||
* @subpackage Helper
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_View_Helper_Navigation_Menu
|
||||
extends Zend_View_Helper_Navigation_HelperAbstract
|
||||
{
|
||||
/**
|
||||
* CSS class to use for the ul element
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_ulClass = 'navigation';
|
||||
|
||||
/**
|
||||
* Whether only active branch should be rendered
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_onlyActiveBranch = false;
|
||||
|
||||
/**
|
||||
* Whether parents should be rendered when only rendering active branch
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_renderParents = true;
|
||||
|
||||
/**
|
||||
* Partial view script to use for rendering menu
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $_partial = null;
|
||||
|
||||
/**
|
||||
* 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_Menu fluent interface,
|
||||
* returns self
|
||||
*/
|
||||
public function menu(Zend_Navigation_Container $container = null)
|
||||
{
|
||||
if (null !== $container) {
|
||||
$this->setContainer($container);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Accessors:
|
||||
|
||||
/**
|
||||
* Sets CSS class to use for the first 'ul' element when rendering
|
||||
*
|
||||
* @param string $ulClass CSS class to set
|
||||
* @return Zend_View_Helper_Navigation_Menu fluent interface, returns self
|
||||
*/
|
||||
public function setUlClass($ulClass)
|
||||
{
|
||||
if (is_string($ulClass)) {
|
||||
$this->_ulClass = $ulClass;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns CSS class to use for the first 'ul' element when rendering
|
||||
*
|
||||
* @return string CSS class
|
||||
*/
|
||||
public function getUlClass()
|
||||
{
|
||||
return $this->_ulClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a flag indicating whether only active branch should be rendered
|
||||
*
|
||||
* @param bool $flag [optional] render only active
|
||||
* branch. Default is true.
|
||||
* @return Zend_View_Helper_Navigation_Menu fluent interface, returns self
|
||||
*/
|
||||
public function setOnlyActiveBranch($flag = true)
|
||||
{
|
||||
$this->_onlyActiveBranch = (bool) $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flag indicating whether only active branch should be rendered
|
||||
*
|
||||
* By default, this value is false, meaning the entire menu will be
|
||||
* be rendered.
|
||||
*
|
||||
* @return bool whether only active branch should be rendered
|
||||
*/
|
||||
public function getOnlyActiveBranch()
|
||||
{
|
||||
return $this->_onlyActiveBranch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables/disables rendering of parents when only rendering active branch
|
||||
*
|
||||
* See {@link setOnlyActiveBranch()} for more information.
|
||||
*
|
||||
* @param bool $flag [optional] render parents when
|
||||
* rendering active branch.
|
||||
* Default is true.
|
||||
* @return Zend_View_Helper_Navigation_Menu fluent interface, returns self
|
||||
*/
|
||||
public function setRenderParents($flag = true)
|
||||
{
|
||||
$this->_renderParents = (bool) $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns flag indicating whether parents should be rendered when rendering
|
||||
* only the active branch
|
||||
*
|
||||
* By default, this value is true.
|
||||
*
|
||||
* @return bool whether parents should be rendered
|
||||
*/
|
||||
public function getRenderParents()
|
||||
{
|
||||
return $this->_renderParents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets which partial view script to use for rendering menu
|
||||
*
|
||||
* @param string|array $partial partial view script or null. If
|
||||
* an array is given, it is
|
||||
* expected to contain two values;
|
||||
* the partial view script to use,
|
||||
* and the module where the script
|
||||
* can be found.
|
||||
* @return Zend_View_Helper_Navigation_Menu fluent interface, returns self
|
||||
*/
|
||||
public function setPartial($partial)
|
||||
{
|
||||
if (null === $partial || is_string($partial) || is_array($partial)) {
|
||||
$this->_partial = $partial;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns partial view script to use for rendering menu
|
||||
*
|
||||
* @return string|array|null
|
||||
*/
|
||||
public function getPartial()
|
||||
{
|
||||
return $this->_partial;
|
||||
}
|
||||
|
||||
// Public methods:
|
||||
|
||||
/**
|
||||
* Returns an HTML string containing an 'a' element for the given page if
|
||||
* the page's href is not empty, and a 'span' element if it is empty
|
||||
*
|
||||
* Overrides {@link Zend_View_Helper_Navigation_Abstract::htmlify()}.
|
||||
*
|
||||
* @param Zend_Navigation_Page $page page to generate HTML for
|
||||
* @return string HTML string for the given page
|
||||
*/
|
||||
public function htmlify(Zend_Navigation_Page $page)
|
||||
{
|
||||
// get label and title for translating
|
||||
$label = $page->getLabel();
|
||||
$title = $page->getTitle();
|
||||
|
||||
// translate label and title?
|
||||
if ($this->getUseTranslator() && $t = $this->getTranslator()) {
|
||||
if (is_string($label) && !empty($label)) {
|
||||
$label = $t->translate($label);
|
||||
}
|
||||
if (is_string($title) && !empty($title)) {
|
||||
$title = $t->translate($title);
|
||||
}
|
||||
}
|
||||
|
||||
// get attribs for element
|
||||
$attribs = array(
|
||||
'id' => $page->getId(),
|
||||
'title' => $title,
|
||||
'class' => $page->getClass()
|
||||
);
|
||||
|
||||
// does page have a href?
|
||||
if ($href = $page->getHref()) {
|
||||
$element = 'a';
|
||||
$attribs['href'] = $href;
|
||||
$attribs['target'] = $page->getTarget();
|
||||
} else {
|
||||
$element = 'span';
|
||||
}
|
||||
|
||||
return '<' . $element . $this->_htmlAttribs($attribs) . '>'
|
||||
. $this->view->escape($label)
|
||||
. '</' . $element . '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes given render options
|
||||
*
|
||||
* @param array $options [optional] options to normalize
|
||||
* @return array normalized options
|
||||
*/
|
||||
protected function _normalizeOptions(array $options = array())
|
||||
{
|
||||
if (isset($options['indent'])) {
|
||||
$options['indent'] = $this->_getWhitespace($options['indent']);
|
||||
} else {
|
||||
$options['indent'] = $this->getIndent();
|
||||
}
|
||||
|
||||
if (isset($options['ulClass']) && $options['ulClass'] !== null) {
|
||||
$options['ulClass'] = (string) $options['ulClass'];
|
||||
} else {
|
||||
$options['ulClass'] = $this->getUlClass();
|
||||
}
|
||||
|
||||
if (array_key_exists('minDepth', $options)) {
|
||||
if (null !== $options['minDepth']) {
|
||||
$options['minDepth'] = (int) $options['minDepth'];
|
||||
}
|
||||
} else {
|
||||
$options['minDepth'] = $this->getMinDepth();
|
||||
}
|
||||
|
||||
if ($options['minDepth'] < 0 || $options['minDepth'] === null) {
|
||||
$options['minDepth'] = 0;
|
||||
}
|
||||
|
||||
if (array_key_exists('maxDepth', $options)) {
|
||||
if (null !== $options['maxDepth']) {
|
||||
$options['maxDepth'] = (int) $options['maxDepth'];
|
||||
}
|
||||
} else {
|
||||
$options['maxDepth'] = $this->getMaxDepth();
|
||||
}
|
||||
|
||||
if (!isset($options['onlyActiveBranch'])) {
|
||||
$options['onlyActiveBranch'] = $this->getOnlyActiveBranch();
|
||||
}
|
||||
|
||||
if (!isset($options['renderParents'])) {
|
||||
$options['renderParents'] = $this->getRenderParents();
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
// Render methods:
|
||||
|
||||
/**
|
||||
* Renders the deepest active menu within [$minDepth, $maxDeth], (called
|
||||
* from {@link renderMenu()})
|
||||
*
|
||||
* @param Zend_Navigation_Container $container container to render
|
||||
* @param array $active active page and depth
|
||||
* @param string $ulClass CSS class for first UL
|
||||
* @param string $indent initial indentation
|
||||
* @param int|null $minDepth minimum depth
|
||||
* @param int|null $maxDepth maximum depth
|
||||
* @return string rendered menu
|
||||
*/
|
||||
protected function _renderDeepestMenu(Zend_Navigation_Container $container,
|
||||
$ulClass,
|
||||
$indent,
|
||||
$minDepth,
|
||||
$maxDepth)
|
||||
{
|
||||
if (!$active = $this->findActive($container, $minDepth - 1, $maxDepth)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// special case if active page is one below minDepth
|
||||
if ($active['depth'] < $minDepth) {
|
||||
if (!$active['page']->hasPages()) {
|
||||
return '';
|
||||
}
|
||||
} else if (!$active['page']->hasPages()) {
|
||||
// found pages has no children; render siblings
|
||||
$active['page'] = $active['page']->getParent();
|
||||
} else if (is_int($maxDepth) && $active['depth'] +1 > $maxDepth) {
|
||||
// children are below max depth; render siblings
|
||||
$active['page'] = $active['page']->getParent();
|
||||
}
|
||||
|
||||
$ulClass = $ulClass ? ' class="' . $ulClass . '"' : '';
|
||||
$html = $indent . '<ul' . $ulClass . '>' . self::EOL;
|
||||
|
||||
foreach ($active['page'] as $subPage) {
|
||||
if (!$this->accept($subPage)) {
|
||||
continue;
|
||||
}
|
||||
$liClass = $subPage->isActive(true) ? ' class="active"' : '';
|
||||
$html .= $indent . ' <li' . $liClass . '>' . self::EOL;
|
||||
$html .= $indent . ' ' . $this->htmlify($subPage) . self::EOL;
|
||||
$html .= $indent . ' </li>' . self::EOL;
|
||||
}
|
||||
|
||||
$html .= $indent . '</ul>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a normal menu (called from {@link renderMenu()})
|
||||
*
|
||||
* @param Zend_Navigation_Container $container container to render
|
||||
* @param string $ulClass CSS class for first UL
|
||||
* @param string $indent initial indentation
|
||||
* @param int|null $minDepth minimum depth
|
||||
* @param int|null $maxDepth maximum depth
|
||||
* @param bool $onlyActive render only active branch?
|
||||
* @return string
|
||||
*/
|
||||
protected function _renderMenu(Zend_Navigation_Container $container,
|
||||
$ulClass,
|
||||
$indent,
|
||||
$minDepth,
|
||||
$maxDepth,
|
||||
$onlyActive)
|
||||
{
|
||||
$html = '';
|
||||
|
||||
// find deepest active
|
||||
if ($found = $this->findActive($container, $minDepth, $maxDepth)) {
|
||||
$foundPage = $found['page'];
|
||||
$foundDepth = $found['depth'];
|
||||
} else {
|
||||
$foundPage = null;
|
||||
}
|
||||
|
||||
// create iterator
|
||||
$iterator = new RecursiveIteratorIterator($container,
|
||||
RecursiveIteratorIterator::SELF_FIRST);
|
||||
if (is_int($maxDepth)) {
|
||||
$iterator->setMaxDepth($maxDepth);
|
||||
}
|
||||
|
||||
// iterate container
|
||||
$prevDepth = -1;
|
||||
foreach ($iterator as $page) {
|
||||
$depth = $iterator->getDepth();
|
||||
$isActive = $page->isActive(true);
|
||||
if ($depth < $minDepth || !$this->accept($page)) {
|
||||
// page is below minDepth or not accepted by acl/visibilty
|
||||
continue;
|
||||
} else if ($onlyActive && !$isActive) {
|
||||
// page is not active itself, but might be in the active branch
|
||||
$accept = false;
|
||||
if ($foundPage) {
|
||||
if ($foundPage->hasPage($page)) {
|
||||
// accept if page is a direct child of the active page
|
||||
$accept = true;
|
||||
} else if ($foundPage->getParent()->hasPage($page)) {
|
||||
// page is a sibling of the active page...
|
||||
if (!$foundPage->hasPages() ||
|
||||
is_int($maxDepth) && $foundDepth + 1 > $maxDepth) {
|
||||
// accept if active page has no children, or the
|
||||
// children are too deep to be rendered
|
||||
$accept = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$accept) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// make sure indentation is correct
|
||||
$depth -= $minDepth;
|
||||
$myIndent = $indent . str_repeat(' ', $depth);
|
||||
|
||||
if ($depth > $prevDepth) {
|
||||
// start new ul tag
|
||||
if ($ulClass && $depth == 0) {
|
||||
$ulClass = ' class="' . $ulClass . '"';
|
||||
} else {
|
||||
$ulClass = '';
|
||||
}
|
||||
$html .= $myIndent . '<ul' . $ulClass . '>' . self::EOL;
|
||||
} else if ($prevDepth > $depth) {
|
||||
// close li/ul tags until we're at current depth
|
||||
for ($i = $prevDepth; $i > $depth; $i--) {
|
||||
$ind = $indent . str_repeat(' ', $i);
|
||||
$html .= $ind . ' </li>' . self::EOL;
|
||||
$html .= $ind . '</ul>' . self::EOL;
|
||||
}
|
||||
// close previous li tag
|
||||
$html .= $myIndent . ' </li>' . self::EOL;
|
||||
} else {
|
||||
// close previous li tag
|
||||
$html .= $myIndent . ' </li>' . self::EOL;
|
||||
}
|
||||
|
||||
// render li tag and page
|
||||
$liClass = $isActive ? ' class="active"' : '';
|
||||
$html .= $myIndent . ' <li' . $liClass . '>' . self::EOL
|
||||
. $myIndent . ' ' . $this->htmlify($page) . self::EOL;
|
||||
|
||||
// store as previous depth for next iteration
|
||||
$prevDepth = $depth;
|
||||
}
|
||||
|
||||
if ($html) {
|
||||
// done iterating container; close open ul/li tags
|
||||
for ($i = $prevDepth+1; $i > 0; $i--) {
|
||||
$myIndent = $indent . str_repeat(' ', $i-1);
|
||||
$html .= $myIndent . ' </li>' . self::EOL
|
||||
. $myIndent . '</ul>' . self::EOL;
|
||||
}
|
||||
$html = rtrim($html, self::EOL);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders helper
|
||||
*
|
||||
* Renders a HTML 'ul' for the given $container. If $container is not given,
|
||||
* the container registered in the helper will be used.
|
||||
*
|
||||
* Available $options:
|
||||
*
|
||||
*
|
||||
* @param Zend_Navigation_Container $container [optional] container to
|
||||
* create menu from. Default
|
||||
* is to use the container
|
||||
* retrieved from
|
||||
* {@link getContainer()}.
|
||||
* @param array $options [optional] options for
|
||||
* controlling rendering
|
||||
* @return string rendered menu
|
||||
*/
|
||||
public function renderMenu(Zend_Navigation_Container $container = null,
|
||||
array $options = array())
|
||||
{
|
||||
if (null === $container) {
|
||||
$container = $this->getContainer();
|
||||
}
|
||||
|
||||
$options = $this->_normalizeOptions($options);
|
||||
|
||||
if ($options['onlyActiveBranch'] && !$options['renderParents']) {
|
||||
$html = $this->_renderDeepestMenu($container,
|
||||
$options['ulClass'],
|
||||
$options['indent'],
|
||||
$options['minDepth'],
|
||||
$options['maxDepth']);
|
||||
} else {
|
||||
$html = $this->_renderMenu($container,
|
||||
$options['ulClass'],
|
||||
$options['indent'],
|
||||
$options['minDepth'],
|
||||
$options['maxDepth'],
|
||||
$options['onlyActiveBranch']);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the inner-most sub menu for the active page in the $container
|
||||
*
|
||||
* This is a convenience method which is equivalent to the following call:
|
||||
* <code>
|
||||
* renderMenu($container, array(
|
||||
* 'indent' => $indent,
|
||||
* 'ulClass' => $ulClass,
|
||||
* 'minDepth' => null,
|
||||
* 'maxDepth' => null,
|
||||
* 'onlyActiveBranch' => true,
|
||||
* 'renderParents' => false
|
||||
* ));
|
||||
* </code>
|
||||
*
|
||||
* @param Zend_Navigation_Container $container [optional] container to
|
||||
* render. Default is to render
|
||||
* the container registered in
|
||||
* the helper.
|
||||
* @param string $ulClass [optional] CSS class to
|
||||
* use for UL element. Default
|
||||
* is to use the value from
|
||||
* {@link getUlClass()}.
|
||||
* @param string|int $indent [optional] indentation as
|
||||
* a string or number of
|
||||
* spaces. Default is to use
|
||||
* the value retrieved from
|
||||
* {@link getIndent()}.
|
||||
* @return string rendered content
|
||||
*/
|
||||
public function renderSubMenu(Zend_Navigation_Container $container = null,
|
||||
$ulClass = null,
|
||||
$indent = null)
|
||||
{
|
||||
return $this->renderMenu($container, array(
|
||||
'indent' => $indent,
|
||||
'ulClass' => $ulClass,
|
||||
'minDepth' => null,
|
||||
'maxDepth' => null,
|
||||
'onlyActiveBranch' => true,
|
||||
'renderParents' => false
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the given $container by invoking the partial view helper
|
||||
*
|
||||
* The container will simply be passed on as a model to the view script
|
||||
* as-is, and will be available in the partial script as 'container', e.g.
|
||||
* <code>echo 'Number of pages: ', count($this->container);</code>.
|
||||
*
|
||||
* @param Zend_Navigation_Container $container [optional] container to
|
||||
* pass to view script. Default
|
||||
* is to use the container
|
||||
* registered in the helper.
|
||||
* @param string|array $partial [optional] partial view
|
||||
* script to use. Default is to
|
||||
* use the partial registered
|
||||
* in the helper. If an array
|
||||
* is given, it is expected to
|
||||
* contain two values; the
|
||||
* partial view script to use,
|
||||
* and the module where the
|
||||
* script can be found.
|
||||
* @return string helper output
|
||||
*/
|
||||
public function renderPartial(Zend_Navigation_Container $container = null,
|
||||
$partial = null)
|
||||
{
|
||||
if (null === $container) {
|
||||
$container = $this->getContainer();
|
||||
}
|
||||
|
||||
if (null === $partial) {
|
||||
$partial = $this->getPartial();
|
||||
}
|
||||
|
||||
if (empty($partial)) {
|
||||
require_once 'Zend/View/Exception.php';
|
||||
$e = new Zend_View_Exception(
|
||||
'Unable to render menu: No partial view script provided'
|
||||
);
|
||||
$e->setView($this->view);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$model = array(
|
||||
'container' => $container
|
||||
);
|
||||
|
||||
if (is_array($partial)) {
|
||||
if (count($partial) != 2) {
|
||||
require_once 'Zend/View/Exception.php';
|
||||
$e = new Zend_View_Exception(
|
||||
'Unable to render menu: A view partial supplied as '
|
||||
. 'an array must contain two values: partial view '
|
||||
. 'script and module where script can be found'
|
||||
);
|
||||
$e->setView($this->view);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this->view->partial($partial[0], $partial[1], $model);
|
||||
}
|
||||
|
||||
return $this->view->partial($partial, null, $model);
|
||||
}
|
||||
|
||||
// Zend_View_Helper_Navigation_Helper:
|
||||
|
||||
/**
|
||||
* Renders menu
|
||||
*
|
||||
* Implements {@link Zend_View_Helper_Navigation_Helper::render()}.
|
||||
*
|
||||
* If a partial view is registered in the helper, the menu will be rendered
|
||||
* using the given partial script. If no partial is registered, the menu
|
||||
* will be rendered as an 'ul' element by the helper's internal method.
|
||||
*
|
||||
* @see renderPartial()
|
||||
* @see renderMenu()
|
||||
*
|
||||
* @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 ($partial = $this->getPartial()) {
|
||||
return $this->renderPartial($container, $partial);
|
||||
} else {
|
||||
return $this->renderMenu($container);
|
||||
}
|
||||
}
|
||||
}
|
483
library/Zend/View/Helper/Navigation/Sitemap.php
Normal file
483
library/Zend/View/Helper/Navigation/Sitemap.php
Normal file
|
@ -0,0 +1,483 @@
|
|||
<?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-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id: Sitemap.php 20104 2010-01-06 21:26:01Z matthew $
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Zend_View_Helper_Navigation_HelperAbstract
|
||||
*/
|
||||
require_once 'Zend/View/Helper/Navigation/HelperAbstract.php';
|
||||
|
||||
/**
|
||||
* Helper for printing sitemaps
|
||||
*
|
||||
* @link http://www.sitemaps.org/protocol.php
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend_View
|
||||
* @subpackage Helper
|
||||
* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Zend_View_Helper_Navigation_Sitemap
|
||||
extends Zend_View_Helper_Navigation_HelperAbstract
|
||||
{
|
||||
/**
|
||||
* Namespace for the <urlset> tag
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SITEMAP_NS = 'http://www.sitemaps.org/schemas/sitemap/0.9';
|
||||
|
||||
/**
|
||||
* Schema URL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SITEMAP_XSD = 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd';
|
||||
|
||||
/**
|
||||
* Whether XML output should be formatted
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_formatOutput = false;
|
||||
|
||||
/**
|
||||
* Whether the XML declaration should be included in XML output
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_useXmlDeclaration = true;
|
||||
|
||||
/**
|
||||
* Whether sitemap should be validated using Zend_Validate_Sitemap_*
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_useSitemapValidators = true;
|
||||
|
||||
/**
|
||||
* Whether sitemap should be schema validated when generated
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_useSchemaValidation = false;
|
||||
|
||||
/**
|
||||
* Server url
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_serverUrl;
|
||||
|
||||
/**
|
||||
* 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_Sitemap fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function sitemap(Zend_Navigation_Container $container = null)
|
||||
{
|
||||
if (null !== $container) {
|
||||
$this->setContainer($container);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Accessors:
|
||||
|
||||
/**
|
||||
* Sets whether XML output should be formatted
|
||||
*
|
||||
* @param bool $formatOutput [optional] whether output
|
||||
* should be formatted. Default
|
||||
* is true.
|
||||
* @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setFormatOutput($formatOutput = true)
|
||||
{
|
||||
$this->_formatOutput = (bool) $formatOutput;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether XML output should be formatted
|
||||
*
|
||||
* @return bool whether XML output should be formatted
|
||||
*/
|
||||
public function getFormatOutput()
|
||||
{
|
||||
return $this->_formatOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the XML declaration should be used in output
|
||||
*
|
||||
* @param bool $useXmlDecl whether XML delcaration
|
||||
* should be rendered
|
||||
* @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setUseXmlDeclaration($useXmlDecl)
|
||||
{
|
||||
$this->_useXmlDeclaration = (bool) $useXmlDecl;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the XML declaration should be used in output
|
||||
*
|
||||
* @return bool whether the XML declaration should be used in output
|
||||
*/
|
||||
public function getUseXmlDeclaration()
|
||||
{
|
||||
return $this->_useXmlDeclaration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether sitemap should be validated using Zend_Validate_Sitemap_*
|
||||
*
|
||||
* @param bool $useSitemapValidators whether sitemap validators
|
||||
* should be used
|
||||
* @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setUseSitemapValidators($useSitemapValidators)
|
||||
{
|
||||
$this->_useSitemapValidators = (bool) $useSitemapValidators;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether sitemap should be validated using Zend_Validate_Sitemap_*
|
||||
*
|
||||
* @return bool whether sitemap should be validated using validators
|
||||
*/
|
||||
public function getUseSitemapValidators()
|
||||
{
|
||||
return $this->_useSitemapValidators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether sitemap should be schema validated when generated
|
||||
*
|
||||
* @param bool $schemaValidation whether sitemap should
|
||||
* validated using XSD Schema
|
||||
* @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setUseSchemaValidation($schemaValidation)
|
||||
{
|
||||
$this->_useSchemaValidation = (bool) $schemaValidation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if sitemap should be schema validated when generated
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseSchemaValidation()
|
||||
{
|
||||
return $this->_useSchemaValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets server url (scheme and host-related stuff without request URI)
|
||||
*
|
||||
* E.g. http://www.example.com
|
||||
*
|
||||
* @param string $serverUrl server URL to set (only
|
||||
* scheme and host)
|
||||
* @throws Zend_Uri_Exception if invalid server URL
|
||||
* @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
|
||||
* self
|
||||
*/
|
||||
public function setServerUrl($serverUrl)
|
||||
{
|
||||
require_once 'Zend/Uri.php';
|
||||
$uri = Zend_Uri::factory($serverUrl);
|
||||
$uri->setFragment('');
|
||||
$uri->setPath('');
|
||||
$uri->setQuery('');
|
||||
|
||||
if ($uri->valid()) {
|
||||
$this->_serverUrl = $uri->getUri();
|
||||
} else {
|
||||
require_once 'Zend/Uri/Exception.php';
|
||||
$e = new Zend_Uri_Exception(sprintf(
|
||||
'Invalid server URL: "%s"',
|
||||
$serverUrl));
|
||||
$e->setView($this->view);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns server URL
|
||||
*
|
||||
* @return string server URL
|
||||
*/
|
||||
public function getServerUrl()
|
||||
{
|
||||
if (!isset($this->_serverUrl)) {
|
||||
$this->_serverUrl = $this->view->serverUrl();
|
||||
}
|
||||
|
||||
return $this->_serverUrl;
|
||||
}
|
||||
|
||||
// Helper methods:
|
||||
|
||||
/**
|
||||
* Escapes string for XML usage
|
||||
*
|
||||
* @param string $string string to escape
|
||||
* @return string escaped string
|
||||
*/
|
||||
protected function _xmlEscape($string)
|
||||
{
|
||||
$enc = 'UTF-8';
|
||||
if ($this->view instanceof Zend_View_Interface
|
||||
&& method_exists($this->view, 'getEncoding')
|
||||
) {
|
||||
$enc = $this->view->getEncoding();
|
||||
}
|
||||
|
||||
// TODO: remove check when minimum PHP version is >= 5.2.3
|
||||
if (version_compare(PHP_VERSION, '5.2.3', '>=')) {
|
||||
// do not encode existing HTML entities
|
||||
return htmlspecialchars($string, ENT_QUOTES, $enc, false);
|
||||
} else {
|
||||
$string = preg_replace('/&(?!(?:#\d++|[a-z]++);)/ui', '&', $string);
|
||||
$string = str_replace(array('<', '>', '\'', '"'), array('<', '>', ''', '"'), $string);
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
// Public methods:
|
||||
|
||||
/**
|
||||
* Returns an escaped absolute URL for the given page
|
||||
*
|
||||
* @param Zend_Navigation_Page $page page to get URL from
|
||||
* @return string
|
||||
*/
|
||||
public function url(Zend_Navigation_Page $page)
|
||||
{
|
||||
$href = $page->getHref();
|
||||
|
||||
if (!isset($href{0})) {
|
||||
// no href
|
||||
return '';
|
||||
} elseif ($href{0} == '/') {
|
||||
// href is relative to root; use serverUrl helper
|
||||
$url = $this->getServerUrl() . $href;
|
||||
} elseif (preg_match('/^[a-z]+:/im', (string) $href)) {
|
||||
// scheme is given in href; assume absolute URL already
|
||||
$url = (string) $href;
|
||||
} else {
|
||||
// href is relative to current document; use url helpers
|
||||
$url = $this->getServerUrl()
|
||||
. rtrim($this->view->url(), '/') . '/'
|
||||
. $href;
|
||||
}
|
||||
|
||||
return $this->_xmlEscape($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a DOMDocument containing the Sitemap XML for the given container
|
||||
*
|
||||
* @param Zend_Navigation_Container $container [optional] container to get
|
||||
* breadcrumbs from, defaults
|
||||
* to what is registered in the
|
||||
* helper
|
||||
* @return DOMDocument DOM representation of the
|
||||
* container
|
||||
* @throws Zend_View_Exception if schema validation is on
|
||||
* and the sitemap is invalid
|
||||
* according to the sitemap
|
||||
* schema, or if sitemap
|
||||
* validators are used and the
|
||||
* loc element fails validation
|
||||
*/
|
||||
public function getDomSitemap(Zend_Navigation_Container $container = null)
|
||||
{
|
||||
if (null === $container) {
|
||||
$container = $this->getContainer();
|
||||
}
|
||||
|
||||
// check if we should validate using our own validators
|
||||
if ($this->getUseSitemapValidators()) {
|
||||
require_once 'Zend/Validate/Sitemap/Changefreq.php';
|
||||
require_once 'Zend/Validate/Sitemap/Lastmod.php';
|
||||
require_once 'Zend/Validate/Sitemap/Loc.php';
|
||||
require_once 'Zend/Validate/Sitemap/Priority.php';
|
||||
|
||||
// create validators
|
||||
$locValidator = new Zend_Validate_Sitemap_Loc();
|
||||
$lastmodValidator = new Zend_Validate_Sitemap_Lastmod();
|
||||
$changefreqValidator = new Zend_Validate_Sitemap_Changefreq();
|
||||
$priorityValidator = new Zend_Validate_Sitemap_Priority();
|
||||
}
|
||||
|
||||
// create document
|
||||
$dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$dom->formatOutput = $this->getFormatOutput();
|
||||
|
||||
// ...and urlset (root) element
|
||||
$urlSet = $dom->createElementNS(self::SITEMAP_NS, 'urlset');
|
||||
$dom->appendChild($urlSet);
|
||||
|
||||
// create iterator
|
||||
$iterator = new RecursiveIteratorIterator($container,
|
||||
RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
$maxDepth = $this->getMaxDepth();
|
||||
if (is_int($maxDepth)) {
|
||||
$iterator->setMaxDepth($maxDepth);
|
||||
}
|
||||
$minDepth = $this->getMinDepth();
|
||||
if (!is_int($minDepth) || $minDepth < 0) {
|
||||
$minDepth = 0;
|
||||
}
|
||||
|
||||
// iterate container
|
||||
foreach ($iterator as $page) {
|
||||
if ($iterator->getDepth() < $minDepth || !$this->accept($page)) {
|
||||
// page should not be included
|
||||
continue;
|
||||
}
|
||||
|
||||
// get absolute url from page
|
||||
if (!$url = $this->url($page)) {
|
||||
// skip page if it has no url (rare case)
|
||||
continue;
|
||||
}
|
||||
|
||||
// create url node for this page
|
||||
$urlNode = $dom->createElementNS(self::SITEMAP_NS, 'url');
|
||||
$urlSet->appendChild($urlNode);
|
||||
|
||||
if ($this->getUseSitemapValidators() &&
|
||||
!$locValidator->isValid($url)) {
|
||||
require_once 'Zend/View/Exception.php';
|
||||
$e = new Zend_View_Exception(sprintf(
|
||||
'Encountered an invalid URL for Sitemap XML: "%s"',
|
||||
$url));
|
||||
$e->setView($this->view);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// put url in 'loc' element
|
||||
$urlNode->appendChild($dom->createElementNS(self::SITEMAP_NS,
|
||||
'loc', $url));
|
||||
|
||||
// add 'lastmod' element if a valid lastmod is set in page
|
||||
if (isset($page->lastmod)) {
|
||||
$lastmod = strtotime((string) $page->lastmod);
|
||||
|
||||
// prevent 1970-01-01...
|
||||
if ($lastmod !== false) {
|
||||
$lastmod = date('c', $lastmod);
|
||||
}
|
||||
|
||||
if (!$this->getUseSitemapValidators() ||
|
||||
$lastmodValidator->isValid($lastmod)) {
|
||||
$urlNode->appendChild(
|
||||
$dom->createElementNS(self::SITEMAP_NS, 'lastmod',
|
||||
$lastmod)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// add 'changefreq' element if a valid changefreq is set in page
|
||||
if (isset($page->changefreq)) {
|
||||
$changefreq = $page->changefreq;
|
||||
if (!$this->getUseSitemapValidators() ||
|
||||
$changefreqValidator->isValid($changefreq)) {
|
||||
$urlNode->appendChild(
|
||||
$dom->createElementNS(self::SITEMAP_NS, 'changefreq',
|
||||
$changefreq)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// add 'priority' element if a valid priority is set in page
|
||||
if (isset($page->priority)) {
|
||||
$priority = $page->priority;
|
||||
if (!$this->getUseSitemapValidators() ||
|
||||
$priorityValidator->isValid($priority)) {
|
||||
$urlNode->appendChild(
|
||||
$dom->createElementNS(self::SITEMAP_NS, 'priority',
|
||||
$priority)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate using schema if specified
|
||||
if ($this->getUseSchemaValidation()) {
|
||||
if (!@$dom->schemaValidate(self::SITEMAP_XSD)) {
|
||||
require_once 'Zend/View/Exception.php';
|
||||
$e = new Zend_View_Exception(sprintf(
|
||||
'Sitemap is invalid according to XML Schema at "%s"',
|
||||
self::SITEMAP_XSD));
|
||||
$e->setView($this->view);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
$dom = $this->getDomSitemap($container);
|
||||
|
||||
$xml = $this->getUseXmlDeclaration() ?
|
||||
$dom->saveXML() :
|
||||
$dom->saveXML($dom->documentElement);
|
||||
|
||||
return rtrim($xml, PHP_EOL);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue