8fc32b918161fdb81c6690834b5cf4698dd17cf4
[lhc/web/wiklou.git] / includes / linkeddata / PageDataRequestHandler.php
1 <?php
2
3 use MediaWiki\Http\HttpAcceptParser;
4 use MediaWiki\Http\HttpAcceptNegotiator;
5
6 /**
7 * Request handler implementing a data interface for mediawiki pages.
8 *
9 * @license GPL-2.0+
10 * @author Daniel Kinzler
11 * @author Amir Sarabadanai
12 */
13
14 class PageDataRequestHandler {
15
16 /**
17 * Checks whether the request is complete, i.e. whether it contains all information needed
18 * to reply with page data.
19 *
20 * This does not check whether the request is valid and will actually produce a successful
21 * response.
22 *
23 * @param string|null $title Page title
24 * @param WebRequest $request
25 *
26 * @return bool
27 * @throws HttpError
28 */
29 public function canHandleRequest( $title, WebRequest $request ) {
30 if ( $title === '' || $title === null ) {
31 if ( $request->getText( 'target', '' ) === '' ) {
32 return false;
33 }
34 }
35
36 return true;
37 }
38
39 /**
40 * Main method for handling requests.
41 *
42 * @param string $title Page title
43 * @param WebRequest $request The request parameters. Known parameters are:
44 * - title: the page title
45 * - format: the format
46 * - oldid|revision: the revision ID
47 * @param OutputPage $output
48 *
49 * @note: Instead of an output page, a WebResponse could be sufficient, but
50 * redirect logic is currently implemented in OutputPage.
51 *
52 * @throws HttpError
53 */
54 public function handleRequest( $title, WebRequest $request, OutputPage $output ) {
55 // No matter what: The response is always public
56 $output->getRequest()->response()->header( 'Access-Control-Allow-Origin: *' );
57
58 $revision = 0;
59
60 $title = $request->getText( 'target', $title );
61 $revision = $request->getInt( 'oldid', $revision );
62 $revision = $request->getInt( 'revision', $revision );
63
64 if ( $title === null || $title === '' ) {
65 //TODO: different error message?
66 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $title ) );
67 }
68
69 try {
70 $title = Title::newFromTextThrow( $title );
71 } catch ( MalformedTitleException $ex ) {
72 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $title ) );
73 }
74
75 $this->httpContentNegotiation( $request, $output, $title, $revision );
76 }
77
78 /**
79 * Applies HTTP content negotiation.
80 * If the negotiation is successful, this method will set the appropriate redirect
81 * in the OutputPage object and return. Otherwise, an HttpError is thrown.
82 *
83 * @param WebRequest $request
84 * @param OutputPage $output
85 * @param Title $title
86 * @param int $revision The desired revision
87 *
88 * @throws HttpError
89 */
90 public function httpContentNegotiation(
91 WebRequest $request,
92 OutputPage $output,
93 Title $title,
94 $revision = 0
95 ) {
96 $contentHandler = ContentHandler::getForTitle( $title );
97 $mimeTypes = $contentHandler->getSupportedFormats();
98
99 $headers = $request->getAllHeaders();
100 if ( isset( $headers['ACCEPT'] ) ) {
101 $parser = new HttpAcceptParser();
102 $accept = $parser->parseWeights( $headers['ACCEPT'] );
103 } else {
104 // anything goes
105 $accept = [
106 '*' => 0.1 // just to make extra sure
107 ];
108 // prefer the default
109 $accept[$mimeTypes[0]] = 1;
110 }
111
112 $negotiator = new HttpAcceptNegotiator( $mimeTypes );
113 $format = $negotiator->getBestSupportedKey( $accept, null );
114
115 if ( $format === null ) {
116 $format = isset( $accept['text/html'] ) ? 'text/html' : null;
117 }
118
119 if ( $format === null ) {
120 $msg = wfMessage( 'pagedata-not-acceptable', implode( ', ', $mimeTypes ) );
121 throw new HttpError( 406, $msg );
122 }
123
124 $url = $this->getDocUrl( $title, $format, $revision );
125 $output->redirect( $url, 303 );
126 }
127
128 /**
129 * Returns a url representing the given title.
130 *
131 * @param Title $title
132 * @param string|null $format The (normalized) format name, or ''
133 * @param int $revision
134 * @return string
135 */
136 private function getDocUrl( Title $title, $format = '', $revision = 0 ) {
137 $params = [];
138
139 if ( $revision > 0 ) {
140 $params['oldid'] = $revision;
141 }
142
143 if ( $format === 'text/html' ) {
144 return $title->getFullURL( $params );
145 }
146
147 $params[ 'action' ] = 'raw';
148
149 return $title->getFullURL( $params );
150 }
151
152 }