39 if ( is_null(
$params[
'text'] ) && is_null(
$params[
'appendtext'] ) &&
40 is_null(
$params[
'prependtext'] ) &&
47 $titleObj = $pageObj->getTitle();
51 if ( $titleObj->isRedirect() ) {
59 $redirValues =
array();
64 if ( !isset(
$titles[$id - 1] ) ) {
68 $redirValues[] =
array(
69 'from' =>
$titles[$id - 1]->getPrefixedText(),
70 'to' => $newTitle->getPrefixedText()
73 $titleObj = $newTitle;
76 $apiResult->setIndexedTagName( $redirValues,
'r' );
77 $apiResult->addValue(
null,
'redirects', $redirValues );
84 if ( !isset(
$params[
'contentmodel'] ) ||
$params[
'contentmodel'] ==
'' ) {
85 $contentHandler = $pageObj->getContentHandler();
93 if ( !isset(
$params[
'contentformat'] ) ||
$params[
'contentformat'] ==
'' ) {
94 $params[
'contentformat'] = $contentHandler->getDefaultFormat();
97 $contentFormat =
$params[
'contentformat'];
99 if ( !$contentHandler->isSupportedFormat( $contentFormat ) ) {
100 $name = $titleObj->getPrefixedDBkey();
101 $model = $contentHandler->getModelID();
103 $this->
dieUsage(
"The requested format $contentFormat is not supported for content model " .
104 " $model used by $name",
'badformat' );
107 if (
$params[
'createonly'] && $titleObj->exists() ) {
110 if (
$params[
'nocreate'] && !$titleObj->exists() ) {
115 $errors = $titleObj->getUserPermissionsErrors(
'edit',
$user );
116 if ( !$titleObj->exists() ) {
117 $errors = array_merge( $errors, $titleObj->getUserPermissionsErrors(
'create',
$user ) );
119 if ( count( $errors ) ) {
124 if ( !is_null(
$params[
'appendtext'] ) || !is_null(
$params[
'prependtext'] ) ) {
125 $content = $pageObj->getContent();
129 # If this is a MediaWiki:x message, then load the messages
130 # and return the message value for x.
131 $text = $titleObj->getDefaultMessageText();
132 if ( $text ===
false ) {
139 $this->
dieUsage( $ex->getMessage(),
'parseerror' );
144 # Otherwise, make a new empty content.
145 $content = $contentHandler->makeEmptyContent();
152 $mode = $contentHandler->getModelID();
153 $this->
dieUsage(
"Can't append to pages using content model $mode",
'appendnotsupported' );
156 if ( !is_null(
$params[
'section'] ) ) {
157 if ( !$contentHandler->supportsSections() ) {
158 $modelName = $contentHandler->getModelID();
160 "Sections are not supported for this content model: $modelName.",
161 'sectionsnotsupported'
165 if (
$params[
'section'] ==
'new' ) {
171 $content = $content->getSection(
$section );
174 $this->
dieUsage(
"There is no section {$section}.",
'nosuchsection' );
182 $text = $content->serialize( $contentFormat );
190 if (
$params[
'undoafter'] > 0 ) {
195 $undoafterRev = Revision::newFromID(
$params[
'undoafter'] );
197 $undoRev = Revision::newFromID(
$params[
'undo'] );
202 if (
$params[
'undoafter'] == 0 ) {
203 $undoafterRev = $undoRev->getPrevious();
209 if ( $undoRev->getPage() != $pageObj->getID() ) {
211 $titleObj->getPrefixedText() ) );
213 if ( $undoafterRev->getPage() != $pageObj->getID() ) {
215 $titleObj->getPrefixedText() ) );
218 $newContent = $contentHandler->getUndoContent(
219 $pageObj->getRevision(),
224 if ( !$newContent ) {
228 $params[
'text'] = $newContent->serialize(
$params[
'contentformat'] );
232 if ( is_null(
$params[
'summary'] ) &&
233 $titleObj->getNextRevisionID( $undoafterRev->getID() ) ==
$params[
'undo']
236 ->params (
$params[
'undo'], $undoRev->getUserText() )->inContentLanguage()->text();
241 if ( !is_null(
$params[
'md5'] ) && md5( $toMD5 ) !==
$params[
'md5'] ) {
247 $requestArray =
array(
248 'wpTextbox1' =>
$params[
'text'],
249 'format' => $contentFormat,
250 'model' => $contentHandler->getModelID(),
251 'wpEditToken' =>
$params[
'token'],
252 'wpIgnoreBlankSummary' =>
''
255 if ( !is_null(
$params[
'summary'] ) ) {
256 $requestArray[
'wpSummary'] =
$params[
'summary'];
259 if ( !is_null(
$params[
'sectiontitle'] ) ) {
260 $requestArray[
'wpSectionTitle'] =
$params[
'sectiontitle'];
265 $requestArray[
'wpUndidRevision'] =
$params[
'undo'];
270 if ( !is_null(
$params[
'basetimestamp'] ) &&
$params[
'basetimestamp'] !=
'' ) {
273 $requestArray[
'wpEdittime'] = $pageObj->getTimestamp();
276 if ( !is_null(
$params[
'starttimestamp'] ) &&
$params[
'starttimestamp'] !=
'' ) {
282 if (
$params[
'minor'] || ( !
$params[
'notminor'] &&
$user->getOption(
'minordefault' ) ) ) {
283 $requestArray[
'wpMinoredit'] =
'';
287 $requestArray[
'wpRecreate'] =
'';
290 if ( !is_null(
$params[
'section'] ) ) {
293 $this->
dieUsage(
"The section parameter must be set to an integer or 'new'",
"invalidsection" );
295 $content = $pageObj->getContent();
296 if (
$section !== 0 && ( !$content || !$content->getSection(
$section ) ) ) {
297 $this->
dieUsage(
"There is no section {$section}.",
'nosuchsection' );
299 $requestArray[
'wpSection'] =
$params[
'section'];
301 $requestArray[
'wpSection'] =
'';
309 } elseif (
$params[
'unwatch'] ) {
314 $requestArray[
'wpWatchthis'] =
'';
319 $requestArray += $this->
getRequest()->getValues();
331 $articleContext->setWikiPage( $pageObj );
332 $articleContext->setUser( $this->
getUser() );
337 $ep =
new EditPage( $articleObject );
340 $ep->allowNonTextContent =
true;
342 $ep->setContextTitle( $titleObj );
343 $ep->importFormData( $req );
344 $content = $ep->textbox1;
348 if ( !is_null(
$params[
'section'] ) &&
349 $contentHandler->supportsSections() && $titleObj->exists()
353 if ( $ep->sectiontitle !==
'' ) {
354 $sectionTitle = $ep->sectiontitle;
356 $sectionTitle = $ep->summary;
359 $contentObj = $contentHandler->unserializeContent( $content, $contentFormat );
361 $fullContentObj = $articleObject->replaceSectionContent(
366 if ( $fullContentObj ) {
367 $content = $fullContentObj->serialize( $contentFormat );
378 if ( !
wfRunHooks(
'APIEditBeforeSave',
array( $ep, $content, &$r ) ) ) {
380 $r[
'result'] =
'Failure';
390 $oldRevId = $articleObject->getRevIdFetched();
394 $oldRequest = $wgRequest;
397 $status = $ep->internalAttemptSave(
$result,
$user->isAllowed(
'bot' ) &&
$params[
'bot'] );
398 $wgRequest = $oldRequest;
401 switch ( $status->value ) {
402 case EditPage::AS_HOOK_ERROR:
403 case EditPage::AS_HOOK_ERROR_EXPECTED:
406 case EditPage::AS_PARSE_ERROR:
407 $this->
dieUsage( $status->getMessage(),
'parseerror' );
409 case EditPage::AS_IMAGE_REDIRECT_ANON:
412 case EditPage::AS_IMAGE_REDIRECT_LOGGED:
415 case EditPage::AS_SPAM_ERROR:
418 case EditPage::AS_BLOCKED_PAGE_FOR_USER:
421 case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
422 case EditPage::AS_CONTENT_TOO_BIG:
425 case EditPage::AS_READ_ONLY_PAGE_ANON:
428 case EditPage::AS_READ_ONLY_PAGE_LOGGED:
431 case EditPage::AS_READ_ONLY_PAGE:
434 case EditPage::AS_RATE_LIMITED:
437 case EditPage::AS_ARTICLE_WAS_DELETED:
440 case EditPage::AS_NO_CREATE_PERMISSION:
443 case EditPage::AS_BLANK_ARTICLE:
446 case EditPage::AS_CONFLICT_DETECTED:
450 case EditPage::AS_TEXTBOX_EMPTY:
453 case EditPage::AS_SUCCESS_NEW_ARTICLE:
457 case EditPage::AS_SUCCESS_UPDATE:
458 $r[
'result'] =
'Success';
459 $r[
'pageid'] = intval( $titleObj->getArticleID() );
460 $r[
'title'] = $titleObj->getPrefixedText();
461 $r[
'contentmodel'] = $titleObj->getContentModel();
462 $newRevId = $articleObject->getLatest();
463 if ( $newRevId == $oldRevId ) {
466 $r[
'oldrevid'] = intval( $oldRevId );
467 $r[
'newrevid'] = intval( $newRevId );
469 $pageObj->getTimestamp() );
473 case EditPage::AS_SUMMARY_NEEDED:
476 case EditPage::AS_END:
479 $errors = $status->getErrorsArray();
495 return 'Create and edit pages.';
501 return array_merge( parent::getPossibleErrors(),
504 array(
'missingtext' ),
505 array(
'createonly-exists' ),
506 array(
'nocreate-missing' ),
507 array(
'nosuchrevid',
'undo' ),
508 array(
'nosuchrevid',
'undoafter' ),
509 array(
'revwrongpage',
'id',
'text' ),
510 array(
'undo-failure' ),
511 array(
'hashcheckfailed' ),
512 array(
'hookaborted' ),
513 array(
'code' =>
'parseerror',
'info' =>
'Failed to parse the given text.' ),
514 array(
'noimageredirect-anon' ),
515 array(
'noimageredirect-logged' ),
516 array(
'spamdetected',
'spam' ),
517 array(
'summaryrequired' ),
518 array(
'blockedtext' ),
519 array(
'contenttoobig', $wgMaxArticleSize ),
520 array(
'noedit-anon' ),
522 array(
'actionthrottledtext' ),
523 array(
'wasdeleted' ),
524 array(
'nocreate-loggedin' ),
525 array(
'blankpage' ),
526 array(
'editconflict' ),
527 array(
'emptynewsection' ),
528 array(
'unknownerror',
'retval' ),
529 array(
'code' =>
'nosuchsection',
'info' =>
'There is no section section.' ),
531 'code' =>
'invalidsection',
532 'info' =>
'The section parameter must be set to an integer or \'new\''
535 'code' =>
'sectionsnotsupported',
536 'info' =>
'Sections are not supported for this type of page.'
539 'code' =>
'editnotsupported',
540 'info' =>
'Editing of this type of page is not supported using the text based edit API.'
543 'code' =>
'appendnotsupported',
544 'info' =>
'This type of page can not be edited by appending or prepending text.' ),
546 'code' =>
'badformat',
547 'info' =>
'The requested serialization format can not be applied to the page\'s content model'
549 array(
'customcssprotected' ),
550 array(
'customjsprotected' ),
564 'sectiontitle' =>
array(
576 'basetimestamp' =>
null,
577 'starttimestamp' =>
null,
579 'createonly' =>
false,
589 'watchlist' =>
array(
599 'prependtext' =>
null,
600 'appendtext' =>
null,
604 'undoafter' =>
array(
611 'contentformat' =>
array(
614 'contentmodel' =>
array(
624 'title' =>
"Title of the page you want to edit. Cannot be used together with {$p}pageid",
625 'pageid' =>
"Page ID of the page you want to edit. Cannot be used together with {$p}title",
626 'section' =>
'Section number. 0 for the top section, \'new\' for a new section',
627 'sectiontitle' =>
'The title for a new section',
628 'text' =>
'Page content',
630 'Edit token. You can get one of these through prop=info.',
631 "The token should always be sent as the last parameter, or at " .
632 "least, after the {$p}text parameter"
635 =>
"Edit summary. Also section title when {$p}section=new and {$p}sectiontitle is not set",
636 'minor' =>
'Minor edit',
637 'notminor' =>
'Non-minor edit',
638 'bot' =>
'Mark this edit as bot',
639 'basetimestamp' =>
array(
640 'Timestamp of the base revision (obtained through prop=revisions&rvprop=timestamp).',
641 'Used to detect edit conflicts; leave unset to ignore conflicts'
643 'starttimestamp' =>
array(
644 'Timestamp when you obtained the edit token.',
645 'Used to detect edit conflicts; leave unset to ignore conflicts'
647 'recreate' =>
'Override any errors about the article having been deleted in the meantime',
648 'createonly' =>
'Don\'t edit the page if it exists already',
649 'nocreate' =>
'Throw an error if the page doesn\'t exist',
650 'watch' =>
'Add the page to your watchlist',
651 'unwatch' =>
'Remove the page from your watchlist',
652 'watchlist' =>
'Unconditionally add or remove the page from your ' .
653 'watchlist, use preferences or do not change watch',
655 "The MD5 hash of the {$p}text parameter, or the {$p}prependtext " .
656 "and {$p}appendtext parameters concatenated.",
657 'If set, the edit won\'t be done unless the hash is correct'
659 'prependtext' =>
"Add this text to the beginning of the page. Overrides {$p}text",
660 'appendtext' =>
array(
"Add this text to the end of the page. Overrides {$p}text.",
661 "Use {$p}section=new to append a new section" ),
662 'undo' =>
"Undo this revision. Overrides {$p}text, {$p}prependtext and {$p}appendtext",
663 'undoafter' =>
'Undo all revisions from undo to this one. If not set, just undo one revision',
664 'redirect' =>
'Automatically resolve redirects',
665 'contentformat' =>
'Content serialization format used for the input text',
666 'contentmodel' =>
'Content model of the new content',
688 'nochange' =>
'boolean',
697 'newtimestamp' =>
array(
715 'api.php?action=edit&title=Test&summary=test%20summary&' .
716 'text=article%20content&basetimestamp=20070824123454&token=%2B\\'
717 =>
'Edit a page (anonymous user)',
718 'api.php?action=edit&title=Test&summary=NOTOC&minor=&' .
719 'prependtext=__NOTOC__%0A&basetimestamp=20070824123454&token=%2B\\'
720 =>
'Prepend __NOTOC__ to a page (anonymous user)',
721 'api.php?action=edit&title=Test&undo=13585&undoafter=13579&' .
722 'basetimestamp=20070824123454&token=%2B\\'
723 =>
'Undo r13579 through r13585 with autosummary (anonymous user)',
728 return 'https://www.mediawiki.org/wiki/API:Edit';