public function execute()
 {
     global $wgHooks;
     $out = $this->mSpecial->getOutput();
     if (!ModerationCanSkip::canSkip($this->moderator)) {
         // In order to merge, moderator must also be automoderated
         throw new ModerationError('moderation-merge-not-automoderated');
     }
     $dbw = wfGetDB(DB_MASTER);
     $row = $dbw->selectRow('moderation', array('mod_namespace AS namespace', 'mod_title AS title', 'mod_user_text AS user_text', 'mod_text AS text', 'mod_conflict AS conflict'), array('mod_id' => $this->id), __METHOD__);
     if (!$row) {
         throw new ModerationError('moderation-edit-not-found');
     }
     if (!$row->conflict) {
         throw new ModerationError('moderation-merge-not-needed');
     }
     $title = Title::makeTitle($row->namespace, $row->title);
     $article = new Article($title);
     ModerationEditHooks::$NewMergeID = $this->id;
     $editPage = new EditPage($article);
     $editPage->isConflict = true;
     $editPage->setContextTitle($title);
     $editPage->textbox1 = $row->text;
     $editPage->summary = wfMessage("moderation-merge-comment", $row->user_text)->inContentLanguage()->plain();
     $editPage->showEditForm();
 }
Esempio n. 2
0
 public function execute()
 {
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) {
         $this->dieUsageMsg('missingtext');
     }
     $pageObj = $this->getTitleOrPageId($params);
     $titleObj = $pageObj->getTitle();
     $apiResult = $this->getResult();
     if ($params['redirect']) {
         if ($params['prependtext'] === null && $params['appendtext'] === null && $params['section'] !== 'new') {
             $this->dieUsage('You have attempted to edit using the "redirect"-following' . ' mode, which must be used in conjuction with section=new, prependtext' . ', or appendtext.', 'redirect-appendonly');
         }
         if ($titleObj->isRedirect()) {
             $oldTitle = $titleObj;
             $titles = Revision::newFromTitle($oldTitle, false, Revision::READ_LATEST)->getContent(Revision::FOR_THIS_USER, $user)->getRedirectChain();
             // array_shift( $titles );
             $redirValues = array();
             /** @var $newTitle Title */
             foreach ($titles as $id => $newTitle) {
                 if (!isset($titles[$id - 1])) {
                     $titles[$id - 1] = $oldTitle;
                 }
                 $redirValues[] = array('from' => $titles[$id - 1]->getPrefixedText(), 'to' => $newTitle->getPrefixedText());
                 $titleObj = $newTitle;
             }
             ApiResult::setIndexedTagName($redirValues, 'r');
             $apiResult->addValue(null, 'redirects', $redirValues);
             // Since the page changed, update $pageObj
             $pageObj = WikiPage::factory($titleObj);
         }
     }
     if (!isset($params['contentmodel']) || $params['contentmodel'] == '') {
         $contentHandler = $pageObj->getContentHandler();
     } else {
         $contentHandler = ContentHandler::getForModelID($params['contentmodel']);
     }
     $name = $titleObj->getPrefixedDBkey();
     $model = $contentHandler->getModelID();
     if ($contentHandler->supportsDirectApiEditing() === false) {
         $this->dieUsage("Direct editing via API is not supported for content model {$model} used by {$name}", 'no-direct-editing');
     }
     if (!isset($params['contentformat']) || $params['contentformat'] == '') {
         $params['contentformat'] = $contentHandler->getDefaultFormat();
     }
     $contentFormat = $params['contentformat'];
     if (!$contentHandler->isSupportedFormat($contentFormat)) {
         $this->dieUsage("The requested format {$contentFormat} is not supported for content model " . " {$model} used by {$name}", 'badformat');
     }
     if ($params['createonly'] && $titleObj->exists()) {
         $this->dieUsageMsg('createonly-exists');
     }
     if ($params['nocreate'] && !$titleObj->exists()) {
         $this->dieUsageMsg('nocreate-missing');
     }
     // Now let's check whether we're even allowed to do this
     $errors = $titleObj->getUserPermissionsErrors('edit', $user);
     if (!$titleObj->exists()) {
         $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $user));
     }
     if (count($errors)) {
         if (is_array($errors[0])) {
             switch ($errors[0][0]) {
                 case 'blockedtext':
                     $this->dieUsage('You have been blocked from editing', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())));
                     break;
                 case 'autoblockedtext':
                     $this->dieUsage('Your IP address has been blocked automatically, because it was used by a blocked user', 'autoblocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())));
                     break;
                 default:
                     $this->dieUsageMsg($errors[0]);
             }
         } else {
             $this->dieUsageMsg($errors[0]);
         }
     }
     $toMD5 = $params['text'];
     if (!is_null($params['appendtext']) || !is_null($params['prependtext'])) {
         $content = $pageObj->getContent();
         if (!$content) {
             if ($titleObj->getNamespace() == NS_MEDIAWIKI) {
                 # If this is a MediaWiki:x message, then load the messages
                 # and return the message value for x.
                 $text = $titleObj->getDefaultMessageText();
                 if ($text === false) {
                     $text = '';
                 }
                 try {
                     $content = ContentHandler::makeContent($text, $this->getTitle());
                 } catch (MWContentSerializationException $ex) {
                     $this->dieUsage($ex->getMessage(), 'parseerror');
                     return;
                 }
             } else {
                 # Otherwise, make a new empty content.
                 $content = $contentHandler->makeEmptyContent();
             }
         }
         // @todo Add support for appending/prepending to the Content interface
         if (!$content instanceof TextContent) {
             $mode = $contentHandler->getModelID();
             $this->dieUsage("Can't append to pages using content model {$mode}", 'appendnotsupported');
         }
         if (!is_null($params['section'])) {
             if (!$contentHandler->supportsSections()) {
                 $modelName = $contentHandler->getModelID();
                 $this->dieUsage("Sections are not supported for this content model: {$modelName}.", 'sectionsnotsupported');
             }
             if ($params['section'] == 'new') {
                 // DWIM if they're trying to prepend/append to a new section.
                 $content = null;
             } else {
                 // Process the content for section edits
                 $section = $params['section'];
                 $content = $content->getSection($section);
                 if (!$content) {
                     $this->dieUsage("There is no section {$section}.", 'nosuchsection');
                 }
             }
         }
         if (!$content) {
             $text = '';
         } else {
             $text = $content->serialize($contentFormat);
         }
         $params['text'] = $params['prependtext'] . $text . $params['appendtext'];
         $toMD5 = $params['prependtext'] . $params['appendtext'];
     }
     if ($params['undo'] > 0) {
         if ($params['undoafter'] > 0) {
             if ($params['undo'] < $params['undoafter']) {
                 list($params['undo'], $params['undoafter']) = array($params['undoafter'], $params['undo']);
             }
             $undoafterRev = Revision::newFromId($params['undoafter']);
         }
         $undoRev = Revision::newFromId($params['undo']);
         if (is_null($undoRev) || $undoRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undo']));
         }
         if ($params['undoafter'] == 0) {
             $undoafterRev = $undoRev->getPrevious();
         }
         if (is_null($undoafterRev) || $undoafterRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undoafter']));
         }
         if ($undoRev->getPage() != $pageObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText()));
         }
         if ($undoafterRev->getPage() != $pageObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText()));
         }
         $newContent = $contentHandler->getUndoContent($pageObj->getRevision(), $undoRev, $undoafterRev);
         if (!$newContent) {
             $this->dieUsageMsg('undo-failure');
         }
         $params['text'] = $newContent->serialize($params['contentformat']);
         // If no summary was given and we only undid one rev,
         // use an autosummary
         if (is_null($params['summary']) && $titleObj->getNextRevisionID($undoafterRev->getID()) == $params['undo']) {
             $params['summary'] = wfMessage('undo-summary')->params($params['undo'], $undoRev->getUserText())->inContentLanguage()->text();
         }
     }
     // See if the MD5 hash checks out
     if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) {
         $this->dieUsageMsg('hashcheckfailed');
     }
     // EditPage wants to parse its stuff from a WebRequest
     // That interface kind of sucks, but it's workable
     $requestArray = array('wpTextbox1' => $params['text'], 'format' => $contentFormat, 'model' => $contentHandler->getModelID(), 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => true, 'wpIgnoreBlankArticle' => true, 'wpIgnoreSelfRedirect' => true, 'bot' => $params['bot']);
     if (!is_null($params['summary'])) {
         $requestArray['wpSummary'] = $params['summary'];
     }
     if (!is_null($params['sectiontitle'])) {
         $requestArray['wpSectionTitle'] = $params['sectiontitle'];
     }
     // TODO: Pass along information from 'undoafter' as well
     if ($params['undo'] > 0) {
         $requestArray['wpUndidRevision'] = $params['undo'];
     }
     // Watch out for basetimestamp == '' or '0'
     // It gets treated as NOW, almost certainly causing an edit conflict
     if ($params['basetimestamp'] !== null && (bool) $this->getMain()->getVal('basetimestamp')) {
         $requestArray['wpEdittime'] = $params['basetimestamp'];
     } else {
         $requestArray['wpEdittime'] = $pageObj->getTimestamp();
     }
     if ($params['starttimestamp'] !== null) {
         $requestArray['wpStarttime'] = $params['starttimestamp'];
     } else {
         $requestArray['wpStarttime'] = wfTimestampNow();
         // Fake wpStartime
     }
     if ($params['minor'] || !$params['notminor'] && $user->getOption('minordefault')) {
         $requestArray['wpMinoredit'] = '';
     }
     if ($params['recreate']) {
         $requestArray['wpRecreate'] = '';
     }
     if (!is_null($params['section'])) {
         $section = $params['section'];
         if (!preg_match('/^((T-)?\\d+|new)$/', $section)) {
             $this->dieUsage("The section parameter must be a valid section id or 'new'", "invalidsection");
         }
         $content = $pageObj->getContent();
         if ($section !== '0' && $section != 'new' && (!$content || !$content->getSection($section))) {
             $this->dieUsage("There is no section {$section}.", 'nosuchsection');
         }
         $requestArray['wpSection'] = $params['section'];
     } else {
         $requestArray['wpSection'] = '';
     }
     $watch = $this->getWatchlistValue($params['watchlist'], $titleObj);
     // Deprecated parameters
     if ($params['watch']) {
         $this->logFeatureUsage('action=edit&watch');
         $watch = true;
     } elseif ($params['unwatch']) {
         $this->logFeatureUsage('action=edit&unwatch');
         $watch = false;
     }
     if ($watch) {
         $requestArray['wpWatchthis'] = '';
     }
     // Apply change tags
     if (count($params['tags'])) {
         if ($user->isAllowed('applychangetags')) {
             $requestArray['wpChangeTags'] = implode(',', $params['tags']);
         } else {
             $this->dieUsage('You don\'t have permission to set change tags.', 'taggingnotallowed');
         }
     }
     // Pass through anything else we might have been given, to support extensions
     // This is kind of a hack but it's the best we can do to make extensions work
     $requestArray += $this->getRequest()->getValues();
     global $wgTitle, $wgRequest;
     $req = new DerivativeRequest($this->getRequest(), $requestArray, true);
     // Some functions depend on $wgTitle == $ep->mTitle
     // TODO: Make them not or check if they still do
     $wgTitle = $titleObj;
     $articleContext = new RequestContext();
     $articleContext->setRequest($req);
     $articleContext->setWikiPage($pageObj);
     $articleContext->setUser($this->getUser());
     /** @var $articleObject Article */
     $articleObject = Article::newFromWikiPage($pageObj, $articleContext);
     $ep = new EditPage($articleObject);
     $ep->setApiEditOverride(true);
     $ep->setContextTitle($titleObj);
     $ep->importFormData($req);
     $content = $ep->textbox1;
     // The following is needed to give the hook the full content of the
     // new revision rather than just the current section. (Bug 52077)
     if (!is_null($params['section']) && $contentHandler->supportsSections() && $titleObj->exists()) {
         // If sectiontitle is set, use it, otherwise use the summary as the section title (for
         // backwards compatibility with old forms/bots).
         if ($ep->sectiontitle !== '') {
             $sectionTitle = $ep->sectiontitle;
         } else {
             $sectionTitle = $ep->summary;
         }
         $contentObj = $contentHandler->unserializeContent($content, $contentFormat);
         $fullContentObj = $articleObject->replaceSectionContent($params['section'], $contentObj, $sectionTitle);
         if ($fullContentObj) {
             $content = $fullContentObj->serialize($contentFormat);
         } else {
             // This most likely means we have an edit conflict which means that the edit
             // wont succeed anyway.
             $this->dieUsageMsg('editconflict');
         }
     }
     // Run hooks
     // Handle APIEditBeforeSave parameters
     $r = array();
     if (!Hooks::run('APIEditBeforeSave', array($ep, $content, &$r))) {
         if (count($r)) {
             $r['result'] = 'Failure';
             $apiResult->addValue(null, $this->getModuleName(), $r);
             return;
         }
         $this->dieUsageMsg('hookaborted');
     }
     // Do the actual save
     $oldRevId = $articleObject->getRevIdFetched();
     $result = null;
     // Fake $wgRequest for some hooks inside EditPage
     // @todo FIXME: This interface SUCKS
     $oldRequest = $wgRequest;
     $wgRequest = $req;
     $status = $ep->attemptSave($result);
     $wgRequest = $oldRequest;
     switch ($status->value) {
         case EditPage::AS_HOOK_ERROR:
         case EditPage::AS_HOOK_ERROR_EXPECTED:
             if (isset($status->apiHookResult)) {
                 $r = $status->apiHookResult;
                 $r['result'] = 'Failure';
                 $apiResult->addValue(null, $this->getModuleName(), $r);
                 return;
             } else {
                 $this->dieUsageMsg('hookaborted');
             }
         case EditPage::AS_PARSE_ERROR:
             $this->dieUsage($status->getMessage(), 'parseerror');
         case EditPage::AS_IMAGE_REDIRECT_ANON:
             $this->dieUsageMsg('noimageredirect-anon');
         case EditPage::AS_IMAGE_REDIRECT_LOGGED:
             $this->dieUsageMsg('noimageredirect-logged');
         case EditPage::AS_SPAM_ERROR:
             $this->dieUsageMsg(array('spamdetected', $result['spam']));
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $this->dieUsage('You have been blocked from editing', 'blocked', 0, array('blockinfo' => ApiQueryUserInfo::getBlockInfo($user->getBlock())));
         case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
         case EditPage::AS_CONTENT_TOO_BIG:
             $this->dieUsageMsg(array('contenttoobig', $this->getConfig()->get('MaxArticleSize')));
         case EditPage::AS_READ_ONLY_PAGE_ANON:
             $this->dieUsageMsg('noedit-anon');
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $this->dieUsageMsg('noedit');
         case EditPage::AS_READ_ONLY_PAGE:
             $this->dieReadOnly();
         case EditPage::AS_RATE_LIMITED:
             $this->dieUsageMsg('actionthrottledtext');
         case EditPage::AS_ARTICLE_WAS_DELETED:
             $this->dieUsageMsg('wasdeleted');
         case EditPage::AS_NO_CREATE_PERMISSION:
             $this->dieUsageMsg('nocreate-loggedin');
         case EditPage::AS_NO_CHANGE_CONTENT_MODEL:
             $this->dieUsageMsg('cantchangecontentmodel');
         case EditPage::AS_BLANK_ARTICLE:
             $this->dieUsageMsg('blankpage');
         case EditPage::AS_CONFLICT_DETECTED:
             $this->dieUsageMsg('editconflict');
         case EditPage::AS_TEXTBOX_EMPTY:
             $this->dieUsageMsg('emptynewsection');
         case EditPage::AS_CHANGE_TAG_ERROR:
             $this->dieStatus($status);
         case EditPage::AS_SUCCESS_NEW_ARTICLE:
             $r['new'] = true;
             // fall-through
         // fall-through
         case EditPage::AS_SUCCESS_UPDATE:
             $r['result'] = 'Success';
             $r['pageid'] = intval($titleObj->getArticleID());
             $r['title'] = $titleObj->getPrefixedText();
             $r['contentmodel'] = $articleObject->getContentModel();
             $newRevId = $articleObject->getLatest();
             if ($newRevId == $oldRevId) {
                 $r['nochange'] = true;
             } else {
                 $r['oldrevid'] = intval($oldRevId);
                 $r['newrevid'] = intval($newRevId);
                 $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $pageObj->getTimestamp());
             }
             break;
         case EditPage::AS_SUMMARY_NEEDED:
             // Shouldn't happen since we set wpIgnoreBlankSummary, but just in case
             $this->dieUsageMsg('summaryrequired');
         case EditPage::AS_END:
         default:
             // $status came from WikiPage::doEdit()
             $errors = $status->getErrorsArray();
             $this->dieUsageMsg($errors[0]);
             // TODO: Add new errors to message map
             break;
     }
     $apiResult->addValue(null, $this->getModuleName(), $r);
 }
Esempio n. 3
0
 /**
  * @depends testAutoMerge
  */
 public function testCheckDirectEditingDisallowed_forNonTextContent()
 {
     $title = Title::newFromText('Dummy:NonTextPageForEditPage');
     $page = WikiPage::factory($title);
     $article = new Article($title);
     $article->getContext()->setTitle($title);
     $ep = new EditPage($article);
     $ep->setContextTitle($title);
     $user = $GLOBALS['wgUser'];
     $edit = ['wpTextbox1' => serialize('non-text content'), 'wpEditToken' => $user->getEditToken(), 'wpEdittime' => '', 'wpStarttime' => wfTimestampNow()];
     $req = new FauxRequest($edit, true);
     $ep->importFormData($req);
     $this->setExpectedException('MWException', 'This content model is not supported: testing');
     $ep->internalAttemptSave($result, false);
 }
Esempio n. 4
0
 public function execute()
 {
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) {
         $this->dieUsageMsg('missingtext');
     }
     $titleObj = Title::newFromText($params['title']);
     if (!$titleObj || $titleObj->isExternal()) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     $apiResult = $this->getResult();
     if ($params['redirect']) {
         if ($titleObj->isRedirect()) {
             $oldTitle = $titleObj;
             $titles = Title::newFromRedirectArray(Revision::newFromTitle($oldTitle)->getText(Revision::FOR_THIS_USER));
             // array_shift( $titles );
             $redirValues = array();
             foreach ($titles as $id => $newTitle) {
                 if (!isset($titles[$id - 1])) {
                     $titles[$id - 1] = $oldTitle;
                 }
                 $redirValues[] = array('from' => $titles[$id - 1]->getPrefixedText(), 'to' => $newTitle->getPrefixedText());
                 $titleObj = $newTitle;
             }
             $apiResult->setIndexedTagName($redirValues, 'r');
             $apiResult->addValue(null, 'redirects', $redirValues);
         }
     }
     if ($params['createonly'] && $titleObj->exists()) {
         $this->dieUsageMsg('createonly-exists');
     }
     if ($params['nocreate'] && !$titleObj->exists()) {
         $this->dieUsageMsg('nocreate-missing');
     }
     // Now let's check whether we're even allowed to do this
     $errors = $titleObj->getUserPermissionsErrors('edit', $user);
     if (!$titleObj->exists()) {
         $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $user));
     }
     if (count($errors)) {
         $this->dieUsageMsg($errors[0]);
     }
     $articleObj = Article::newFromTitle($titleObj, $this->getContext());
     $toMD5 = $params['text'];
     if (!is_null($params['appendtext']) || !is_null($params['prependtext'])) {
         // For non-existent pages, Article::getContent()
         // returns an interface message rather than ''
         // We do want getContent()'s behavior for non-existent
         // MediaWiki: pages, though
         if ($articleObj->getID() == 0 && $titleObj->getNamespace() != NS_MEDIAWIKI) {
             $content = '';
         } else {
             $content = $articleObj->getContent();
         }
         if (!is_null($params['section'])) {
             // Process the content for section edits
             global $wgParser;
             $section = intval($params['section']);
             $content = $wgParser->getSection($content, $section, false);
             if ($content === false) {
                 $this->dieUsage("There is no section {$section}.", 'nosuchsection');
             }
         }
         $params['text'] = $params['prependtext'] . $content . $params['appendtext'];
         $toMD5 = $params['prependtext'] . $params['appendtext'];
     }
     if ($params['undo'] > 0) {
         if ($params['undoafter'] > 0) {
             if ($params['undo'] < $params['undoafter']) {
                 list($params['undo'], $params['undoafter']) = array($params['undoafter'], $params['undo']);
             }
             $undoafterRev = Revision::newFromID($params['undoafter']);
         }
         $undoRev = Revision::newFromID($params['undo']);
         if (is_null($undoRev) || $undoRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undo']));
         }
         if ($params['undoafter'] == 0) {
             $undoafterRev = $undoRev->getPrevious();
         }
         if (is_null($undoafterRev) || $undoafterRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undoafter']));
         }
         if ($undoRev->getPage() != $articleObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText()));
         }
         if ($undoafterRev->getPage() != $articleObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText()));
         }
         $newtext = $articleObj->getUndoText($undoRev, $undoafterRev);
         if ($newtext === false) {
             $this->dieUsageMsg('undo-failure');
         }
         $params['text'] = $newtext;
         // If no summary was given and we only undid one rev,
         // use an autosummary
         if (is_null($params['summary']) && $titleObj->getNextRevisionID($undoafterRev->getID()) == $params['undo']) {
             $params['summary'] = wfMsgForContent('undo-summary', $params['undo'], $undoRev->getUserText());
         }
     }
     // See if the MD5 hash checks out
     if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) {
         $this->dieUsageMsg('hashcheckfailed');
     }
     // EditPage wants to parse its stuff from a WebRequest
     // That interface kind of sucks, but it's workable
     $requestArray = array('wpTextbox1' => $params['text'], 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => '');
     if (!is_null($params['summary'])) {
         $requestArray['wpSummary'] = $params['summary'];
     }
     if (!is_null($params['sectiontitle'])) {
         $requestArray['wpSectionTitle'] = $params['sectiontitle'];
     }
     // Watch out for basetimestamp == ''
     // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict
     if (!is_null($params['basetimestamp']) && $params['basetimestamp'] != '') {
         $requestArray['wpEdittime'] = wfTimestamp(TS_MW, $params['basetimestamp']);
     } else {
         $requestArray['wpEdittime'] = $articleObj->getTimestamp();
     }
     if (!is_null($params['starttimestamp']) && $params['starttimestamp'] != '') {
         $requestArray['wpStarttime'] = wfTimestamp(TS_MW, $params['starttimestamp']);
     } else {
         $requestArray['wpStarttime'] = wfTimestampNow();
         // Fake wpStartime
     }
     if ($params['minor'] || !$params['notminor'] && $user->getGlobalPreference('minordefault')) {
         $requestArray['wpMinoredit'] = '';
     }
     if ($params['recreate']) {
         $requestArray['wpRecreate'] = '';
     }
     if (!is_null($params['section'])) {
         $section = intval($params['section']);
         if ($section == 0 && $params['section'] != '0' && $params['section'] != 'new') {
             $this->dieUsage("The section parameter must be set to an integer or 'new'", "invalidsection");
         }
         $requestArray['wpSection'] = $params['section'];
     } else {
         $requestArray['wpSection'] = '';
     }
     $watch = $this->getWatchlistValue($params['watchlist'], $titleObj);
     // Deprecated parameters
     if ($params['watch']) {
         $watch = true;
     } elseif ($params['unwatch']) {
         $watch = false;
     }
     if ($watch) {
         $requestArray['wpWatchthis'] = '';
     }
     global $wgTitle, $wgRequest;
     $req = new DerivativeRequest($this->getRequest(), $requestArray, true);
     // Some functions depend on $wgTitle == $ep->mTitle
     // TODO: Make them not or check if they still do
     $wgTitle = $titleObj;
     $ep = new EditPage($articleObj);
     $ep->setContextTitle($titleObj);
     $ep->importFormData($req);
     // Run hooks
     // Handle APIEditBeforeSave parameters
     $r = array();
     if (!wfRunHooks('APIEditBeforeSave', array($ep, $ep->textbox1, &$r))) {
         if (count($r)) {
             $r['result'] = 'Failure';
             $apiResult->addValue(null, $this->getModuleName(), $r);
             return;
         } else {
             $this->dieUsageMsg('hookaborted');
         }
     }
     // Do the actual save
     $oldRevId = $articleObj->getRevIdFetched();
     $result = null;
     // Fake $wgRequest for some hooks inside EditPage
     // @todo FIXME: This interface SUCKS
     $oldRequest = $wgRequest;
     $wgRequest = $req;
     $status = $ep->internalAttemptSave($result, $user->isAllowed('bot') && $params['bot']);
     $wgRequest = $oldRequest;
     global $wgMaxArticleSize;
     switch ($status->value) {
         case EditPage::AS_HOOK_ERROR:
         case EditPage::AS_HOOK_ERROR_EXPECTED:
             $this->dieUsageMsg('hookaborted');
         case EditPage::AS_IMAGE_REDIRECT_ANON:
             $this->dieUsageMsg('noimageredirect-anon');
         case EditPage::AS_IMAGE_REDIRECT_LOGGED:
             $this->dieUsageMsg('noimageredirect-logged');
         case EditPage::AS_SPAM_ERROR:
             $this->dieUsageMsg(array('spamdetected', $result['spam']));
         case EditPage::AS_FILTERING:
             $this->dieUsageMsg('filtered');
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $this->dieUsageMsg('blockedtext');
         case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
         case EditPage::AS_CONTENT_TOO_BIG:
             $this->dieUsageMsg(array('contenttoobig', $wgMaxArticleSize));
         case EditPage::AS_READ_ONLY_PAGE_ANON:
             $this->dieUsageMsg('noedit-anon');
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $this->dieUsageMsg('noedit');
         case EditPage::AS_READ_ONLY_PAGE:
             $this->dieReadOnly();
         case EditPage::AS_RATE_LIMITED:
             $this->dieUsageMsg('actionthrottledtext');
         case EditPage::AS_ARTICLE_WAS_DELETED:
             $this->dieUsageMsg('wasdeleted');
         case EditPage::AS_NO_CREATE_PERMISSION:
             $this->dieUsageMsg('nocreate-loggedin');
         case EditPage::AS_BLANK_ARTICLE:
             $this->dieUsageMsg('blankpage');
         case EditPage::AS_CONFLICT_DETECTED:
             $this->dieUsageMsg('editconflict');
             // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
         // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
         case EditPage::AS_TEXTBOX_EMPTY:
             $this->dieUsageMsg('emptynewsection');
         case EditPage::AS_SUCCESS_NEW_ARTICLE:
             $r['new'] = '';
         case EditPage::AS_SUCCESS_UPDATE:
             $r['result'] = 'Success';
             $r['pageid'] = intval($titleObj->getArticleID());
             $r['title'] = $titleObj->getPrefixedText();
             $newRevId = $articleObj->getLatest();
             if ($newRevId == $oldRevId) {
                 $r['nochange'] = '';
             } else {
                 $r['oldrevid'] = intval($oldRevId);
                 $r['newrevid'] = intval($newRevId);
                 $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $articleObj->getTimestamp());
                 wfRunHooks('ApiEditPage::SuccessfulApiEdit', [$newRevId]);
                 wfSetupSession();
             }
             break;
         case EditPage::AS_SUMMARY_NEEDED:
             $this->dieUsageMsg('summaryrequired');
         case EditPage::AS_END:
             // $status came from WikiPage::doEdit()
             $errors = $status->getErrorsArray();
             $this->dieUsageMsg($errors[0]);
             // TODO: Add new errors to message map
             break;
         default:
             if (is_string($status->value) && strlen($status->value)) {
                 $this->dieUsage("An unknown return value was returned by Editpage. The code returned was \"{$status->value}\"", $status->value);
             } else {
                 $this->dieUsageMsg(array('unknownerror', $status->value));
             }
     }
     $apiResult->addValue(null, $this->getModuleName(), $r);
 }
 /**
  * Performs an edit and checks the result.
  *
  * @param string|Title $title The title of the page to edit
  * @param string|null $baseText Some text to create the page with before attempting the edit.
  * @param User|string|null $user The user to perform the edit as.
  * @param array $edit An array of request parameters used to define the edit to perform.
  *              Some well known fields are:
  *              * wpTextbox1: the text to submit
  *              * wpSummary: the edit summary
  *              * wpEditToken: the edit token (will be inserted if not provided)
  *              * wpEdittime: timestamp of the edit's base revision (will be inserted
  *                if not provided)
  *              * wpStarttime: timestamp when the edit started (will be inserted if not provided)
  *              * wpSectionTitle: the section to edit
  *              * wpMinorEdit: mark as minor edit
  *              * wpWatchthis: whether to watch the page
  * @param int|null $expectedCode The expected result code (EditPage::AS_XXX constants).
  *                  Set to null to skip the check.
  * @param string|null $expectedText The text expected to be on the page after the edit.
  *                  Set to null to skip the check.
  * @param string|null $message An optional message to show along with any error message.
  *
  * @return WikiPage The page that was just edited, useful for getting the edit's rev_id, etc.
  */
 protected function assertEdit($title, $baseText, $user = null, array $edit, $expectedCode = null, $expectedText = null, $message = null)
 {
     if (is_string($title)) {
         $ns = $this->getDefaultWikitextNS();
         $title = Title::newFromText($title, $ns);
     }
     $this->assertNotNull($title);
     if (is_string($user)) {
         $user = User::newFromName($user);
         if ($user->getId() === 0) {
             $user->addToDatabase();
         }
     }
     $page = WikiPage::factory($title);
     if ($baseText !== null) {
         $content = ContentHandler::makeContent($baseText, $title);
         $page->doEditContent($content, "base text for test");
         $this->forceRevisionDate($page, '20120101000000');
         //sanity check
         $page->clear();
         $currentText = ContentHandler::getContentText($page->getContent());
         # EditPage rtrim() the user input, so we alter our expected text
         # to reflect that.
         $this->assertEditedTextEquals($baseText, $currentText);
     }
     if ($user == null) {
         $user = $GLOBALS['wgUser'];
     } else {
         $this->setMwGlobals('wgUser', $user);
     }
     if (!isset($edit['wpEditToken'])) {
         $edit['wpEditToken'] = $user->getEditToken();
     }
     if (!isset($edit['wpEdittime'])) {
         $edit['wpEdittime'] = $page->exists() ? $page->getTimestamp() : '';
     }
     if (!isset($edit['wpStarttime'])) {
         $edit['wpStarttime'] = wfTimestampNow();
     }
     $req = new FauxRequest($edit, true);
     // session ??
     $article = new Article($title);
     $article->getContext()->setTitle($title);
     $ep = new EditPage($article);
     $ep->setContextTitle($title);
     $ep->importFormData($req);
     $bot = isset($edit['bot']) ? (bool) $edit['bot'] : false;
     // this is where the edit happens!
     // Note: don't want to use EditPage::AttemptSave, because it messes with $wgOut
     // and throws exceptions like PermissionsError
     $status = $ep->internalAttemptSave($result, $bot);
     if ($expectedCode !== null) {
         // check edit code
         $this->assertEquals($expectedCode, $status->value, "Expected result code mismatch. {$message}");
     }
     $page = WikiPage::factory($title);
     if ($expectedText !== null) {
         // check resulting page text
         $content = $page->getContent();
         $text = ContentHandler::getContentText($content);
         # EditPage rtrim() the user input, so we alter our expected text
         # to reflect that.
         $this->assertEditedTextEquals($expectedText, $text, "Expected article text mismatch. {$message}");
     }
     return $page;
 }
Esempio n. 6
0
 public function execute()
 {
     $user = $this->getUser();
     $params = $this->extractRequestParams();
     if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) {
         $this->dieUsageMsg('missingtext');
     }
     $pageObj = $this->getTitleOrPageId($params);
     $titleObj = $pageObj->getTitle();
     $apiResult = $this->getResult();
     if ($params['redirect']) {
         if ($titleObj->isRedirect()) {
             $oldTitle = $titleObj;
             $titles = Revision::newFromTitle($oldTitle, false, Revision::READ_LATEST)->getContent(Revision::FOR_THIS_USER, $user)->getRedirectChain();
             // array_shift( $titles );
             $redirValues = array();
             /** @var $newTitle Title */
             foreach ($titles as $id => $newTitle) {
                 if (!isset($titles[$id - 1])) {
                     $titles[$id - 1] = $oldTitle;
                 }
                 $redirValues[] = array('from' => $titles[$id - 1]->getPrefixedText(), 'to' => $newTitle->getPrefixedText());
                 $titleObj = $newTitle;
             }
             $apiResult->setIndexedTagName($redirValues, 'r');
             $apiResult->addValue(null, 'redirects', $redirValues);
             // Since the page changed, update $pageObj
             $pageObj = WikiPage::factory($titleObj);
         }
     }
     if (!isset($params['contentmodel']) || $params['contentmodel'] == '') {
         $contentHandler = $pageObj->getContentHandler();
     } else {
         $contentHandler = ContentHandler::getForModelID($params['contentmodel']);
     }
     // @todo ask handler whether direct editing is supported at all! make allowFlatEdit() method or some such
     if (!isset($params['contentformat']) || $params['contentformat'] == '') {
         $params['contentformat'] = $contentHandler->getDefaultFormat();
     }
     $contentFormat = $params['contentformat'];
     if (!$contentHandler->isSupportedFormat($contentFormat)) {
         $name = $titleObj->getPrefixedDBkey();
         $model = $contentHandler->getModelID();
         $this->dieUsage("The requested format {$contentFormat} is not supported for content model " . " {$model} used by {$name}", 'badformat');
     }
     if ($params['createonly'] && $titleObj->exists()) {
         $this->dieUsageMsg('createonly-exists');
     }
     if ($params['nocreate'] && !$titleObj->exists()) {
         $this->dieUsageMsg('nocreate-missing');
     }
     // Now let's check whether we're even allowed to do this
     $errors = $titleObj->getUserPermissionsErrors('edit', $user);
     if (!$titleObj->exists()) {
         $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $user));
     }
     if (count($errors)) {
         $this->dieUsageMsg($errors[0]);
     }
     $toMD5 = $params['text'];
     if (!is_null($params['appendtext']) || !is_null($params['prependtext'])) {
         $content = $pageObj->getContent();
         if (!$content) {
             if ($titleObj->getNamespace() == NS_MEDIAWIKI) {
                 # If this is a MediaWiki:x message, then load the messages
                 # and return the message value for x.
                 $text = $titleObj->getDefaultMessageText();
                 if ($text === false) {
                     $text = '';
                 }
                 try {
                     $content = ContentHandler::makeContent($text, $this->getTitle());
                 } catch (MWContentSerializationException $ex) {
                     $this->dieUsage($ex->getMessage(), 'parseerror');
                     return;
                 }
             } else {
                 # Otherwise, make a new empty content.
                 $content = $contentHandler->makeEmptyContent();
             }
         }
         // @todo Add support for appending/prepending to the Content interface
         if (!$content instanceof TextContent) {
             $mode = $contentHandler->getModelID();
             $this->dieUsage("Can't append to pages using content model {$mode}", 'appendnotsupported');
         }
         if (!is_null($params['section'])) {
             if (!$contentHandler->supportsSections()) {
                 $modelName = $contentHandler->getModelID();
                 $this->dieUsage("Sections are not supported for this content model: {$modelName}.", 'sectionsnotsupported');
             }
             // Process the content for section edits
             $section = intval($params['section']);
             $content = $content->getSection($section);
             if (!$content) {
                 $this->dieUsage("There is no section {$section}.", 'nosuchsection');
             }
         }
         if (!$content) {
             $text = '';
         } else {
             $text = $content->serialize($contentFormat);
         }
         $params['text'] = $params['prependtext'] . $text . $params['appendtext'];
         $toMD5 = $params['prependtext'] . $params['appendtext'];
     }
     if ($params['undo'] > 0) {
         if ($params['undoafter'] > 0) {
             if ($params['undo'] < $params['undoafter']) {
                 list($params['undo'], $params['undoafter']) = array($params['undoafter'], $params['undo']);
             }
             $undoafterRev = Revision::newFromID($params['undoafter']);
         }
         $undoRev = Revision::newFromID($params['undo']);
         if (is_null($undoRev) || $undoRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undo']));
         }
         if ($params['undoafter'] == 0) {
             $undoafterRev = $undoRev->getPrevious();
         }
         if (is_null($undoafterRev) || $undoafterRev->isDeleted(Revision::DELETED_TEXT)) {
             $this->dieUsageMsg(array('nosuchrevid', $params['undoafter']));
         }
         if ($undoRev->getPage() != $pageObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoRev->getID(), $titleObj->getPrefixedText()));
         }
         if ($undoafterRev->getPage() != $pageObj->getID()) {
             $this->dieUsageMsg(array('revwrongpage', $undoafterRev->getID(), $titleObj->getPrefixedText()));
         }
         $newContent = $contentHandler->getUndoContent($pageObj->getRevision(), $undoRev, $undoafterRev);
         if (!$newContent) {
             $this->dieUsageMsg('undo-failure');
         }
         $params['text'] = $newContent->serialize($params['contentformat']);
         // If no summary was given and we only undid one rev,
         // use an autosummary
         if (is_null($params['summary']) && $titleObj->getNextRevisionID($undoafterRev->getID()) == $params['undo']) {
             $params['summary'] = wfMessage('undo-summary', $params['undo'], $undoRev->getUserText())->inContentLanguage()->text();
         }
     }
     // See if the MD5 hash checks out
     if (!is_null($params['md5']) && md5($toMD5) !== $params['md5']) {
         $this->dieUsageMsg('hashcheckfailed');
     }
     // EditPage wants to parse its stuff from a WebRequest
     // That interface kind of sucks, but it's workable
     $requestArray = array('wpTextbox1' => $params['text'], 'format' => $contentFormat, 'model' => $contentHandler->getModelID(), 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => '');
     if (!is_null($params['summary'])) {
         $requestArray['wpSummary'] = $params['summary'];
     }
     if (!is_null($params['sectiontitle'])) {
         $requestArray['wpSectionTitle'] = $params['sectiontitle'];
     }
     // TODO: Pass along information from 'undoafter' as well
     if ($params['undo'] > 0) {
         $requestArray['wpUndidRevision'] = $params['undo'];
     }
     // Watch out for basetimestamp == ''
     // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict
     if (!is_null($params['basetimestamp']) && $params['basetimestamp'] != '') {
         $requestArray['wpEdittime'] = wfTimestamp(TS_MW, $params['basetimestamp']);
     } else {
         $requestArray['wpEdittime'] = $pageObj->getTimestamp();
     }
     if (!is_null($params['starttimestamp']) && $params['starttimestamp'] != '') {
         $requestArray['wpStarttime'] = wfTimestamp(TS_MW, $params['starttimestamp']);
     } else {
         $requestArray['wpStarttime'] = wfTimestampNow();
         // Fake wpStartime
     }
     if ($params['minor'] || !$params['notminor'] && $user->getOption('minordefault')) {
         $requestArray['wpMinoredit'] = '';
     }
     if ($params['recreate']) {
         $requestArray['wpRecreate'] = '';
     }
     if (!is_null($params['section'])) {
         $section = intval($params['section']);
         if ($section == 0 && $params['section'] != '0' && $params['section'] != 'new') {
             $this->dieUsage("The section parameter must be set to an integer or 'new'", "invalidsection");
         }
         $requestArray['wpSection'] = $params['section'];
     } else {
         $requestArray['wpSection'] = '';
     }
     $watch = $this->getWatchlistValue($params['watchlist'], $titleObj);
     // Deprecated parameters
     if ($params['watch']) {
         $watch = true;
     } elseif ($params['unwatch']) {
         $watch = false;
     }
     if ($watch) {
         $requestArray['wpWatchthis'] = '';
     }
     global $wgTitle, $wgRequest;
     $req = new DerivativeRequest($this->getRequest(), $requestArray, true);
     // Some functions depend on $wgTitle == $ep->mTitle
     // TODO: Make them not or check if they still do
     $wgTitle = $titleObj;
     $articleContext = new RequestContext();
     $articleContext->setRequest($req);
     $articleContext->setWikiPage($pageObj);
     $articleContext->setUser($this->getUser());
     /** @var $articleObject Article */
     $articleObject = Article::newFromWikiPage($pageObj, $articleContext);
     $ep = new EditPage($articleObject);
     // allow editing of non-textual content.
     $ep->allowNonTextContent = true;
     $ep->setContextTitle($titleObj);
     $ep->importFormData($req);
     // Run hooks
     // Handle APIEditBeforeSave parameters
     $r = array();
     if (!wfRunHooks('APIEditBeforeSave', array($ep, $ep->textbox1, &$r))) {
         if (count($r)) {
             $r['result'] = 'Failure';
             $apiResult->addValue(null, $this->getModuleName(), $r);
             return;
         } else {
             $this->dieUsageMsg('hookaborted');
         }
     }
     // Do the actual save
     $oldRevId = $articleObject->getRevIdFetched();
     $result = null;
     // Fake $wgRequest for some hooks inside EditPage
     // @todo FIXME: This interface SUCKS
     $oldRequest = $wgRequest;
     $wgRequest = $req;
     $status = $ep->internalAttemptSave($result, $user->isAllowed('bot') && $params['bot']);
     $wgRequest = $oldRequest;
     global $wgMaxArticleSize;
     switch ($status->value) {
         case EditPage::AS_HOOK_ERROR:
         case EditPage::AS_HOOK_ERROR_EXPECTED:
             $this->dieUsageMsg('hookaborted');
         case EditPage::AS_PARSE_ERROR:
             $this->dieUsage($status->getMessage(), 'parseerror');
         case EditPage::AS_IMAGE_REDIRECT_ANON:
             $this->dieUsageMsg('noimageredirect-anon');
         case EditPage::AS_IMAGE_REDIRECT_LOGGED:
             $this->dieUsageMsg('noimageredirect-logged');
         case EditPage::AS_SPAM_ERROR:
             $this->dieUsageMsg(array('spamdetected', $result['spam']));
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $this->dieUsageMsg('blockedtext');
         case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
         case EditPage::AS_CONTENT_TOO_BIG:
             $this->dieUsageMsg(array('contenttoobig', $wgMaxArticleSize));
         case EditPage::AS_READ_ONLY_PAGE_ANON:
             $this->dieUsageMsg('noedit-anon');
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $this->dieUsageMsg('noedit');
         case EditPage::AS_READ_ONLY_PAGE:
             $this->dieReadOnly();
         case EditPage::AS_RATE_LIMITED:
             $this->dieUsageMsg('actionthrottledtext');
         case EditPage::AS_ARTICLE_WAS_DELETED:
             $this->dieUsageMsg('wasdeleted');
         case EditPage::AS_NO_CREATE_PERMISSION:
             $this->dieUsageMsg('nocreate-loggedin');
         case EditPage::AS_BLANK_ARTICLE:
             $this->dieUsageMsg('blankpage');
         case EditPage::AS_CONFLICT_DETECTED:
             $this->dieUsageMsg('editconflict');
             // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
         // case EditPage::AS_SUMMARY_NEEDED: Can't happen since we set wpIgnoreBlankSummary
         case EditPage::AS_TEXTBOX_EMPTY:
             $this->dieUsageMsg('emptynewsection');
         case EditPage::AS_SUCCESS_NEW_ARTICLE:
             $r['new'] = '';
             // fall-through
         // fall-through
         case EditPage::AS_SUCCESS_UPDATE:
             $r['result'] = 'Success';
             $r['pageid'] = intval($titleObj->getArticleID());
             $r['title'] = $titleObj->getPrefixedText();
             $r['contentmodel'] = $titleObj->getContentModel();
             $newRevId = $articleObject->getLatest();
             if ($newRevId == $oldRevId) {
                 $r['nochange'] = '';
             } else {
                 $r['oldrevid'] = intval($oldRevId);
                 $r['newrevid'] = intval($newRevId);
                 $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $pageObj->getTimestamp());
             }
             break;
         case EditPage::AS_SUMMARY_NEEDED:
             $this->dieUsageMsg('summaryrequired');
         case EditPage::AS_END:
         default:
             // $status came from WikiPage::doEdit()
             $errors = $status->getErrorsArray();
             $this->dieUsageMsg($errors[0]);
             // TODO: Add new errors to message map
             break;
     }
     $apiResult->addValue(null, $this->getModuleName(), $r);
 }
 protected function doStore(EditPage $editor)
 {
     $title = $editor->getTitle();
     // If they used redlink=1 and the page exists, redirect to the main article and send notice
     if ($this->getRequest()->getBool('redlink') && $title->exists()) {
         $this->logMessage(wfMessage('sf_autoedit_redlinkexists')->parse(), self::WARNING);
     }
     $permErrors = $title->getUserPermissionsErrors('edit', $this->getUser());
     // if this title needs to be created, user needs create rights
     if (!$title->exists()) {
         $permErrors = array_merge($permErrors, wfArrayDiff2($title->getUserPermissionsErrors('create', $this->getUser()), $permErrors));
     }
     if ($permErrors) {
         // Auto-block user's IP if the account was "hard" blocked
         $this->getUser()->spreadAnyEditBlock();
         foreach ($permErrors as $error) {
             $this->logMessage(call_user_func_array('wfMessage', $error)->parse());
         }
         return;
     }
     $resultDetails = false;
     # Allow bots to exempt some edits from bot flagging
     $bot = $this->getUser()->isAllowed('bot') && $editor->bot;
     $request = $editor->sfFauxRequest;
     if ($editor->tokenOk($request)) {
         $ctx = RequestContext::getMain();
         $tempTitle = $ctx->getTitle();
         $ctx->setTitle($title);
         $status = $editor->internalAttemptSave($resultDetails, $bot);
         $ctx->setTitle($tempTitle);
     } else {
         throw new MWException(wfMessage('session_fail_preview')->parse());
     }
     switch ($status->value) {
         case EditPage::AS_HOOK_ERROR_EXPECTED:
             // A hook function returned an error
             // show normal Edit page
             // remove Preview and Diff standard buttons from editor page
             Hooks::register('EditPageBeforeEditButtons', function (&$editor, &$buttons, &$tabindex) {
                 foreach (array_keys($buttons) as $key) {
                     if ($key !== 'save') {
                         unset($buttons[$key]);
                     }
                 }
             });
             // Context title needed for correct Cancel link
             $editor->setContextTitle($title);
             $editor->showEditForm();
             return false;
             // success
         // success
         case EditPage::AS_CONTENT_TOO_BIG:
             // Content too big (> $wgMaxArticleSize)
         // Content too big (> $wgMaxArticleSize)
         case EditPage::AS_ARTICLE_WAS_DELETED:
             // article was deleted while editting and param wpRecreate == false or form was not posted
         // article was deleted while editting and param wpRecreate == false or form was not posted
         case EditPage::AS_CONFLICT_DETECTED:
             // (non-resolvable) edit conflict
         // (non-resolvable) edit conflict
         case EditPage::AS_SUMMARY_NEEDED:
             // no edit summary given and the user has forceeditsummary set and the user is not editting in his own userspace or talkspace and wpIgnoreBlankSummary == false
         // no edit summary given and the user has forceeditsummary set and the user is not editting in his own userspace or talkspace and wpIgnoreBlankSummary == false
         case EditPage::AS_TEXTBOX_EMPTY:
             // user tried to create a new section without content
         // user tried to create a new section without content
         case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
             // article is too big (> $wgMaxArticleSize), after merging in the new section
         // article is too big (> $wgMaxArticleSize), after merging in the new section
         case EditPage::AS_END:
             // WikiPage::doEdit() was unsuccessfull
             throw new MWException(wfMessage('sf_autoedit_fail', $this->mOptions['target'])->parse());
         case EditPage::AS_HOOK_ERROR:
             // Article update aborted by a hook function
             $this->logMessage('Article update aborted by a hook function', self::DEBUG);
             return false;
             // success
             // TODO: This error code only exists from 1.21 onwards. It is
             // suitably handled by the default branch, but really should get its
             // own branch. Uncomment once compatibility to pre1.21 is dropped.
             //			case EditPage::AS_PARSE_ERROR: // can't parse content
             //
             //				throw new MWException( $status->getHTML() );
             //				return true; // fail
         // success
         // TODO: This error code only exists from 1.21 onwards. It is
         // suitably handled by the default branch, but really should get its
         // own branch. Uncomment once compatibility to pre1.21 is dropped.
         //			case EditPage::AS_PARSE_ERROR: // can't parse content
         //
         //				throw new MWException( $status->getHTML() );
         //				return true; // fail
         case EditPage::AS_SUCCESS_NEW_ARTICLE:
             // Article successfully created
             $query = $resultDetails['redirect'] ? 'redirect=no' : '';
             $anchor = isset($resultDetails['sectionanchor']) ? $resultDetails['sectionanchor'] : '';
             $this->getOutput()->redirect($title->getFullURL($query) . $anchor);
             $this->getResult()->addValue(NULL, 'redirect', $title->getFullURL($query) . $anchor);
             return false;
             // success
         // success
         case EditPage::AS_SUCCESS_UPDATE:
             // Article successfully updated
             $extraQuery = '';
             $sectionanchor = $resultDetails['sectionanchor'];
             // Give extensions a chance to modify URL query on update
             Hooks::run('ArticleUpdateBeforeRedirect', array($editor->getArticle(), &$sectionanchor, &$extraQuery));
             if ($resultDetails['redirect']) {
                 if ($extraQuery == '') {
                     $extraQuery = 'redirect=no';
                 } else {
                     $extraQuery = 'redirect=no&' . $extraQuery;
                 }
             }
             $this->getOutput()->redirect($title->getFullURL($extraQuery) . $sectionanchor);
             $this->getResult()->addValue(NULL, 'redirect', $title->getFullURL($extraQuery) . $sectionanchor);
             return false;
             // success
         // success
         case EditPage::AS_BLANK_ARTICLE:
             // user tried to create a blank page
             $this->logMessage('User tried to create a blank page', self::DEBUG);
             $this->getOutput()->redirect($editor->getContextTitle()->getFullURL());
             $this->getResult()->addValue(NULL, 'redirect', $editor->getContextTitle()->getFullURL());
             return false;
             // success
         // success
         case EditPage::AS_SPAM_ERROR:
             // summary contained spam according to one of the regexes in $wgSummarySpamRegex
             $match = $resultDetails['spam'];
             if (is_array($match)) {
                 $match = $this->getLanguage()->listToText($match);
             }
             throw new MWException(wfMessage('spamprotectionmatch', wfEscapeWikiText($match))->parse());
             // FIXME: Include better error message
         // FIXME: Include better error message
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             // User is blocked from editting editor page
             throw new UserBlockedError($this->getUser()->getBlock());
         case EditPage::AS_IMAGE_REDIRECT_ANON:
             // anonymous user is not allowed to upload (User::isAllowed('upload') == false)
         // anonymous user is not allowed to upload (User::isAllowed('upload') == false)
         case EditPage::AS_IMAGE_REDIRECT_LOGGED:
             // logged in user is not allowed to upload (User::isAllowed('upload') == false)
             throw new PermissionsError('upload');
         case EditPage::AS_READ_ONLY_PAGE_ANON:
             // editor anonymous user is not allowed to edit editor page
         // editor anonymous user is not allowed to edit editor page
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             // editor logged in user is not allowed to edit editor page
             throw new PermissionsError('edit');
         case EditPage::AS_READ_ONLY_PAGE:
             // wiki is in readonly mode (wfReadOnly() == true)
             throw new ReadOnlyError();
         case EditPage::AS_RATE_LIMITED:
             // rate limiter for action 'edit' was tripped
             throw new ThrottledError();
         case EditPage::AS_NO_CREATE_PERMISSION:
             // user tried to create editor page, but is not allowed to do that ( Title->usercan('create') == false )
             $permission = $title->isTalkPage() ? 'createtalk' : 'createpage';
             throw new PermissionsError($permission);
         default:
             // We don't recognize $status->value. The only way that can happen
             // is if an extension hook aborted from inside ArticleSave.
             // Render the status object into $editor->hookError
             $editor->hookError = '<div class="error">' . $status->getWikitext() . '</div>';
             throw new MWException($status->getHTML());
     }
 }
 public function execute($par)
 {
     global $wgUser, $wgRequest, $wgOut, $wgCommentboxNamespaces;
     if (!$wgRequest->wasPosted()) {
         $wgOut->redirect(Title::newMainPage()->getFullURL());
         return;
     }
     $this->setHeaders();
     $Pagename = $wgRequest->getText('wpPageName');
     $Author = $wgRequest->getText('wpAuthor', '');
     $Comment = $wgRequest->getText('wpComment', '');
     $title = Title::newFromText($Pagename);
     if ($title == NULL || !$title->exists()) {
         $this->fail('commentbox-error-page-nonexistent');
         return;
     }
     if (!array_key_exists($title->getNamespace(), $wgCommentboxNamespaces) || !$wgCommentboxNamespaces[$title->getNamespace()]) {
         $this->fail('commentbox-error-namespace', $title);
         return;
     }
     if ($Comment == '' || $Comment == wfMsgNoTrans('commentbox-prefill')) {
         $this->fail('commentbox-error-empty-comment', $title);
         return;
     }
     if (!$title->userCan('edit')) {
         $this->displayRestrictionError();
         return;
     }
     // TODO: Integrate with SpamBlacklist etc.
     // Currently, no http/https-links are allowed at all
     $matches = array();
     if (preg_match('@https?://[-.\\w]+@', $Comment, $matches) || preg_match('@https?://[-.\\w]+@', $Author, $matches)) {
         $wgOut->setPageTitle(wfMsg('spamprotectiontitle'));
         $wgOut->setRobotPolicy('noindex,nofollow');
         $wgOut->setArticleRelated(false);
         $wgOut->addWikiMsg('spamprotectiontext');
         $wgOut->addWikiMsg('spamprotectionmatch', "<nowiki>{$matches[0]}</nowiki>");
         $wgOut->returnToMain(false, $title);
         return;
     }
     $article = new Article($title);
     $text = $article->getContent();
     $subject = '';
     if (!preg_match(wfMsgForContentNoTrans('commentbox-regex'), $text)) {
         $subject = wfMsgForContent('commentbox-first-comment-heading') . "\n";
     }
     $sig = $wgUser->isLoggedIn() ? "-- ~~~~" : "-- {$Author} ~~~~~";
     // Append <br /> after each newline, except if the user started a new paragraph
     $Comment = preg_replace('/(?<!\\n)\\n(?!\\n)/', "<br />\n", $Comment);
     $text .= "\n\n" . $subject . $Comment . "\n<br />" . $sig;
     $reqArr = array('wpTextbox1' => $text, 'wpSummary' => wfMsgForContent('commentbox-log'), 'wpEditToken' => $wgUser->editToken(), 'wpIgnoreBlankSummary' => '', 'wpStarttime' => wfTimestampNow(), 'wpEdittime' => $article->getTimestamp());
     $request = new FauxRequest($reqArr, true);
     $ep = new EditPage($article);
     $ep->setContextTitle($title);
     $ep->importFormData($request);
     $details = array();
     // Passed by ref
     $status = $ep->internalAttemptSave($details);
     $retval = $status->value;
     switch ($retval) {
         case EditPage::AS_SUCCESS_UPDATE:
             $wgOut->redirect($title->getFullURL());
             break;
         case EditPage::AS_SPAM_ERROR:
             $ep->spamPageWithContent($details['spam']);
             break;
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $wgOut->blockedPage();
             break;
         case EditPage::AS_READ_ONLY_PAGE_ANON:
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $wgOut->permissionRequired('edit');
             break;
         case EditPage::AS_READ_ONLY_PAGE:
             $wgOut->readOnlyPage();
     }
 }