1<?php
2/**
3 * Copyright © 2004 Brion Vibber <brion@pobox.com>
4 * https://www.mediawiki.org/
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * http://www.gnu.org/copyleft/gpl.html
20 *
21 * @file
22 */
23
24/**
25 * Class to support the outputting of syndication feeds in Atom and RSS format.
26 *
27 * @stable to extend
28 * @ingroup Feed
29 */
30abstract class ChannelFeed extends FeedItem {
31
32	/** @var TemplateParser */
33	protected $templateParser;
34
35	/**
36	 * @stable to call
37	 *
38	 * @param string|Title $title Feed's title
39	 * @param string $description
40	 * @param string $url URL uniquely designating the feed.
41	 * @param string $date Feed's date
42	 * @param string $author Author's user name
43	 * @param string $comments
44	 *
45	 */
46	public function __construct(
47		$title, $description, $url, $date = '', $author = '', $comments = ''
48	) {
49		parent::__construct( $title, $description, $url, $date, $author, $comments );
50		$this->templateParser = new TemplateParser();
51	}
52
53	/**
54	 * Generate Header of the feed
55	 * @par Example:
56	 * @code
57	 * print "<feed>";
58	 * @endcode
59	 */
60	abstract public function outHeader();
61
62	/**
63	 * Generate an item
64	 * @par Example:
65	 * @code
66	 * print "<item>...</item>";
67	 * @endcode
68	 * @param FeedItem $item
69	 */
70	abstract public function outItem( $item );
71
72	/**
73	 * Generate Footer of the feed
74	 * @par Example:
75	 * @code
76	 * print "</feed>";
77	 * @endcode
78	 */
79	abstract public function outFooter();
80
81	/**
82	 * Setup and send HTTP headers. Don't send any content;
83	 * content might end up being cached and re-sent with
84	 * these same headers later.
85	 *
86	 * This should be called from the outHeader() method,
87	 * but can also be called separately.
88	 */
89	public function httpHeaders() {
90		global $wgOut, $wgVaryOnXFP;
91
92		# We take over from $wgOut, excepting its cache header info
93		$wgOut->disable();
94		$mimetype = $this->contentType();
95		header( "Content-type: $mimetype; charset=UTF-8" );
96
97		// Set a sane filename
98		$mimeAnalyzer = MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer();
99		$ext = $mimeAnalyzer->getExtensionFromMimeTypeOrNull( $mimetype ) ?? 'xml';
100		header( "Content-Disposition: inline; filename=\"feed.{$ext}\"" );
101
102		if ( $wgVaryOnXFP ) {
103			$wgOut->addVaryHeader( 'X-Forwarded-Proto' );
104		}
105		$wgOut->sendCacheControl();
106	}
107
108	/**
109	 * Return an internet media type to be sent in the headers.
110	 *
111	 * @stable to override
112	 *
113	 * @return string
114	 */
115	private function contentType() {
116		global $wgRequest;
117
118		$ctype = $wgRequest->getVal( 'ctype', 'application/xml' );
119		$allowedctypes = [
120			'application/xml',
121			'text/xml',
122			'application/rss+xml',
123			'application/atom+xml'
124		];
125
126		return ( in_array( $ctype, $allowedctypes ) ? $ctype : 'application/xml' );
127	}
128
129	/**
130	 * Output the initial XML headers.
131	 */
132	protected function outXmlHeader() {
133		$this->httpHeaders();
134		echo '<?xml version="1.0"?>' . "\n";
135	}
136}
137