Merge "Add 3D filetype for STL files"
[lhc/web/wiklou.git] / includes / linkeddata / PageDataRequestHandler.php
1 <?php
2
3 use Wikimedia\Http\HttpAcceptParser;
4 use Wikimedia\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 $subPage
24 * @param WebRequest $request
25 *
26 * @return bool
27 * @throws HttpError
28 */
29 public function canHandleRequest( $subPage, WebRequest $request ) {
30 if ( $subPage === '' || $subPage === null ) {
31 if ( $request->getText( 'target', '' ) === '' ) {
32 return false;
33 } else {
34 return true;
35 }
36 }
37
38 $parts = explode( '/', $subPage, 2 );
39 if ( $parts !== 2 ) {
40 $slot = $parts[0];
41 if ( $slot === 'main' or $slot === '' ) {
42 return true;
43 }
44 }
45
46 return false;
47 }
48
49 /**
50 * Main method for handling requests.
51 *
52 * @param string $subPage
53 * @param WebRequest $request The request parameters. Known parameters are:
54 * - title: the page title
55 * - format: the format
56 * - oldid|revision: the revision ID
57 * @param OutputPage $output
58 *
59 * @note: Instead of an output page, a WebResponse could be sufficient, but
60 * redirect logic is currently implemented in OutputPage.
61 *
62 * @throws HttpError
63 */
64 public function handleRequest( $subPage, WebRequest $request, OutputPage $output ) {
65 // No matter what: The response is always public
66 $output->getRequest()->response()->header( 'Access-Control-Allow-Origin: *' );
67
68 if ( !$this->canHandleRequest( $subPage, $request ) ) {
69 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $subPage ) );
70 }
71
72 $revision = 0;
73
74 $parts = explode( '/', $subPage, 2 );
75 if ( $subPage !== '' ) {
76 $title = $parts[1];
77 } else {
78 $title = $request->getText( 'target', '' );
79 }
80
81 $revision = $request->getInt( 'oldid', $revision );
82 $revision = $request->getInt( 'revision', $revision );
83
84 if ( $title === null || $title === '' ) {
85 //TODO: different error message?
86 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $title ) );
87 }
88
89 try {
90 $title = Title::newFromTextThrow( $title );
91 } catch ( MalformedTitleException $ex ) {
92 throw new HttpError( 400, wfMessage( 'pagedata-bad-title', $title ) );
93 }
94
95 $this->httpContentNegotiation( $request, $output, $title, $revision );
96 }
97
98 /**
99 * Applies HTTP content negotiation.
100 * If the negotiation is successful, this method will set the appropriate redirect
101 * in the OutputPage object and return. Otherwise, an HttpError is thrown.
102 *
103 * @param WebRequest $request
104 * @param OutputPage $output
105 * @param Title $title
106 * @param int $revision The desired revision
107 *
108 * @throws HttpError
109 */
110 public function httpContentNegotiation(
111 WebRequest $request,
112 OutputPage $output,
113 Title $title,
114 $revision = 0
115 ) {
116 $contentHandler = ContentHandler::getForTitle( $title );
117 $mimeTypes = $contentHandler->getSupportedFormats();
118
119 $headers = $request->getAllHeaders();
120 if ( isset( $headers['ACCEPT'] ) ) {
121 $parser = new HttpAcceptParser();
122 $accept = $parser->parseWeights( $headers['ACCEPT'] );
123 } else {
124 // anything goes
125 $accept = [
126 '*' => 0.1 // just to make extra sure
127 ];
128 // prefer the default
129 $accept[$mimeTypes[0]] = 1;
130 }
131
132 $negotiator = new HttpAcceptNegotiator( $mimeTypes );
133 $format = $negotiator->getBestSupportedKey( $accept, null );
134
135 if ( $format === null ) {
136 $format = isset( $accept['text/html'] ) ? 'text/html' : null;
137 }
138
139 if ( $format === null ) {
140 $msg = wfMessage( 'pagedata-not-acceptable', implode( ', ', $mimeTypes ) );
141 throw new HttpError( 406, $msg );
142 }
143
144 $url = $this->getDocUrl( $title, $format, $revision );
145 $output->redirect( $url, 303 );
146 }
147
148 /**
149 * Returns a url representing the given title.
150 *
151 * @param Title $title
152 * @param string|null $format The (normalized) format name, or ''
153 * @param int $revision
154 * @return string
155 */
156 private function getDocUrl( Title $title, $format = '', $revision = 0 ) {
157 $params = [];
158
159 if ( $revision > 0 ) {
160 $params['oldid'] = $revision;
161 }
162
163 if ( $format === 'text/html' ) {
164 return $title->getFullURL( $params );
165 }
166
167 $params[ 'action' ] = 'raw';
168
169 return $title->getFullURL( $params );
170 }
171
172 }