1<?php 2/** 3 * Generates individually sitemap.org compatible XML files for use with Google and other search engines. 4 * It supports albums and images as well as optionally Zenpage pages, news articles and news categories. 5 * Sitemaps need to be generated via the button on the admin overview page and are cached as static 6 * files in the <var>/%STATIC_CACHE_FOLDER%/sitemap/</var> folder. 7 * Individual sitemaps are generated for all of the above item types as well as a sitemapindex file. 8 * Album sitemaps are split into individual sitemaps per album (incl. all albums pages) and image sitemaps 9 * into individual sitemaps per album. 10 * 11 * Based on the plugin by Jeppe Toustrup (Tenzer) http://github.com/Tenzer/zenphoto-sitemap 12 * 13 * The sitemapindex file can be referenced via <var>www.yourdomain.com/zenphoto/index.php?sitemap</var> or 14 * with modrewrite <var>www.yourdomain.com/zenphoto/?sitemap</var>. 15 * 16 * <b>IMPORTANT:</b> A multilingual sitemap requires the <var>dynamic-locale</var> plugin and either the <var>seo_locale</var> plugin or <i>language subdomains</i>. 17 * 18 * @author Malte Müller (acrylian), Jeppe Toustrup (Tenzer), timo, Blue Dragonfly and Francois Marechal (frankm) 19 * @package plugins 20 * @subpackage sitemap-extended 21 */ 22$plugin_is_filter = 0 | CLASS_PLUGIN; 23$plugin_description = gettext('Generates sitemap.org compatible XML files for use with Google and other search engines.'); 24$plugin_notice = gettext('<strong>Note:</strong> The index links may not match if using the Zenpage option "news on index" that some themes provide! Also it does not "know" about "custom pages" outside Zenpage or any special custom theme setup!!'); 25$plugin_author = 'Malte Müller (acrylian), Jeppe Toustrup (Tenzer), timo, Blue Dragonfly and Francois Marechal (frankm)'; 26$plugin_category = gettext('SEO'); 27$option_interface = 'sitemapOptions'; 28 29zp_register_filter('admin_utilities_buttons', 'sitemap::button'); 30 31$sitemapfolder = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/sitemap'; 32if (!file_exists($sitemapfolder)) { 33 if (!mkdir_recursive($sitemapfolder, FOLDER_MOD)) { 34 die(gettext("sitemap cache folder could not be created. Please try to create it manually via FTP with chmod 0777.")); 35 } 36} 37if (getOption('sitemap_galleryindex')) { 38 purgeOption('sitemap_galleryindex'); 39} 40define('SITEMAP_CHUNK', getOption('sitemap_processing_chunk')); 41define('GOOGLE_SITEMAP', getOption('sitemap_google')); 42if (getOption('multi_lingual') && defined('LOCALE_TYPE')) { 43 define('SITEMAP_LOCALE_TYPE', LOCALE_TYPE); 44} else { 45 define('SITEMAP_LOCALE_TYPE', 0); 46} 47 48/** 49 * Plugin option handling class 50 * 51 */ 52class sitemapOptions { 53 54 var $startmtime; 55 var $disable = false; // manual disable caching a page 56 57 function __construct() { 58 setOptionDefault('sitemap_changefreq_index', 'daily'); 59 setOptionDefault('sitemap_changefreq_albums', 'daily'); 60 setOptionDefault('sitemap_changefreq_images', 'daily'); 61 setOptionDefault('sitemap_changefreq_pages', 'weekly'); 62 setOptionDefault('sitemap_changefreq_newsindex', 'daily'); 63 setOptionDefault('sitemap_changefreq_news', 'daily'); 64 setOptionDefault('sitemap_changefreq_newscats', 'weekly'); 65 setOptionDefault('sitemap_lastmod_albums', 'mtime'); 66 setOptionDefault('sitemap_lastmod_images', 'mtime'); 67 setOptionDefault('sitemap_processing_chunk', 25); 68 setOptionDefault('sitemap_google', 0); 69 setOptionDefault('sitemap_google_fullimage', 0); 70 } 71 72 function getOptionsSupported() { 73 global $_common_locale_type; 74 $localdesc = '<p>' . gettext('If checked links to the alternative languages will be in the form <code><em>language</em>.domain</code> where <code><em>language</em></code> is the language code, e.g. <code><em>fr</em></code> for French.') . '</p>'; 75 if (!$_common_locale_type) { 76 $localdesc .= '<p>' . gettext('This requires that you have created the appropriate subdomains pointing to your Zenphoto installation. That is <code>fr.mydomain.com/zenphoto/</code> must point to the same location as <code>mydomain.com/zenphoto/</code>. (Some providers will automatically redirect undefined subdomains to the main domain. If your provider does this, no subdomain creation is needed.)') . '</p>'; 77 } 78 $options = array( 79 gettext('Album date') => array( 80 'key' => 'sitemap_lastmod_albums', 81 'type' => OPTION_TYPE_SELECTOR, 82 'order' => 0, 83 'selections' => array( 84 gettext("date") => "date", 85 gettext("mtime") => "mtime", 86 gettext("last change date") => 'lastchange'), 87 'desc' => gettext('Field to use for the last modification date of albums.')), 88 gettext('Image date') => array( 89 'key' => 'sitemap_lastmod_images', 90 'type' => OPTION_TYPE_SELECTOR, 91 'order' => 1, 92 'selections' => array( 93 gettext("date") => "date", 94 gettext("mtime") => "mtime", 95 gettext("last change date") => 'lastchange'), 96 'desc' => gettext('Field to use for the last modification date of images.')), 97 gettext('Change frequency - Zenphoto index') => array( 98 'key' => 'sitemap_changefreq_index', 99 'type' => OPTION_TYPE_SELECTOR, 100 'order' => 2, 101 'selections' => array(gettext("always") => "always", 102 gettext("hourly") => "hourly", 103 gettext("daily") => "daily", 104 gettext("weekly") => "weekly", 105 gettext("monthly") => "monthly", 106 gettext("yearly") => "yearly", 107 gettext("never") => "never"), 108 'desc' => ''), 109 gettext('Change frequency - albums') => array( 110 'key' => 'sitemap_changefreq_albums', 111 'type' => OPTION_TYPE_SELECTOR, 112 'order' => 3, 113 'selections' => array(gettext("always") => "always", 114 gettext("hourly") => "hourly", 115 gettext("daily") => "daily", 116 gettext("weekly") => "weekly", 117 gettext("monthly") => "monthly", 118 gettext("yearly") => "yearly", 119 gettext("never") => "never"), 120 'desc' => ''), 121 gettext('Change frequency - images') => array( 122 'key' => 'sitemap_changefreq_images', 123 'type' => OPTION_TYPE_SELECTOR, 124 'order' => 4, 125 'selections' => array(gettext("always") => "always", 126 gettext("hourly") => "hourly", 127 gettext("daily") => "daily", 128 gettext("weekly") => "weekly", 129 gettext("monthly") => "monthly", 130 gettext("yearly") => "yearly", 131 gettext("never") => "never"), 132 'desc' => ''), 133 gettext('Change frequency - Zenpage pages') => array( 134 'key' => 'sitemap_changefreq_pages', 135 'type' => OPTION_TYPE_SELECTOR, 136 'order' => 5, 137 'selections' => array(gettext("always") => "always", 138 gettext("hourly") => "hourly", 139 gettext("daily") => "daily", 140 gettext("weekly") => "weekly", 141 gettext("monthly") => "monthly", 142 gettext("yearly") => "yearly", 143 gettext("never") => "never"), 144 'desc' => ''), 145 gettext('Change frequency - Zenpage news index') => array( 146 'key' => 'sitemap_changefreq_newsindex', 147 'type' => OPTION_TYPE_SELECTOR, 148 'order' => 6, 149 'selections' => array(gettext("always") => "always", 150 gettext("hourly") => "hourly", 151 gettext("daily") => "daily", 152 gettext("weekly") => "weekly", 153 gettext("monthly") => "monthly", 154 gettext("yearly") => "yearly", 155 gettext("never") => "never"), 156 'desc' => ''), 157 gettext('Change frequency: Zenpage news articles') => array( 158 'key' => 'sitemap_changefreq_news', 159 'type' => OPTION_TYPE_SELECTOR, 160 'order' => 7, 161 'selections' => array(gettext("always") => "always", 162 gettext("hourly") => "hourly", 163 gettext("daily") => "daily", 164 gettext("weekly") => "weekly", 165 gettext("monthly") => "monthly", 166 gettext("yearly") => "yearly", 167 gettext("never") => "never"), 168 'desc' => ''), 169 gettext('Change frequency - Zenpage news categories') => array( 170 'key' => 'sitemap_changefreq_newscats', 171 'type' => OPTION_TYPE_SELECTOR, 172 'order' => 8, 173 'selections' => array(gettext("always") => "always", 174 gettext("hourly") => "hourly", 175 gettext("daily") => "daily", 176 gettext("weekly") => "weekly", 177 gettext("monthly") => "monthly", 178 gettext("yearly") => "yearly", 179 gettext("never") => "never"), 180 'desc' => ''), 181 gettext('Enable Google image and video extension') => array( 182 'key' => 'sitemap_google', 183 'type' => OPTION_TYPE_CHECKBOX, 184 'order' => 9, 185 'desc' => gettext('If checked, the XML output file will be formatted using the Google XML image and video extensions where applicable.') . '<p class="notebox">' . gettext('<strong>Note:</strong> Other search engines (Yahoo, Bing) might not be able to read your sitemap. Also the Google extensions cover only image and video formats. If you use custom file types that are not covered by Zenphoto standard plugins or types like .mp3, .txt and .html you should probably not use this or modify the plugin. Also, if your site is really huge think about if you really need this setting as the creation may cause extra workload of your server and result in timeouts') . '</p>'), 186 gettext('Google image and video extension: Link full image ') => array( 187 'key' => 'sitemap_google_fullimage', 188 'type' => OPTION_TYPE_CHECKBOX, 189 'order' => 10, 190 'desc' => gettext('If checked, the original full image is referenced instead of the sized images in the cache. For image formats only.')), 191 gettext('Google - URL to image license') => array( 192 'key' => 'sitemap_license', 193 'type' => OPTION_TYPE_TEXTBOX, 194 'order' => 12, 195 'multilingual' => false, 196 'desc' => gettext('Optional. Used only if the Google extension is checked. Must be an absolute URL address of the form: http://mydomain.com/license.html')), 197 gettext('Sitemap processing chunk') => array( 198 'key' => 'sitemap_processing_chunk', 199 'type' => OPTION_TYPE_TEXTBOX, 200 'order' => 13, 201 'desc' => gettext('The number of albums that will be processed for each sitemap file. Lower this value if you get script timeouts when creating the files.')), 202 gettext('Use subdomains') . '*' => array( 203 'key' => 'dynamic_locale_subdomain', 204 'type' => OPTION_TYPE_CHECKBOX, 205 'order' => 14, 206 'disabled' => $_common_locale_type, 207 'desc' => $localdesc) 208 ); 209 if ($_common_locale_type) { 210 $options['note'] = array( 211 'key' => 'sitemap_locale_type', 212 'type' => OPTION_TYPE_NOTE, 213 'order' => 15, 214 'desc' => '<p class="notebox">' . $_common_locale_type . '</p>'); 215 } else { 216 $_common_locale_type = gettext('* This option may be set via the <a href="javascript:gotoName(\'sitemap-extended\');"><em>sitemap-extended</em></a> plugin options.'); 217 $options['note'] = array( 218 'key' => 'sitemap_locale_type', 219 'type' => OPTION_TYPE_NOTE, 220 'order' => 16, 221 'desc' => gettext('<p class="notebox">*<strong>Note:</strong> The setting of this option is shared with other plugins.</p>')); 222 } 223 return $options; 224 } 225 226 function handleOption($option, $currentValue) { 227 228 } 229 230} 231 232if (isset($_GET['sitemap'])) { 233 $sitemappath = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/sitemap/sitemapindex.xml'; 234 if (file_exists($sitemappath)) { 235 $sitemapfile = file_get_contents($sitemappath); 236 echo $sitemapfile; 237 } 238 exitZP(); 239} 240 241/** 242 * Sitemap class 243 */ 244class sitemap { 245 246 /** 247 * creates the Utilities button to purge the static sitemap cache 248 * @param array $buttons 249 * @return array 250 */ 251 static function button($buttons) { 252 $buttons[] = array( 253 'category' => gettext('Seo'), 254 'enable' => true, 255 'button_text' => gettext('Sitemap tools'), 256 'formname' => 'sitemap_button', 257 'action' => FULLWEBPATH . '/' . ZENFOLDER . '/' . PLUGIN_FOLDER . '/sitemap-extended/sitemap-extended-admin.php', 258 'icon' => FULLWEBPATH . '/' . ZENFOLDER . '/images/cache.png', 259 'title' => gettext('Generate or purge sitemap cache files.'), 260 'alt' => '', 261 'hidden' => '', 262 'rights' => ADMIN_RIGHTS 263 ); 264 return $buttons; 265 } 266 267 /** 268 * Simple helper function which simply outputs a string and ends it of with a new-line. 269 * @param string $string text string 270 * @return string 271 */ 272 static function echonl($string) { 273 return $string . "\n"; 274 } 275 276 /** 277 * Generates a sitemap file. 278 * 279 * @param string $filename How the file should be named. ".xml" is appended automatically 280 * @param string $data The actual sitemap data as generated by the appropiate functions 281 */ 282 static function generateCacheFile($filename, $data) { 283 if (!empty($data)) { 284 $filepath = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/sitemap/' . $filename . '.xml'; 285 $handler = fopen($filepath, 'w'); 286 fwrite($handler, $data); 287 fclose($handler); 288 echo '<li>' . $filename . '</li>'; 289 } 290 } 291 292 /** 293 * Generates the sitemap index file that points to the individual sitemaps from the content of the sitemap cache. 294 * It is always named "sitemapindex.xml" 295 */ 296 static function generateIndexCacheFile() { 297 $data = ''; 298 $cachefolder = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/sitemap/'; 299 $dirs = array_diff(scandir($cachefolder), array('.', '..', '.DS_Store', 'Thumbs.db', '.htaccess', '.svn')); 300 if ($dirs) { 301 $data .= sitemap::echonl('<?xml version="1.0" encoding="UTF-8"?>'); 302 $data .= sitemap::echonl('<sitemapindex xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); 303 foreach ($dirs as $dir) { 304 $data .= sitemap::echonl("\t<sitemap>"); 305 $data .= sitemap::echonl("\t\t<loc>" . FULLWEBPATH . '/' . STATIC_CACHE_FOLDER . '/sitemap/' . $dir . '</loc>'); 306 $data .= sitemap::echonl("\t\t<lastmod>" . sitemap::getISO8601Date() . '</lastmod>'); 307 $data .= sitemap::echonl("\t</sitemap>"); 308 } 309 $data .= sitemap::echonl('</sitemapindex>'); 310 $filepath = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/sitemap/sitemapindex.xml'; 311 $handler = fopen($filepath, 'w'); 312 fwrite($handler, $data); 313 fclose($handler); 314 echo '<p>sitemapindex.xml created.</p>'; 315 } 316 } 317 318 /** 319 * Checks the changefreq value if entered manually and makes sure it is only one of the supported regarding sitemap.org 320 * @param string $changefreq One of the supported changefrequence values regarding sitemap.org. Default is empty or wrong is "daily". 321 * @return string 322 */ 323 static function getChangefreq($changefreq = '') { 324 $changefreq = sanitize($changefreq); 325 switch ($changefreq) { 326 case 'always': 327 case 'hourly': 328 case 'daily': 329 case 'weekly': 330 case 'monthly': 331 case 'yearly': 332 case 'never': 333 $changefreq = $changefreq; 334 break; 335 default: 336 $changefreq = 'daily'; 337 break; 338 } 339 return $changefreq; 340 } 341 342 /** 343 * Gets the dateformat for images and albums only. 344 * @param object $obj image or album object 345 * @param string $option "date" or "mtime". If "mtime" is discovered to be not set, the date values is taken instead so we don't get 1970-01-10 dates 346 * @return string 347 */ 348 static function getDateformat($obj, $option) { 349 $date = ''; 350 switch ($option) { 351 case 'date': 352 default: 353 $date = $obj->getDatetime(); 354 break; 355 case 'mtime': 356 $timestamp = $obj->get('mtime'); 357 if ($timestamp == 0) { 358 $date = $obj->getDatetime(); 359 } else { 360 return gmstrftime('%Y-%m-%dT%H:%M:%SZ', $timestamp); 361 // For more streamlined but PHP5-only equivalent, remove the above line and uncomment the following: 362 // return gmstrftime(DATE_ISO8601, $timestamp); 363 } 364 break; 365 case 'lastchange': 366 $date = sitemap::getLastChangeDate($obj, true); 367 break; 368 } 369 return sitemap::getISO8601Date($date); 370 // For more streamlined but PHP5-only equivalent, remove the above line and uncomment the following: 371 // return gmstrftime(DATE_ISO8601, strtotime($date)); 372 } 373 374 /** 375 * Gets the limit and offset for the db queries for sitemap splitting. 376 * @param int $items_per_sitemap Number of items per sitemap 377 * @return string 378 */ 379 static function getDBLimit($items_per_sitemap = 2) { 380 global $_sitemap_number; 381 if ($_sitemap_number < 1) { 382 $_sitemap_number = 1; 383 } 384 $offset = ($_sitemap_number - 1) * $items_per_sitemap; 385 $limit = " LIMIT " . $offset . "," . $items_per_sitemap; 386 return $limit; 387 } 388 389 /* * TODO index links are not splitted into several sitemaps yet 390 * 391 * Gets the links to the index of a Zenphoto gallery incl. index pagination 392 * 393 * @return string 394 */ 395 396 static function getIndexLinks() { 397 global $_zp_gallery, $_sitemap_number; 398 $data = ''; 399 if ($_sitemap_number < 2) { 400 set_context(ZP_INDEX); 401 $albums_per_page = getOption('albums_per_page'); 402 if (getOption('custom_index_page')) { 403 $galleryindex = getCustomGalleryIndexURL(1, ''); 404 } else { 405 $galleryindex = getStandardGalleryIndexURL(1, ''); 406 } 407 $toplevelpages = getTotalPages(); 408 $data .= sitemap::echonl('<?xml version="1.0" encoding="UTF-8"?>'); 409 $data .= sitemap::echonl('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); 410 $sitemap_locales = generateLanguageList(); 411 $changefreq = sitemap::getChangefreq(getOption('sitemap_changefreq_index')); 412 // normal index/homepage we need in any case always 413 $date = sitemap::getISO8601Date(); 414 switch (SITEMAP_LOCALE_TYPE) { 415 case 1: 416 foreach ($sitemap_locales as $locale) { 417 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . seo_locale::localePath(true, $locale) . "/</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 418 } 419 break; 420 case 2: 421 foreach ($sitemap_locales as $locale) { 422 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . dynamic_locale::fullHostPath($locale) . "/</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 423 } 424 break; 425 default: 426 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . FULLWEBPATH . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 427 break; 428 } 429 // the extra ones if we have a custom gallery index 430 if (getOption('custom_index_page')) { 431 switch (SITEMAP_LOCALE_TYPE) { 432 case 1: 433 foreach ($sitemap_locales as $locale) { 434 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . seo_locale::localePath(true, $locale) . '/' . $galleryindex . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 435 } 436 break; 437 case 2: 438 foreach ($sitemap_locales as $locale) { 439 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . dynamic_locale::fullHostPath($locale) . '/' . $galleryindex . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 440 } 441 break; 442 default: 443 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . FULLWEBPATH . $galleryindex . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 444 break; 445 } 446 } 447 // print further index pages if available 448 if ($toplevelpages) { 449 for ($x = 2; $x <= $toplevelpages; $x++) { 450 if (getOption('custom_index_page')) { 451 $galleryindex = getCustomGalleryIndexURL($x, ''); 452 } else { 453 $galleryindex = getStandardGalleryIndexURL($x, ''); 454 } 455 switch (SITEMAP_LOCALE_TYPE) { 456 case 1: 457 foreach ($sitemap_locales as $locale) { 458 $url = seo_locale::localePath(true, $locale) . $galleryindex; 459 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 460 } 461 break; 462 case 2: 463 foreach ($sitemap_locales as $locale) { 464 $url = dynamic_locale::fullHostPath($locale) . $galleryindex; 465 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 466 } 467 break; 468 default: 469 $url = FULLWEBPATH . $galleryindex; 470 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 471 break; 472 } 473 } 474 } 475 $data .= sitemap::echonl('</urlset>'); // End off the <urlset> tag 476 restore_context(); 477 return $data; 478 } // sitemap number end 479 } 480 481 /** 482 * 483 * Enter description here ... 484 * @param object $obj the starting point 485 * @param array $albumlist the container for the results 486 */ 487 static function getAlbumList($obj, &$albumlist) { 488 global $_zp_gallery; 489 $locallist = $obj->getAlbums(); 490 foreach ($locallist as $folder) { 491 $album = newAlbum($folder); 492 if ($album->isPublic() && !$album->isProtected()) { 493 $albumlist[] = array('folder' => $album->name, 'date' => $album->getDateTime(), 'title' => $album->getTitle()); 494 if (!$album->isDynamic()) { 495 sitemap::getAlbumList($album, $albumlist); 496 } 497 } 498 } 499 } 500 501 /** 502 * gateway check for albums (no refinement of the criteria) 503 * 504 * @deprecated Unused 505 * @param object $album 506 */ 507 static function passAlbums($album) { 508 return true; 509 } 510 511 /** 512 * gateway function for images (screens out dynamic albums and password protected albums) 513 * 514 * @deprecated Unused 515 * @param object $album 516 */ 517 static function passImages($album) { 518 return !$album->isDynamic() && !$album->getPassword(); 519 } 520 521 /** 522 * Places album and all of its album pages on one sitemap 523 * 524 * Gets links to all albums incl. pagination and if the Google image video extension is enabled for images using this as well. 525 * This is independent from the images fetched by getSitemapImages(). 526 * 527 * NOTE: Using the Google extension is currently NOT recommended if you have a huge gallery. 528 * 529 * @return string 530 */ 531 static function getAlbums() { 532 global $_zp_gallery, $_sitemap_number; 533 $data_start = $data = ''; 534 $sitemap_locales = generateLanguageList(); 535 $albumchangefreq = getOption('sitemap_changefreq_albums'); 536 $imagechangefreq = getOption('sitemap_changefreq_images'); 537 $albumlastmod = getOption('sitemap_lastmod_albums'); 538 $albumlastmod = sanitize($albumlastmod); 539 $imagelastmod = getOption('sitemap_lastmod_images'); 540 $albums = array(); 541 sitemap::getAlbumList($_zp_gallery, $albums); 542 $offset = ($_sitemap_number - 1); 543 $albums = array_slice($albums, $offset, SITEMAP_CHUNK); 544 if (!empty($albums)) { 545 $data_start .= sitemap::echonl('<?xml version="1.0" encoding="UTF-8"?>'); 546 $data_start .= sitemap::echonl('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); 547 foreach ($albums as $album) { 548 $albumobj = newAlbum($album['folder']); 549 set_context(ZP_ALBUM); 550 makeAlbumCurrent($albumobj); 551 $pageCount = getTotalPages(); 552 //$imageCount = getNumImages(); 553 //$images = $albumobj->getImages(); 554 $date = sitemap::getDateformat($albumobj, $albumlastmod); 555 switch (SITEMAP_LOCALE_TYPE) { 556 case 1: 557 foreach ($sitemap_locales as $locale) { 558 $url = seo_locale::localePath(true, $locale) . '/' . pathurlencode($albumobj->linkname) . '/'; 559 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $albumchangefreq . "</changefreq>\n\t\t<priority>0.8</priority>\n"); 560 $data .= sitemap::echonl("\t</url>"); 561 } 562 break; 563 case 2: 564 foreach ($sitemap_locales as $locale) { 565 $url = rewrite_path(pathurlencode($albumobj->linkname) . '/', '?album=' . pathurlencode($albumobj->name), dynamic_locale::fullHostPath($locale)); 566 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $albumchangefreq . "</changefreq>\n\t\t<priority>0.8</priority>\n"); 567 $data .= sitemap::echonl("\t</url>"); 568 } 569 break; 570 default: 571 $url = rewrite_path(pathurlencode($albumobj->linkname) . '/', '?album=' . pathurlencode($albumobj->name), FULLWEBPATH); 572 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $albumchangefreq . "</changefreq>\n\t\t<priority>0.8</priority>\n"); 573 $data .= sitemap::echonl("\t</url>"); 574 break; 575 } 576 // print album pages if avaiable 577 if ($pageCount > 1) { 578 for ($x = 2; $x <= $pageCount; $x++) { 579 switch (SITEMAP_LOCALE_TYPE) { 580 case 1: 581 foreach ($sitemap_locales as $locale) { 582 $url = seo_locale::localePath(true, $locale) . '/' . pathurlencode($albumobj->linkname) . '/' . _PAGE_ . '/' . $x . '/'; 583 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $albumchangefreq . "</changefreq>\n\t\t<priority>0.8</priority>\n"); 584 $data .= sitemap::echonl("\t</url>"); 585 } 586 break; 587 case 2: 588 foreach ($sitemap_locales as $locale) { 589 $url = rewrite_path(pathurlencode($albumobj->linkname) . '/' . _PAGE_ . '/' . $x . '/', '?album=' . pathurlencode($albumobj->name) . '&page=' . $x, dynamic_locale::fullHostPath($locale)); 590 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $albumchangefreq . "</changefreq>\n\t\t<priority>0.8</priority>\n"); 591 $data .= sitemap::echonl("\t</url>"); 592 } 593 break; 594 default: 595 $url = rewrite_path(pathurlencode($albumobj->linkname) . '/' . _PAGE_ . '/' . $x . '/', '?album=' . pathurlencode($albumobj->name) . '&page=' . $x, FULLWEBPATH); 596 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $albumchangefreq . "</changefreq>\n\t\t<priority>0.8</priority>\n"); 597 $data .= sitemap::echonl("\t</url>"); 598 break; 599 } 600 } 601 } 602 } 603 if (!empty($data)) { 604 $data = $data_start . $data . sitemap::echonl('</urlset>'); // End off the <urlset> tag 605 } 606 } 607 restore_context(); 608 return $data; 609 } 610 611 /** 612 * currently this splitts only sitemaps for albums and its images. Spliting the images itself requires a major rework... 613 * 614 * Gets links to all images for all albums (album by album) 615 * 616 * @return string 617 */ 618 static function getImages() { 619 global $_zp_gallery, $_sitemap_number; 620 $data_start = $data = ''; 621 $sitemap_locales = generateLanguageList(); 622 $imagechangefreq = getOption('sitemap_changefreq_images'); 623 $imagelastmod = getOption('sitemap_lastmod_images'); 624 $limit = sitemap::getDBLimit(1); 625 $albums = array(); 626 sitemap::getAlbumList($_zp_gallery, $albums); 627 $offset = ($_sitemap_number - 1); 628 $albums = array_slice($albums, $offset, SITEMAP_CHUNK); 629 if ($albums) { 630 $data_start .= sitemap::echonl('<?xml version="1.0" encoding="UTF-8"?>'); 631 if (GOOGLE_SITEMAP) { 632 $data_start .= sitemap::echonl('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">'); 633 } else { 634 $data_start .= sitemap::echonl('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); 635 } 636 foreach ($albums as $album) { 637 @set_time_limit(120); // Extend script timeout to allow for gathering the images. 638 $albumobj = newAlbum($album['folder']); 639 $images = $albumobj->getImages(); 640 // print plain images links if available 641 if ($images) { 642 foreach ($images as $image) { 643 $imageobj = newImage($albumobj, $image); 644 if($imageobj->isPublic() && !$albumobj->isDynamic()) { 645 $ext = getSuffix($imageobj->filename); 646 $date = sitemap::getDateformat($imageobj, $imagelastmod); 647 switch (SITEMAP_LOCALE_TYPE) { 648 case 1: 649 foreach ($sitemap_locales as $locale) { 650 $path = seo_locale::localePath(true, $locale) . '/' . pathurlencode($albumobj->linkname) . '/' . urlencode($imageobj->filename) . IM_SUFFIX; 651 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $path . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $imagechangefreq . "</changefreq>\n\t\t<priority>0.6</priority>\n"); 652 if (GOOGLE_SITEMAP) { 653 $data .= sitemap::getGoogleImageVideoExtras($albumobj, $imageobj, $locale); 654 } 655 $data .= sitemap::echonl("</url>"); 656 } 657 break; 658 case 2: 659 foreach ($sitemap_locales as $locale) { 660 $path = rewrite_path(pathurlencode($albumobj->linkname) . '/' . urlencode($imageobj->filename) . IM_SUFFIX, '?album=' . pathurlencode($albumobj->name) . '&image=' . urlencode($imageobj->filename), dynamic_locale::fullHostPath($locale)); 661 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $path . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $imagechangefreq . "</changefreq>\n\t\t<priority>0.6</priority>\n"); 662 if (GOOGLE_SITEMAP) { 663 $data .= sitemap::getGoogleImageVideoExtras($albumobj, $imageobj, $locale); 664 } 665 $data .= sitemap::echonl("</url>"); 666 } 667 break; 668 default: 669 $path = rewrite_path(pathurlencode($albumobj->linkname) . '/' . urlencode($imageobj->filename) . IM_SUFFIX, '?album=' . pathurlencode($albumobj->name) . '&image=' . urlencode($imageobj->filename), FULLWEBPATH); 670 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $path . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $imagechangefreq . "</changefreq>\n\t\t<priority>0.6</priority>\n"); 671 if (GOOGLE_SITEMAP) { 672 $data .= sitemap::getGoogleImageVideoExtras($albumobj, $imageobj, NULL); 673 } 674 $data .= sitemap::echonl("</url>"); 675 break; 676 } 677 } 678 } 679 } 680 } 681 if (!empty($data)) { 682 $data = $data_start . $data . sitemap::echonl('</urlset>'); // End off the <urlset> tag 683 } 684 } 685 return $data; 686 } 687 688 /** 689 * Helper function to get the loop index if the Google video extension is enabled 690 */ 691 static function getGoogleLoopIndex($imageCount, $pageCount) { 692 if (GOOGLE_SITEMAP) { 693 $loop_index = array(); 694 for ($x = 1; $x <= $pageCount; $x++) { 695 if ($imageCount < ($x * getOption('images_per_page'))) { 696 $val = $imageCount - (($x - 1) * getOption('images_per_page')); 697 } else { 698 $val = getOption('images_per_page'); 699 } 700 array_push($loop_index, $val); 701 } 702 return $loop_index; 703 } 704 return NULL; 705 } 706 707 /** 708 * Helper function to get the image/video extra entries for albums if the Google video extension is enabled 709 * @return string 710 */ 711 static function getGoogleImageVideoExtras($albumobj, $imageobj, $locale) { 712 $data = ''; 713 $host = PROTOCOL . '://' . html_encode($_SERVER["HTTP_HOST"]); 714 $ext = strtolower(strrchr($imageobj->filename, ".")); 715 $location = ''; 716 if ($imageobj->getLocation()) { 717 $location .= $imageobj->getLocation($locale) . ', '; 718 } 719 if ($imageobj->getCity()) { 720 $location .= $imageobj->getCity($locale) . ', '; 721 } 722 if ($imageobj->getState()) { 723 $location .= $imageobj->getState($locale) . ', '; 724 } 725 if ($imageobj->getCountry()) { 726 $location .= $imageobj->getCountry($locale); 727 } 728 $license = getOption('sitemap_license'); 729 if (empty($license)) { 730 $license = $imageobj->getCopyrightURL(); 731 } 732 if (isImageVideo($imageobj) && in_array($ext, array('.mpg', '.mpeg', '.mp4', '.m4v', '.mov', '.wmv', '.asf', '.avi', '.ra', '.ram', '.flv', '.swf'))) { // google says it can index these so we list them even if unsupported by Zenphoto 733 $data .= sitemap::echonl("\t\t<video:video>\n\t\t\t<video:thumbnail_loc>" . $host . html_encode($imageobj->getThumb()) . "</video:thumbnail_loc>\n"); 734 $data .= sitemap::echonl("\t\t\t<video:title>" . html_encode($imageobj->getTitle($locale)) . "</video:title>"); 735 if ($imageobj->getDesc()) { 736 $data .= sitemap::echonl("\t\t\t<video:description>" . html_encode(getBare($imageobj->getDesc($locale))) . "</video:description>"); 737 } 738 $data .= sitemap::echonl("\t\t\t<video:content_loc>" . $host . pathurlencode($imageobj->getFullImageURL()) . "</video:content_loc>"); 739 $data .= sitemap::echonl("\t\t</video:video>"); 740 } else if (in_array($ext, array('.jpg', '.jpeg', '.gif', '.png'))) { // this might need to be extended! 741 if (getOption('sitemap_google_fullimage')) { 742 $imagelocation = $host . pathurlencode($imageobj->getFullImageURL()); 743 } else { 744 $imagelocation = $host . html_encode($imageobj->getSizedImage(getOption('image_size'))); 745 } 746 $data .= sitemap::echonl("\t\t<image:image>\n\t\t\t<image:loc>" . html_encode($imagelocation) . "</image:loc>\n"); 747 // disabled for the multilingual reasons above 748 $data .= sitemap::echonl("\t\t\t<image:title>" . html_encode($imageobj->getTitle($locale)) . "</image:title>"); 749 if ($imageobj->getDesc()) { 750 $data .= sitemap::echonl("\t\t\t<image:caption>" . html_encode(getBare($imageobj->getDesc($locale))) . "</image:caption>"); 751 } 752 if (!empty($license)) { 753 $data .= sitemap::echonl("\t\t\t<image:license>" . html_encode($license) . "</image:license>"); 754 } 755 // location is kept although the same multilingual issue applies 756 if (!empty($location)) { 757 $data .= sitemap::echonl("\t\t\t<image:geo_location>" . html_encode($location) . "</image:geo_location>"); 758 } 759 $data .= sitemap::echonl("\t\t</image:image>"); 760 } 761 return $data; 762 } 763 764 /** 765 * Gets links to all Zenpage pages 766 * 767 * @return string 768 */ 769 static function getZenpagePages() { 770 global $_zp_zenpage, $_sitemap_number; 771 //not splitted into several sitemaps yet 772 if ($_sitemap_number == 1) { 773 $data_start = $data = ''; 774 $limit = sitemap::getDBLimit(2); 775 $sitemap_locales = generateLanguageList(); 776 $changefreq = getOption('sitemap_changefreq_pages'); 777 $pages = $_zp_zenpage->getPages(true); 778 if ($pages) { 779 $data_start .= sitemap::echonl('<?xml version="1.0" encoding="UTF-8"?>'); 780 $data_start .= sitemap::echonl('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); 781 foreach ($pages as $page) { 782 $pageobj = new ZenpagePage($page['titlelink']); 783 if ($pageobj->isPublic() && !$pageobj->isProtected()) { 784 $date = sitemap::getLastChangeDate($pageobj, false); 785 switch (SITEMAP_LOCALE_TYPE) { 786 case 1: 787 foreach ($sitemap_locales as $locale) { 788 $url = seo_locale::localePath(true, $locale) . '/' . _PAGES_ . '/' . urlencode($page['titlelink']) . '/'; 789 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 790 } 791 break; 792 case 2: 793 foreach ($sitemap_locales as $locale) { 794 $url = rewrite_path(_PAGES_ . '/' . urlencode($page['titlelink']) . '/', '?p=pages&title=' . urlencode($page['titlelink']), dynamic_locale::fullHostPath($locale)); 795 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 796 } 797 break; 798 default: 799 $url = rewrite_path(_PAGES_ . '/' . urlencode($page['titlelink']) . '/', '?p=pages&title=' . urlencode($page['titlelink']), FULLWEBPATH); 800 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 801 break; 802 } 803 } 804 805 } 806 if (!empty($data)) { 807 $data = $data_start . $data . sitemap::echonl('</urlset>'); // End off the <urlset> tag 808 } 809 } 810 return $data; 811 } 812 } 813 814 /** 815 * Gets links to the main Zenpage news index incl. pagination 816 * 817 * @return string 818 */ 819 static function getZenpageNewsIndex() { 820 global $_zp_zenpage, $_sitemap_number; 821 //not splitted into several sitemaps yet 822 if ($_sitemap_number == 1) { 823 $data = ''; 824 $data .= sitemap::echonl('<?xml version="1.0" encoding="UTF-8"?>'); 825 $data .= sitemap::echonl('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); 826 $sitemap_locales = generateLanguageList(); 827 $changefreq = getOption('sitemap_changefreq_newsindex'); 828 $date = sitemap::getISO8601Date(); 829 switch (SITEMAP_LOCALE_TYPE) { 830 case 1: 831 foreach ($sitemap_locales as $locale) { 832 $url = seo_locale::localePath(true, $locale) . '/' . _NEWS_ . '/1/'; 833 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 834 } 835 Break; 836 case 2: 837 foreach ($sitemap_locales as $locale) { 838 $url = rewrite_path(_NEWS_ . '/1/', '?p=news&page=1', dynamic_locale::fullHostPath($locale)); 839 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 840 } 841 Break; 842 default: 843 $url = rewrite_path(_NEWS_ . '/1/', '?p=news&page=1', FULLWEBPATH); 844 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 845 Break; 846 } 847 // getting pages for the main news loop 848 /* Not used anyway 849 if(!empty($articlesperpage)) { 850 $zenpage_articles_per_page = sanitize_numeric($articlesperpage); 851 } else { 852 $zenpage_articles_per_page = ZP_ARTICLES_PER_PAGE; 853 } */ 854 $zenpage_articles_per_page = ZP_ARTICLES_PER_PAGE; 855 $newspages = ceil($_zp_zenpage->getTotalArticles() / $zenpage_articles_per_page); 856 if ($newspages > 1) { 857 for ($x = 2; $x <= $newspages; $x++) { 858 switch (SITEMAP_LOCALE_TYPE) { 859 case 1: 860 foreach ($sitemap_locales as $locale) { 861 $url = seo_locale::localePath(true, $locale) . '/' . _NEWS_ . '/' . $x . '/'; 862 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 863 } 864 break; 865 case 2: 866 foreach ($sitemap_locales as $locale) { 867 $url = rewrite_path(_NEWS_ . '/' . $x . '/', '?p=news&page=' . $x, dynamic_locale::fullHostPath($locale)); 868 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 869 } 870 break; 871 default: 872 $url = rewrite_path(_NEWS_ . '/' . $x . '/', '?p=news&page=' . $x, FULLWEBPATH); 873 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 874 break; 875 } 876 } 877 } 878 $data .= sitemap::echonl('</urlset>'); // End off the <urlset> tag 879 return $data; 880 } 881 } 882 883 /** 884 * Gets to the Zenpage news articles 885 * 886 * @param string $changefreq One of the supported changefrequence values regarding sitemap.org. Default is empty or wrong is "daily". 887 * @return string 888 */ 889 static function getZenpageNewsArticles() { 890 global $_zp_zenpage, $_sitemap_number; 891 //not splitted into several sitemaps yet 892 if ($_sitemap_number == 1) { 893 $data_start = $data = ''; 894 $sitemap_locales = generateLanguageList(); 895 $changefreq = getOption('sitemap_changefreq_news'); 896 $articles = $_zp_zenpage->getArticles('', 'published', true, "date", "desc"); 897 if ($articles) { 898 $data_start .= sitemap::echonl('<?xml version="1.0" encoding="UTF-8"?>'); 899 $data_start .= sitemap::echonl('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); 900 foreach ($articles as $article) { 901 $articleobj = new ZenpageNews($article['titlelink']); 902 if ($articleobj->isPublic() && !$articleobj->isProtected()) { 903 $date = sitemap::getLastChangeDate($articleobj, false); 904 switch (SITEMAP_LOCALE_TYPE) { 905 case 1: 906 foreach ($sitemap_locales as $locale) { 907 $url = seo_locale::localePath(true, $locale) . '/' . _NEWS_ . '/' . urlencode($articleobj->getTitlelink()) . '/'; 908 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 909 } 910 break; 911 case 2: 912 foreach ($sitemap_locales as $locale) { 913 $url = rewrite_path(_NEWS_ . '/' . urlencode($articleobj->getTitlelink()) . '/', '?p=news&title=' . urlencode($articleobj->getTitlelink()), dynamic_locale::fullHostPath($locale)); 914 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 915 } 916 break; 917 default: 918 $url = rewrite_path(_NEWS_ . '/' . urlencode($articleobj->getTitlelink()) . '/', '?p=news&title=' . urlencode($articleobj->getTitlelink()), FULLWEBPATH); 919 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<lastmod>" . $date . "</lastmod>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 920 break; 921 } 922 } 923 } 924 if (!empty($data)) { 925 $data = $data_start . $data . sitemap::echonl('</urlset>'); // End off the <urlset> tag 926 } 927 } 928 return $data; 929 } 930 } 931 932 /** 933 * Gets links to Zenpage news categories incl. pagination 934 * 935 * @return string 936 */ 937 static function getZenpageNewsCategories() { 938 global $_zp_zenpage, $_sitemap_number; 939 //TODO not splitted into several sitemaps yet 940 if ($_sitemap_number == 1) { 941 $data_start = $data = ''; 942 $sitemap_locales = generateLanguageList(); 943 $changefreq = getOption('sitemap_changefreq_newscats'); 944 $newscats = $_zp_zenpage->getAllCategories(); 945 if ($newscats) { 946 $data_start .= sitemap::echonl('<?xml version="1.0" encoding="UTF-8"?>'); 947 $data_start .= sitemap::echonl('<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); 948 foreach ($newscats as $newscat) { 949 $catobj = new ZenpageCategory($newscat['titlelink']); 950 if ($catobj->isPublic() && !$catobj->isProtected()) { 951 switch (SITEMAP_LOCALE_TYPE) { 952 case 1: 953 foreach ($sitemap_locales as $locale) { 954 $url = seo_locale::localePath(true, $locale) . '/' . _CATEGORY_ . '/' . urlencode($catobj->getTitlelink()) . '/1/'; 955 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 956 } 957 break; 958 case 2: 959 foreach ($sitemap_locales as $locale) { 960 $url = rewrite_path(_CATEGORY_ . '/' . urlencode($catobj->getTitlelink()) . '/1/', '?p=news&category=' . urlencode($catobj->getTitlelink()) . '&page=1', dynamic_locale::fullHostPath($locale)); 961 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 962 } 963 break; 964 default: 965 $url = rewrite_path(_CATEGORY_ . '/' . urlencode($catobj->getTitlelink()) . '/1/', '?p=news&category=' . urlencode($catobj->getTitlelink()) . '&page=1', FULLWEBPATH); 966 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 967 break; 968 } 969 // getting pages for the categories 970 /* 971 if(!empty($articlesperpage)) { 972 $zenpage_articles_per_page = sanitize_numeric($articlesperpage); 973 } else { 974 $zenpage_articles_per_page = ZP_ARTICLES_PER_PAGE; 975 } */ 976 $zenpage_articles_per_page = ZP_ARTICLES_PER_PAGE; 977 $articlecount = count($catobj->getArticles()); 978 $catpages = ceil($articlecount / $zenpage_articles_per_page); 979 if ($catpages > 1) { 980 for ($x = 2; $x <= $catpages; $x++) { 981 switch (SITEMAP_LOCALE_TYPE) { 982 case 1: 983 foreach ($sitemap_locales as $locale) { 984 $url = seo_locale::localePath(true, $locale) . '/' . _CATEGORY_ . '/' . urlencode($catobj->getTitlelink()) . '/' . $x . '/'; 985 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 986 } 987 break; 988 case 2: 989 foreach ($sitemap_locales as $locale) { 990 $url = rewrite_path(_CATEGORY_ . '/' . urlencode($catobj->getTitlelink()) . '/' . $x . '/', '?p=news&category=' . urlencode($catobj->getTitlelink()) . '&page=' . $x, dynamic_locale::fullHostPath($locale)); 991 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 992 } 993 break; 994 default: 995 $url = rewrite_path(_CATEGORY_ . '/' . urlencode($catobj->getTitlelink()) . '/' . $x . '/', '?p=news&category=' . urlencode($catobj->getTitlelink()) . '&page=' . $x, FULLWEBPATH); 996 $data .= sitemap::echonl("\t<url>\n\t\t<loc>" . $url . "</loc>\n\t\t<changefreq>" . $changefreq . "</changefreq>\n\t\t<priority>0.9</priority>\n\t</url>"); 997 break; 998 } 999 } 1000 } 1001 } 1002 } 1003 1004 if (!empty($data)) { 1005 $data = $data_start . $data . sitemap::echonl('</urlset>'); // End off the <urlset> tag 1006 } 1007 } 1008 return $data; 1009 } 1010 } 1011 1012 /** 1013 * Cleans out the cache folder. 1014 * 1015 */ 1016 static function clearCache() { 1017 $cachefolder = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/sitemap/'; 1018 if (is_dir($cachefolder)) { 1019 $handle = opendir($cachefolder); 1020 while (false !== ($filename = readdir($handle))) { 1021 $fullname = $cachefolder . '/' . $filename; 1022 if (is_dir($fullname) && !(substr($filename, 0, 1) == '.')) { 1023 if (($filename != '.') && ($filename != '..')) { 1024 RSS::clearRSSCache($fullname); 1025 rmdir($fullname); 1026 } 1027 } else { 1028 if (file_exists($fullname) && !(substr($filename, 0, 1) == '.')) { 1029 @chmod($fullname, 0777); 1030 unlink($fullname); 1031 } 1032 } 1033 } 1034 closedir($handle); 1035 } 1036 } 1037 1038 /** 1039 * Returns an ISO-8601 compliant date/time string for the given date/time. 1040 * While PHP5 can use the date format constant DATE_ISO8601, this function is designed to allow PHP4 use as well. 1041 * Eventually it can be deprecated, by: 1042 * 1. Replacing parameterless references to this function with date(DATE_ISO8601) 1043 * 2. Replacing references to this function in sitemap_getDateformat as documented there 1044 * 1045 */ 1046 static function getISO8601Date($date = '') { 1047 if (empty($date)) { 1048 return gmstrftime('%Y-%m-%dT%H:%M:%SZ'); 1049 } else { 1050 return gmstrftime('%Y-%m-%dT%H:%M:%SZ', strtotime($date)); 1051 } 1052 } 1053 1054 static function printAvailableSitemaps() { 1055 $cachefolder = SERVERPATH . '/' . STATIC_CACHE_FOLDER . '/sitemap/'; 1056 $dirs = array_diff(scandir($cachefolder), array('.', '..', '.DS_Store', 'Thumbs.db', '.htaccess', '.svn')); 1057 echo '<h2>' . gettext('Available sitemap files:') . '</h2>'; 1058 if (!$dirs) { 1059 echo '<p>' . gettext('No sitemap files available.') . '</p>'; 1060 } else { 1061 echo '<ol>'; 1062 foreach ($dirs as $dir) { 1063 $filemtime = filemtime($cachefolder . $dir); 1064 $lastchange = date('Y-m-d H:m:s', $filemtime); 1065 ?> 1066 <li><a target="_blank" href="<?php echo FULLWEBPATH . '/' . STATIC_CACHE_FOLDER; ?>/sitemap/<?php echo $dir; ?>"><?php echo $dir; ?></a> (<small><?php echo $lastchange; ?>)</small> 1067 </li> 1068 <?php 1069 } 1070 echo '</ol>'; 1071 } 1072 } 1073 1074 /** 1075 * Gets the date as Y-m-d or if available last change date of $obj 1076 * 1077 * @param obj $obj 1078 * @param bool $fulldate True to return the full date incl. time, otherwise the date only 1079 * @return string 1080 */ 1081 static function getLastChangeDate($obj, $fulldate = false) { 1082 $date = $obj->getDatetime(); 1083 if (!$fulldate) { 1084 $date = substr($date, 0, 10); 1085 } 1086 $lastchange = ''; 1087 if (!is_null($obj->getLastchange())) { 1088 $lastchange = $obj->getLastchange(); 1089 if (!$fulldate) { 1090 $lastchange = substr($lastchange, 0, 10); 1091 } 1092 } 1093 if ($date > $lastchange && !empty($lastchange)) { 1094 return $lastchange; 1095 } 1096 return $date; 1097 } 1098 1099} 1100