[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/ -> Feed.php (source)

   1  <?php
   2  /**
   3   * Basic support for outputting syndication feeds in RSS, other formats.
   4   *
   5   * Contain a feed class as well as classes to build rss / atom ... feeds
   6   * Available feeds are defined in Defines.php
   7   *
   8   * Copyright © 2004 Brion Vibber <[email protected]>
   9   * https://www.mediawiki.org/
  10   *
  11   * This program is free software; you can redistribute it and/or modify
  12   * it under the terms of the GNU General Public License as published by
  13   * the Free Software Foundation; either version 2 of the License, or
  14   * (at your option) any later version.
  15   *
  16   * This program is distributed in the hope that it will be useful,
  17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19   * GNU General Public License for more details.
  20   *
  21   * You should have received a copy of the GNU General Public License along
  22   * with this program; if not, write to the Free Software Foundation, Inc.,
  23   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  24   * http://www.gnu.org/copyleft/gpl.html
  25   *
  26   * @file
  27   */
  28  
  29  /**
  30   * @defgroup Feed Feed
  31   */
  32  
  33  /**
  34   * A base class for basic support for outputting syndication feeds in RSS and other formats.
  35   *
  36   * @ingroup Feed
  37   */
  38  class FeedItem {
  39      /** @var Title */
  40      public $title;
  41  
  42      public $description;
  43  
  44      public $url;
  45  
  46      public $date;
  47  
  48      public $author;
  49  
  50      public $uniqueId;
  51  
  52      public $comments;
  53  
  54      public $rssIsPermalink = false;
  55  
  56      /**
  57       * Constructor
  58       *
  59       * @param string|Title $title Item's title
  60       * @param string $description
  61       * @param string $url URL uniquely designating the item.
  62       * @param string $date Item's date
  63       * @param string $author Author's user name
  64       * @param string $comments
  65       */
  66  	function __construct( $title, $description, $url, $date = '', $author = '', $comments = '' ) {
  67          $this->title = $title;
  68          $this->description = $description;
  69          $this->url = $url;
  70          $this->uniqueId = $url;
  71          $this->date = $date;
  72          $this->author = $author;
  73          $this->comments = $comments;
  74      }
  75  
  76      /**
  77       * Encode $string so that it can be safely embedded in a XML document
  78       *
  79       * @param string $string String to encode
  80       * @return string
  81       */
  82  	public function xmlEncode( $string ) {
  83          $string = str_replace( "\r\n", "\n", $string );
  84          $string = preg_replace( '/[\x00-\x08\x0b\x0c\x0e-\x1f]/', '', $string );
  85          return htmlspecialchars( $string );
  86      }
  87  
  88      /**
  89       * Get the unique id of this item
  90       *
  91       * @return string
  92       */
  93  	public function getUniqueId() {
  94          if ( $this->uniqueId ) {
  95              return $this->xmlEncode( $this->uniqueId );
  96          }
  97      }
  98  
  99      /**
 100       * Set the unique id of an item
 101       *
 102       * @param string $uniqueId Unique id for the item
 103       * @param bool $rssIsPermalink Set to true if the guid (unique id) is a permalink (RSS feeds only)
 104       */
 105  	public function setUniqueId( $uniqueId, $rssIsPermalink = false ) {
 106          $this->uniqueId = $uniqueId;
 107          $this->rssIsPermalink = $rssIsPermalink;
 108      }
 109  
 110      /**
 111       * Get the title of this item; already xml-encoded
 112       *
 113       * @return string
 114       */
 115  	public function getTitle() {
 116          return $this->xmlEncode( $this->title );
 117      }
 118  
 119      /**
 120       * Get the URL of this item; already xml-encoded
 121       *
 122       * @return string
 123       */
 124  	public function getUrl() {
 125          return $this->xmlEncode( $this->url );
 126      }
 127  
 128      /**
 129       * Get the description of this item; already xml-encoded
 130       *
 131       * @return string
 132       */
 133  	public function getDescription() {
 134          return $this->xmlEncode( $this->description );
 135      }
 136  
 137      /**
 138       * Get the language of this item
 139       *
 140       * @return string
 141       */
 142  	public function getLanguage() {
 143          global $wgLanguageCode;
 144          return $wgLanguageCode;
 145      }
 146  
 147      /**
 148       * Get the date of this item
 149       *
 150       * @return string
 151       */
 152  	public function getDate() {
 153          return $this->date;
 154      }
 155  
 156      /**
 157       * Get the author of this item; already xml-encoded
 158       *
 159       * @return string
 160       */
 161  	public function getAuthor() {
 162          return $this->xmlEncode( $this->author );
 163      }
 164  
 165      /**
 166       * Get the comment of this item; already xml-encoded
 167       *
 168       * @return string
 169       */
 170  	public function getComments() {
 171          return $this->xmlEncode( $this->comments );
 172      }
 173  
 174      /**
 175       * Quickie hack... strip out wikilinks to more legible form from the comment.
 176       *
 177       * @param string $text Wikitext
 178       * @return string
 179       */
 180  	public static function stripComment( $text ) {
 181          return preg_replace( '/\[\[([^]]*\|)?([^]]+)\]\]/', '\2', $text );
 182      }
 183      /**#@-*/
 184  }
 185  
 186  /**
 187   * @todo document (needs one-sentence top-level class description).
 188   * @ingroup Feed
 189   */
 190  abstract class ChannelFeed extends FeedItem {
 191      /**
 192       * Generate Header of the feed
 193       * @par Example:
 194       * @code
 195       * print "<feed>";
 196       * @endcode
 197       */
 198      abstract public function outHeader();
 199  
 200      /**
 201       * Generate an item
 202       * @par Example:
 203       * @code
 204       * print "<item>...</item>";
 205       * @endcode
 206       * @param FeedItem $item
 207       */
 208      abstract public function outItem( $item );
 209  
 210      /**
 211       * Generate Footer of the feed
 212       * @par Example:
 213       * @code
 214       * print "</feed>";
 215       * @endcode
 216       */
 217      abstract public function outFooter();
 218  
 219      /**
 220       * Setup and send HTTP headers. Don't send any content;
 221       * content might end up being cached and re-sent with
 222       * these same headers later.
 223       *
 224       * This should be called from the outHeader() method,
 225       * but can also be called separately.
 226       */
 227  	public function httpHeaders() {
 228          global $wgOut, $wgVaryOnXFP;
 229  
 230          # We take over from $wgOut, excepting its cache header info
 231          $wgOut->disable();
 232          $mimetype = $this->contentType();
 233          header( "Content-type: $mimetype; charset=UTF-8" );
 234          if ( $wgVaryOnXFP ) {
 235              $wgOut->addVaryHeader( 'X-Forwarded-Proto' );
 236          }
 237          $wgOut->sendCacheControl();
 238  
 239      }
 240  
 241      /**
 242       * Return an internet media type to be sent in the headers.
 243       *
 244       * @return string
 245       */
 246  	private function contentType() {
 247          global $wgRequest;
 248  
 249          $ctype = $wgRequest->getVal( 'ctype', 'application/xml' );
 250          $allowedctypes = array(
 251              'application/xml',
 252              'text/xml',
 253              'application/rss+xml',
 254              'application/atom+xml'
 255          );
 256  
 257          return ( in_array( $ctype, $allowedctypes ) ? $ctype : 'application/xml' );
 258      }
 259  
 260      /**
 261       * Output the initial XML headers.
 262       */
 263  	protected function outXmlHeader() {
 264          $this->httpHeaders();
 265          echo '<?xml version="1.0"?>' . "\n";
 266      }
 267  }
 268  
 269  /**
 270   * Generate a RSS feed
 271   *
 272   * @ingroup Feed
 273   */
 274  class RSSFeed extends ChannelFeed {
 275  
 276      /**
 277       * Format a date given a timestamp
 278       *
 279       * @param int $ts Timestamp
 280       * @return string Date string
 281       */
 282  	function formatTime( $ts ) {
 283          return gmdate( 'D, d M Y H:i:s \G\M\T', wfTimestamp( TS_UNIX, $ts ) );
 284      }
 285  
 286      /**
 287       * Output an RSS 2.0 header
 288       */
 289  	function outHeader() {
 290          global $wgVersion;
 291  
 292          $this->outXmlHeader();
 293          ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
 294      <channel>
 295          <title><?php print $this->getTitle() ?></title>
 296          <link><?php print wfExpandUrl( $this->getUrl(), PROTO_CURRENT ) ?></link>
 297          <description><?php print $this->getDescription() ?></description>
 298          <language><?php print $this->getLanguage() ?></language>
 299          <generator>MediaWiki <?php print $wgVersion ?></generator>
 300          <lastBuildDate><?php print $this->formatTime( wfTimestampNow() ) ?></lastBuildDate>
 301  <?php
 302      }
 303  
 304      /**
 305       * Output an RSS 2.0 item
 306       * @param FeedItem $item Item to be output
 307       */
 308  	function outItem( $item ) {
 309          // @codingStandardsIgnoreStart Ignore long lines and formatting issues.
 310      ?>
 311          <item>
 312              <title><?php print $item->getTitle(); ?></title>
 313              <link><?php print wfExpandUrl( $item->getUrl(), PROTO_CURRENT ); ?></link>
 314              <guid<?php if ( !$item->rssIsPermalink ) { print ' isPermaLink="false"'; } ?>><?php print $item->getUniqueId(); ?></guid>
 315              <description><?php print $item->getDescription() ?></description>
 316              <?php if ( $item->getDate() ) { ?><pubDate><?php print $this->formatTime( $item->getDate() ); ?></pubDate><?php } ?>
 317              <?php if ( $item->getAuthor() ) { ?><dc:creator><?php print $item->getAuthor(); ?></dc:creator><?php }?>
 318              <?php if ( $item->getComments() ) { ?><comments><?php print wfExpandUrl( $item->getComments(), PROTO_CURRENT ); ?></comments><?php }?>
 319          </item>
 320  <?php
 321          // @codingStandardsIgnoreEnd
 322      }
 323  
 324      /**
 325       * Output an RSS 2.0 footer
 326       */
 327  	function outFooter() {
 328      ?>
 329      </channel>
 330  </rss><?php
 331      }
 332  }
 333  
 334  /**
 335   * Generate an Atom feed
 336   *
 337   * @ingroup Feed
 338   */
 339  class AtomFeed extends ChannelFeed {
 340      /**
 341       * @todo document
 342       * @param string|int $ts
 343       * @return string
 344       */
 345  	function formatTime( $ts ) {
 346          // need to use RFC 822 time format at least for rss2.0
 347          return gmdate( 'Y-m-d\TH:i:s', wfTimestamp( TS_UNIX, $ts ) );
 348      }
 349  
 350      /**
 351       * Outputs a basic header for Atom 1.0 feeds.
 352       */
 353  	function outHeader() {
 354          global $wgVersion;
 355  
 356          $this->outXmlHeader();
 357          // @codingStandardsIgnoreStart Ignore long lines and formatting issues.
 358          ?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="<?php print $this->getLanguage() ?>">
 359          <id><?php print $this->getFeedId() ?></id>
 360          <title><?php print $this->getTitle() ?></title>
 361          <link rel="self" type="application/atom+xml" href="<?php print wfExpandUrl( $this->getSelfUrl(), PROTO_CURRENT ) ?>"/>
 362          <link rel="alternate" type="text/html" href="<?php print wfExpandUrl( $this->getUrl(), PROTO_CURRENT ) ?>"/>
 363          <updated><?php print $this->formatTime( wfTimestampNow() ) ?>Z</updated>
 364          <subtitle><?php print $this->getDescription() ?></subtitle>
 365          <generator>MediaWiki <?php print $wgVersion ?></generator>
 366  
 367  <?php
 368          // @codingStandardsIgnoreEnd
 369      }
 370  
 371      /**
 372       * Atom 1.0 requires a unique, opaque IRI as a unique identifier
 373       * for every feed we create. For now just use the URL, but who
 374       * can tell if that's right? If we put options on the feed, do we
 375       * have to change the id? Maybe? Maybe not.
 376       *
 377       * @return string
 378       */
 379  	private function getFeedId() {
 380          return $this->getSelfUrl();
 381      }
 382  
 383      /**
 384       * Atom 1.0 requests a self-reference to the feed.
 385       * @return string
 386       */
 387  	private function getSelfUrl() {
 388          global $wgRequest;
 389          return htmlspecialchars( $wgRequest->getFullRequestURL() );
 390      }
 391  
 392      /**
 393       * Output a given item.
 394       * @param FeedItem $item
 395       */
 396  	function outItem( $item ) {
 397          global $wgMimeType;
 398          // @codingStandardsIgnoreStart Ignore long lines and formatting issues.
 399      ?>
 400      <entry>
 401          <id><?php print $item->getUniqueId(); ?></id>
 402          <title><?php print $item->getTitle(); ?></title>
 403          <link rel="alternate" type="<?php print $wgMimeType ?>" href="<?php print wfExpandUrl( $item->getUrl(), PROTO_CURRENT ); ?>"/>
 404          <?php if ( $item->getDate() ) { ?>
 405          <updated><?php print $this->formatTime( $item->getDate() ); ?>Z</updated>
 406          <?php } ?>
 407  
 408          <summary type="html"><?php print $item->getDescription() ?></summary>
 409          <?php if ( $item->getAuthor() ) { ?><author><name><?php print $item->getAuthor(); ?></name></author><?php }?>
 410      </entry>
 411  
 412  <?php /* @todo FIXME: Need to add comments
 413      <?php if( $item->getComments() ) { ?><dc:comment><?php print $item->getComments() ?></dc:comment><?php }?>
 414        */
 415      }
 416  
 417      /**
 418       * Outputs the footer for Atom 1.0 feed (basically '\</feed\>').
 419       */
 420  	function outFooter() {?>
 421      </feed><?php
 422          // @codingStandardsIgnoreEnd
 423      }
 424  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1