00001 <?php
00026 require_once 'Zend/View/Helper/Navigation/HelperAbstract.php';
00027
00039 class Zend_View_Helper_Navigation_Sitemap
00040 extends Zend_View_Helper_Navigation_HelperAbstract
00041 {
00047 const SITEMAP_NS = 'http://www.sitemaps.org/schemas/sitemap/0.9';
00048
00054 const SITEMAP_XSD = 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd';
00055
00061 protected $_formatOutput = false;
00062
00068 protected $_useXmlDeclaration = true;
00069
00075 protected $_useSitemapValidators = true;
00076
00082 protected $_useSchemaValidation = false;
00083
00089 protected $_serverUrl;
00090
00100 public function sitemap(Zend_Navigation_Container $container = null)
00101 {
00102 if (null !== $container) {
00103 $this->setContainer($container);
00104 }
00105
00106 return $this;
00107 }
00108
00109
00110
00120 public function setFormatOutput($formatOutput = true)
00121 {
00122 $this->_formatOutput = (bool) $formatOutput;
00123 return $this;
00124 }
00125
00131 public function getFormatOutput()
00132 {
00133 return $this->_formatOutput;
00134 }
00135
00144 public function setUseXmlDeclaration($useXmlDecl)
00145 {
00146 $this->_useXmlDeclaration = (bool) $useXmlDecl;
00147 return $this;
00148 }
00149
00155 public function getUseXmlDeclaration()
00156 {
00157 return $this->_useXmlDeclaration;
00158 }
00159
00168 public function setUseSitemapValidators($useSitemapValidators)
00169 {
00170 $this->_useSitemapValidators = (bool) $useSitemapValidators;
00171 return $this;
00172 }
00173
00179 public function getUseSitemapValidators()
00180 {
00181 return $this->_useSitemapValidators;
00182 }
00183
00192 public function setUseSchemaValidation($schemaValidation)
00193 {
00194 $this->_useSchemaValidation = (bool) $schemaValidation;
00195 return $this;
00196 }
00197
00203 public function getUseSchemaValidation()
00204 {
00205 return $this->_useSchemaValidation;
00206 }
00207
00219 public function setServerUrl($serverUrl)
00220 {
00221 require_once 'Zend/Uri.php';
00222 $uri = Zend_Uri::factory($serverUrl);
00223 $uri->setFragment('');
00224 $uri->setPath('');
00225 $uri->setQuery('');
00226
00227 if ($uri->valid()) {
00228 $this->_serverUrl = $uri->getUri();
00229 } else {
00230 require_once 'Zend/Uri/Exception.php';
00231 throw new Zend_Uri_Exception(sprintf(
00232 'Invalid server URL: "%s"',
00233 $serverUrl));
00234 }
00235
00236 return $this;
00237 }
00238
00244 public function getServerUrl()
00245 {
00246 if (!isset($this->_serverUrl)) {
00247 $this->_serverUrl = $this->view->serverUrl();
00248 }
00249
00250 return $this->_serverUrl;
00251 }
00252
00253
00254
00261 protected function _xmlEscape($string)
00262 {
00263 $enc = 'UTF-8';
00264 if ($this->view instanceof Zend_View_Interface
00265 && method_exists($this->view, 'getEncoding')
00266 ) {
00267 $enc = $this->view->getEncoding();
00268 }
00269
00270
00271 if (version_compare(PHP_VERSION, '5.2.3', '>=')) {
00272
00273 return htmlspecialchars($string, ENT_QUOTES, $enc, false);
00274 } else {
00275 $string = preg_replace('/&(?!(?:#\d++|[a-z]++);)/ui', '&', $string);
00276 $string = str_replace(array('<', '>', '\'', '"'), array('<', '>', ''', '"'), $string);
00277 return $string;
00278 }
00279 }
00280
00281
00282
00289 public function url(Zend_Navigation_Page $page)
00290 {
00291 $href = $page->getHref();
00292
00293 if (!isset($href{0})) {
00294
00295 return '';
00296 } elseif ($href{0} == '/') {
00297
00298 $url = $this->getServerUrl() . $href;
00299 } elseif (preg_match('/^[a-z]+:/im', (string) $href)) {
00300
00301 $url = (string) $href;
00302 } else {
00303
00304 $url = $this->getServerUrl()
00305 . rtrim($this->view->url(), '/') . '/'
00306 . $href;
00307 }
00308
00309 return $this->_xmlEscape($url);
00310 }
00311
00328 public function getDomSitemap(Zend_Navigation_Container $container = null)
00329 {
00330 if (null === $container) {
00331 $container = $this->getContainer();
00332 }
00333
00334
00335 if ($this->getUseSitemapValidators()) {
00336 require_once 'Zend/Validate/Sitemap/Changefreq.php';
00337 require_once 'Zend/Validate/Sitemap/Lastmod.php';
00338 require_once 'Zend/Validate/Sitemap/Loc.php';
00339 require_once 'Zend/Validate/Sitemap/Priority.php';
00340
00341
00342 $locValidator = new Zend_Validate_Sitemap_Loc();
00343 $lastmodValidator = new Zend_Validate_Sitemap_Lastmod();
00344 $changefreqValidator = new Zend_Validate_Sitemap_Changefreq();
00345 $priorityValidator = new Zend_Validate_Sitemap_Priority();
00346 }
00347
00348
00349 $dom = new DOMDocument('1.0', 'UTF-8');
00350 $dom->formatOutput = $this->getFormatOutput();
00351
00352
00353 $urlSet = $dom->createElementNS(self::SITEMAP_NS, 'urlset');
00354 $dom->appendChild($urlSet);
00355
00356
00357 $iterator = new RecursiveIteratorIterator($container,
00358 RecursiveIteratorIterator::SELF_FIRST);
00359
00360 $maxDepth = $this->getMaxDepth();
00361 if (is_int($maxDepth)) {
00362 $iterator->setMaxDepth($maxDepth);
00363 }
00364 $minDepth = $this->getMinDepth();
00365 if (!is_int($minDepth) || $minDepth < 0) {
00366 $minDepth = 0;
00367 }
00368
00369
00370 foreach ($iterator as $page) {
00371 if ($iterator->getDepth() < $minDepth || !$this->accept($page)) {
00372
00373 continue;
00374 }
00375
00376
00377 if (!$url = $this->url($page)) {
00378
00379 continue;
00380 }
00381
00382
00383 $urlNode = $dom->createElementNS(self::SITEMAP_NS, 'url');
00384 $urlSet->appendChild($urlNode);
00385
00386 if ($this->getUseSitemapValidators() &&
00387 !$locValidator->isValid($url)) {
00388 require_once 'Zend/View/Exception.php';
00389 throw new Zend_View_Exception(sprintf(
00390 'Encountered an invalid URL for Sitemap XML: "%s"',
00391 $url));
00392 }
00393
00394
00395 $urlNode->appendChild($dom->createElementNS(self::SITEMAP_NS,
00396 'loc', $url));
00397
00398
00399 if (isset($page->lastmod)) {
00400 $lastmod = strtotime((string) $page->lastmod);
00401
00402
00403 if ($lastmod !== false) {
00404 $lastmod = date('c', $lastmod);
00405 }
00406
00407 if (!$this->getUseSitemapValidators() ||
00408 $lastmodValidator->isValid($lastmod)) {
00409 $urlNode->appendChild(
00410 $dom->createElementNS(self::SITEMAP_NS, 'lastmod',
00411 $lastmod)
00412 );
00413 }
00414 }
00415
00416
00417 if (isset($page->changefreq)) {
00418 $changefreq = $page->changefreq;
00419 if (!$this->getUseSitemapValidators() ||
00420 $changefreqValidator->isValid($changefreq)) {
00421 $urlNode->appendChild(
00422 $dom->createElementNS(self::SITEMAP_NS, 'changefreq',
00423 $changefreq)
00424 );
00425 }
00426 }
00427
00428
00429 if (isset($page->priority)) {
00430 $priority = $page->priority;
00431 if (!$this->getUseSitemapValidators() ||
00432 $priorityValidator->isValid($priority)) {
00433 $urlNode->appendChild(
00434 $dom->createElementNS(self::SITEMAP_NS, 'priority',
00435 $priority)
00436 );
00437 }
00438 }
00439 }
00440
00441
00442 if ($this->getUseSchemaValidation()) {
00443 if (!@$dom->schemaValidate(self::SITEMAP_XSD)) {
00444 require_once 'Zend/View/Exception.php';
00445 throw new Zend_View_Exception(sprintf(
00446 'Sitemap is invalid according to XML Schema at "%s"',
00447 self::SITEMAP_XSD));
00448 }
00449 }
00450
00451 return $dom;
00452 }
00453
00454
00455
00467 public function render(Zend_Navigation_Container $container = null)
00468 {
00469 $dom = $this->getDomSitemap($container);
00470
00471 $xml = $this->getUseXmlDeclaration() ?
00472 $dom->saveXML() :
00473 $dom->saveXML($dom->documentElement);
00474
00475 return rtrim($xml, PHP_EOL);
00476 }
00477 }