[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/Sitemap/ -> Mapper.php (source)

   1  <?php
   2  
   3  /**
   4   * Sitemap handling functions
   5   *
   6   * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
   7   * @author     Michael Hamann <michael@content-space.de>
   8   */
   9  
  10  namespace dokuwiki\Sitemap;
  11  
  12  use dokuwiki\Extension\Event;
  13  use dokuwiki\HTTP\DokuHTTPClient;
  14  use dokuwiki\Logger;
  15  
  16  /**
  17   * A class for building sitemaps and pinging search engines with the sitemap URL.
  18   *
  19   * @author Michael Hamann
  20   */
  21  class Mapper
  22  {
  23      /**
  24       * Builds a Google Sitemap of all public pages known to the indexer
  25       *
  26       * The map is placed in the cache directory named sitemap.xml.gz - This
  27       * file needs to be writable!
  28       *
  29       * @author Michael Hamann
  30       * @author Andreas Gohr
  31       * @link   https://www.google.com/webmasters/sitemaps/docs/en/about.html
  32       * @link   http://www.sitemaps.org/
  33       *
  34       * @return bool
  35       */
  36      public static function generate()
  37      {
  38          global $conf;
  39          if ($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) return false;
  40  
  41          $sitemap = Mapper::getFilePath();
  42  
  43          if (file_exists($sitemap)) {
  44              if (!is_writable($sitemap)) return false;
  45          } elseif (!is_writable(dirname($sitemap))) {
  46              return false;
  47          }
  48  
  49          if (
  50              @filesize($sitemap) &&
  51              @filemtime($sitemap) > (time() - ($conf['sitemap'] * 86400))
  52          ) { // 60*60*24=86400
  53              Logger::debug('Sitemapper::generate(): Sitemap up to date');
  54              return false;
  55          }
  56  
  57          Logger::debug("Sitemapper::generate(): using $sitemap");
  58  
  59          $pages = idx_get_indexer()->getPages();
  60          Logger::debug('Sitemapper::generate(): creating sitemap using ' . count($pages) . ' pages');
  61          $items = [];
  62  
  63          // build the sitemap items
  64          foreach ($pages as $id) {
  65              //skip hidden, non existing and restricted files
  66              if (isHiddenPage($id)) continue;
  67              if (auth_aclcheck($id, '', []) < AUTH_READ) continue;
  68              $item = Item::createFromID($id);
  69              if ($item instanceof Item)
  70                  $items[] = $item;
  71          }
  72  
  73          $eventData = ['items' => &$items, 'sitemap' => &$sitemap];
  74          $event = new Event('SITEMAP_GENERATE', $eventData);
  75          if ($event->advise_before(true)) {
  76              //save the new sitemap
  77              $event->result = io_saveFile($sitemap, (new Mapper())->getXML($items));
  78          }
  79          $event->advise_after();
  80  
  81          return $event->result;
  82      }
  83  
  84      /**
  85       * Builds the sitemap XML string from the given array auf SitemapItems.
  86       *
  87       * @param $items array The SitemapItems that shall be included in the sitemap.
  88       * @return string The sitemap XML.
  89       *
  90       * @author Michael Hamann
  91       */
  92      private function getXML($items)
  93      {
  94          ob_start();
  95          echo '<?xml version="1.0" encoding="UTF-8"?>' . NL;
  96          echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . NL;
  97          foreach ($items as $item) {
  98              /** @var Item $item */
  99              echo $item->toXML();
 100          }
 101          echo '</urlset>' . NL;
 102          $result = ob_get_contents();
 103          ob_end_clean();
 104          return $result;
 105      }
 106  
 107      /**
 108       * Helper function for getting the path to the sitemap file.
 109       *
 110       * @return string The path to the sitemap file.
 111       *
 112       * @author Michael Hamann
 113       */
 114      public static function getFilePath()
 115      {
 116          global $conf;
 117  
 118          $sitemap = $conf['cachedir'] . '/sitemap.xml';
 119          if (self::sitemapIsCompressed()) {
 120              $sitemap .= '.gz';
 121          }
 122  
 123          return $sitemap;
 124      }
 125  
 126      /**
 127       * Helper function for checking if the sitemap is compressed
 128       *
 129       * @return bool If the sitemap file is compressed
 130       */
 131      public static function sitemapIsCompressed()
 132      {
 133          global $conf;
 134          return $conf['compression'] === 'bz2' || $conf['compression'] === 'gz';
 135      }
 136  
 137      /**
 138       * Pings search engines with the sitemap url. Plugins can add or remove
 139       * urls to ping using the SITEMAP_PING event.
 140       *
 141       * @author Michael Hamann
 142       *
 143       * @return bool
 144       */
 145      public static function pingSearchEngines()
 146      {
 147          //ping search engines...
 148          $http = new DokuHTTPClient();
 149          $http->timeout = 8;
 150  
 151          $encoded_sitemap_url = urlencode(wl('', ['do' => 'sitemap'], true, '&'));
 152          $ping_urls = [
 153              'google'    => 'https://www.google.com/ping?sitemap=' . $encoded_sitemap_url,
 154              'yandex'    => 'https://webmaster.yandex.com/ping?sitemap=' . $encoded_sitemap_url
 155          ];
 156  
 157          $data = [
 158              'ping_urls' => $ping_urls,
 159              'encoded_sitemap_url' => $encoded_sitemap_url
 160          ];
 161          $event = new Event('SITEMAP_PING', $data);
 162          if ($event->advise_before(true)) {
 163              foreach ($data['ping_urls'] as $name => $url) {
 164                  Logger::debug("Sitemapper::PingSearchEngines(): pinging $name");
 165                  $resp = $http->get($url);
 166                  if ($http->error) {
 167                      Logger::debug("Sitemapper:pingSearchengines(): $http->error", $resp);
 168                  }
 169              }
 170          }
 171          $event->advise_after();
 172  
 173          return true;
 174      }
 175  }