MediaWiki master
EditHandler.php
Go to the documentation of this file.
1<?php
2
4
12use MediaWiki\Rest\TokenAwareHandlerTrait;
17use RuntimeException;
19
23abstract class EditHandler extends ActionModuleBasedHandler {
25
27 protected $config;
28
33
37 protected $titleParser;
38
42 protected $titleFormatter;
43
47 protected $revisionLookup;
48
56 public function __construct(
62 ) {
63 $this->config = $config;
64 $this->contentHandlerFactory = $contentHandlerFactory;
65 $this->titleParser = $titleParser;
66 $this->titleFormatter = $titleFormatter;
67 $this->revisionLookup = $revisionLookup;
68 }
69
70 public function needsWriteAccess() {
71 return true;
72 }
73
79 abstract protected function getTitleParameter();
80
84 protected function mapActionModuleResult( array $data ) {
85 if ( isset( $data['error'] ) ) {
86 throw new LocalizedHttpException( new MessageValue( 'apierror-' . $data['error'] ), 400 );
87 }
88
89 if ( !isset( $data['edit'] ) || !$data['edit']['result'] ) {
90 throw new RuntimeException( 'Bad result structure received from ApiEditPage' );
91 }
92
93 if ( $data['edit']['result'] !== 'Success' ) {
94 // Probably an edit conflict
95 // TODO: which code for null edits?
96 throw new LocalizedHttpException(
97 new MessageValue( "rest-edit-conflict", [ $data['edit']['result'] ] ),
98 409
99 );
100 }
101
102 $title = $this->titleParser->parseTitle( $data['edit']['title'] );
103
104 // This seems wasteful. This is the downside of delegating to the action API module:
105 // if we need additional data in the response, we have to load it.
106 $revision = $this->revisionLookup->getRevisionById( (int)$data['edit']['newrevid'] );
107 $content = $revision->getContent( SlotRecord::MAIN );
108
109 return [
110 'id' => $data['edit']['pageid'],
111 'title' => $this->titleFormatter->getPrefixedText( $title ),
112 'key' => $this->titleFormatter->getPrefixedDBkey( $title ),
113 'latest' => [
114 'id' => $data['edit']['newrevid'],
115 'timestamp' => $data['edit']['newtimestamp'],
116 ],
117 'license' => [
118 'url' => $this->config->get( MainConfigNames::RightsUrl ),
119 'title' => $this->config->get( MainConfigNames::RightsText )
120 ],
121 'content_model' => $data['edit']['contentmodel'],
122 'source' => $content->serialize(),
123 ];
124 }
125
129 protected function throwHttpExceptionForActionModuleError( IApiMessage $msg, $statusCode = 400 ) {
130 $code = $msg->getApiCode();
131
132 if ( $code === 'protectedpage' ) {
133 throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 403 );
134 }
135
136 if ( $code === 'badtoken' ) {
137 throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 403 );
138 }
139
140 if ( $code === 'missingtitle' ) {
141 throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 404 );
142 }
143
144 if ( $code === 'articleexists' ) {
145 throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 409 );
146 }
147
148 if ( $code === 'editconflict' ) {
149 throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 409 );
150 }
151
152 if ( $code === 'ratelimited' ) {
153 throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 429 );
154 }
155
156 // Fall through to generic handling of the error (status 400).
157 parent::throwHttpExceptionForActionModuleError( $msg, $statusCode );
158 }
159
160 protected function mapActionModuleResponse(
161 WebResponse $actionModuleResponse,
162 array $actionModuleResult,
163 Response $response
164 ) {
165 parent::mapActionModuleResponse(
166 $actionModuleResponse,
167 $actionModuleResult,
168 $response
169 );
170
171 if ( $actionModuleResult['edit']['new'] ?? false ) {
172 $response->setStatus( 201 );
173 }
174 }
175
176}
A class containing constants representing the names of configuration variables.
const RightsText
Name constant for the RightsText setting, for use with Config::get()
const RightsUrl
Name constant for the RightsUrl setting, for use with Config::get()
Allow programs to request this object from WebRequest::response() and handle all outputting (or lack ...
Base class for REST handlers that are implemented by mapping to an existing ApiModule.
makeMessageValue(IApiMessage $msg)
Constructs a MessageValue from an IApiMessage.
Base class for REST API handlers that perform page edits (main slot only).
__construct(Config $config, IContentHandlerFactory $contentHandlerFactory, TitleParser $titleParser, TitleFormatter $titleFormatter, RevisionLookup $revisionLookup)
needsWriteAccess()
Indicates whether this route requires write access.
getTitleParameter()
Returns the requested title.
mapActionModuleResult(array $data)
Maps an action API result to a REST API result.mixed Data structure to be converted to JSON and wrapp...
throwHttpExceptionForActionModuleError(IApiMessage $msg, $statusCode=400)
Throws a HttpException for a given IApiMessage that represents an error.Never returns normally....
IContentHandlerFactory $contentHandlerFactory
mapActionModuleResponse(WebResponse $actionModuleResponse, array $actionModuleResult, Response $response)
Transfers relevant information, such as header values, from the WebResponse constructed by the action...
setStatus( $code, $reasonPhrase='')
Set the status code and, optionally, reason phrase.
Definition Response.php:58
Value object representing a content slot associated with a page revision.
Value object representing a message for i18n.
Interface for messages with machine-readable data for use by the API.
getApiCode()
Returns a machine-readable code for use by the API.
Interface for configuration instances.
Definition Config.php:32
Service for looking up page revisions.
A title formatter service for MediaWiki.
A title parser service for MediaWiki.
Copyright (C) 2011-2020 Wikimedia Foundation and others.