75 parent::__construct( $main, $action );
77 $this->contentHandlerFactory = $contentHandlerFactory;
78 $this->pageEditStash = $pageEditStash;
79 $this->revisionLookup = $revisionLookup;
80 $this->statsdDataFactory = $statsdDataFactory;
81 $this->wikiPageFactory = $wikiPageFactory;
82 $this->tempUserCreator = $tempUserCreator;
83 $this->userFactory = $userFactory;
90 if ( $user->isBot() ) {
95 $title = $page->getTitle();
98 if ( !$this->contentHandlerFactory
99 ->getContentHandler( $params[
'contentmodel'] )
100 ->isSupportedFormat( $params[
'contentformat'] )
103 [
'apierror-badformat-generic', $params[
'contentformat'], $params[
'contentmodel'] ],
110 if ( $params[
'stashedtexthash'] !==
null ) {
112 $textHash = $params[
'stashedtexthash'];
113 if ( !preg_match(
'/^[0-9a-f]{40}$/', $textHash ) ) {
114 $this->
dieWithError(
'apierror-stashedit-missingtext',
'missingtext' );
116 $text = $this->pageEditStash->fetchInputText( $textHash );
117 if ( !is_string( $text ) ) {
118 $this->
dieWithError(
'apierror-stashedit-missingtext',
'missingtext' );
123 $text = rtrim( str_replace(
"\r\n",
"\n", $params[
'text'] ) );
124 $textHash = sha1( $text );
127 $textContent = $this->contentHandlerFactory
128 ->getContentHandler( $params[
'contentmodel'] )
129 ->unserializeContent( $text, $params[
'contentformat'] );
131 $page = $this->wikiPageFactory->newFromTitle( $title );
132 if ( $page->exists() ) {
134 $baseRev = $this->revisionLookup->getRevisionByPageId(
139 $this->
dieWithError( [
'apierror-nosuchrevid', $params[
'baserevid'] ] );
141 $currentRev = $page->getRevisionRecord();
142 if ( !$currentRev ) {
143 $this->
dieWithError( [
'apierror-missingrev-pageid', $page->getId() ],
'missingrev' );
146 $editContent = $page->replaceSectionAtRev(
149 $params[
'sectiontitle'],
152 if ( !$editContent ) {
153 $this->
dieWithError(
'apierror-sectionreplacefailed',
'replacefailed' );
155 if ( $currentRev->getId() == $baseRev->getId() ) {
160 $baseContent = $baseRev->getContent( SlotRecord::MAIN );
161 $currentContent = $currentRev->getContent( SlotRecord::MAIN );
162 if ( !$baseContent || !$currentContent ) {
163 $this->
dieWithError( [
'apierror-missingcontent-pageid', $page->getId() ],
'missingrev' );
166 $baseModel = $baseContent->getModel();
167 $currentModel = $currentContent->getModel();
172 $content = $this->contentHandlerFactory
173 ->getContentHandler( $baseModel )
174 ->merge3( $baseContent, $editContent, $currentContent );
175 }
catch ( Exception $e ) {
178 [
'apierror-contentmodel-mismatch', $currentModel, $baseModel ]
195 if ( !$user->authorizeWrite(
'stashedit', $title ) ) {
196 $status =
'ratelimited';
198 $user = $this->getUserForPreview();
199 $updater = $page->newPageUpdater( $user );
200 $status = $this->pageEditStash->parseAndCache( $updater,
$content, $user, $params[
'summary'] );
201 $this->pageEditStash->stashInputText( $text, $textHash );
204 $this->statsdDataFactory->increment(
"editstash.cache_stores.$status" );
206 $ret = [
'status' => $status ];
208 if ( $status !==
'ratelimited' || $params[
'stashedtexthash'] !==
null ) {
209 $ret[
'texthash'] = $textHash;
215 private function getUserForPreview() {
217 if ( $this->tempUserCreator->shouldAutoCreate( $user,
'edit' ) ) {
218 return $this->userFactory->newUnsavedTempUser(
219 $this->tempUserCreator->getStashedName( $this->getRequest()->getSession() )
228 ParamValidator::PARAM_TYPE =>
'string',
229 ParamValidator::PARAM_REQUIRED =>
true
232 ParamValidator::PARAM_TYPE =>
'string',
235 ParamValidator::PARAM_TYPE =>
'string'
238 ParamValidator::PARAM_TYPE =>
'text',
239 ParamValidator::PARAM_DEFAULT => null
241 'stashedtexthash' => [
242 ParamValidator::PARAM_TYPE =>
'string',
243 ParamValidator::PARAM_DEFAULT => null
246 ParamValidator::PARAM_TYPE =>
'string',
247 ParamValidator::PARAM_DEFAULT =>
''
250 ParamValidator::PARAM_TYPE => $this->contentHandlerFactory->getContentModels(),
251 ParamValidator::PARAM_REQUIRED =>
true
254 ParamValidator::PARAM_TYPE => $this->contentHandlerFactory->getAllContentFormats(),
255 ParamValidator::PARAM_REQUIRED =>
true
258 ParamValidator::PARAM_TYPE =>
'integer',
259 ParamValidator::PARAM_REQUIRED =>
true
This abstract class implements many basic API functions, and is the base of all API classes.
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
requireOnlyOneParameter( $params,... $required)
Die if 0 or more than one of a certain set of parameters is set and not false.
getResult()
Get the result object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
getModuleName()
Get the name of the module being executed by this instance.
getTitleOrPageId( $params, $load=false)
Attempts to load a WikiPage object from a title or pageid parameter, if possible.
dieWithException(Throwable $exception, array $options=[])
Abort execution with an error derived from a throwable.
This is the main API class, used for both external and internal processing.
static create( $msg, $code=null, array $data=null)
Create an IApiMessage for the message.
Prepare an edit in shared cache so that it can be reused on edit.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
isInternal()
Indicates whether this module is considered to be "internal".
__construct(ApiMain $main, $action, IContentHandlerFactory $contentHandlerFactory, PageEditStash $pageEditStash, RevisionLookup $revisionLookup, IBufferingStatsdDataFactory $statsdDataFactory, WikiPageFactory $wikiPageFactory, TempUserCreator $tempUserCreator, UserFactory $userFactory)
needsToken()
Returns the token type this module requires in order to execute.
isWriteMode()
Indicates whether this module requires write mode.
mustBePosted()
Indicates whether this module must be called with a POST request.
Service for creating WikiPage objects.
Manage the pre-emptive page parsing for edits to wiki pages.
MediaWiki adaptation of StatsdDataFactory that provides buffering functionality.