import v1.1.0_beta1 | 2009-08-21
This commit is contained in:
469
libs/Zend/View/Helper/Navigation/Sitemap.php
Normal file
469
libs/Zend/View/Helper/Navigation/Sitemap.php
Normal file
@ -0,0 +1,469 @@
|
||||
<?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-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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-2008 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';
|
||||
throw new Zend_Uri_Exception(sprintf(
|
||||
'Invalid server URL: "%s"',
|
||||
$serverUrl));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// 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, 'UTF-8', 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';
|
||||
throw new Zend_View_Exception(sprintf(
|
||||
'Encountered an invalid URL for Sitemap XML: "%s"',
|
||||
$url));
|
||||
}
|
||||
|
||||
// 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';
|
||||
throw new Zend_View_Exception(sprintf(
|
||||
'Sitemap is invalid according to XML Schema at "%s"',
|
||||
self::SITEMAP_XSD));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user