Example #1
0
 /**
  * Extracts the title, token, and reason from the request parameters and invokes
  * the local delete() function with these as arguments. It does not make use of
  * the delete function specified by Article.php. If the deletion succeeds, the
  * details of the article deleted and the reason for deletion are added to the
  * result object.
  */
 public function execute()
 {
     global $wgUser;
     $params = $this->extractRequestParams();
     $this->requireOnlyOneParameter($params, 'title', 'pageid');
     if (!isset($params['token'])) {
         $this->dieUsageMsg(array('missingparam', 'token'));
     }
     if (isset($params['title'])) {
         $titleObj = Title::newFromText($params['title']);
         if (!$titleObj) {
             $this->dieUsageMsg(array('invalidtitle', $params['title']));
         }
     } else {
         if (isset($params['pageid'])) {
             $titleObj = Title::newFromID($params['pageid']);
             if (!$titleObj) {
                 $this->dieUsageMsg(array('nosuchpageid', $params['pageid']));
             }
         }
     }
     if (!$titleObj->exists()) {
         $this->dieUsageMsg(array('notanarticle'));
     }
     $reason = isset($params['reason']) ? $params['reason'] : NULL;
     if ($titleObj->getNamespace() == NS_FILE) {
         $retval = self::deleteFile($params['token'], $titleObj, $params['oldimage'], $reason, false);
         if (count($retval)) {
             // We don't care about multiple errors, just report one of them
             $this->dieUsageMsg(reset($retval));
         }
     } else {
         $articleObj = new Article($titleObj);
         if ($articleObj->isBigDeletion() && !$wgUser->isAllowed('bigdelete')) {
             global $wgDeleteRevisionsLimit;
             $this->dieUsageMsg(array('delete-toobig', $wgDeleteRevisionsLimit));
         }
         $retval = self::delete($articleObj, $params['token'], $reason);
         if (count($retval)) {
             // We don't care about multiple errors, just report one of them
             $this->dieUsageMsg(reset($retval));
         }
         if ($params['watch'] || $wgUser->getOption('watchdeletion')) {
             $articleObj->doWatch();
         } else {
             if ($params['unwatch']) {
                 $articleObj->doUnwatch();
             }
         }
     }
     $r = array('title' => $titleObj->getPrefixedText(), 'reason' => $reason);
     $this->getResult()->addValue(null, $this->getModuleName(), $r);
 }
Example #2
0
 function doSubmit()
 {
     global $wgOut, $wgUser, $wgMaximumMovedPages, $wgLang;
     global $wgFixDoubleRedirects;
     if ($wgUser->pingLimiter('move')) {
         $wgOut->rateLimited();
         return;
     }
     $ot = $this->oldTitle;
     $nt = $this->newTitle;
     # Delete to make way if requested
     if ($wgUser->isAllowed('delete') && $this->deleteAndMove) {
         $article = new Article($nt);
         # Disallow deletions of big articles
         $bigHistory = $article->isBigDeletion();
         if ($bigHistory && !$nt->userCan('bigdelete')) {
             global $wgDeleteRevisionsLimit;
             $this->showForm(array('delete-toobig', $wgLang->formatNum($wgDeleteRevisionsLimit)));
             return;
         }
         // Delete an associated image if there is
         $file = wfLocalFile($nt);
         if ($file->exists()) {
             $file->delete(wfMsgForContent('delete_and_move_reason'), false);
         }
         // This may output an error message and exit
         $article->doDelete(wfMsgForContent('delete_and_move_reason'));
     }
     # don't allow moving to pages with # in
     if (!$nt || $nt->getFragment() != '') {
         $this->showForm('badtitletext');
         return;
     }
     # Show a warning if the target file exists on a shared repo
     if ($nt->getNamespace() == NS_FILE && !($this->moveOverShared && $wgUser->isAllowed('reupload-shared')) && !RepoGroup::singleton()->getLocalRepo()->findFile($nt) && wfFindFile($nt)) {
         $this->showForm(array('file-exists-sharedrepo'));
         return;
     }
     if ($wgUser->isAllowed('suppressredirect')) {
         $createRedirect = $this->leaveRedirect;
     } else {
         $createRedirect = true;
     }
     # Do the actual move.
     $error = $ot->moveTo($nt, true, $this->reason, $createRedirect);
     if ($error !== true) {
         # @todo FIXME: Show all the errors in a list, not just the first one
         $this->showForm(reset($error));
         return;
     }
     if ($wgFixDoubleRedirects && $this->fixRedirects) {
         DoubleRedirectJob::fixRedirects('move', $ot, $nt);
     }
     wfRunHooks('SpecialMovepageAfterMove', array(&$this, &$ot, &$nt));
     $wgOut->setPagetitle(wfMsg('pagemovedsub'));
     $oldUrl = $ot->getFullUrl('redirect=no');
     $newUrl = $nt->getFullUrl();
     $oldText = $ot->getPrefixedText();
     $newText = $nt->getPrefixedText();
     $oldLink = "<span class='plainlinks'>[{$oldUrl} {$oldText}]</span>";
     $newLink = "<span class='plainlinks'>[{$newUrl} {$newText}]</span>";
     $msgName = $createRedirect ? 'movepage-moved-redirect' : 'movepage-moved-noredirect';
     $wgOut->addWikiMsg('movepage-moved', $oldLink, $newLink, $oldText, $newText);
     $wgOut->addWikiMsg($msgName);
     # Now we move extra pages we've been asked to move: subpages and talk
     # pages.  First, if the old page or the new page is a talk page, we
     # can't move any talk pages: cancel that.
     if ($ot->isTalkPage() || $nt->isTalkPage()) {
         $this->moveTalk = false;
     }
     if (!$ot->userCan('move-subpages')) {
         $this->moveSubpages = false;
     }
     # Next make a list of id's.  This might be marginally less efficient
     # than a more direct method, but this is not a highly performance-cri-
     # tical code path and readable code is more important here.
     #
     # Note: this query works nicely on MySQL 5, but the optimizer in MySQL
     # 4 might get confused.  If so, consider rewriting as a UNION.
     #
     # If the target namespace doesn't allow subpages, moving with subpages
     # would mean that you couldn't move them back in one operation, which
     # is bad.
     # @todo FIXME: A specific error message should be given in this case.
     // @todo FIXME: Use Title::moveSubpages() here
     $dbr = wfGetDB(DB_MASTER);
     if ($this->moveSubpages && (MWNamespace::hasSubpages($nt->getNamespace()) || $this->moveTalk && MWNamespace::hasSubpages($nt->getTalkPage()->getNamespace()))) {
         $conds = array('page_title' . $dbr->buildLike($ot->getDBkey() . '/', $dbr->anyString()) . ' OR page_title = ' . $dbr->addQuotes($ot->getDBkey()));
         $conds['page_namespace'] = array();
         if (MWNamespace::hasSubpages($nt->getNamespace())) {
             $conds['page_namespace'][] = $ot->getNamespace();
         }
         if ($this->moveTalk && MWNamespace::hasSubpages($nt->getTalkPage()->getNamespace())) {
             $conds['page_namespace'][] = $ot->getTalkPage()->getNamespace();
         }
     } elseif ($this->moveTalk) {
         $conds = array('page_namespace' => $ot->getTalkPage()->getNamespace(), 'page_title' => $ot->getDBkey());
     } else {
         # Skip the query
         $conds = null;
     }
     $extraPages = array();
     if (!is_null($conds)) {
         $extraPages = TitleArray::newFromResult($dbr->select('page', array('page_id', 'page_namespace', 'page_title'), $conds, __METHOD__));
     }
     $extraOutput = array();
     $skin = $this->getSkin();
     $count = 1;
     foreach ($extraPages as $oldSubpage) {
         if ($ot->equals($oldSubpage)) {
             # Already did this one.
             continue;
         }
         $newPageName = preg_replace('#^' . preg_quote($ot->getDBkey(), '#') . '#', StringUtils::escapeRegexReplacement($nt->getDBkey()), $oldSubpage->getDBkey());
         if ($oldSubpage->isTalkPage()) {
             $newNs = $nt->getTalkPage()->getNamespace();
         } else {
             $newNs = $nt->getSubjectPage()->getNamespace();
         }
         # Bug 14385: we need makeTitleSafe because the new page names may
         # be longer than 255 characters.
         $newSubpage = Title::makeTitleSafe($newNs, $newPageName);
         if (!$newSubpage) {
             $oldLink = $skin->linkKnown($oldSubpage);
             $extraOutput[] = wfMsgHtml('movepage-page-unmoved', $oldLink, htmlspecialchars(Title::makeName($newNs, $newPageName)));
             continue;
         }
         # This was copy-pasted from Renameuser, bleh.
         if ($newSubpage->exists() && !$oldSubpage->isValidMoveTarget($newSubpage)) {
             $link = $skin->linkKnown($newSubpage);
             $extraOutput[] = wfMsgHtml('movepage-page-exists', $link);
         } else {
             $success = $oldSubpage->moveTo($newSubpage, true, $this->reason, $createRedirect);
             if ($success === true) {
                 if ($this->fixRedirects) {
                     DoubleRedirectJob::fixRedirects('move', $oldSubpage, $newSubpage);
                 }
                 $oldLink = $skin->linkKnown($oldSubpage, null, array(), array('redirect' => 'no'));
                 $newLink = $skin->linkKnown($newSubpage);
                 $extraOutput[] = wfMsgHtml('movepage-page-moved', $oldLink, $newLink);
                 ++$count;
                 if ($count >= $wgMaximumMovedPages) {
                     $extraOutput[] = wfMsgExt('movepage-max-pages', array('parsemag', 'escape'), $wgLang->formatNum($wgMaximumMovedPages));
                     break;
                 }
             } else {
                 $oldLink = $skin->linkKnown($oldSubpage);
                 $newLink = $skin->link($newSubpage);
                 $extraOutput[] = wfMsgHtml('movepage-page-unmoved', $oldLink, $newLink);
             }
         }
     }
     if ($extraOutput !== array()) {
         $wgOut->addHTML("<ul>\n<li>" . implode("</li>\n<li>", $extraOutput) . "</li>\n</ul>");
     }
     # Deal with watches (we don't watch subpages)
     if ($this->watch && $wgUser->isLoggedIn()) {
         $wgUser->addWatch($ot);
         $wgUser->addWatch($nt);
     } else {
         $wgUser->removeWatch($ot);
         $wgUser->removeWatch($nt);
     }
     # Re-clear the file redirect cache, which may have been polluted by
     # parsing in messages above. See CR r56745.
     # @todo FIXME: Needs a more robust solution inside FileRepo.
     if ($ot->getNamespace() == NS_FILE) {
         RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect($ot);
     }
 }
 /**
  * We have our own delete() function, since Article.php's implementation is split in two phases
  *
  * @param Article $article - Article object to work on
  * @param string $token - Delete token (same as edit token)
  * @param string $reason - Reason for the deletion. Autogenerated if NULL
  * @return Title::getUserPermissionsErrors()-like array
  */
 public static function delete(&$article, $token, &$reason = null)
 {
     global $wgUser;
     if ($article->isBigDeletion() && !$wgUser->isAllowed('bigdelete')) {
         global $wgDeleteRevisionsLimit;
         return array(array('delete-toobig', $wgDeleteRevisionsLimit));
     }
     $title = $article->getTitle();
     $errors = self::getPermissionsError($title, $token);
     if (count($errors)) {
         return $errors;
     }
     // Auto-generate a summary, if necessary
     if (is_null($reason)) {
         // Need to pass a throwaway variable because generateReason expects
         // a reference
         $hasHistory = false;
         $reason = $article->generateReason($hasHistory);
         if ($reason === false) {
             return array(array('cannotdelete'));
         }
     }
     $error = '';
     if (!wfRunHooks('ArticleDelete', array(&$article, &$wgUser, &$reason, $error))) {
         $this->dieUsageMsg(array('hookaborted', $error));
     }
     // Luckily, Article.php provides a reusable delete function that does the hard work for us
     if ($article->doDeleteArticle($reason)) {
         wfRunHooks('ArticleDeleteComplete', array(&$article, &$wgUser, $reason, $article->getId()));
         return array();
     }
     return array(array('cannotdelete', $article->mTitle->getPrefixedText()));
 }