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