[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/Feed/ -> FeedCreator.php (source)

   1  <?php
   2  
   3  namespace dokuwiki\Feed;
   4  
   5  use dokuwiki\Extension\Event;
   6  
   7  class FeedCreator
   8  {
   9      /** @var \UniversalFeedCreator */
  10      protected $feed;
  11  
  12      /** @var FeedCreatorOptions */
  13      protected $options;
  14  
  15      /**
  16       * @param FeedCreatorOptions $options
  17       */
  18      public function __construct(FeedCreatorOptions $options)
  19      {
  20          $this->options = $options;
  21  
  22          $this->feed = new \UniversalFeedCreator();
  23          $this->feed->title = $this->options->get('title');
  24          $this->feed->description = $this->options->get('subtitle');
  25          $this->feed->link = DOKU_URL;
  26          $this->feed->syndicationURL = DOKU_URL . 'feed.php';
  27          $this->feed->cssStyleSheet = DOKU_URL . 'lib/exe/css.php?s=feed';
  28  
  29          $this->initLogo();
  30      }
  31  
  32      /**
  33       * Build the feed
  34       *
  35       * @return string The raw XML for the feed
  36       */
  37      public function build()
  38      {
  39          switch ($this->options->get('feed_mode')) {
  40              case 'list':
  41                  $items = $this->fetchItemsFromNamespace();
  42                  break;
  43              case 'search':
  44                  $items = $this->fetchItemsFromSearch();
  45                  break;
  46              case 'recent':
  47                  $items = $this->fetchItemsFromRecentChanges();
  48                  break;
  49              default:
  50                  $items = $this->fetchItemsFromPlugin();
  51          }
  52  
  53          $eventData = [
  54              'rss' => $this->feed,
  55              'data' => &$items,
  56              'opt' =>  &$this->options->options,
  57          ];
  58          $event = new Event('FEED_DATA_PROCESS', $eventData);
  59          if ($event->advise_before(false)) {
  60              foreach ($items as $item) {
  61                  $this->createAndAddItem($item);
  62              }
  63          }
  64          $event->advise_after();
  65  
  66          return $this->feed->createFeed($this->options->getType());
  67      }
  68  
  69      /**
  70       * Process the raw data, create feed item and add it to the feed
  71       *
  72       * @param array|string $data raw item data
  73       * @return \FeedItem
  74       * @triggers FEED_ITEM_ADD
  75       */
  76      protected function createAndAddItem($data)
  77      {
  78          if (is_string($data)) {
  79              $data = ['id' => $data];
  80          }
  81  
  82          if (($data['mode'] ?? '') == 'media' || isset($data['media'])) {
  83              $data['id'] = $data['media'] ?? $data['id'];
  84              $proc = new FeedMediaProcessor($data);
  85          } else {
  86              $proc = new FeedPageProcessor($data);
  87          }
  88  
  89          $item = new \FeedItem();
  90          $item->title = $proc->getTitle();
  91          if ($this->options->get('show_summary') && $proc->getSummary()) {
  92              $item->title .= ' - ' . $proc->getSummary();
  93          }
  94          $item->date = $proc->getRev();
  95          [$item->authorEmail, $item->author] = $proc->getAuthor();
  96          $item->link = $proc->getURL($this->options->get('link_to'));
  97          $item->description = $proc->getBody($this->options->get('item_content'));
  98  
  99          $evdata = [
 100              'item' => $item,
 101              'opt' => &$this->options->options,
 102              'ditem' => &$data,
 103              'rss' => $this->feed,
 104          ];
 105  
 106          $evt = new Event('FEED_ITEM_ADD', $evdata);
 107          if ($evt->advise_before()) {
 108              $this->feed->addItem($item);
 109          }
 110          $evt->advise_after();
 111  
 112          return $item;
 113      }
 114  
 115      /**
 116       * Read all pages from a namespace
 117       *
 118       * @todo this currently does not honor the rss_media setting and only ever lists pages
 119       * @return array
 120       */
 121      protected function fetchItemsFromNamespace()
 122      {
 123          global $conf;
 124  
 125          $ns = ':' . cleanID($this->options->get('namespace'));
 126          $ns = utf8_encodeFN(str_replace(':', '/', $ns));
 127  
 128          $data = [];
 129          $search_opts = [
 130              'depth' => 1,
 131              'pagesonly' => true,
 132              'listfiles' => true
 133          ];
 134          search(
 135              $data,
 136              $conf['datadir'],
 137              'search_universal',
 138              $search_opts,
 139              $ns,
 140              $lvl = 1,
 141              $this->options->get('sort')
 142          );
 143  
 144          return $data;
 145      }
 146  
 147      /**
 148       * Add the result of a full text search to the feed object
 149       *
 150       * @return array
 151       */
 152      protected function fetchItemsFromSearch()
 153      {
 154          if (!actionOK('search')) throw new \RuntimeException('search is disabled');
 155          if (!$this->options->get('search_query')) return [];
 156  
 157          $data = ft_pageSearch($this->options->get('search_query'), $poswords);
 158          return array_keys($data);
 159      }
 160  
 161      /**
 162       * Add recent changed pages to the feed object
 163       *
 164       * @return array
 165       */
 166      protected function fetchItemsFromRecentChanges()
 167      {
 168          global $conf;
 169          $flags = 0;
 170          if (!$this->options->get('show_deleted')) $flags += RECENTS_SKIP_DELETED;
 171          if (!$this->options->get('show_minor')) $flags += RECENTS_SKIP_MINORS;
 172          if ($this->options->get('only_new')) $flags += RECENTS_ONLY_CREATION;
 173          if ($this->options->get('content_type') == 'media' && $conf['mediarevisions']) {
 174              $flags += RECENTS_MEDIA_CHANGES;
 175          }
 176          if ($this->options->get('content_type') == 'both' && $conf['mediarevisions']) {
 177              $flags += RECENTS_MEDIA_PAGES_MIXED;
 178          }
 179  
 180          return getRecents(0, $this->options->get('items'), $this->options->get('namespace'), $flags);
 181      }
 182  
 183      /**
 184       * Add items from a plugin to the feed object
 185       *
 186       * @triggers FEED_MODE_UNKNOWN
 187       * @return array
 188       */
 189      protected function fetchItemsFromPlugin()
 190      {
 191          $eventData = [
 192              'opt' => $this->options->options,
 193              'data' => [],
 194          ];
 195          $event = new Event('FEED_MODE_UNKNOWN', $eventData);
 196          if ($event->advise_before(true)) {
 197              throw new \RuntimeException('unknown feed mode');
 198          }
 199          $event->advise_after();
 200  
 201          return $eventData['data'];
 202      }
 203  
 204      /**
 205       * Add a logo to the feed
 206       *
 207       * Looks at different possible candidates for a logo and adds the first one
 208       *
 209       * @return void
 210       */
 211      protected function initLogo()
 212      {
 213          global $conf;
 214  
 215          $this->feed->image = new \FeedImage();
 216          $this->feed->image->title = $conf['title'];
 217          $this->feed->image->link = DOKU_URL;
 218          $this->feed->image->url = tpl_getMediaFile([
 219              ':wiki:logo.svg',
 220              ':logo.svg',
 221              ':wiki:logo.png',
 222              ':logo.png',
 223              ':wiki:logo.jpg',
 224              ':logo.jpg',
 225              ':wiki:favicon.ico',
 226              ':favicon.ico',
 227              ':wiki:dokuwiki.svg',
 228              ':wiki:dokuwiki-128.png',
 229              'images/favicon.ico'
 230          ], true);
 231      }
 232  }