68 $this->uniqueId =
$url;
81 $string = str_replace(
"\r\n",
"\n", $string );
82 $string = preg_replace(
'/[\x00-\x08\x0b\x0c\x0e-\x1f]/',
'', $string );
83 return htmlspecialchars( $string );
102 if ( $this->uniqueId ) {
150 return $this->
xmlEncode( $this->description );
187 return $this->
xmlEncode( $this->author );
205 return $this->
xmlEncode( $this->comments );
224 return preg_replace(
'/\[\[([^]]*\|)?([^]]+)\]\]/',
'\2', $text );
234 abstract class ChannelFeed
extends FeedItem {
247 function __construct(
$title, $description, $url, $date =
'', $author =
'', $comments =
'' ) {
248 parent::__construct(
$title, $description, $url, $date, $author, $comments );
249 $this->templateParser =
new TemplateParser();
259 abstract public function outHeader();
269 abstract public function outItem( $item );
278 abstract public function outFooter();
288 public function httpHeaders() {
291 # We take over from $wgOut, excepting its cache header info
293 $mimetype = $this->contentType();
294 header(
"Content-type: $mimetype; charset=UTF-8" );
298 ->getExtensionsForType( $mimetype );
299 $ext = $exts ? strtok( $exts,
' ' ) :
'xml';
300 header(
"Content-Disposition: inline; filename=\"feed.{$ext}\"" );
303 $wgOut->addVaryHeader(
'X-Forwarded-Proto' );
305 $wgOut->sendCacheControl();
313 private function contentType() {
316 $ctype =
$wgRequest->getVal(
'ctype',
'application/xml' );
320 'application/rss+xml',
321 'application/atom+xml'
324 return ( in_array( $ctype, $allowedctypes ) ? $ctype :
'application/xml' );
330 protected function outXmlHeader() {
331 $this->httpHeaders();
332 echo
'<?xml version="1.0"?>' .
"\n";
341 class RSSFeed
extends ChannelFeed {
349 function formatTime( $ts ) {
351 return gmdate(
'D, d M Y H:i:s \G\M\T',
wfTimestamp( TS_UNIX, $ts ) );
358 function outHeader() {
361 $this->outXmlHeader();
365 'title' => $this->getTitle(),
367 'description' => $this->getDescription(),
368 'language' => $this->xmlEncode( $this->getLanguage() ),
370 'timestamp' => $this->xmlEncode( $this->formatTime(
wfTimestampNow() ) )
372 print $this->templateParser->processTemplate(
'RSSHeader', $templateParams );
379 function outItem( $item ) {
383 "title" => $item->getTitle(),
385 "permalink" => $item->rssIsPermalink,
386 "uniqueID" => $item->getUniqueID(),
387 "description" => $item->getDescription(),
388 "date" => $this->xmlEncode( $this->formatTime( $item->getDate() ) ),
389 "author" => $item->getAuthor()
391 $comments = $item->getCommentsUnescaped();
394 $templateParams[
"comments"] = $commentsEscaped;
396 print $this->templateParser->processTemplate(
'RSSItem', $templateParams );
402 function outFooter() {
403 print
"</channel></rss>";
412 class AtomFeed
extends ChannelFeed {
419 function formatTime( $timestamp ) {
422 return gmdate(
'Y-m-d\TH:i:s',
wfTimestamp( TS_UNIX, $timestamp ) );
429 function outHeader() {
431 $this->outXmlHeader();
435 'language' => $this->xmlEncode( $this->getLanguage() ),
436 'feedID' => $this->getFeedId(),
437 'title' => $this->getTitle(),
439 'selfUrl' => $this->getSelfUrl(),
440 'timestamp' => $this->xmlEncode( $this->formatTime(
wfTimestampNow() ) ),
441 'description' => $this->getDescription(),
444 print $this->templateParser->processTemplate(
'AtomHeader', $templateParams );
455 private function getFeedId() {
456 return $this->getSelfUrl();
463 private function getSelfUrl() {
465 return htmlspecialchars(
$wgRequest->getFullRequestURL() );
472 function outItem( $item ) {
477 "uniqueID" => $item->getUniqueID(),
478 "title" => $item->getTitle(),
481 "date" => $this->xmlEncode( $this->formatTime( $item->getDate() ) ),
482 "description" => $item->getDescription(),
483 "author" => $item->getAuthor()
485 print $this->templateParser->processTemplate(
'AtomItem', $templateParams );
491 function outFooter() {