adding zend project folders into old campcaster.

This commit is contained in:
naomiaro 2010-12-07 14:19:27 -05:00
parent 56abfaf28e
commit 7ef0c18b26
4045 changed files with 1054952 additions and 0 deletions

View 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 = ' &gt; ';
/**
* 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);
}
}
}

View 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);
}

View 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'
);
}
}
}

View 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) : '';
}
}

View 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);
}
}
}

View 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', '&amp;', $string);
$string = str_replace(array('<', '>', '\'', '"'), array('&lt;', '&gt;', '&#39;', '&quot;'), $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);
}
}