X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FFeed.php;h=0e715df2ff3c6b73129687f468e4df3fdaa7df76;hb=19124fd1d24d0426743c6e0dd83a5a9eae896e66;hp=bc7747fe7297f6412e7744e0b2a94416ab210eca;hpb=63752d25bfc28159f5f9b6a2e9a6a6d784959fd0;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Feed.php b/includes/Feed.php index bc7747fe72..0e715df2ff 100644 --- a/includes/Feed.php +++ b/includes/Feed.php @@ -84,13 +84,23 @@ class FeedItem { } /** - * Get the unique id of this item - * + * Get the unique id of this item; already xml-encoded + * @return string + */ + public function getUniqueID() { + $id = $this->getUniqueIDUnescaped(); + if ( $id ) { + return $this->xmlEncode( $id ); + } + } + + /** + * Get the unique id of this item, without any escaping * @return string */ - public function getUniqueId() { + public function getUniqueIdUnescaped() { if ( $this->uniqueId ) { - return $this->xmlEncode( wfExpandUrl( $this->uniqueId, PROTO_CURRENT ) ); + return wfExpandUrl( $this->uniqueId, PROTO_CURRENT ); } } @@ -123,6 +133,14 @@ class FeedItem { return $this->xmlEncode( $this->url ); } + /** Get the URL of this item without any escaping + * + * @return string + */ + public function getUrlUnescaped() { + return $this->url; + } + /** * Get the description of this item; already xml-encoded * @@ -132,6 +150,14 @@ class FeedItem { return $this->xmlEncode( $this->description ); } + /** + * Get the description of this item without any escaping + * + */ + public function getDescriptionUnescaped() { + return $this->description; + } + /** * Get the language of this item * @@ -160,6 +186,15 @@ class FeedItem { return $this->xmlEncode( $this->author ); } + /** + * Get the author of this item without any escaping + * + * @return string + */ + public function getAuthorUnescaped() { + return $this->author; + } + /** * Get the comment of this item; already xml-encoded * @@ -169,6 +204,15 @@ class FeedItem { return $this->xmlEncode( $this->comments ); } + /** + * Get the comment of this item without any escaping + * + * @return string + */ + public function getCommentsUnescaped() { + return $this->comments; + } + /** * Quickie hack... strip out wikilinks to more legible form from the comment. * @@ -187,6 +231,23 @@ class FeedItem { * @ingroup Feed */ abstract class ChannelFeed extends FeedItem { + + /** @var TemplateParser */ + protected $templateParser; + + /** + * @param string|Title $title Feed's title + * @param string $description + * @param string $url URL uniquely designating the feed. + * @param string $date Feed's date + * @param string $author Author's user name + * @param string $comments + */ + function __construct( $title, $description, $url, $date = '', $author = '', $comments = '' ) { + parent::__construct( $title, $description, $url, $date, $author, $comments ); + $this->templateParser = new TemplateParser(); + } + /** * Generate Header of the feed * @par Example: @@ -230,6 +291,13 @@ abstract class ChannelFeed extends FeedItem { $wgOut->disable(); $mimetype = $this->contentType(); header( "Content-type: $mimetype; charset=UTF-8" ); + + // Set a sane filename + $exts = MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer() + ->getExtensionsForType( $mimetype ); + $ext = $exts ? strtok( $exts, ' ' ) : 'xml'; + header( "Content-Disposition: inline; filename=\"feed.{$ext}\"" ); + if ( $wgVaryOnXFP ) { $wgOut->addVaryHeader( 'X-Forwarded-Proto' ); } @@ -272,13 +340,15 @@ abstract class ChannelFeed extends FeedItem { class RSSFeed extends ChannelFeed { /** - * Format a date given a timestamp + * Format a date given a timestamp. If a timestamp is not given, nothing is returned * - * @param int $ts Timestamp - * @return string Date string + * @param int|null $ts Timestamp + * @return string|null Date string */ function formatTime( $ts ) { - return gmdate( 'D, d M Y H:i:s \G\M\T', wfTimestamp( TS_UNIX, $ts ) ); + if ( $ts ) { + return gmdate( 'D, d M Y H:i:s \G\M\T', wfTimestamp( TS_UNIX, $ts ) ); + } } /** @@ -288,15 +358,17 @@ class RSSFeed extends ChannelFeed { global $wgVersion; $this->outXmlHeader(); - ?> - - <?php print $this->getTitle() ?> - getUrl(), PROTO_CURRENT ) ?> - getDescription() ?> - getLanguage() ?> - MediaWiki - formatTime( wfTimestampNow() ) ?> - $this->getTitle(), + 'url' => $this->xmlEncode( wfExpandUrl( $this->getUrlUnescaped(), PROTO_CURRENT ) ), + 'description' => $this->getDescription(), + 'language' => $this->xmlEncode( $this->getLanguage() ), + 'version' => $this->xmlEncode( $wgVersion ), + 'timestamp' => $this->xmlEncode( $this->formatTime( wfTimestampNow() ) ) + ]; + print $this->templateParser->processTemplate( 'RSSHeader', $templateParams ); } /** @@ -304,28 +376,30 @@ class RSSFeed extends ChannelFeed { * @param FeedItem $item Item to be output */ function outItem( $item ) { - // @codingStandardsIgnoreStart Ignore long lines and formatting issues. - ?> - - <?php print $item->getTitle(); ?> - getUrl(), PROTO_CURRENT ); ?> - rssIsPermalink ) { print ' isPermaLink="false"'; } ?>>getUniqueId(); ?> - getDescription() ?> - getDate() ) { ?>formatTime( $item->getDate() ); ?> - getAuthor() ) { ?>getAuthor(); ?> - getComments() ) { ?>getComments(), PROTO_CURRENT ); ?> - - $item->getTitle(), + "url" => $this->xmlEncode( wfExpandUrl( $item->getUrlUnescaped(), PROTO_CURRENT ) ), + "permalink" => $item->rssIsPermalink, + "uniqueID" => $item->getUniqueId(), + "description" => $item->getDescription(), + "date" => $this->xmlEncode( $this->formatTime( $item->getDate() ) ), + "author" => $item->getAuthor() + ]; + $comments = $item->getCommentsUnescaped(); + if ( $comments ) { + $commentsEscaped = $this->xmlEncode( wfExpandUrl( $comments, PROTO_CURRENT ) ); + $templateParams["comments"] = $commentsEscaped; + } + print $this->templateParser->processTemplate( 'RSSItem', $templateParams ); } /** * Output an RSS 2.0 footer */ function outFooter() { - ?> - -"; } } @@ -336,14 +410,16 @@ class RSSFeed extends ChannelFeed { */ class AtomFeed extends ChannelFeed { /** - * Format a date given timestamp. + * Format a date given timestamp, if one is given. * - * @param string|int $timestamp - * @return string + * @param string|int|null $timestamp + * @return string|null */ function formatTime( $timestamp ) { - // need to use RFC 822 time format at least for rss2.0 - return gmdate( 'Y-m-d\TH:i:s', wfTimestamp( TS_UNIX, $timestamp ) ); + if ( $timestamp ) { + // need to use RFC 822 time format at least for rss2.0 + return gmdate( 'Y-m-d\TH:i:s', wfTimestamp( TS_UNIX, $timestamp ) ); + } } /** @@ -351,20 +427,20 @@ class AtomFeed extends ChannelFeed { */ function outHeader() { global $wgVersion; - $this->outXmlHeader(); - // @codingStandardsIgnoreStart Ignore long lines and formatting issues. - ?> - getFeedId() ?> - <?php print $this->getTitle() ?> - - - formatTime( wfTimestampNow() ) ?>Z - getDescription() ?> - MediaWiki - - $this->xmlEncode( $this->getLanguage() ), + 'feedID' => $this->getFeedID(), + 'title' => $this->getTitle(), + 'url' => $this->xmlEncode( wfExpandUrl( $this->getUrlUnescaped(), PROTO_CURRENT ) ), + 'selfUrl' => $this->getSelfUrl(), + 'timestamp' => $this->xmlEncode( $this->formatTime( wfTimestampNow() ) ), + 'description' => $this->getDescription(), + 'version' => $this->xmlEncode( $wgVersion ), + ]; + print $this->templateParser->processTemplate( 'AtomHeader', $templateParams ); } /** @@ -394,30 +470,24 @@ class AtomFeed extends ChannelFeed { */ function outItem( $item ) { global $wgMimeType; - // @codingStandardsIgnoreStart Ignore long lines and formatting issues. - ?> - - getUniqueId(); ?> - <?php print $item->getTitle(); ?> - - getDate() ) { ?> - formatTime( $item->getDate() ); ?>Z - - - getDescription() ?> - getAuthor() ) { ?>getAuthor(); ?> - - -getComments() ) { ?>getComments() ?> - */ + // Manually escaping rather than letting Mustache do it because Mustache + // uses htmlentities, which does not work with XML + $templateParams = [ + "uniqueID" => $item->getUniqueId(), + "title" => $item->getTitle(), + "mimeType" => $this->xmlEncode( $wgMimeType ), + "url" => $this->xmlEncode( wfExpandUrl( $item->getUrlUnescaped(), PROTO_CURRENT ) ), + "date" => $this->xmlEncode( $this->formatTime( $item->getDate() ) ), + "description" => $item->getDescription(), + "author" => $item->getAuthor() + ]; + print $this->templateParser->processTemplate( 'AtomItem', $templateParams ); } /** * Outputs the footer for Atom 1.0 feed (basically '\'). */ - function outFooter() {?> - "; } }