MediaWiki  master
EditHandler.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki\Rest\Handler;
4 
5 use Config;
6 use IApiMessage;
13 use TitleFormatter;
14 use TitleParser;
15 use WebResponse;
17 
21 abstract class EditHandler extends ActionModuleBasedHandler {
22 
24  protected $config;
25 
30 
34  protected $titleParser;
35 
39  protected $titleFormatter;
40 
44  protected $revisionLookup;
45 
53  public function __construct(
59  ) {
60  $this->config = $config;
61  $this->contentHandlerFactory = $contentHandlerFactory;
62  $this->titleParser = $titleParser;
63  $this->titleFormatter = $titleFormatter;
64  $this->revisionLookup = $revisionLookup;
65  }
66 
67  public function needsWriteAccess() {
68  return true;
69  }
70 
76  abstract protected function getTitleParameter();
77 
81  protected function mapActionModuleResult( array $data ) {
82  if ( isset( $data['error'] ) ) {
83  throw new LocalizedHttpException( new MessageValue( 'apierror-' . $data['error'] ), 400 );
84  }
85 
86  if ( !isset( $data['edit'] ) || !$data['edit']['result'] ) {
87  throw new HttpException( 'Bad result structure received from ApiEditPage' );
88  }
89 
90  if ( $data['edit']['result'] !== 'Success' ) {
91  // Probably an edit conflict
92  // TODO: which code for null edits?
93  throw new HttpException( $data['edit']['result'], 409 );
94  }
95 
96  $title = $this->titleParser->parseTitle( $data['edit']['title'] );
97 
98  // This seems wasteful. This is the downside of delegating to the action API module:
99  // if we need additional data in the response, we have to load it.
100  $revision = $this->revisionLookup->getRevisionById( (int)$data['edit']['newrevid'] );
101  $content = $revision->getContent( SlotRecord::MAIN );
102 
103  return [
104  'id' => $data['edit']['pageid'],
105  'title' => $this->titleFormatter->getPrefixedText( $title ),
106  'key' => $this->titleFormatter->getPrefixedDBkey( $title ),
107  'latest' => [
108  'id' => $data['edit']['newrevid'],
109  'timestamp' => $data['edit']['newtimestamp'],
110  ],
111  'license' => [
112  'url' => $this->config->get( 'RightsUrl' ),
113  'title' => $this->config->get( 'RightsText' )
114  ],
115  'content_model' => $data['edit']['contentmodel'],
116  'source' => $content->serialize(),
117  ];
118  }
119 
123  protected function throwHttpExceptionForActionModuleError( IApiMessage $msg, $statusCode = 400 ) {
124  $code = $msg->getApiCode();
125 
126  if ( $code === 'protectedpage' ) {
127  throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 403 );
128  }
129 
130  if ( $code === 'badtoken' ) {
131  throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 403 );
132  }
133 
134  if ( $code === 'missingtitle' ) {
135  throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 404 );
136  }
137 
138  if ( $code === 'articleexists' ) {
139  throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 409 );
140  }
141 
142  if ( $code === 'editconflict' ) {
143  throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 409 );
144  }
145 
146  if ( $code === 'ratelimited' ) {
147  throw new LocalizedHttpException( $this->makeMessageValue( $msg ), 429 );
148  }
149 
150  // Fall through to generic handling of the error (status 400).
151  parent::throwHttpExceptionForActionModuleError( $msg, $statusCode );
152  }
153 
166  protected function getActionModuleToken() {
167  $body = $this->getValidatedBody();
168 
169  if ( $this->getSession()->getProvider()->safeAgainstCsrf() ) {
170  if ( !empty( $body['token'] ) ) {
171  throw new LocalizedHttpException(
172  new MessageValue( 'rest-extraneous-csrf-token' ),
173  400
174  );
175  }
176 
177  // Since the session is safe against CSRF, just use a known-good token.
178  return $this->getUser()->getEditToken();
179  } else {
180  return $body['token'] ?? '';
181  }
182  }
183 
184  protected function mapActionModuleResponse(
185  WebResponse $actionModuleResponse,
186  array $actionModuleResult,
187  Response $response
188  ) {
189  parent::mapActionModuleResponse(
190  $actionModuleResponse,
191  $actionModuleResult,
192  $response
193  );
194 
195  if ( $actionModuleResult['edit']['new'] ?? false ) {
196  $response->setStatus( 201 );
197  }
198  }
199 
200 }
MediaWiki\Rest\Handler
Definition: AbstractContributionHandler.php:3
MediaWiki\Rest\Handler\ActionModuleBasedHandler
Base class for REST handlers that are implemented by mapping to an existing ApiModule.
Definition: ActionModuleBasedHandler.php:29
MediaWiki\Rest\Handler\ActionModuleBasedHandler\makeMessageValue
makeMessageValue(IApiMessage $msg)
Constructs a MessageValue from an IApiMessage.
Definition: ActionModuleBasedHandler.php:250
MediaWiki\Rest\Handler\EditHandler\$contentHandlerFactory
IContentHandlerFactory $contentHandlerFactory
Definition: EditHandler.php:29
MediaWiki\Rest\Handler\EditHandler\$titleParser
TitleParser $titleParser
Definition: EditHandler.php:34
IApiMessage\getApiCode
getApiCode()
Returns a machine-readable code for use by the API.
MediaWiki\Rest\Handler\EditHandler\getActionModuleToken
getActionModuleToken()
Determines the CSRF token to be passed to the action module.
Definition: EditHandler.php:166
MediaWiki\Rest\Handler\EditHandler\$titleFormatter
TitleFormatter $titleFormatter
Definition: EditHandler.php:39
IApiMessage
Interface for messages with machine-readable data for use by the API.
Definition: IApiMessage.php:39
MediaWiki\Rest\Handler\EditHandler\mapActionModuleResult
mapActionModuleResult(array $data)
Maps an action API result to a REST API result.Data structure retrieved from the ApiResult returned b...
Definition: EditHandler.php:81
Revision\RevisionLookup
Service for looking up page revisions.
Definition: RevisionLookup.php:38
MediaWiki\Rest\Handler\ActionModuleBasedHandler\getSession
getSession()
Definition: ActionModuleBasedHandler.php:48
Wikimedia\Message\MessageValue
Value object representing a message for i18n.
Definition: MessageValue.php:16
Config
Interface for configuration instances.
Definition: Config.php:30
MediaWiki\Rest\Handler\EditHandler\$config
Config $config
Definition: EditHandler.php:24
MediaWiki\Rest\Handler\EditHandler\mapActionModuleResponse
mapActionModuleResponse(WebResponse $actionModuleResponse, array $actionModuleResult, Response $response)
Transfers relevant information, such as header values, from the WebResponse constructed by the action...
Definition: EditHandler.php:184
MediaWiki\Rest\Handler\getValidatedBody
getValidatedBody()
Fetch the validated body.
Definition: Handler.php:269
MediaWiki\Rest\Handler\EditHandler\needsWriteAccess
needsWriteAccess()
Indicates whether this route requires write access.
Definition: EditHandler.php:67
MediaWiki\Rest\Response
Definition: Response.php:8
$title
$title
Definition: testCompression.php:38
TitleParser
A title parser service for MediaWiki.
Definition: TitleParser.php:33
MediaWiki\Rest\Handler\EditHandler
Base class for REST API handlers that perform page edits (main slot only).
Definition: EditHandler.php:21
MediaWiki\Rest\Handler\ActionModuleBasedHandler\getUser
getUser()
Definition: ActionModuleBasedHandler.php:41
MediaWiki\Rest\Handler\EditHandler\getTitleParameter
getTitleParameter()
Returns the requested title.
$content
$content
Definition: router.php:76
MediaWiki\Rest\Handler\EditHandler\throwHttpExceptionForActionModuleError
throwHttpExceptionForActionModuleError(IApiMessage $msg, $statusCode=400)
Throws a HttpException for a given IApiMessage that represents an error.Never returns normally....
Definition: EditHandler.php:123
MediaWiki\Content\IContentHandlerFactory
Definition: IContentHandlerFactory.php:10
MediaWiki\Rest\HttpException
This is the base exception class for non-fatal exceptions thrown from REST handlers.
Definition: HttpException.php:12
TitleFormatter
A title formatter service for MediaWiki.
Definition: TitleFormatter.php:34
MediaWiki\Rest\Response\setStatus
setStatus( $code, $reasonPhrase='')
Set the status code and, optionally, reason phrase.
Definition: Response.php:44
MediaWiki\Rest\Handler\EditHandler\$revisionLookup
RevisionLookup $revisionLookup
Definition: EditHandler.php:44
WebResponse
Allow programs to request this object from WebRequest::response() and handle all outputting (or lack ...
Definition: WebResponse.php:30
MediaWiki\Rest\Handler\EditHandler\__construct
__construct(Config $config, IContentHandlerFactory $contentHandlerFactory, TitleParser $titleParser, TitleFormatter $titleFormatter, RevisionLookup $revisionLookup)
Definition: EditHandler.php:53
MediaWiki\Rest\LocalizedHttpException
@newable
Definition: LocalizedHttpException.php:10
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:39