44 private $contentHandlerFactory;
47 private $pageEditStash;
50 private $revisionLookup;
53 private $statsdDataFactory;
56 private $wikiPageFactory;
76 parent::__construct( $main, $action );
78 $this->contentHandlerFactory = $contentHandlerFactory;
79 $this->pageEditStash = $pageEditStash;
80 $this->revisionLookup = $revisionLookup;
81 $this->statsdDataFactory = $statsdDataFactory;
82 $this->wikiPageFactory = $wikiPageFactory;
89 if ( $user->isBot() ) {
94 $title = $page->getTitle();
97 if ( !$this->contentHandlerFactory
98 ->getContentHandler( $params[
'contentmodel'] )
99 ->isSupportedFormat( $params[
'contentformat'] )
102 [
'apierror-badformat-generic', $params[
'contentformat'], $params[
'contentmodel'] ],
109 if ( $params[
'stashedtexthash'] !==
null ) {
111 $textHash = $params[
'stashedtexthash'];
112 if ( !preg_match(
'/^[0-9a-f]{40}$/', $textHash ) ) {
113 $this->
dieWithError(
'apierror-stashedit-missingtext',
'missingtext' );
115 $text = $this->pageEditStash->fetchInputText( $textHash );
116 if ( !is_string( $text ) ) {
117 $this->
dieWithError(
'apierror-stashedit-missingtext',
'missingtext' );
122 $text = rtrim( str_replace(
"\r\n",
"\n", $params[
'text'] ) );
123 $textHash = sha1( $text );
126 $textContent = $this->contentHandlerFactory
127 ->getContentHandler( $params[
'contentmodel'] )
128 ->unserializeContent( $text, $params[
'contentformat'] );
130 $page = $this->wikiPageFactory->newFromTitle(
$title );
131 if ( $page->exists() ) {
133 $baseRev = $this->revisionLookup->getRevisionByPageId(
138 $this->
dieWithError( [
'apierror-nosuchrevid', $params[
'baserevid'] ] );
140 $currentRev = $page->getRevisionRecord();
141 if ( !$currentRev ) {
142 $this->
dieWithError( [
'apierror-missingrev-pageid', $page->getId() ],
'missingrev' );
145 $editContent = $page->replaceSectionAtRev(
148 $params[
'sectiontitle'],
151 if ( !$editContent ) {
152 $this->
dieWithError(
'apierror-sectionreplacefailed',
'replacefailed' );
154 if ( $currentRev->getId() == $baseRev->getId() ) {
159 $baseContent = $baseRev->getContent( SlotRecord::MAIN );
160 $currentContent = $currentRev->getContent( SlotRecord::MAIN );
161 if ( !$baseContent || !$currentContent ) {
162 $this->
dieWithError( [
'apierror-missingcontent-pageid', $page->getId() ],
'missingrev' );
165 $baseModel = $baseContent->getModel();
166 $currentModel = $currentContent->getModel();
171 $content = $this->contentHandlerFactory
172 ->getContentHandler( $baseModel )
173 ->merge3( $baseContent, $editContent, $currentContent );
174 }
catch ( Exception $e ) {
176 'wrap' => ApiMessage::create(
177 [
'apierror-contentmodel-mismatch', $currentModel, $baseModel ]
194 if ( $user->pingLimiter(
'stashedit' ) ) {
195 $status =
'ratelimited';
197 $updater = $page->newPageUpdater( $user );
198 $status = $this->pageEditStash->parseAndCache( $updater,
$content, $user, $params[
'summary'] );
199 $this->pageEditStash->stashInputText( $text, $textHash );
202 $this->statsdDataFactory->increment(
"editstash.cache_stores.$status" );
204 $ret = [
'status' => $status ];
206 if ( $status !==
'ratelimited' || $params[
'stashedtexthash'] !==
null ) {
207 $ret[
'texthash'] = $textHash;
216 ParamValidator::PARAM_TYPE =>
'string',
217 ParamValidator::PARAM_REQUIRED =>
true
220 ParamValidator::PARAM_TYPE =>
'string',
223 ParamValidator::PARAM_TYPE =>
'string'
226 ParamValidator::PARAM_TYPE =>
'text',
227 ParamValidator::PARAM_DEFAULT => null
229 'stashedtexthash' => [
230 ParamValidator::PARAM_TYPE =>
'string',
231 ParamValidator::PARAM_DEFAULT => null
234 ParamValidator::PARAM_TYPE =>
'string',
235 ParamValidator::PARAM_DEFAULT =>
''
238 ParamValidator::PARAM_TYPE => $this->contentHandlerFactory->getContentModels(),
239 ParamValidator::PARAM_REQUIRED =>
true
242 ParamValidator::PARAM_TYPE => $this->contentHandlerFactory->getAllContentFormats(),
243 ParamValidator::PARAM_REQUIRED =>
true
246 ParamValidator::PARAM_TYPE =>
'integer',
247 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 none 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)
Get a WikiPage object from a title or pageid param, 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.
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 "internal" Internal API modules are not (yet) intended for 3rd party...
needsToken()
Returns the token type this module requires in order to execute.
isWriteMode()
Indicates whether this module requires write mode.
__construct(ApiMain $main, $action, IContentHandlerFactory $contentHandlerFactory, PageEditStash $pageEditStash, RevisionLookup $revisionLookup, IBufferingStatsdDataFactory $statsdDataFactory, WikiPageFactory $wikiPageFactory)
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.