MediaWiki  master
ApiEditPage.php
Go to the documentation of this file.
1 <?php
27 
44 class ApiEditPage extends ApiBase {
45 
47 
48  public function __construct( ApiMain $mainModule, $moduleName, $modulePrefix = '' ) {
49  parent::__construct( $mainModule, $moduleName, $modulePrefix );
50 
51  $this->watchlistExpiryEnabled = $this->getConfig()->get( 'WatchlistExpiry' );
52  $this->watchlistMaxDuration = $this->getConfig()->get( 'WatchlistExpiryMaxDuration' );
53  }
54 
55  public function execute() {
57 
58  $user = $this->getUser();
59  $params = $this->extractRequestParams();
60 
61  $this->requireAtLeastOneParameter( $params, 'text', 'appendtext', 'prependtext', 'undo' );
62 
63  $pageObj = $this->getTitleOrPageId( $params );
64  $titleObj = $pageObj->getTitle();
65  $apiResult = $this->getResult();
66  $revisionLookup = MediaWikiServices::getInstance()->getRevisionLookup();
67 
68  if ( $params['redirect'] ) {
69  if ( $params['prependtext'] === null && $params['appendtext'] === null
70  && $params['section'] !== 'new'
71  ) {
72  $this->dieWithError( 'apierror-redirect-appendonly' );
73  }
74  if ( $titleObj->isRedirect() ) {
75  $oldTitle = $titleObj;
76 
77  $titles = $revisionLookup
78  ->getRevisionByTitle( $oldTitle, 0, IDBAccessObject::READ_LATEST )
79  ->getContent( SlotRecord::MAIN, RevisionRecord::FOR_THIS_USER, $user )
80  ->getRedirectChain();
81  // array_shift( $titles );
82  '@phan-var Title[] $titles';
83 
84  $redirValues = [];
85 
87  foreach ( $titles as $id => $newTitle ) {
88  $titles[$id - 1] = $titles[$id - 1] ?? $oldTitle;
89 
90  $redirValues[] = [
91  'from' => $titles[$id - 1]->getPrefixedText(),
92  'to' => $newTitle->getPrefixedText()
93  ];
94 
95  $titleObj = $newTitle;
96 
97  // T239428: Check whether the new title is valid
98  if ( $titleObj->isExternal() || !$titleObj->canExist() ) {
99  $redirValues[count( $redirValues ) - 1]['to'] = $titleObj->getFullText();
100  $this->dieWithError(
101  [
102  'apierror-edit-invalidredirect',
103  Message::plaintextParam( $oldTitle->getPrefixedText() ),
104  Message::plaintextParam( $titleObj->getFullText() ),
105  ],
106  'edit-invalidredirect',
107  [ 'redirects' => $redirValues ]
108  );
109  }
110  }
111 
112  ApiResult::setIndexedTagName( $redirValues, 'r' );
113  $apiResult->addValue( null, 'redirects', $redirValues );
114 
115  // Since the page changed, update $pageObj
116  $pageObj = WikiPage::factory( $titleObj );
117  }
118  }
119 
120  if ( $params['contentmodel'] ) {
121  $contentHandler = $this->getContentHandlerFactory()
122  ->getContentHandler( $params['contentmodel'] );
123  } else {
124  $contentHandler = $pageObj->getContentHandler();
125  }
126  $contentModel = $contentHandler->getModelID();
127 
128  $name = $titleObj->getPrefixedDBkey();
129  $model = $contentHandler->getModelID();
130 
131  if ( $params['undo'] > 0 ) {
132  // allow undo via api
133  } elseif ( $contentHandler->supportsDirectApiEditing() === false ) {
134  $this->dieWithError( [ 'apierror-no-direct-editing', $model, $name ] );
135  }
136 
137  $contentFormat = $params['contentformat'] ?: $contentHandler->getDefaultFormat();
138 
139  if ( !$contentHandler->isSupportedFormat( $contentFormat ) ) {
140  $this->dieWithError( [ 'apierror-badformat', $contentFormat, $model, $name ] );
141  }
142 
143  if ( $params['createonly'] && $titleObj->exists() ) {
144  $this->dieWithError( 'apierror-articleexists' );
145  }
146  if ( $params['nocreate'] && !$titleObj->exists() ) {
147  $this->dieWithError( 'apierror-missingtitle' );
148  }
149 
150  // Now let's check whether we're even allowed to do this
152  $titleObj,
153  $titleObj->exists() ? 'edit' : [ 'edit', 'create' ],
154  [ 'autoblock' => true ]
155  );
156 
157  $toMD5 = $params['text'];
158  if ( $params['appendtext'] !== null || $params['prependtext'] !== null ) {
159  $content = $pageObj->getContent();
160 
161  if ( !$content ) {
162  if ( $titleObj->getNamespace() === NS_MEDIAWIKI ) {
163  # If this is a MediaWiki:x message, then load the messages
164  # and return the message value for x.
165  $text = $titleObj->getDefaultMessageText();
166  if ( $text === false ) {
167  $text = '';
168  }
169 
170  try {
171  $content = ContentHandler::makeContent( $text, $titleObj );
172  } catch ( MWContentSerializationException $ex ) {
173  $this->dieWithException( $ex, [
174  'wrap' => ApiMessage::create( 'apierror-contentserializationexception', 'parseerror' )
175  ] );
176  return;
177  }
178  } else {
179  # Otherwise, make a new empty content.
180  $content = $contentHandler->makeEmptyContent();
181  }
182  }
183 
184  // @todo Add support for appending/prepending to the Content interface
185 
186  if ( !( $content instanceof TextContent ) ) {
187  $modelName = $contentHandler->getModelID();
188  $this->dieWithError( [ 'apierror-appendnotsupported', $modelName ] );
189  }
190 
191  if ( $params['section'] !== null ) {
192  if ( !$contentHandler->supportsSections() ) {
193  $modelName = $contentHandler->getModelID();
194  $this->dieWithError( [ 'apierror-sectionsnotsupported', $modelName ] );
195  }
196 
197  if ( $params['section'] == 'new' ) {
198  // DWIM if they're trying to prepend/append to a new section.
199  $content = null;
200  } else {
201  // Process the content for section edits
202  $section = $params['section'];
203  $content = $content->getSection( $section );
204 
205  if ( !$content ) {
206  $this->dieWithError( [ 'apierror-nosuchsection', wfEscapeWikiText( $section ) ] );
207  }
208  }
209  }
210 
211  if ( !$content ) {
212  $text = '';
213  } else {
214  $text = $content->serialize( $contentFormat );
215  }
216 
217  $params['text'] = $params['prependtext'] . $text . $params['appendtext'];
218  $toMD5 = $params['prependtext'] . $params['appendtext'];
219  }
220 
221  if ( $params['undo'] > 0 ) {
222  if ( $params['undoafter'] > 0 ) {
223  $undoafterRev = $revisionLookup->getRevisionById( $params['undoafter'] );
224  }
225  $undoRev = $revisionLookup->getRevisionById( $params['undo'] );
226  if ( $undoRev === null || $undoRev->isDeleted( RevisionRecord::DELETED_TEXT ) ) {
227  $this->dieWithError( [ 'apierror-nosuchrevid', $params['undo'] ] );
228  }
229 
230  if ( $params['undoafter'] == 0 ) {
231  $undoafterRev = $revisionLookup->getPreviousRevision( $undoRev );
232  }
233  if ( $undoafterRev === null || $undoafterRev->isDeleted( RevisionRecord::DELETED_TEXT ) ) {
234  $this->dieWithError( [ 'apierror-nosuchrevid', $params['undoafter'] ] );
235  }
236 
237  if ( $undoRev->getPageId() != $pageObj->getId() ) {
238  $this->dieWithError( [ 'apierror-revwrongpage', $undoRev->getId(),
239  $titleObj->getPrefixedText() ] );
240  }
241  if ( $undoafterRev->getPageId() != $pageObj->getId() ) {
242  $this->dieWithError( [ 'apierror-revwrongpage', $undoafterRev->getId(),
243  $titleObj->getPrefixedText() ] );
244  }
245 
246  $newContent = $contentHandler->getUndoContent(
247  $pageObj->getRevisionRecord()->getContent( SlotRecord::MAIN ),
248  $undoRev->getContent( SlotRecord::MAIN ),
249  $undoafterRev->getContent( SlotRecord::MAIN ),
250  $pageObj->getRevisionRecord()->getId() === $undoRev->getId()
251  );
252 
253  if ( !$newContent ) {
254  $this->dieWithError( 'undo-failure', 'undofailure' );
255  }
256  if ( !$params['contentmodel'] && !$params['contentformat'] ) {
257  // If we are reverting content model, the new content model
258  // might not support the current serialization format, in
259  // which case go back to the old serialization format,
260  // but only if the user hasn't specified a format/model
261  // parameter.
262  if ( !$newContent->isSupportedFormat( $contentFormat ) ) {
263  $undoafterRevMainSlot = $undoafterRev->getSlot(
264  SlotRecord::MAIN,
265  RevisionRecord::RAW
266  );
267  $contentFormat = $undoafterRevMainSlot->getFormat();
268  if ( !$contentFormat ) {
269  // fall back to default content format for the model
270  // of $undoafterRev
271  $contentFormat = MediaWikiServices::getInstance()
272  ->getContentHandlerFactory()
273  ->getContentHandler( $undoafterRevMainSlot->getModel() )
274  ->getDefaultFormat();
275  }
276  }
277  // Override content model with model of undid revision.
278  $contentModel = $newContent->getModel();
279  $undoContentModel = true;
280  }
281  $params['text'] = $newContent->serialize( $contentFormat );
282  // If no summary was given and we only undid one rev,
283  // use an autosummary
284 
285  if ( $params['summary'] === null ) {
286  $nextRev = $revisionLookup->getNextRevision( $undoafterRev );
287  if ( $nextRev && $nextRev->getId() == $params['undo'] ) {
288  $undoRevUser = $undoRev->getUser();
289  $params['summary'] = wfMessage( 'undo-summary' )
290  ->params( $params['undo'], $undoRevUser ? $undoRevUser->getName() : '' )
291  ->inContentLanguage()->text();
292  }
293  }
294  }
295 
296  // See if the MD5 hash checks out
297  if ( $params['md5'] !== null && md5( $toMD5 ) !== $params['md5'] ) {
298  $this->dieWithError( 'apierror-badmd5' );
299  }
300 
301  // EditPage wants to parse its stuff from a WebRequest
302  // That interface kind of sucks, but it's workable
303  $requestArray = [
304  'wpTextbox1' => $params['text'],
305  'format' => $contentFormat,
306  'model' => $contentModel,
307  'wpEditToken' => $params['token'],
308  'wpIgnoreBlankSummary' => true,
309  'wpIgnoreBlankArticle' => true,
310  'wpIgnoreSelfRedirect' => true,
311  'bot' => $params['bot'],
312  'wpUnicodeCheck' => EditPage::UNICODE_CHECK,
313  ];
314 
315  if ( $params['summary'] !== null ) {
316  $requestArray['wpSummary'] = $params['summary'];
317  }
318 
319  if ( $params['sectiontitle'] !== null ) {
320  $requestArray['wpSectionTitle'] = $params['sectiontitle'];
321  }
322 
323  if ( $params['undo'] > 0 ) {
324  $requestArray['wpUndidRevision'] = $params['undo'];
325  }
326  if ( $params['undoafter'] > 0 ) {
327  $requestArray['wpUndoAfter'] = $params['undoafter'];
328  }
329 
330  // Skip for baserevid == null or '' or '0' or 0
331  if ( !empty( $params['baserevid'] ) ) {
332  $requestArray['editRevId'] = $params['baserevid'];
333  }
334 
335  // Watch out for basetimestamp == '' or '0'
336  // It gets treated as NOW, almost certainly causing an edit conflict
337  if ( $params['basetimestamp'] !== null && (bool)$this->getMain()->getVal( 'basetimestamp' ) ) {
338  $requestArray['wpEdittime'] = $params['basetimestamp'];
339  } elseif ( empty( $params['baserevid'] ) ) {
340  // Only set if baserevid is not set. Otherwise, conflicts would be ignored,
341  // due to the way userWasLastToEdit() works.
342  $requestArray['wpEdittime'] = $pageObj->getTimestamp();
343  }
344 
345  if ( $params['starttimestamp'] !== null ) {
346  $requestArray['wpStarttime'] = $params['starttimestamp'];
347  } else {
348  $requestArray['wpStarttime'] = wfTimestampNow(); // Fake wpStartime
349  }
350 
351  if ( $params['minor'] || ( !$params['notminor'] && $user->getOption( 'minordefault' ) ) ) {
352  $requestArray['wpMinoredit'] = '';
353  }
354 
355  if ( $params['recreate'] ) {
356  $requestArray['wpRecreate'] = '';
357  }
358 
359  if ( $params['section'] !== null ) {
360  $section = $params['section'];
361  if ( !preg_match( '/^((T-)?\d+|new)$/', $section ) ) {
362  $this->dieWithError( 'apierror-invalidsection' );
363  }
364  $content = $pageObj->getContent();
365  if ( $section !== '0' && $section != 'new'
366  && ( !$content || !$content->getSection( $section ) )
367  ) {
368  $this->dieWithError( [ 'apierror-nosuchsection', $section ] );
369  }
370  $requestArray['wpSection'] = $params['section'];
371  } else {
372  $requestArray['wpSection'] = '';
373  }
374 
375  $watch = $this->getWatchlistValue( $params['watchlist'], $titleObj, $user );
376 
377  // Deprecated parameters
378  if ( $params['watch'] ) {
379  $watch = true;
380  } elseif ( $params['unwatch'] ) {
381  $watch = false;
382  }
383 
384  if ( $watch ) {
385  $requestArray['wpWatchthis'] = true;
386  $watchlistExpiry = $this->getExpiryFromParams( $params );
387 
388  if ( $watchlistExpiry ) {
389  $requestArray['wpWatchlistExpiry'] = $watchlistExpiry;
390  }
391  }
392 
393  // Apply change tags
394  if ( $params['tags'] ) {
395  $tagStatus = ChangeTags::canAddTagsAccompanyingChange( $params['tags'], $user );
396  if ( $tagStatus->isOK() ) {
397  $requestArray['wpChangeTags'] = implode( ',', $params['tags'] );
398  } else {
399  $this->dieStatus( $tagStatus );
400  }
401  }
402 
403  // Pass through anything else we might have been given, to support extensions
404  // This is kind of a hack but it's the best we can do to make extensions work
405  $requestArray += $this->getRequest()->getValues();
406 
407  global $wgTitle, $wgRequest;
408 
409  $req = new DerivativeRequest( $this->getRequest(), $requestArray, true );
410 
411  // Some functions depend on $wgTitle == $ep->mTitle
412  // TODO: Make them not or check if they still do
413  $wgTitle = $titleObj;
414 
415  $articleContext = new RequestContext;
416  $articleContext->setRequest( $req );
417  $articleContext->setWikiPage( $pageObj );
418  $articleContext->setUser( $this->getUser() );
419 
421  $articleObject = Article::newFromWikiPage( $pageObj, $articleContext );
422 
423  $ep = new EditPage( $articleObject );
424 
425  $ep->setApiEditOverride( true );
426  $ep->setContextTitle( $titleObj );
427  $ep->importFormData( $req );
428 
429  // T255700: Ensure content models of the base content
430  // and fetched revision remain the same before attempting to save.
431  $editRevId = $requestArray['editRevId'] ?? false;
432  $baseRev = $revisionLookup->getRevisionByTitle( $titleObj, $editRevId );
433  $baseContentModel = $baseRev
434  ? $baseRev->getContent( SlotRecord::MAIN )->getModel()
435  : $pageObj->getContentModel();
436 
437  // However, allow the content models to possibly differ if we are intentionally
438  // changing them or we are doing an undo edit that is reverting content model change.
439  $contentModelsCanDiffer = $params['contentmodel'] || isset( $undoContentModel );
440 
441  if ( !$contentModelsCanDiffer && $contentModel !== $baseContentModel ) {
442  $this->dieWithError( [ 'apierror-contentmodel-mismatch', $contentModel, $baseContentModel ] );
443  }
444 
445  // Do the actual save
446  $oldRevId = $articleObject->getRevIdFetched();
447  $result = null;
448 
449  // Fake $wgRequest for some hooks inside EditPage
450  // @todo FIXME: This interface SUCKS
451  $oldRequest = $wgRequest;
452  $wgRequest = $req;
453 
454  $status = $ep->attemptSave( $result );
455  $wgRequest = $oldRequest;
456 
457  $r = [];
458  switch ( $status->value ) {
461  if ( isset( $status->apiHookResult ) ) {
462  $r = $status->apiHookResult;
463  $r['result'] = 'Failure';
464  $apiResult->addValue( null, $this->getModuleName(), $r );
465  return;
466  }
467  if ( !$status->getErrors() ) {
468  // This appears to be unreachable right now, because all
469  // code paths will set an error. Could change, though.
470  $status->fatal( 'hookaborted' ); // @codeCoverageIgnore
471  }
472  $this->dieStatus( $status );
473 
474  // These two cases will normally have been caught earlier, and will
475  // only occur if something blocks the user between the earlier
476  // check and the check in EditPage (presumably a hook). It's not
477  // obvious that this is even possible.
478  // @codeCoverageIgnoreStart
480  $this->dieBlocked( $user->getBlock() );
481 
483  $this->dieReadOnly();
484  // @codeCoverageIgnoreEnd
485 
487  $r['new'] = true;
488  // fall-through
489 
491  $r['result'] = 'Success';
492  $r['pageid'] = (int)$titleObj->getArticleID();
493  $r['title'] = $titleObj->getPrefixedText();
494  $r['contentmodel'] = $articleObject->getPage()->getContentModel();
495  $newRevId = $articleObject->getPage()->getLatest();
496  if ( $newRevId == $oldRevId ) {
497  $r['nochange'] = true;
498  } else {
499  $r['oldrevid'] = (int)$oldRevId;
500  $r['newrevid'] = (int)$newRevId;
501  $r['newtimestamp'] = wfTimestamp( TS_ISO_8601,
502  $pageObj->getTimestamp() );
503  }
504 
505  if ( $watch ) {
506  $r['watched'] = true;
507 
508  $watchedItemStore = MediaWikiServices::getInstance()->getWatchedItemStore();
509  $watchlistExpiry = $this->getWatchlistExpiry(
510  $watchedItemStore,
511  $titleObj,
512  $user
513  );
514 
515  if ( $watchlistExpiry ) {
516  $r['watchlistexpiry'] = $watchlistExpiry;
517  }
518  }
519  break;
520 
521  default:
522  if ( !$status->getErrors() ) {
523  // EditPage sometimes only sets the status code without setting
524  // any actual error messages. Supply defaults for those cases.
525  switch ( $status->value ) {
526  // Currently needed
528  $status->fatal( 'apierror-noimageredirect-anon' );
529  break;
531  $status->fatal( 'apierror-noimageredirect' );
532  break;
535  $status->fatal( 'apierror-contenttoobig', $this->getConfig()->get( 'MaxArticleSize' ) );
536  break;
538  $status->fatal( 'apierror-noedit-anon' );
539  break;
541  $status->fatal( 'apierror-cantchangecontentmodel' );
542  break;
544  $status->fatal( 'apierror-pagedeleted' );
545  break;
547  $status->fatal( 'edit-conflict' );
548  break;
549 
550  // Currently shouldn't be needed, but here in case
551  // hooks use them without setting appropriate
552  // errors on the status.
553  // @codeCoverageIgnoreStart
555  $status->fatal( 'apierror-spamdetected', $result['spam'] );
556  break;
558  $status->fatal( 'apierror-noedit' );
559  break;
561  $status->fatal( 'apierror-ratelimited' );
562  break;
564  $status->fatal( 'nocreate-loggedin' );
565  break;
567  $status->fatal( 'apierror-emptypage' );
568  break;
570  $status->fatal( 'apierror-emptynewsection' );
571  break;
573  $status->fatal( 'apierror-summaryrequired' );
574  break;
575  default:
576  wfWarn( __METHOD__ . ": Unknown EditPage code {$status->value} with no message" );
577  $status->fatal( 'apierror-unknownerror-editpage', $status->value );
578  break;
579  // @codeCoverageIgnoreEnd
580  }
581  }
582  $this->dieStatus( $status );
583  }
584  $apiResult->addValue( null, $this->getModuleName(), $r );
585  }
586 
587  public function mustBePosted() {
588  return true;
589  }
590 
591  public function isWriteMode() {
592  return true;
593  }
594 
595  public function getAllowedParams() {
596  $params = [
597  'title' => [
598  ApiBase::PARAM_TYPE => 'string',
599  ],
600  'pageid' => [
601  ApiBase::PARAM_TYPE => 'integer',
602  ],
603  'section' => null,
604  'sectiontitle' => [
605  ApiBase::PARAM_TYPE => 'string',
606  ],
607  'text' => [
608  ApiBase::PARAM_TYPE => 'text',
609  ],
610  'summary' => null,
611  'tags' => [
612  ApiBase::PARAM_TYPE => 'tags',
613  ApiBase::PARAM_ISMULTI => true,
614  ],
615  'minor' => false,
616  'notminor' => false,
617  'bot' => false,
618  'baserevid' => [
619  ApiBase::PARAM_TYPE => 'integer',
620  ],
621  'basetimestamp' => [
622  ApiBase::PARAM_TYPE => 'timestamp',
623  ],
624  'starttimestamp' => [
625  ApiBase::PARAM_TYPE => 'timestamp',
626  ],
627  'recreate' => false,
628  'createonly' => false,
629  'nocreate' => false,
630  'watch' => [
631  ApiBase::PARAM_DFLT => false,
633  ],
634  'unwatch' => [
635  ApiBase::PARAM_DFLT => false,
637  ],
638  ];
639 
640  // Params appear in the docs in the order they are defined,
641  // which is why this is here and not at the bottom.
642  $params += $this->getWatchlistParams();
643 
644  return $params + [
645  'md5' => null,
646  'prependtext' => [
647  ApiBase::PARAM_TYPE => 'text',
648  ],
649  'appendtext' => [
650  ApiBase::PARAM_TYPE => 'text',
651  ],
652  'undo' => [
653  ApiBase::PARAM_TYPE => 'integer',
654  ApiBase::PARAM_MIN => 0,
656  ],
657  'undoafter' => [
658  ApiBase::PARAM_TYPE => 'integer',
659  ApiBase::PARAM_MIN => 0,
661  ],
662  'redirect' => [
663  ApiBase::PARAM_TYPE => 'boolean',
664  ApiBase::PARAM_DFLT => false,
665  ],
666  'contentformat' => [
667  ApiBase::PARAM_TYPE => $this->getContentHandlerFactory()->getAllContentFormats(),
668  ],
669  'contentmodel' => [
670  ApiBase::PARAM_TYPE => $this->getContentHandlerFactory()->getContentModels(),
671  ],
672  'token' => [
673  // Standard definition automatically inserted
674  ApiBase::PARAM_HELP_MSG_APPEND => [ 'apihelp-edit-param-token' ],
675  ],
676  ];
677  }
678 
679  public function needsToken() {
680  return 'csrf';
681  }
682 
683  protected function getExamplesMessages() {
684  return [
685  'action=edit&title=Test&summary=test%20summary&' .
686  'text=article%20content&baserevid=1234567&token=123ABC'
687  => 'apihelp-edit-example-edit',
688  'action=edit&title=Test&summary=NOTOC&minor=&' .
689  'prependtext=__NOTOC__%0A&basetimestamp=2007-08-24T12:34:54Z&token=123ABC'
690  => 'apihelp-edit-example-prepend',
691  'action=edit&title=Test&undo=13585&undoafter=13579&' .
692  'basetimestamp=2007-08-24T12:34:54Z&token=123ABC'
693  => 'apihelp-edit-example-undo',
694  ];
695  }
696 
697  public function getHelpUrls() {
698  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Edit';
699  }
700 
702  return MediaWikiServices::getInstance()->getContentHandlerFactory();
703  }
704 }
ApiEditPage
A module that allows for editing and creating pages.
Definition: ApiEditPage.php:44
MediaWiki\EditPage\IEditObject\AS_READ_ONLY_PAGE_ANON
const AS_READ_ONLY_PAGE_ANON
Status: this anonymous user is not allowed to edit this page.
Definition: IEditObject.php:50
DerivativeRequest
Similar to FauxRequest, but only fakes URL parameters and method (POST or GET) and use the base reque...
Definition: DerivativeRequest.php:36
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:48
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:71
MediaWiki\EditPage\IEditObject\AS_ARTICLE_WAS_DELETED
const AS_ARTICLE_WAS_DELETED
Status: article was deleted while editing and wpRecreate == false or form was not posted.
Definition: IEditObject.php:62
MediaWiki\EditPage\IEditObject\AS_SUCCESS_NEW_ARTICLE
const AS_SUCCESS_NEW_ARTICLE
Status: Article successfully created.
Definition: IEditObject.php:35
Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:47
MediaWiki\EditPage\IEditObject\AS_BLOCKED_PAGE_FOR_USER
const AS_BLOCKED_PAGE_FOR_USER
Status: User is blocked from editing this page.
Definition: IEditObject.php:44
ApiEditPage\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiEditPage.php:683
MediaWiki\EditPage\IEditObject\AS_TEXTBOX_EMPTY
const AS_TEXTBOX_EMPTY
Status: user tried to create a new section without content.
Definition: IEditObject.php:80
getExpiryFromParams
getExpiryFromParams(array $params)
Get formatted expiry from the given parameters, or null if no expiry was provided.
Definition: ApiWatchlistTrait.php:139
RequestContext\setRequest
setRequest(WebRequest $request)
Definition: RequestContext.php:127
NS_MEDIAWIKI
const NS_MEDIAWIKI
Definition: Defines.php:71
MediaWiki\EditPage\IEditObject\AS_SUMMARY_NEEDED
const AS_SUMMARY_NEEDED
Status: no edit summary given and the user has forceeditsummary set and the user is not editing in hi...
Definition: IEditObject.php:77
MediaWiki\EditPage\IEditObject\AS_CONFLICT_DETECTED
const AS_CONFLICT_DETECTED
Status: (non-resolvable) edit conflict.
Definition: IEditObject.php:71
ApiEditPage\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiEditPage.php:697
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:166
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1370
ApiEditPage\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiEditPage.php:595
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1831
ApiBase\getTitleOrPageId
getTitleOrPageId( $params, $load=false)
Get a WikiPage object from a title or pageid param, if possible.
Definition: ApiBase.php:975
ApiBase\PARAM_TYPE
const PARAM_TYPE
Definition: ApiBase.php:69
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:558
MediaWiki\EditPage\IEditObject\AS_SPAM_ERROR
const AS_SPAM_ERROR
Status: summary contained spam according to one of the regexes in $wgSummarySpamRegex.
Definition: IEditObject.php:89
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1230
ApiBase\dieBlocked
dieBlocked(AbstractBlock $block)
Throw an ApiUsageException, which will (if uncaught) call the main module's error handler and die wit...
Definition: ApiBase.php:1397
MediaWiki\EditPage\IEditObject\AS_CONTENT_TOO_BIG
const AS_CONTENT_TOO_BIG
Status: Content too big (> $wgMaxArticleSize)
Definition: IEditObject.php:47
ContextSource\getRequest
getRequest()
Definition: ContextSource.php:80
MediaWiki\EditPage\IEditObject\AS_NO_CREATE_PERMISSION
const AS_NO_CREATE_PERMISSION
Status: user tried to create this page, but is not allowed to do that.
Definition: IEditObject.php:65
MediaWiki\EditPage\IEditObject\AS_SUCCESS_UPDATE
const AS_SUCCESS_UPDATE
Status: Article successfully updated.
Definition: IEditObject.php:32
ApiEditPage\mustBePosted
mustBePosted()
Indicates whether this module must be called with a POST request Stable to override.
Definition: ApiEditPage.php:587
ContextSource\getUser
getUser()
Stable to override.
Definition: ContextSource.php:135
ApiEditPage\getContentHandlerFactory
getContentHandlerFactory()
Definition: ApiEditPage.php:701
ApiBase\PARAM_HELP_MSG_APPEND
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition: ApiBase.php:109
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:52
ApiBase\PARAM_DEPRECATED
const PARAM_DEPRECATED
Definition: ApiBase.php:74
ApiBase\PARAM_MIN
const PARAM_MIN
Definition: ApiBase.php:72
Article\newFromWikiPage
static newFromWikiPage(WikiPage $page, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition: Article.php:190
MediaWiki\EditPage\IEditObject\AS_RATE_LIMITED
const AS_RATE_LIMITED
Status: rate limiter for action 'edit' was tripped.
Definition: IEditObject.php:59
EditPage\UNICODE_CHECK
const UNICODE_CHECK
Used for Unicode support checks.
Definition: EditPage.php:86
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:170
ApiEditPage\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiEditPage.php:55
ApiEditPage\__construct
__construct(ApiMain $mainModule, $moduleName, $modulePrefix='')
Stable to call.
Definition: ApiEditPage.php:48
MWContentSerializationException
Exception representing a failure to serialize or unserialize a content object.
Definition: MWContentSerializationException.php:8
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:706
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1860
RequestContext
Group all the pieces relevant to the context of a request into one instance @newable.
Definition: RequestContext.php:40
ApiBase\requireAtLeastOneParameter
requireAtLeastOneParameter( $params,... $required)
Die if none of a certain set of parameters is set and not false.
Definition: ApiBase.php:903
ApiMessage\create
static create( $msg, $code=null, array $data=null)
Create an IApiMessage for the message.
Definition: ApiMessage.php:43
ContentHandler\makeContent
static makeContent( $text, Title $title=null, $modelId=null, $format=null)
Convenience function for creating a Content object from a given textual representation.
Definition: ContentHandler.php:142
$wgTitle
$wgTitle
Definition: Setup.php:795
MediaWiki\EditPage\IEditObject\AS_NO_CHANGE_CONTENT_MODEL
const AS_NO_CHANGE_CONTENT_MODEL
Status: user tried to modify the content model, but is not allowed to do that ( User::isAllowed('edit...
Definition: IEditObject.php:101
MediaWiki\EditPage\IEditObject\AS_READ_ONLY_PAGE_LOGGED
const AS_READ_ONLY_PAGE_LOGGED
Status: this logged in user is not allowed to edit this page.
Definition: IEditObject.php:53
getWatchlistValue
getWatchlistValue(string $watchlist, Title $title, User $user, ?string $userOption=null)
Return true if we're to watch the page, false if not.
Definition: ApiWatchlistTrait.php:92
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:601
$content
$content
Definition: router.php:76
MediaWiki\Content\IContentHandlerFactory
Definition: IContentHandlerFactory.php:10
MediaWiki\EditPage\IEditObject\AS_IMAGE_REDIRECT_ANON
const AS_IMAGE_REDIRECT_ANON
Status: anonymous user is not allowed to upload (User::isAllowed('upload') == false)
Definition: IEditObject.php:92
Message\plaintextParam
static plaintextParam( $plaintext)
Definition: Message.php:1104
ApiBase\dieReadOnly
dieReadOnly()
Helper function for readonly errors.
Definition: ApiBase.php:1456
ApiBase\useTransactionalTimeLimit
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition: ApiBase.php:1228
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1504
ApiEditPage\isWriteMode
isWriteMode()
Indicates whether this module requires write mode.
Definition: ApiEditPage.php:591
TextContent
Content object implementation for representing flat text.
Definition: TextContent.php:39
EditPage
The edit page/HTML interface (split from Article) The actual database and text munging is still in Ar...
Definition: EditPage.php:79
getWatchlistExpiry
getWatchlistExpiry(WatchedItemStoreInterface $store, Title $title, User $user)
Get existing expiry from the database.
Definition: ApiWatchlistTrait.php:156
ApiWatchlistTrait
trait ApiWatchlistTrait
An ApiWatchlistTrait adds class properties and convenience methods for APIs that allow you to watch a...
Definition: ApiWatchlistTrait.php:17
ApiBase\PARAM_RANGE_ENFORCE
const PARAM_RANGE_ENFORCE
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:92
ChangeTags\canAddTagsAccompanyingChange
static canAddTagsAccompanyingChange(array $tags, User $user=null)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
Definition: ChangeTags.php:598
MediaWiki\EditPage\IEditObject\AS_BLANK_ARTICLE
const AS_BLANK_ARTICLE
Status: user tried to create a blank page and wpIgnoreBlankArticle == false.
Definition: IEditObject.php:68
Title
Represents a title within MediaWiki.
Definition: Title.php:46
getWatchlistParams
getWatchlistParams(array $watchOptions=[])
Get additional allow params specific to watchlisting.
Definition: ApiWatchlistTrait.php:35
MediaWiki\EditPage\IEditObject\AS_IMAGE_REDIRECT_LOGGED
const AS_IMAGE_REDIRECT_LOGGED
Status: logged in user is not allowed to upload (User::isAllowed('upload') == false)
Definition: IEditObject.php:95
MediaWiki\EditPage\IEditObject\AS_MAX_ARTICLE_SIZE_EXCEEDED
const AS_MAX_ARTICLE_SIZE_EXCEEDED
Status: article is too big (> $wgMaxArticleSize), after merging in the new section.
Definition: IEditObject.php:83
ApiBase\PARAM_DFLT
const PARAM_DFLT
Definition: ApiBase.php:67
MediaWiki\EditPage\IEditObject\AS_READ_ONLY_PAGE
const AS_READ_ONLY_PAGE
Status: wiki is in readonly mode (wfReadOnly() == true)
Definition: IEditObject.php:56
ApiBase\dieWithException
dieWithException(Throwable $exception, array $options=[])
Abort execution with an error derived from a throwable.
Definition: ApiBase.php:1382
ApiBase\dieStatus
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
Definition: ApiBase.php:1428
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:437
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
Definition: ApiBase.php:68
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:453
wfWarn
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
Definition: GlobalFunctions.php:1080
ApiBase\checkTitleUserPermissions
checkTitleUserPermissions(LinkTarget $linkTarget, $actions, array $options=[])
Helper function for permission-denied errors.
Definition: ApiBase.php:1497
$wgRequest
if(! $wgDBerrorLogTZ) $wgRequest
Definition: Setup.php:645
MediaWiki\EditPage\IEditObject\AS_HOOK_ERROR_EXPECTED
const AS_HOOK_ERROR_EXPECTED
Status: A hook function returned an error.
Definition: IEditObject.php:41
ApiEditPage\needsToken
needsToken()
Returns the token type this module requires in order to execute.
Definition: ApiEditPage.php:679
MediaWiki\EditPage\IEditObject\AS_HOOK_ERROR
const AS_HOOK_ERROR
Status: Article update aborted by a hook function.
Definition: IEditObject.php:38
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:40