PageRenderTime 22ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Zend/View/Helper/Navigation/Sitemap.php

https://gitlab.com/LisovyiEvhenii/ismextensions
PHP | 444 lines | 192 code | 51 blank | 201 comment | 27 complexity | 960d3bd171fbe2ca66ba073afd33140a MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_View
  17. * @subpackage Helper
  18. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_View_Helper_Navigation_HelperAbstract
  24. */
  25. #require_once 'Zend/View/Helper/Navigation/HelperAbstract.php';
  26. /**
  27. * Helper for printing sitemaps
  28. *
  29. * @link http://www.sitemaps.org/protocol.php
  30. *
  31. * @category Zend
  32. * @package Zend_View
  33. * @subpackage Helper
  34. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  35. * @license http://framework.zend.com/license/new-bsd New BSD License
  36. */
  37. class Zend_View_Helper_Navigation_Sitemap
  38. extends Zend_View_Helper_Navigation_HelperAbstract
  39. {
  40. /**
  41. * Namespace for the <urlset> tag
  42. *
  43. * @var string
  44. */
  45. const SITEMAP_NS = 'http://www.sitemaps.org/schemas/sitemap/0.9';
  46. /**
  47. * Schema URL
  48. *
  49. * @var string
  50. */
  51. const SITEMAP_XSD = 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd';
  52. /**
  53. * Whether the XML declaration should be included in XML output
  54. *
  55. * @var bool
  56. */
  57. protected $_useXmlDeclaration = true;
  58. /**
  59. * Whether sitemap should be validated using Zend_Validate_Sitemap_*
  60. *
  61. * @var bool
  62. */
  63. protected $_useSitemapValidators = true;
  64. /**
  65. * Whether sitemap should be schema validated when generated
  66. *
  67. * @var bool
  68. */
  69. protected $_useSchemaValidation = false;
  70. /**
  71. * Server url
  72. *
  73. * @var string
  74. */
  75. protected $_serverUrl;
  76. /**
  77. * View helper entry point:
  78. * Retrieves helper and optionally sets container to operate on
  79. *
  80. * @param Zend_Navigation_Container $container [optional] container to
  81. * operate on
  82. * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
  83. * self
  84. */
  85. public function sitemap(Zend_Navigation_Container $container = null)
  86. {
  87. if (null !== $container) {
  88. $this->setContainer($container);
  89. }
  90. return $this;
  91. }
  92. // Accessors:
  93. /**
  94. * Sets whether the XML declaration should be used in output
  95. *
  96. * @param bool $useXmlDecl whether XML delcaration
  97. * should be rendered
  98. * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
  99. * self
  100. */
  101. public function setUseXmlDeclaration($useXmlDecl)
  102. {
  103. $this->_useXmlDeclaration = (bool) $useXmlDecl;
  104. return $this;
  105. }
  106. /**
  107. * Returns whether the XML declaration should be used in output
  108. *
  109. * @return bool whether the XML declaration should be used in output
  110. */
  111. public function getUseXmlDeclaration()
  112. {
  113. return $this->_useXmlDeclaration;
  114. }
  115. /**
  116. * Sets whether sitemap should be validated using Zend_Validate_Sitemap_*
  117. *
  118. * @param bool $useSitemapValidators whether sitemap validators
  119. * should be used
  120. * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
  121. * self
  122. */
  123. public function setUseSitemapValidators($useSitemapValidators)
  124. {
  125. $this->_useSitemapValidators = (bool) $useSitemapValidators;
  126. return $this;
  127. }
  128. /**
  129. * Returns whether sitemap should be validated using Zend_Validate_Sitemap_*
  130. *
  131. * @return bool whether sitemap should be validated using validators
  132. */
  133. public function getUseSitemapValidators()
  134. {
  135. return $this->_useSitemapValidators;
  136. }
  137. /**
  138. * Sets whether sitemap should be schema validated when generated
  139. *
  140. * @param bool $schemaValidation whether sitemap should
  141. * validated using XSD Schema
  142. * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
  143. * self
  144. */
  145. public function setUseSchemaValidation($schemaValidation)
  146. {
  147. $this->_useSchemaValidation = (bool) $schemaValidation;
  148. return $this;
  149. }
  150. /**
  151. * Returns true if sitemap should be schema validated when generated
  152. *
  153. * @return bool
  154. */
  155. public function getUseSchemaValidation()
  156. {
  157. return $this->_useSchemaValidation;
  158. }
  159. /**
  160. * Sets server url (scheme and host-related stuff without request URI)
  161. *
  162. * E.g. http://www.example.com
  163. *
  164. * @param string $serverUrl server URL to set (only
  165. * scheme and host)
  166. * @throws Zend_Uri_Exception if invalid server URL
  167. * @return Zend_View_Helper_Navigation_Sitemap fluent interface, returns
  168. * self
  169. */
  170. public function setServerUrl($serverUrl)
  171. {
  172. #require_once 'Zend/Uri.php';
  173. $uri = Zend_Uri::factory($serverUrl);
  174. $uri->setFragment('');
  175. $uri->setPath('');
  176. $uri->setQuery('');
  177. if ($uri->valid()) {
  178. $this->_serverUrl = $uri->getUri();
  179. } else {
  180. #require_once 'Zend/Uri/Exception.php';
  181. $e = new Zend_Uri_Exception(sprintf(
  182. 'Invalid server URL: "%s"',
  183. $serverUrl));
  184. $e->setView($this->view);
  185. throw $e;
  186. }
  187. return $this;
  188. }
  189. /**
  190. * Returns server URL
  191. *
  192. * @return string server URL
  193. */
  194. public function getServerUrl()
  195. {
  196. if (!isset($this->_serverUrl)) {
  197. $this->_serverUrl = $this->view->serverUrl();
  198. }
  199. return $this->_serverUrl;
  200. }
  201. // Helper methods:
  202. /**
  203. * Escapes string for XML usage
  204. *
  205. * @param string $string string to escape
  206. * @return string escaped string
  207. */
  208. protected function _xmlEscape($string)
  209. {
  210. $enc = 'UTF-8';
  211. if ($this->view instanceof Zend_View_Interface
  212. && method_exists($this->view, 'getEncoding')
  213. ) {
  214. $enc = $this->view->getEncoding();
  215. }
  216. // do not encode existing HTML entities
  217. return htmlspecialchars($string, ENT_QUOTES, $enc, false);
  218. }
  219. // Public methods:
  220. /**
  221. * Returns an escaped absolute URL for the given page
  222. *
  223. * @param Zend_Navigation_Page $page page to get URL from
  224. * @return string
  225. */
  226. public function url(Zend_Navigation_Page $page)
  227. {
  228. $href = $page->getHref();
  229. if (!isset($href{0})) {
  230. // no href
  231. return '';
  232. } elseif ($href{0} == '/') {
  233. // href is relative to root; use serverUrl helper
  234. $url = $this->getServerUrl() . $href;
  235. } elseif (preg_match('/^[a-z]+:/im', (string) $href)) {
  236. // scheme is given in href; assume absolute URL already
  237. $url = (string) $href;
  238. } else {
  239. // href is relative to current document; use url helpers
  240. $url = $this->getServerUrl()
  241. . rtrim($this->view->url(), '/') . '/'
  242. . $href;
  243. }
  244. return $this->_xmlEscape($url);
  245. }
  246. /**
  247. * Returns a DOMDocument containing the Sitemap XML for the given container
  248. *
  249. * @param Zend_Navigation_Container $container [optional] container to get
  250. * breadcrumbs from, defaults
  251. * to what is registered in the
  252. * helper
  253. * @return DOMDocument DOM representation of the
  254. * container
  255. * @throws Zend_View_Exception if schema validation is on
  256. * and the sitemap is invalid
  257. * according to the sitemap
  258. * schema, or if sitemap
  259. * validators are used and the
  260. * loc element fails validation
  261. */
  262. public function getDomSitemap(Zend_Navigation_Container $container = null)
  263. {
  264. if (null === $container) {
  265. $container = $this->getContainer();
  266. }
  267. // check if we should validate using our own validators
  268. if ($this->getUseSitemapValidators()) {
  269. #require_once 'Zend/Validate/Sitemap/Changefreq.php';
  270. #require_once 'Zend/Validate/Sitemap/Lastmod.php';
  271. #require_once 'Zend/Validate/Sitemap/Loc.php';
  272. #require_once 'Zend/Validate/Sitemap/Priority.php';
  273. // create validators
  274. $locValidator = new Zend_Validate_Sitemap_Loc();
  275. $lastmodValidator = new Zend_Validate_Sitemap_Lastmod();
  276. $changefreqValidator = new Zend_Validate_Sitemap_Changefreq();
  277. $priorityValidator = new Zend_Validate_Sitemap_Priority();
  278. }
  279. // create document
  280. $dom = new DOMDocument('1.0', 'UTF-8');
  281. $dom->formatOutput = $this->getFormatOutput();
  282. // ...and urlset (root) element
  283. $urlSet = $dom->createElementNS(self::SITEMAP_NS, 'urlset');
  284. $dom->appendChild($urlSet);
  285. // create iterator
  286. $iterator = new RecursiveIteratorIterator($container,
  287. RecursiveIteratorIterator::SELF_FIRST);
  288. $maxDepth = $this->getMaxDepth();
  289. if (is_int($maxDepth)) {
  290. $iterator->setMaxDepth($maxDepth);
  291. }
  292. $minDepth = $this->getMinDepth();
  293. if (!is_int($minDepth) || $minDepth < 0) {
  294. $minDepth = 0;
  295. }
  296. // iterate container
  297. foreach ($iterator as $page) {
  298. if ($iterator->getDepth() < $minDepth || !$this->accept($page)) {
  299. // page should not be included
  300. continue;
  301. }
  302. // get absolute url from page
  303. if (!$url = $this->url($page)) {
  304. // skip page if it has no url (rare case)
  305. continue;
  306. }
  307. // create url node for this page
  308. $urlNode = $dom->createElementNS(self::SITEMAP_NS, 'url');
  309. $urlSet->appendChild($urlNode);
  310. if ($this->getUseSitemapValidators() &&
  311. !$locValidator->isValid($url)) {
  312. #require_once 'Zend/View/Exception.php';
  313. $e = new Zend_View_Exception(sprintf(
  314. 'Encountered an invalid URL for Sitemap XML: "%s"',
  315. $url));
  316. $e->setView($this->view);
  317. throw $e;
  318. }
  319. // put url in 'loc' element
  320. $urlNode->appendChild($dom->createElementNS(self::SITEMAP_NS,
  321. 'loc', $url));
  322. // add 'lastmod' element if a valid lastmod is set in page
  323. if (isset($page->lastmod)) {
  324. $lastmod = strtotime((string) $page->lastmod);
  325. // prevent 1970-01-01...
  326. if ($lastmod !== false) {
  327. $lastmod = date('c', $lastmod);
  328. }
  329. if (!$this->getUseSitemapValidators() ||
  330. $lastmodValidator->isValid($lastmod)) {
  331. $urlNode->appendChild(
  332. $dom->createElementNS(self::SITEMAP_NS, 'lastmod',
  333. $lastmod)
  334. );
  335. }
  336. }
  337. // add 'changefreq' element if a valid changefreq is set in page
  338. if (isset($page->changefreq)) {
  339. $changefreq = $page->changefreq;
  340. if (!$this->getUseSitemapValidators() ||
  341. $changefreqValidator->isValid($changefreq)) {
  342. $urlNode->appendChild(
  343. $dom->createElementNS(self::SITEMAP_NS, 'changefreq',
  344. $changefreq)
  345. );
  346. }
  347. }
  348. // add 'priority' element if a valid priority is set in page
  349. if (isset($page->priority)) {
  350. $priority = $page->priority;
  351. if (!$this->getUseSitemapValidators() ||
  352. $priorityValidator->isValid($priority)) {
  353. $urlNode->appendChild(
  354. $dom->createElementNS(self::SITEMAP_NS, 'priority',
  355. $priority)
  356. );
  357. }
  358. }
  359. }
  360. // validate using schema if specified
  361. if ($this->getUseSchemaValidation()) {
  362. if (!@$dom->schemaValidate(self::SITEMAP_XSD)) {
  363. #require_once 'Zend/View/Exception.php';
  364. $e = new Zend_View_Exception(sprintf(
  365. 'Sitemap is invalid according to XML Schema at "%s"',
  366. self::SITEMAP_XSD));
  367. $e->setView($this->view);
  368. throw $e;
  369. }
  370. }
  371. return $dom;
  372. }
  373. // Zend_View_Helper_Navigation_Helper:
  374. /**
  375. * Renders helper
  376. *
  377. * Implements {@link Zend_View_Helper_Navigation_Helper::render()}.
  378. *
  379. * @param Zend_Navigation_Container $container [optional] container to
  380. * render. Default is to
  381. * render the container
  382. * registered in the helper.
  383. * @return string helper output
  384. */
  385. public function render(Zend_Navigation_Container $container = null)
  386. {
  387. $dom = $this->getDomSitemap($container);
  388. $xml = $this->getUseXmlDeclaration() ?
  389. $dom->saveXML() :
  390. $dom->saveXML($dom->documentElement);
  391. return rtrim($xml, self::EOL);
  392. }
  393. }