| Current Path : /var/www/www.indacotrentino.com/www/vendor/laminas/laminas-view/src/Helper/Navigation/ |
| Current File : /var/www/www.indacotrentino.com/www/vendor/laminas/laminas-view/src/Helper/Navigation/Sitemap.php |
<?php
declare(strict_types=1);
namespace Laminas\View\Helper\Navigation;
use DOMDocument;
use Laminas\Navigation\AbstractContainer;
use Laminas\Navigation\Page\AbstractPage;
use Laminas\Stdlib\ErrorHandler;
use Laminas\Uri;
use Laminas\Validator\Sitemap\Changefreq;
use Laminas\Validator\Sitemap\Lastmod;
use Laminas\Validator\Sitemap\Loc;
use Laminas\Validator\Sitemap\Priority;
use Laminas\View\Exception;
use RecursiveIteratorIterator;
use function date;
use function in_array;
use function is_int;
use function preg_match;
use function rtrim;
use function sprintf;
use function strtotime;
use function trim;
use const PHP_EOL;
/**
* Helper for printing sitemaps
*
* @link http://www.sitemaps.org/protocol.php
*/
class Sitemap extends AbstractHelper
{
/**
* Namespace for the <urlset> tag
*
* @var string
*/
public const SITEMAP_NS = 'http://www.sitemaps.org/schemas/sitemap/0.9';
/**
* Schema URL
*
* @var string
*/
public const SITEMAP_XSD = 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd';
/**
* Whether XML output should be formatted
*
* @var bool
*/
protected $formatOutput = false;
/**
* Server url
*
* @var string
*/
protected $serverUrl;
/**
* List of urls in the sitemap
*
* @var array
*/
protected $urls = [];
/**
* Whether sitemap should be validated using Laminas\Validate\Sitemap\*
*
* @var bool
*/
protected $useSitemapValidators = true;
/**
* Whether sitemap should be schema validated when generated
*
* @var bool
*/
protected $useSchemaValidation = false;
/**
* Whether the XML declaration should be included in XML output
*
* @var bool
*/
protected $useXmlDeclaration = true;
/**
* Helper entry point
*
* @param string|AbstractContainer $container container to operate on
* @return Sitemap
*/
public function __invoke($container = null)
{
if (null !== $container) {
$this->setContainer($container);
}
return $this;
}
/**
* Renders helper
*
* Implements {@link HelperInterface::render()}.
*
* @param AbstractContainer $container [optional] container to render. Default is
* to render the container registered in the helper.
* @return string
*/
public function render($container = null)
{
$dom = $this->getDomSitemap($container);
$xml = $this->getUseXmlDeclaration() ?
$dom->saveXML() :
$dom->saveXML($dom->documentElement);
return rtrim($xml, PHP_EOL);
}
/**
* Returns a DOMDocument containing the Sitemap XML for the given container
*
* @param AbstractContainer|null $container [optional] container to get
* breadcrumbs from, defaults
* to what is registered in the
* helper
* @return DOMDocument DOM representation of the
* container
* @throws Exception\RuntimeException 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(?AbstractContainer $container = null)
{
// Reset the urls
$this->urls = [];
if (null === $container) {
$container = $this->getContainer();
}
$locValidator = null;
$lastmodValidator = null;
$changefreqValidator = null;
$priorityValidator = null;
// check if we should validate using our own validators
if ($this->getUseSitemapValidators()) {
// create validators
$locValidator = new Loc();
$lastmodValidator = new Lastmod();
$changefreqValidator = new Changefreq();
$priorityValidator = new 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)
// or already is in the sitemap
continue;
}
// create url node for this page
$urlNode = $dom->createElementNS(self::SITEMAP_NS, 'url');
$urlSet->appendChild($urlNode);
if (
$this->getUseSitemapValidators()
&& ! $locValidator->isValid($url)
) {
throw new Exception\RuntimeException(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)
) {
// Cast $lastmod to string in case no validation was used
$urlNode->appendChild(
$dom->createElementNS(self::SITEMAP_NS, 'lastmod', (string) $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()) {
ErrorHandler::start();
$test = $dom->schemaValidate(self::SITEMAP_XSD);
$error = ErrorHandler::stop();
if (! $test) {
throw new Exception\RuntimeException(sprintf(
'Sitemap is invalid according to XML Schema at "%s"',
self::SITEMAP_XSD
), 0, $error);
}
}
return $dom;
}
/**
* Returns an escaped absolute URL for the given page
*
* @return null|string
*/
public function url(AbstractPage $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
$basePathHelper = $this->getView()->plugin('basepath');
$curDoc = $basePathHelper();
$curDoc = '/' === $curDoc ? '' : trim($curDoc, '/');
$url = rtrim($this->getServerUrl(), '/') . '/'
. $curDoc
. (empty($curDoc) ? '' : '/') . $href;
}
if (! in_array($url, $this->urls)) {
$this->urls[] = $url;
return $this->xmlEscape($url);
}
return null;
}
/**
* Escapes string for XML usage
*
* @param string $string
* @return string
*/
protected function xmlEscape($string)
{
$escaper = $this->view->plugin('escapeHtml');
return $escaper($string);
}
/**
* Sets whether XML output should be formatted
*
* @param bool $formatOutput
* @return Sitemap
*/
public function setFormatOutput($formatOutput = true)
{
$this->formatOutput = (bool) $formatOutput;
return $this;
}
/**
* Returns whether XML output should be formatted
*
* @return bool
*/
public function getFormatOutput()
{
return $this->formatOutput;
}
/**
* Sets server url (scheme and host-related stuff without request URI)
*
* E.g. http://www.example.com
*
* @param string $serverUrl
* @return Sitemap
* @throws Exception\InvalidArgumentException
*/
public function setServerUrl($serverUrl)
{
$uri = Uri\UriFactory::factory($serverUrl);
$uri->setFragment('');
$uri->setPath('');
$uri->setQuery('');
if ($uri->isValid()) {
$this->serverUrl = $uri->toString();
} else {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid server URL: "%s"',
$serverUrl
));
}
return $this;
}
/**
* Returns server URL
*
* @return string
*/
public function getServerUrl()
{
if (! isset($this->serverUrl)) {
$serverUrlHelper = $this->getView()->plugin('serverUrl');
$this->serverUrl = $serverUrlHelper();
}
return $this->serverUrl;
}
/**
* Sets whether sitemap should be validated using Laminas\Validate\Sitemap_*
*
* @param bool $useSitemapValidators
* @return Sitemap
*/
public function setUseSitemapValidators($useSitemapValidators)
{
$this->useSitemapValidators = (bool) $useSitemapValidators;
return $this;
}
/**
* Returns whether sitemap should be validated using Laminas\Validate\Sitemap_*
*
* @return bool
*/
public function getUseSitemapValidators()
{
return $this->useSitemapValidators;
}
/**
* Sets whether sitemap should be schema validated when generated
*
* @param bool $schemaValidation
* @return Sitemap
*/
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 whether the XML declaration should be used in output
*
* @param bool $useXmlDecl
* @return Sitemap
*/
public function setUseXmlDeclaration($useXmlDecl)
{
$this->useXmlDeclaration = (bool) $useXmlDecl;
return $this;
}
/**
* Returns whether the XML declaration should be used in output
*
* @return bool
*/
public function getUseXmlDeclaration()
{
return $this->useXmlDeclaration;
}
}