Example #1
0
 /**
  * Fetch initial editing page content.
  *
  * @param $def_text string
  * @return mixed string on success, $def_text for invalid sections
  * @private
  */
 function getContent($def_text = '')
 {
     global $wgOut, $wgRequest, $wgParser;
     wfProfileIn(__METHOD__);
     $text = false;
     // For message page not locally set, use the i18n message.
     // For other non-existent articles, use preload text if any.
     if (!$this->mTitle->exists() || $this->section == 'new') {
         if ($this->mTitle->getNamespace() == NS_MEDIAWIKI && $this->section != 'new') {
             # If this is a system message, get the default text.
             $text = $this->mTitle->getDefaultMessageText();
         }
         if ($text === false) {
             # If requested, preload some text.
             $preload = $wgRequest->getVal('preload', $this->section === 'new' ? 'MediaWiki:addsection-preload' : '');
             $text = $this->getPreloadedText($preload);
         }
         // For existing pages, get text based on "undo" or section parameters.
     } else {
         if ($this->section != '') {
             // Get section edit text (returns $def_text for invalid sections)
             $text = $wgParser->getSection($this->getOriginalContent(), $this->section, $def_text);
         } else {
             $undoafter = $wgRequest->getInt('undoafter');
             $undo = $wgRequest->getInt('undo');
             if ($undo > 0 && $undoafter > 0) {
                 if ($undo < $undoafter) {
                     # If they got undoafter and undo round the wrong way, switch them
                     list($undo, $undoafter) = array($undoafter, $undo);
                 }
                 $undorev = Revision::newFromId($undo);
                 $oldrev = Revision::newFromId($undoafter);
                 # Sanity check, make sure it's the right page,
                 # the revisions exist and they were not deleted.
                 # Otherwise, $text will be left as-is.
                 if (!is_null($undorev) && !is_null($oldrev) && $undorev->getPage() == $oldrev->getPage() && $undorev->getPage() == $this->mTitle->getArticleId() && !$undorev->isDeleted(Revision::DELETED_TEXT) && !$oldrev->isDeleted(Revision::DELETED_TEXT)) {
                     $text = $this->mArticle->getUndoText($undorev, $oldrev);
                     if ($text === false) {
                         # Warn the user that something went wrong
                         $undoMsg = 'failure';
                     } else {
                         # Inform the user of our success and set an automatic edit summary
                         $undoMsg = 'success';
                         # If we just undid one rev, use an autosummary
                         $firstrev = $oldrev->getNext();
                         if ($firstrev->getId() == $undo) {
                             $undoSummary = wfMsgForContent('undo-summary', $undo, $undorev->getUserText());
                             if ($this->summary === '') {
                                 $this->summary = $undoSummary;
                             } else {
                                 $this->summary = $undoSummary . wfMsgForContent('colon-separator') . $this->summary;
                             }
                             $this->undidRev = $undo;
                         }
                         $this->formtype = 'diff';
                     }
                 } else {
                     // Failed basic sanity checks.
                     // Older revisions may have been removed since the link
                     // was created, or we may simply have got bogus input.
                     $undoMsg = 'norev';
                 }
                 $class = ($undoMsg == 'success' ? '' : 'error ') . "mw-undo-{$undoMsg}";
                 $this->editFormPageTop .= $wgOut->parse("<div class=\"{$class}\">" . wfMsgNoTrans('undo-' . $undoMsg) . '</div>', true, true);
             }
             if ($text === false) {
                 $text = $this->getOriginalContent();
             }
         }
     }
     wfProfileOut(__METHOD__);
     return $text;
 }
Example #2
0
 public function execute()
 {
     global $wgUser;
     $params = $this->extractRequestParams();
     if (is_null($params['text']) && is_null($params['appendtext']) && is_null($params['prependtext']) && $params['undo'] == 0) {
         $this->dieUsageMsg(array('missingtext'));
     }
     $titleObj = Title::newFromText($params['title']);
     if (!$titleObj || $titleObj->isExternal()) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     if ($params['redirect']) {
         if ($titleObj->isRedirect()) {
             $oldTitle = $titleObj;
             $titles = Title::newFromRedirectArray(Revision::newFromTitle($oldTitle)->getText(Revision::FOR_THIS_USER));
             $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;
             }
             $this->getResult()->setIndexedTagName($redirValues, 'r');
             $this->getResult()->addValue(null, 'redirects', $redirValues);
         }
     }
     // Some functions depend on $wgTitle == $ep->mTitle
     global $wgTitle;
     $wgTitle = $titleObj;
     if ($params['createonly'] && $titleObj->exists()) {
         $this->dieUsageMsg(array('createonly-exists'));
     }
     if ($params['nocreate'] && !$titleObj->exists()) {
         $this->dieUsageMsg(array('nocreate-missing'));
     }
     // Now let's check whether we're even allowed to do this
     $errors = $titleObj->getUserPermissionsErrors('edit', $wgUser);
     if (!$titleObj->exists()) {
         $errors = array_merge($errors, $titleObj->getUserPermissionsErrors('create', $wgUser));
     }
     if (count($errors)) {
         $this->dieUsageMsg($errors[0]);
     }
     $articleObj = new Article($titleObj);
     $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(array('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(array('hashcheckfailed'));
     }
     $ep = new EditPage($articleObj);
     // EditPage wants to parse its stuff from a WebRequest
     // That interface kind of sucks, but it's workable
     $reqArr = array('wpTextbox1' => $params['text'], 'wpEditToken' => $params['token'], 'wpIgnoreBlankSummary' => '');
     if (!is_null($params['summary'])) {
         $reqArr['wpSummary'] = $params['summary'];
     }
     // Watch out for basetimestamp == ''
     // wfTimestamp() treats it as NOW, almost certainly causing an edit conflict
     if (!is_null($params['basetimestamp']) && $params['basetimestamp'] != '') {
         $reqArr['wpEdittime'] = wfTimestamp(TS_MW, $params['basetimestamp']);
     } else {
         $reqArr['wpEdittime'] = $articleObj->getTimestamp();
     }
     if (!is_null($params['starttimestamp']) && $params['starttimestamp'] != '') {
         $reqArr['wpStarttime'] = wfTimestamp(TS_MW, $params['starttimestamp']);
     } else {
         $reqArr['wpStarttime'] = wfTimestampNow();
         // Fake wpStartime
     }
     if ($params['minor'] || !$params['notminor'] && $wgUser->getOption('minordefault')) {
         $reqArr['wpMinoredit'] = '';
     }
     if ($params['recreate']) {
         $reqArr['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");
         }
         $reqArr['wpSection'] = $params['section'];
     } else {
         $reqArr['wpSection'] = '';
     }
     $watch = $this->getWatchlistValue($params['watchlist'], $titleObj);
     // Deprecated parameters
     if ($params['watch']) {
         $watch = true;
     } elseif ($params['unwatch']) {
         $watch = false;
     }
     if ($watch) {
         $reqArr['wpWatchthis'] = '';
     }
     $req = new FauxRequest($reqArr, true);
     $ep->importFormData($req);
     // Run hooks
     // Handle CAPTCHA parameters
     global $wgRequest;
     if (!is_null($params['captchaid'])) {
         $wgRequest->setVal('wpCaptchaId', $params['captchaid']);
     }
     if (!is_null($params['captchaword'])) {
         $wgRequest->setVal('wpCaptchaWord', $params['captchaword']);
     }
     $r = array();
     if (!wfRunHooks('APIEditBeforeSave', array($ep, $ep->textbox1, &$r))) {
         if (count($r)) {
             $r['result'] = 'Failure';
             $this->getResult()->addValue(null, $this->getModuleName(), $r);
             return;
         } else {
             $this->dieUsageMsg(array('hookaborted'));
         }
     }
     // Do the actual save
     $oldRevId = $articleObj->getRevIdFetched();
     $result = null;
     // Fake $wgRequest for some hooks inside EditPage
     // FIXME: This interface SUCKS
     $oldRequest = $wgRequest;
     $wgRequest = $req;
     $retval = $ep->internalAttemptSave($result, $wgUser->isAllowed('bot') && $params['bot']);
     $wgRequest = $oldRequest;
     global $wgMaxArticleSize;
     switch ($retval) {
         case EditPage::AS_HOOK_ERROR:
         case EditPage::AS_HOOK_ERROR_EXPECTED:
             $this->dieUsageMsg(array('hookaborted'));
         case EditPage::AS_IMAGE_REDIRECT_ANON:
             $this->dieUsageMsg(array('noimageredirect-anon'));
         case EditPage::AS_IMAGE_REDIRECT_LOGGED:
             $this->dieUsageMsg(array('noimageredirect-logged'));
         case EditPage::AS_SPAM_ERROR:
             $this->dieUsageMsg(array('spamdetected', $result['spam']));
         case EditPage::AS_FILTERING:
             $this->dieUsageMsg(array('filtered'));
         case EditPage::AS_BLOCKED_PAGE_FOR_USER:
             $this->dieUsageMsg(array('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(array('noedit-anon'));
         case EditPage::AS_READ_ONLY_PAGE_LOGGED:
             $this->dieUsageMsg(array('noedit'));
         case EditPage::AS_READ_ONLY_PAGE:
             $this->dieReadOnly();
         case EditPage::AS_RATE_LIMITED:
             $this->dieUsageMsg(array('actionthrottledtext'));
         case EditPage::AS_ARTICLE_WAS_DELETED:
             $this->dieUsageMsg(array('wasdeleted'));
         case EditPage::AS_NO_CREATE_PERMISSION:
             $this->dieUsageMsg(array('nocreate-loggedin'));
         case EditPage::AS_BLANK_ARTICLE:
             $this->dieUsageMsg(array('blankpage'));
         case EditPage::AS_CONFLICT_DETECTED:
             $this->dieUsageMsg(array('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(array('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();
             // HACK: We create a new Article object here because getRevIdFetched()
             // refuses to be run twice, and because Title::getLatestRevId()
             // won't fetch from the master unless we select for update, which we
             // don't want to do.
             $newArticle = new Article($titleObj);
             $newRevId = $newArticle->getRevIdFetched();
             if ($newRevId == $oldRevId) {
                 $r['nochange'] = '';
             } else {
                 $r['oldrevid'] = intval($oldRevId);
                 $r['newrevid'] = intval($newRevId);
                 $r['newtimestamp'] = wfTimestamp(TS_ISO_8601, $newArticle->getTimestamp());
             }
             break;
         case EditPage::AS_SUMMARY_NEEDED:
             $this->dieUsageMsg(array('summaryrequired'));
         case EditPage::AS_END:
             // This usually means some kind of race condition
             // or DB weirdness occurred. Fall through to throw an unknown
             // error.
             // This needs fixing higher up, as Article::doEdit should be
             // used rather than Article::updateArticle, so that specific
             // error conditions can be returned
         // This usually means some kind of race condition
         // or DB weirdness occurred. Fall through to throw an unknown
         // error.
         // This needs fixing higher up, as Article::doEdit should be
         // used rather than Article::updateArticle, so that specific
         // error conditions can be returned
         default:
             $this->dieUsageMsg(array('unknownerror', $retval));
     }
     $this->getResult()->addValue(null, $this->getModuleName(), $r);
 }
 /**
  * Fetch initial editing page content.
  *
  * @param $def_text string
  * @returns mixed string on success, $def_text for invalid sections
  * @private
  */
 function getContent($def_text = '')
 {
     global $wgOut, $wgRequest, $wgParser;
     wfProfileIn(__METHOD__);
     # Get variables from query string :P
     $section = $wgRequest->getVal('section');
     $preload = $wgRequest->getVal('preload', $section === 'new' ? 'MediaWiki:addsection-preload' : '');
     $undoafter = $wgRequest->getVal('undoafter');
     $undo = $wgRequest->getVal('undo');
     // For message page not locally set, use the i18n message.
     // For other non-existent articles, use preload text if any.
     if (!$this->mTitle->exists()) {
         if ($this->mTitle->getNamespace() == NS_MEDIAWIKI) {
             # If this is a system message, get the default text.
             $text = $this->mTitle->getDefaultMessageText();
             if ($text === false) {
                 $text = $this->getPreloadedText($preload);
             }
         } else {
             # If requested, preload some text.
             $text = $this->getPreloadedText($preload);
         }
         // For existing pages, get text based on "undo" or section parameters.
     } else {
         $text = $this->mArticle->getContent();
         if ($undo > 0 && $undoafter > 0 && $undo < $undoafter) {
             # If they got undoafter and undo round the wrong way, switch them
             list($undo, $undoafter) = array($undoafter, $undo);
         }
         if ($undo > 0 && $undo > $undoafter) {
             # Undoing a specific edit overrides section editing; section-editing
             # doesn't work with undoing.
             if ($undoafter) {
                 $undorev = Revision::newFromId($undo);
                 $oldrev = Revision::newFromId($undoafter);
             } else {
                 $undorev = Revision::newFromId($undo);
                 $oldrev = $undorev ? $undorev->getPrevious() : null;
             }
             # Sanity check, make sure it's the right page,
             # the revisions exist and they were not deleted.
             # Otherwise, $text will be left as-is.
             if (!is_null($undorev) && !is_null($oldrev) && $undorev->getPage() == $oldrev->getPage() && $undorev->getPage() == $this->mArticle->getID() && !$undorev->isDeleted(Revision::DELETED_TEXT) && !$oldrev->isDeleted(Revision::DELETED_TEXT)) {
                 $undotext = $this->mArticle->getUndoText($undorev, $oldrev);
                 if ($undotext === false) {
                     # Warn the user that something went wrong
                     $this->editFormPageTop .= $wgOut->parse('<div class="error mw-undo-failure">' . wfMsgNoTrans('undo-failure') . '</div>');
                 } else {
                     $text = $undotext;
                     # Inform the user of our success and set an automatic edit summary
                     $this->editFormPageTop .= $wgOut->parse('<div class="mw-undo-success">' . wfMsgNoTrans('undo-success') . '</div>');
                     $firstrev = $oldrev->getNext();
                     # If we just undid one rev, use an autosummary
                     if ($firstrev->mId == $undo) {
                         $this->summary = wfMsgForContent('undo-summary', $undo, $undorev->getUserText());
                         $this->undidRev = $undo;
                     }
                     $this->formtype = 'diff';
                 }
             } else {
                 // Failed basic sanity checks.
                 // Older revisions may have been removed since the link
                 // was created, or we may simply have got bogus input.
                 $this->editFormPageTop .= $wgOut->parse('<div class="error mw-undo-norev">' . wfMsgNoTrans('undo-norev') . '</div>');
             }
         } elseif ($section != '') {
             if ($section == 'new') {
                 $text = $this->getPreloadedText($preload);
             } else {
                 // Get section edit text (returns $def_text for invalid sections)
                 $text = $wgParser->getSection($text, $section, $def_text);
             }
         }
     }
     wfProfileOut(__METHOD__);
     return $text;
 }