Example #1
0
 /**
  * Move page to a title which is either a redirect to the
  * source page or nonexistent
  *
  * @param $nt Title the page to move to, which should be a redirect or nonexistent
  * @param $reason String The reason for the move
  * @param $createRedirect Bool Whether to leave a redirect at the old title.  Ignored
  *   if the user doesn't have the suppressredirect right
  */
 private function moveToInternal(&$nt, $reason = '', $createRedirect = true)
 {
     global $wgUser, $wgContLang;
     $moveOverRedirect = $nt->exists();
     $commentMsg = $moveOverRedirect ? '1movedto2_redir' : '1movedto2';
     $comment = wfMsgForContent($commentMsg, $this->getPrefixedText(), $nt->getPrefixedText());
     if ($reason) {
         $comment .= wfMsgForContent('colon-separator') . $reason;
     }
     # Truncate for whole multibyte characters.
     $comment = $wgContLang->truncate($comment, 255);
     $oldid = $this->getArticleID();
     $latest = $this->getLatestRevID();
     $dbw = wfGetDB(DB_MASTER);
     if ($moveOverRedirect) {
         $rcts = $dbw->timestamp($nt->getEarliestRevTime());
         $newid = $nt->getArticleID();
         $newns = $nt->getNamespace();
         $newdbk = $nt->getDBkey();
         # Delete the old redirect. We don't save it to history since
         # by definition if we've got here it's rather uninteresting.
         # We have to remove it so that the next step doesn't trigger
         # a conflict on the unique namespace+title index...
         $dbw->delete('page', array('page_id' => $newid), __METHOD__);
         if (!$dbw->cascadingDeletes()) {
             $dbw->delete('revision', array('rev_page' => $newid), __METHOD__);
             global $wgUseTrackbacks;
             if ($wgUseTrackbacks) {
                 $dbw->delete('trackbacks', array('tb_page' => $newid), __METHOD__);
             }
             $dbw->delete('pagelinks', array('pl_from' => $newid), __METHOD__);
             $dbw->delete('imagelinks', array('il_from' => $newid), __METHOD__);
             $dbw->delete('categorylinks', array('cl_from' => $newid), __METHOD__);
             $dbw->delete('templatelinks', array('tl_from' => $newid), __METHOD__);
             $dbw->delete('externallinks', array('el_from' => $newid), __METHOD__);
             $dbw->delete('langlinks', array('ll_from' => $newid), __METHOD__);
             $dbw->delete('iwlinks', array('iwl_from' => $newid), __METHOD__);
             $dbw->delete('redirect', array('rd_from' => $newid), __METHOD__);
         }
         // If the target page was recently created, it may have an entry in recentchanges still
         $dbw->delete('recentchanges', array('rc_timestamp' => $rcts, 'rc_namespace' => $newns, 'rc_title' => $newdbk, 'rc_new' => 1), __METHOD__);
     }
     # Save a null revision in the page's history notifying of the move
     $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true);
     if (!is_object($nullRevision)) {
         throw new MWException('No valid null revision produced in ' . __METHOD__);
     }
     $nullRevId = $nullRevision->insertOn($dbw);
     $now = wfTimestampNow();
     # Change the name of the target page:
     $dbw->update('page', array('page_touched' => $dbw->timestamp($now), 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), __METHOD__);
     $nt->resetArticleID($oldid);
     $article = new Article($nt);
     wfRunHooks('NewRevisionFromEditComplete', array($article, $nullRevision, $latest, $wgUser));
     $article->setCachedLastEditTime($now);
     # Recreate the redirect, this time in the other direction.
     if ($createRedirect || !$wgUser->isAllowed('suppressredirect')) {
         $mwRedir = MagicWord::get('redirect');
         $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n";
         $redirectArticle = new Article($this);
         $newid = $redirectArticle->insertOn($dbw);
         $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText));
         $redirectRevision->insertOn($dbw);
         $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0);
         wfRunHooks('NewRevisionFromEditComplete', array($redirectArticle, $redirectRevision, false, $wgUser));
         # Now, we record the link from the redirect to the new title.
         # It should have no other outgoing links...
         $dbw->delete('pagelinks', array('pl_from' => $newid), __METHOD__);
         $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDBkey()), __METHOD__);
         $redirectSuppressed = false;
     } else {
         $this->resetArticleID(0);
         $redirectSuppressed = true;
     }
     # Log the move
     $log = new LogPage('move');
     $logType = $moveOverRedirect ? 'move_redir' : 'move';
     $log->addEntry($logType, $this, $reason, array(1 => $nt->getPrefixedText(), 2 => $redirectSuppressed));
     # Purge caches for old and new titles
     if ($moveOverRedirect) {
         # A simple purge is enough when moving over a redirect
         $nt->purgeSquid();
     } else {
         # Purge caches as per article creation, including any pages that link to this title
         Article::onArticleCreate($nt);
     }
     $this->purgeSquid();
 }
Example #2
0
 /**
  * Article::doEdit()
  *
  * Change an existing article or create a new article. Updates RC and all necessary caches,
  * optionally via the deferred update array.
  *
  * $wgUser must be set before calling this function.
  *
  * @param $text String: new text
  * @param $summary String: edit summary
  * @param $flags Integer bitfield:
  *      EDIT_NEW
  *          Article is known or assumed to be non-existent, create a new one
  *      EDIT_UPDATE
  *          Article is known or assumed to be pre-existing, update it
  *      EDIT_MINOR
  *          Mark this edit minor, if the user is allowed to do so
  *      EDIT_SUPPRESS_RC
  *          Do not log the change in recentchanges
  *      EDIT_FORCE_BOT
  *          Mark the edit a "bot" edit regardless of user rights
  *      EDIT_DEFER_UPDATES
  *          Defer some of the updates until the end of index.php
  *      EDIT_AUTOSUMMARY
  *          Fill in blank summaries with generated text where possible
  *
  * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
  * If EDIT_UPDATE is specified and the article doesn't exist, the function will an
  * edit-gone-missing error. If EDIT_NEW is specified and the article does exist, an
  * edit-already-exists error will be returned. These two conditions are also possible with
  * auto-detection due to MediaWiki's performance-optimised locking strategy.
  *
  * @param $baseRevId the revision ID this edit was based off, if any
  * @param $user Optional user object, $wgUser will be used if not passed
  *
  * @return Status object. Possible errors:
  *     edit-hook-aborted:       The ArticleSave hook aborted the edit but didn't set the fatal flag of $status
  *     edit-gone-missing:       In update mode, but the article didn't exist
  *     edit-conflict:           In update mode, the article changed unexpectedly
  *     edit-no-change:          Warning that the text was the same as before
  *     edit-already-exists:     In creation mode, but the article already exists
  *
  *  Extensions may define additional errors.
  *
  *  $return->value will contain an associative array with members as follows:
  *     new:                     Boolean indicating if the function attempted to create a new article
  *     revision:                The revision object for the inserted revision, or null
  *
  *  Compatibility note: this function previously returned a boolean value indicating success/failure
  */
 public function doEdit($text, $summary, $flags = 0, $baseRevId = false, $user = null)
 {
     global $wgUser, $wgDBtransactions, $wgUseAutomaticEditSummaries;
     # Low-level sanity check
     if ($this->mTitle->getText() === '') {
         throw new MWException('Something is trying to edit an article with an empty title');
     }
     wfProfileIn(__METHOD__);
     $user = is_null($user) ? $wgUser : $user;
     $status = Status::newGood(array());
     # Load $this->mTitle->getArticleID() and $this->mLatest if it's not already
     $this->loadPageData();
     $flags = $this->checkFlags($flags);
     if (!wfRunHooks('ArticleSave', array(&$this, &$user, &$text, &$summary, $flags & EDIT_MINOR, null, null, &$flags, &$status))) {
         wfDebug(__METHOD__ . ": ArticleSave hook aborted save!\n");
         if ($status->isOK()) {
             $status->fatal('edit-hook-aborted');
         }
         wfProfileOut(__METHOD__);
         return $status;
     }
     # Silently ignore EDIT_MINOR if not allowed
     $isminor = $flags & EDIT_MINOR && $user->isAllowed('minoredit');
     $bot = $flags & EDIT_FORCE_BOT;
     $oldtext = $this->getRawText();
     // current revision
     $oldsize = strlen($oldtext);
     # Provide autosummaries if one is not provided and autosummaries are enabled.
     if ($wgUseAutomaticEditSummaries && $flags & EDIT_AUTOSUMMARY && $summary == '') {
         $summary = $this->getAutosummary($oldtext, $text, $flags);
     }
     $editInfo = $this->prepareTextForEdit($text);
     $text = $editInfo->pst;
     $newsize = strlen($text);
     $dbw = wfGetDB(DB_MASTER);
     $now = wfTimestampNow();
     $this->mTimestamp = $now;
     if ($flags & EDIT_UPDATE) {
         # Update article, but only if changed.
         $status->value['new'] = false;
         # Make sure the revision is either completely inserted or not inserted at all
         if (!$wgDBtransactions) {
             $userAbort = ignore_user_abort(true);
         }
         $changed = strcmp($text, $oldtext) != 0;
         if ($changed) {
             $this->mGoodAdjustment = (int) $this->isCountable($text) - (int) $this->isCountable($oldtext);
             $this->mTotalAdjustment = 0;
             if (!$this->mLatest) {
                 # Article gone missing
                 wfDebug(__METHOD__ . ": EDIT_UPDATE specified but article doesn't exist\n");
                 $status->fatal('edit-gone-missing');
                 wfProfileOut(__METHOD__);
                 return $status;
             }
             $revision = new Revision(array('page' => $this->getId(), 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $text, 'parent_id' => $this->mLatest, 'user' => $user->getId(), 'user_text' => $user->getName()));
             $dbw->begin();
             $revisionId = $revision->insertOn($dbw);
             # Update page
             #
             # Note that we use $this->mLatest instead of fetching a value from the master DB
             # during the course of this function. This makes sure that EditPage can detect
             # edit conflicts reliably, either by $ok here, or by $article->getTimestamp()
             # before this function is called. A previous function used a separate query, this
             # creates a window where concurrent edits can cause an ignored edit conflict.
             $ok = $this->updateRevisionOn($dbw, $revision, $this->mLatest);
             if (!$ok) {
                 /* Belated edit conflict! Run away!! */
                 $status->fatal('edit-conflict');
                 # Delete the invalid revision if the DB is not transactional
                 if (!$wgDBtransactions) {
                     $dbw->delete('revision', array('rev_id' => $revisionId), __METHOD__);
                 }
                 $revisionId = 0;
                 $dbw->rollback();
             } else {
                 global $wgUseRCPatrol;
                 wfRunHooks('NewRevisionFromEditComplete', array($this, $revision, $baseRevId, $user));
                 # Update recentchanges
                 if (!($flags & EDIT_SUPPRESS_RC)) {
                     # Mark as patrolled if the user can do so
                     $patrolled = $wgUseRCPatrol && $this->mTitle->userCan('autopatrol');
                     # Add RC row to the DB
                     $rc = RecentChange::notifyEdit($now, $this->mTitle, $isminor, $user, $summary, $this->mLatest, $this->getTimestamp(), $bot, '', $oldsize, $newsize, $revisionId, $patrolled);
                     # Log auto-patrolled edits
                     if ($patrolled) {
                         PatrolLog::record($rc, true);
                     }
                 }
                 $user->incEditCount();
                 $dbw->commit();
             }
         } else {
             $status->warning('edit-no-change');
             $revision = null;
             // Keep the same revision ID, but do some updates on it
             $revisionId = $this->getRevIdFetched();
             // Update page_touched, this is usually implicit in the page update
             // Other cache updates are done in onArticleEdit()
             $this->mTitle->invalidateCache();
         }
         if (!$wgDBtransactions) {
             ignore_user_abort($userAbort);
         }
         // Now that ignore_user_abort is restored, we can respond to fatal errors
         if (!$status->isOK()) {
             wfProfileOut(__METHOD__);
             return $status;
         }
         # Invalidate cache of this article and all pages using this article
         # as a template. Partly deferred.
         Article::onArticleEdit($this->mTitle);
         # Update links tables, site stats, etc.
         $this->editUpdates($text, $summary, $isminor, $now, $revisionId, $changed);
     } else {
         # Create new article
         $status->value['new'] = true;
         # Set statistics members
         # We work out if it's countable after PST to avoid counter drift
         # when articles are created with {{subst:}}
         $this->mGoodAdjustment = (int) $this->isCountable($text);
         $this->mTotalAdjustment = 1;
         $dbw->begin();
         # Add the page record; stake our claim on this title!
         # This will return false if the article already exists
         $newid = $this->insertOn($dbw);
         if ($newid === false) {
             $dbw->rollback();
             $status->fatal('edit-already-exists');
             wfProfileOut(__METHOD__);
             return $status;
         }
         # Save the revision text...
         $revision = new Revision(array('page' => $newid, 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $text, 'user' => $user->getId(), 'user_text' => $user->getName()));
         $revisionId = $revision->insertOn($dbw);
         $this->mTitle->resetArticleID($newid);
         # Update the page record with revision data
         $this->updateRevisionOn($dbw, $revision, 0);
         wfRunHooks('NewRevisionFromEditComplete', array($this, $revision, false, $user));
         # Update recentchanges
         if (!($flags & EDIT_SUPPRESS_RC)) {
             global $wgUseRCPatrol, $wgUseNPPatrol;
             # Mark as patrolled if the user can do so
             $patrolled = ($wgUseRCPatrol || $wgUseNPPatrol) && $this->mTitle->userCan('autopatrol');
             # Add RC row to the DB
             $rc = RecentChange::notifyNew($now, $this->mTitle, $isminor, $user, $summary, $bot, '', strlen($text), $revisionId, $patrolled);
             # Log auto-patrolled edits
             if ($patrolled) {
                 PatrolLog::record($rc, true);
             }
         }
         $user->incEditCount();
         $dbw->commit();
         # Update links, etc.
         $this->editUpdates($text, $summary, $isminor, $now, $revisionId, true);
         # Clear caches
         Article::onArticleCreate($this->mTitle);
         wfRunHooks('ArticleInsertComplete', array(&$this, &$user, $text, $summary, $flags & EDIT_MINOR, null, null, &$flags, $revision));
     }
     # Do updates right now unless deferral was requested
     if (!($flags & EDIT_DEFER_UPDATES)) {
         wfDoUpdates();
     }
     // Return the new revision (or null) to the caller
     $status->value['revision'] = $revision;
     wfRunHooks('ArticleSaveComplete', array(&$this, &$user, $text, $summary, $flags & EDIT_MINOR, null, null, &$flags, $revision, &$status, $baseRevId));
     wfProfileOut(__METHOD__);
     return $status;
 }
Example #3
0
 /**
  * Article::doEdit()
  *
  * Change an existing article or create a new article. Updates RC and all necessary caches, 
  * optionally via the deferred update array.
  *
  * $wgUser must be set before calling this function.
  *
  * @param string $text New text
  * @param string $summary Edit summary
  * @param integer $flags bitfield:
  *      EDIT_NEW
  *          Article is known or assumed to be non-existent, create a new one
  *      EDIT_UPDATE
  *          Article is known or assumed to be pre-existing, update it
  *      EDIT_MINOR
  *          Mark this edit minor, if the user is allowed to do so
  *      EDIT_SUPPRESS_RC
  *          Do not log the change in recentchanges
  *      EDIT_FORCE_BOT
  *          Mark the edit a "bot" edit regardless of user rights
  *      EDIT_DEFER_UPDATES
  *          Defer some of the updates until the end of index.php
  *      EDIT_AUTOSUMMARY
  *          Fill in blank summaries with generated text where possible
  * 
  * If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected. 
  * If EDIT_UPDATE is specified and the article doesn't exist, the function will return false. If 
  * EDIT_NEW is specified and the article does exist, a duplicate key error will cause an exception
  * to be thrown from the Database. These two conditions are also possible with auto-detection due
  * to MediaWiki's performance-optimised locking strategy.
  *
  * @return bool success
  */
 function doEdit($text, $summary, $flags = 0)
 {
     global $wgUser, $wgDBtransactions;
     wfProfileIn(__METHOD__);
     $good = true;
     if (!($flags & EDIT_NEW) && !($flags & EDIT_UPDATE)) {
         $aid = $this->mTitle->getArticleID(GAID_FOR_UPDATE);
         if ($aid) {
             $flags |= EDIT_UPDATE;
         } else {
             $flags |= EDIT_NEW;
         }
     }
     if (!wfRunHooks('ArticleSave', array(&$this, &$wgUser, &$text, &$summary, $flags & EDIT_MINOR, null, null, &$flags))) {
         wfDebug(__METHOD__ . ": ArticleSave hook aborted save!\n");
         wfProfileOut(__METHOD__);
         return false;
     }
     # Silently ignore EDIT_MINOR if not allowed
     $isminor = $flags & EDIT_MINOR && $wgUser->isAllowed('minoredit');
     $bot = $wgUser->isAllowed('bot') || $flags & EDIT_FORCE_BOT;
     $oldtext = $this->getContent();
     $oldsize = strlen($oldtext);
     # Provide autosummaries if one is not provided.
     if ($flags & EDIT_AUTOSUMMARY && $summary == '') {
         $summary = $this->getAutosummary($oldtext, $text, $flags);
     }
     $text = $this->preSaveTransform($text);
     $newsize = strlen($text);
     $dbw =& wfGetDB(DB_MASTER);
     $now = wfTimestampNow();
     if ($flags & EDIT_UPDATE) {
         # Update article, but only if changed.
         # Make sure the revision is either completely inserted or not inserted at all
         if (!$wgDBtransactions) {
             $userAbort = ignore_user_abort(true);
         }
         $lastRevision = 0;
         $revisionId = 0;
         if (0 != strcmp($text, $oldtext)) {
             $this->mGoodAdjustment = (int) $this->isCountable($text) - (int) $this->isCountable($oldtext);
             $this->mTotalAdjustment = 0;
             $lastRevision = $dbw->selectField('page', 'page_latest', array('page_id' => $this->getId()));
             if (!$lastRevision) {
                 # Article gone missing
                 wfDebug(__METHOD__ . ": EDIT_UPDATE specified but article doesn't exist\n");
                 wfProfileOut(__METHOD__);
                 return false;
             }
             $revision = new Revision(array('page' => $this->getId(), 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $text));
             $dbw->begin();
             $revisionId = $revision->insertOn($dbw);
             # Update page
             $ok = $this->updateRevisionOn($dbw, $revision, $lastRevision);
             if (!$ok) {
                 /* Belated edit conflict! Run away!! */
                 $good = false;
                 $dbw->rollback();
             } else {
                 # Update recentchanges
                 if (!($flags & EDIT_SUPPRESS_RC)) {
                     $rcid = RecentChange::notifyEdit($now, $this->mTitle, $isminor, $wgUser, $summary, $lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize, $revisionId);
                     # Mark as patrolled if the user can do so
                     if ($wgUser->isAllowed('autopatrol')) {
                         RecentChange::markPatrolled($rcid);
                     }
                 }
                 $wgUser->incEditCount();
                 $dbw->commit();
             }
         } else {
             // Keep the same revision ID, but do some updates on it
             $revisionId = $this->getRevIdFetched();
             // Update page_touched, this is usually implicit in the page update
             // Other cache updates are done in onArticleEdit()
             $this->mTitle->invalidateCache();
         }
         if (!$wgDBtransactions) {
             ignore_user_abort($userAbort);
         }
         if ($good) {
             # Invalidate cache of this article and all pages using this article
             # as a template. Partly deferred.
             Article::onArticleEdit($this->mTitle);
             # Update links tables, site stats, etc.
             $changed = strcmp($oldtext, $text) != 0;
             $this->editUpdates($text, $summary, $isminor, $now, $revisionId, $changed);
         }
     } else {
         # Create new article
         # Set statistics members
         # We work out if it's countable after PST to avoid counter drift
         # when articles are created with {{subst:}}
         $this->mGoodAdjustment = (int) $this->isCountable($text);
         $this->mTotalAdjustment = 1;
         $dbw->begin();
         # Add the page record; stake our claim on this title!
         # This will fail with a database query exception if the article already exists
         $newid = $this->insertOn($dbw);
         # Save the revision text...
         $revision = new Revision(array('page' => $newid, 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $text));
         $revisionId = $revision->insertOn($dbw);
         $this->mTitle->resetArticleID($newid);
         # Update the page record with revision data
         $this->updateRevisionOn($dbw, $revision, 0);
         if (!($flags & EDIT_SUPPRESS_RC)) {
             $rcid = RecentChange::notifyNew($now, $this->mTitle, $isminor, $wgUser, $summary, $bot, '', strlen($text), $revisionId);
             # Mark as patrolled if the user can
             if ($wgUser->isAllowed('autopatrol')) {
                 RecentChange::markPatrolled($rcid);
             }
         }
         $wgUser->incEditCount();
         $dbw->commit();
         # Update links, etc.
         $this->editUpdates($text, $summary, $isminor, $now, $revisionId, true);
         # Clear caches
         Article::onArticleCreate($this->mTitle);
         wfRunHooks('ArticleInsertComplete', array(&$this, &$wgUser, $text, $summary, $flags & EDIT_MINOR, null, null, &$flags));
     }
     if ($good && !($flags & EDIT_DEFER_UPDATES)) {
         wfDoUpdates();
     }
     wfRunHooks('ArticleSaveComplete', array(&$this, &$wgUser, $text, $summary, $flags & EDIT_MINOR, null, null, &$flags));
     wfProfileOut(__METHOD__);
     return $good;
 }
Example #4
0
    $restored++;
}
// Was anything restored at all?
if ($restored == 0) {
    print "Nothing was restored\n";
    exit(1);
}
if ($revision) {
    // Attach the latest revision to the page...
    $wasnew = $article->updateIfNewerOn($dbw, $revision, $previousRevId);
    if ($newid || $wasnew) {
        // Update site stats, link tables, etc
        $article->createUpdates($revision);
    }
    if ($newid) {
        Article::onArticleCreate($page);
    } else {
        Article::onArticleEdit($page);
    }
    if ($page->getNamespace() == NS_IMAGE) {
        $update = new HTMLCacheUpdate($page, 'imagelinks');
        $update->doUpdate();
    }
} else {
    // Revision couldn't be created. This is very weird
    print "We got an unknown error\n";
    exit(1);
}
# Now that it's safely stored, take it out of the archive
$dbw->delete('archive', array('ar_namespace' => $page->getNamespace(), 'ar_title' => $page->getDBkey(), $oldones), __METHOD__);
print $page->getPrefixedText();
Example #5
0
 /**
  * This is the meaty bit -- restores archived revisions of the given page
  * to the cur/old tables. If the page currently exists, all revisions will
  * be stuffed into old, otherwise the most recent will go into cur.
  *
  * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
  * @param string $comment
  * @param array $fileVersions
  * @param bool $unsuppress, remove all ar_deleted/fa_deleted restrictions of seletected revs
  *
  * @return mixed number of revisions restored or false on failure
  */
 private function undeleteRevisions($timestamps, $unsuppress = false, $comment = '')
 {
     if (wfReadOnly()) {
         return false;
     }
     $restoreAll = empty($timestamps);
     $dbw = wfGetDB(DB_MASTER);
     # Does this page already exist? We'll have to update it...
     $article = new Article($this->title);
     $options = 'FOR UPDATE';
     // lock page
     $page = $dbw->selectRow('page', array('page_id', 'page_latest'), array('page_namespace' => $this->title->getNamespace(), 'page_title' => $this->title->getDBkey()), __METHOD__, $options);
     if ($page) {
         $makepage = false;
         # Page already exists. Import the history, and if necessary
         # we'll update the latest revision field in the record.
         $newid = 0;
         $pageId = $page->page_id;
         $previousRevId = $page->page_latest;
         # Get the time span of this page
         $previousTimestamp = $dbw->selectField('revision', 'rev_timestamp', array('rev_id' => $previousRevId), __METHOD__);
         if ($previousTimestamp === false) {
             wfDebug(__METHOD__ . ": existing page refers to a page_latest that does not exist\n");
             return 0;
         }
     } else {
         # Have to create a new article...
         $makepage = true;
         $previousRevId = 0;
         $previousTimestamp = 0;
     }
     if ($restoreAll) {
         $oldones = '1 = 1';
         # All revisions...
     } else {
         $oldts = implode(',', array_map(array(&$dbw, 'addQuotes'), array_map(array(&$dbw, 'timestamp'), $timestamps)));
         $oldones = "ar_timestamp IN ( {$oldts} )";
     }
     /**
      * Select each archived revision...
      */
     $result = $dbw->select('archive', array('ar_rev_id', 'ar_text', 'ar_comment', 'ar_user', 'ar_user_text', 'ar_timestamp', 'ar_minor_edit', 'ar_flags', 'ar_text_id', 'ar_deleted', 'ar_page_id', 'ar_len'), array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), __METHOD__, array('ORDER BY' => 'ar_timestamp'));
     $ret = $dbw->resultObject($result);
     $rev_count = $dbw->numRows($result);
     if (!$rev_count) {
         wfDebug(__METHOD__ . ": no revisions to restore\n");
         return false;
         // ???
     }
     $ret->seek($rev_count - 1);
     // move to last
     $row = $ret->fetchObject();
     // get newest archived rev
     $ret->seek(0);
     // move back
     if ($makepage) {
         // Check the state of the newest to-be version...
         if (!$unsuppress && $row->ar_deleted & Revision::DELETED_TEXT) {
             return false;
             // we can't leave the current revision like this!
         }
         // Safe to insert now...
         $newid = $article->insertOn($dbw);
         $pageId = $newid;
     } else {
         // Check if a deleted revision will become the current revision...
         if ($row->ar_timestamp > $previousTimestamp) {
             // Check the state of the newest to-be version...
             if (!$unsuppress && $row->ar_deleted & Revision::DELETED_TEXT) {
                 return false;
                 // we can't leave the current revision like this!
             }
         }
     }
     $revision = null;
     $restored = 0;
     while ($row = $ret->fetchObject()) {
         // Check for key dupes due to shitty archive integrity.
         if ($row->ar_rev_id) {
             $exists = $dbw->selectField('revision', '1', array('rev_id' => $row->ar_rev_id), __METHOD__);
             if ($exists) {
                 continue;
             }
             // don't throw DB errors
         }
         // Insert one revision at a time...maintaining deletion status
         // unless we are specifically removing all restrictions...
         $revision = Revision::newFromArchiveRow($row, array('page' => $pageId, 'deleted' => $unsuppress ? 0 : $row->ar_deleted));
         $revision->insertOn($dbw);
         $restored++;
         wfRunHooks('ArticleRevisionUndeleted', array(&$this->title, $revision, $row->ar_page_id));
     }
     # Now that it's safely stored, take it out of the archive
     $dbw->delete('archive', array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), __METHOD__);
     // Was anything restored at all?
     if ($restored == 0) {
         return 0;
     }
     if ($revision) {
         // Attach the latest revision to the page...
         $wasnew = $article->updateIfNewerOn($dbw, $revision, $previousRevId);
         if ($newid || $wasnew) {
             // Update site stats, link tables, etc
             $article->createUpdates($revision);
         }
         if ($newid) {
             wfRunHooks('ArticleUndelete', array(&$this->title, true, $comment));
             Article::onArticleCreate($this->title);
         } else {
             wfRunHooks('ArticleUndelete', array(&$this->title, false, $comment));
             Article::onArticleEdit($this->title);
         }
         if ($this->title->getNamespace() == NS_FILE) {
             $update = new HTMLCacheUpdate($this->title, 'imagelinks');
             $update->doUpdate();
         }
     } else {
         // Revision couldn't be created. This is very weird
         return self::UNDELETE_UNKNOWNERR;
     }
     return $restored;
 }
Example #6
0
 function importOldRevision()
 {
     $dbw = wfGetDB(DB_MASTER);
     # Sneak a single revision into place
     $user = User::newFromName($this->getUser());
     if ($user) {
         $userId = intval($user->getId());
         $userText = $user->getName();
     } else {
         $userId = 0;
         $userText = $this->getUser();
     }
     // avoid memory leak...?
     $linkCache = LinkCache::singleton();
     $linkCache->clear();
     $article = new Article($this->title);
     $pageId = $article->getId();
     if ($pageId == 0) {
         # must create the page...
         $pageId = $article->insertOn($dbw);
         $created = true;
     } else {
         $created = false;
         $prior = $dbw->selectField('revision', '1', array('rev_page' => $pageId, 'rev_timestamp' => $dbw->timestamp($this->timestamp), 'rev_user_text' => $userText, 'rev_comment' => $this->getComment()), __METHOD__);
         if ($prior) {
             // FIXME: this could fail slightly for multiple matches :P
             wfDebug(__METHOD__ . ": skipping existing revision for [[" . $this->title->getPrefixedText() . "]], timestamp " . $this->timestamp . "\n");
             return false;
         }
     }
     # FIXME: Use original rev_id optionally (better for backups)
     # Insert the row
     $revision = new Revision(array('page' => $pageId, 'text' => $this->getText(), 'comment' => $this->getComment(), 'user' => $userId, 'user_text' => $userText, 'timestamp' => $this->timestamp, 'minor_edit' => $this->minor));
     $revId = $revision->insertOn($dbw);
     $changed = $article->updateIfNewerOn($dbw, $revision);
     # To be on the safe side...
     $tempTitle = $GLOBALS['wgTitle'];
     $GLOBALS['wgTitle'] = $this->title;
     if ($created) {
         wfDebug(__METHOD__ . ": running onArticleCreate\n");
         Article::onArticleCreate($this->title);
         wfDebug(__METHOD__ . ": running create updates\n");
         $article->createUpdates($revision);
     } elseif ($changed) {
         wfDebug(__METHOD__ . ": running onArticleEdit\n");
         Article::onArticleEdit($this->title);
         wfDebug(__METHOD__ . ": running edit updates\n");
         $article->editUpdates($this->getText(), $this->getComment(), $this->minor, $this->timestamp, $revId);
     }
     $GLOBALS['wgTitle'] = $tempTitle;
     return true;
 }
 /**
  * This is the meaty bit -- restores archived revisions of the given page
  * to the cur/old tables. If the page currently exists, all revisions will
  * be stuffed into old, otherwise the most recent will go into cur.
  *
  * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
  * @param string $comment
  * @param array $fileVersions
  *
  * @return mixed number of revisions restored or false on failure
  */
 private function undeleteRevisions($timestamps)
 {
     if (wfReadOnly()) {
         return false;
     }
     $restoreAll = empty($timestamps);
     $dbw = wfGetDB(DB_MASTER);
     # Does this page already exist? We'll have to update it...
     $article = new Article($this->title);
     $options = 'FOR UPDATE';
     $page = $dbw->selectRow('page', array('page_id', 'page_latest'), array('page_namespace' => $this->title->getNamespace(), 'page_title' => $this->title->getDBkey()), __METHOD__, $options);
     if ($page) {
         # Page already exists. Import the history, and if necessary
         # we'll update the latest revision field in the record.
         $newid = 0;
         $pageId = $page->page_id;
         $previousRevId = $page->page_latest;
     } else {
         # Have to create a new article...
         $newid = $article->insertOn($dbw);
         $pageId = $newid;
         $previousRevId = 0;
     }
     if ($restoreAll) {
         $oldones = '1 = 1';
         # All revisions...
     } else {
         $oldts = implode(',', array_map(array(&$dbw, 'addQuotes'), array_map(array(&$dbw, 'timestamp'), $timestamps)));
         $oldones = "ar_timestamp IN ( {$oldts} )";
     }
     /**
      * Restore each revision...
      */
     $result = $dbw->select('archive', array('ar_rev_id', 'ar_text', 'ar_comment', 'ar_user', 'ar_user_text', 'ar_timestamp', 'ar_minor_edit', 'ar_flags', 'ar_text_id', 'ar_page_id', 'ar_len'), array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), __METHOD__, array('ORDER BY' => 'ar_timestamp'));
     if ($dbw->numRows($result) < count($timestamps)) {
         wfDebug(__METHOD__ . ": couldn't find all requested rows\n");
         return false;
     }
     $revision = null;
     $restored = 0;
     while ($row = $dbw->fetchObject($result)) {
         if ($row->ar_text_id) {
             // Revision was deleted in 1.5+; text is in
             // the regular text table, use the reference.
             // Specify null here so the so the text is
             // dereferenced for page length info if needed.
             $revText = null;
         } else {
             // Revision was deleted in 1.4 or earlier.
             // Text is squashed into the archive row, and
             // a new text table entry will be created for it.
             $revText = Revision::getRevisionText($row, 'ar_');
         }
         $revision = new Revision(array('page' => $pageId, 'id' => $row->ar_rev_id, 'text' => $revText, 'comment' => $row->ar_comment, 'user' => $row->ar_user, 'user_text' => $row->ar_user_text, 'timestamp' => $row->ar_timestamp, 'minor_edit' => $row->ar_minor_edit, 'text_id' => $row->ar_text_id, 'len' => $row->ar_len));
         $revision->insertOn($dbw);
         $restored++;
         wfRunHooks('ArticleRevisionUndeleted', array(&$this->title, $revision, $row->ar_page_id));
     }
     // Was anything restored at all?
     if ($restored == 0) {
         return 0;
     }
     if ($revision) {
         // Attach the latest revision to the page...
         $wasnew = $article->updateIfNewerOn($dbw, $revision, $previousRevId);
         if ($newid || $wasnew) {
             // Update site stats, link tables, etc
             $article->createUpdates($revision);
         }
         if ($newid) {
             wfRunHooks('ArticleUndelete', array(&$this->title, true));
             Article::onArticleCreate($this->title);
         } else {
             wfRunHooks('ArticleUndelete', array(&$this->title, false));
             Article::onArticleEdit($this->title);
         }
         if ($this->title->getNamespace() == NS_IMAGE) {
             $update = new HTMLCacheUpdate($this->title, 'imagelinks');
             $update->doUpdate();
         }
     } else {
         // Revision couldn't be created. This is very weird
         return self::UNDELETE_UNKNOWNERR;
     }
     # Now that it's safely stored, take it out of the archive
     $dbw->delete('archive', array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), __METHOD__);
     return $restored;
 }
Example #8
0
 function insertNewArticle($article, $text, $summary, $isminor, $watchthis, $suppressRC = false, $comment = false)
 {
     global $wgOut, $wgUser;
     global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer;
     $fname = 'Article::insertNewArticle';
     wfProfileIn($fname);
     $article->mGoodAdjustment = $article->isCountable($text);
     $article->mTotalAdjustment = 1;
     $ns = $article->mTitle->getNamespace();
     $ttl = $article->mTitle->getDBkey();
     # If this is a comment, add the summary as headline
     if ($comment && $summary != "") {
         $text = "== {$summary} ==\n\n" . $text;
     }
     $text = $article->preSaveTransform($text);
     $isminor = $isminor && $wgUser->isLoggedIn() ? 1 : 0;
     $now = wfTimestampNow();
     $dbw =& wfGetDB(DB_MASTER);
     # Add the page record; stake our claim on this title!
     $newid = $article->insertOn($dbw);
     # Save the revision text...
     $revision = new Revision(array('page' => $newid, 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $text));
     $revisionId = $revision->insertOn($dbw);
     $article->mTitle->resetArticleID($newid);
     # Update the page record with revision data
     $article->updateRevisionOn($dbw, $revision, 0);
     Article::onArticleCreate($article->mTitle);
     if (!$suppressRC) {
         RecentChange::notifyNew($now, $article->mTitle, $isminor, $wgUser, $summary, 'default', '', strlen($text), $revisionId);
     }
     if ($watchthis) {
         #if(!$article->mTitle->userIsWatching()) $this->watch($article);
         if (wfRunHooks('WatchArticle', array(&$wgUser, &$article))) {
             $wgUser->addWatch($article->mTitle);
             $wgUser->saveSettings();
             wfRunHooks('WatchArticleComplete', array(&$wgUser, &$article));
         }
     }
     # The talk page isn't in the regular link tables, so we need to update manually:
     $talkns = $ns ^ 1;
     # talk -> normal; normal -> talk
     $dbw->update('page', array('page_touched' => $dbw->timestamp($now)), array('page_namespace' => $talkns, 'page_title' => $ttl), $fname);
     # standard deferred updates
     $article->editUpdates($text, $summary, $isminor, $now, $revisionId);
     if ($this->mprotect == "yes") {
         # $this->mprotect
         # $this->mprotect_reason
         $id = $article->mTitle->getArticleID();
         $limit = 'sysop';
         $dbw->update('page', array('page_touched' => $dbw->timestamp(), 'page_restrictions' => (string) $limit), array('page_id' => $id), 'Article::protect');
         $restrictions = "move=" . $limit;
         $restrictions .= ":edit=" . $limit;
         if (!$moveonly) {
             #$restrictions .= ":edit=" . $limit;
         }
         if (wfRunHooks('ArticleProtect', array(&$article, &$wgUser, $limit == 'sysop', $this->mprotect_reason, $moveonly))) {
             $dbw =& wfGetDB(DB_MASTER);
             $dbw->update('page', array('page_touched' => $dbw->timestamp(), 'page_restrictions' => $restrictions), array('page_id' => $id), 'Article::protect');
             wfRunHooks('ArticleProtectComplete', array(&$article, &$wgUser, $limit == 'sysop', $this->mprotect_reason, $moveonly));
             $log = new LogPage('protect');
             $log->addEntry('protect', $article->mTitle, $this->mprotect_reason);
         }
     }
     # AWC - Edit
     # Dont want ot redirect...
     #$oldid = 0; # new article
     #$article->showArticle( $text, wfMsg( 'newarticle' ), false, $isminor, $now, $summary, $oldid );
     wfProfileOut($fname);
 }
 /**
  * Duplicate one page to another, including full histories
  * Does some basic error-catching, but not as much as the code above [should]
  *
  * @param $source Title to duplicate
  * @param $dest Title to save to
  * @return bool
  */
 private function duplicate(&$source, &$dest)
 {
     global $wgUser, $wgBot;
     if (!$source->exists() || $dest->exists()) {
         return false;
     }
     # Source doesn't exist, or destination does
     $dbw = wfGetDB(DB_MASTER);
     $dbw->begin();
     $sid = $source->getArticleId();
     # Create an article representing the destination page and save it
     $destArticle = new Article($dest);
     $aid = $destArticle->insertOn($dbw);
     # Perform the revision duplication
     # An INSERT...SELECT here seems to f**k things up
     $res = $dbw->select('revision', '*', array('rev_page' => $sid), __METHOD__);
     if ($res && $dbw->numRows($res) > 0) {
         while ($row = $dbw->fetchObject($res)) {
             $values['rev_page'] = $aid;
             $values['rev_text_id'] = $row->rev_text_id;
             $values['rev_comment'] = $row->rev_comment;
             $values['rev_user'] = $row->rev_user;
             $values['rev_user_text'] = $row->rev_user_text;
             $values['rev_timestamp'] = $row->rev_timestamp;
             $values['rev_minor_edit'] = $row->rev_minor_edit;
             $values['rev_deleted'] = $row->rev_deleted;
             $dbw->insert('revision', $values, __METHOD__);
         }
         $dbw->freeResult($res);
     }
     # Update page record
     $latest = $dbw->selectField('revision', 'MAX(rev_id)', array('rev_page' => $aid), __METHOD__);
     $rev = Revision::newFromId($latest);
     $destArticle->updateRevisionOn($dbw, $rev);
     # Commit transaction
     $dbw->commit();
     # Create a null revision with an explanation; do cache clearances, etc.
     $dbw->begin();
     $comment = wfMsgForContent('duplicator-summary', $source->getPrefixedText());
     $nr = Revision::newNullRevision($dbw, $aid, $comment, true);
     $nid = $nr->insertOn($dbw);
     $destArticle->updateRevisionOn($dbw, $nr);
     $destArticle->createUpdates($nr);
     Article::onArticleCreate($dest);
     $bot = $wgUser->isAllowed('bot');
     RecentChange::notifyNew($nr->getTimestamp(), $dest, true, $wgUser, $comment, $bot);
     $dest->invalidateCache();
     $dbw->commit();
     return true;
 }
Example #10
0
 /**
  * Theoretically we could defer these whole insert and update
  * functions for after display, but that's taking a big leap
  * of faith, and we want to be able to report database
  * errors at some point.
  * @private
  */
 function insertNewArticle($text, $summary, $isminor, $watchthis, $suppressRC = false, $comment = false)
 {
     global $wgOut, $wgUser;
     global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer;
     $fname = 'Article::insertNewArticle';
     wfProfileIn($fname);
     $this->mGoodAdjustment = $this->isCountable($text);
     $this->mTotalAdjustment = 1;
     $ns = $this->mTitle->getNamespace();
     $ttl = $this->mTitle->getDBkey();
     # If this is a comment, add the summary as headline
     if ($comment && $summary != "") {
         $text = "== {$summary} ==\n\n" . $text;
     }
     $text = $this->preSaveTransform($text);
     $isminor = $isminor && $wgUser->isLoggedIn() ? 1 : 0;
     $now = wfTimestampNow();
     $dbw =& wfGetDB(DB_MASTER);
     # Add the page record; stake our claim on this title!
     $newid = $this->insertOn($dbw);
     # Save the revision text...
     $revision = new Revision(array('page' => $newid, 'comment' => $summary, 'minor_edit' => $isminor, 'text' => $text));
     $revisionId = $revision->insertOn($dbw);
     $this->mTitle->resetArticleID($newid);
     # Update the page record with revision data
     $this->updateRevisionOn($dbw, $revision, 0);
     Article::onArticleCreate($this->mTitle);
     if ($watchthis) {
         if (!$this->mTitle->userIsWatching()) {
             $this->watch();
         }
     } else {
         if ($this->mTitle->userIsWatching()) {
             $this->unwatch();
         }
     }
     # The talk page isn't in the regular link tables, so we need to update manually:
     $talkns = $ns ^ 1;
     # talk -> normal; normal -> talk
     $dbw->update('page', array('page_touched' => $dbw->timestamp($now)), array('page_namespace' => $talkns, 'page_title' => $ttl), $fname);
     # standard deferred updates
     $this->editUpdates($text);
     # TG PATCH. Moved from some lines above to here
     # Is important to call RecentChange::notifyNew _after_ editUpdates
     # because a user_newtalk flag and addwatch might be committed in editUpdates
     # which triggers the sending of an Enotif in RecentChange::notifyNew just right now
     if (!$suppressRC) {
         RecentChange::notifyNew($now, $this->mTitle, $isminor, $wgUser, $summary, 'default', '', strlen($text), $revisionId);
     }
     $oldid = 0;
     # new article
     $this->showArticle($text, wfMsg('newarticle'), false);
     wfProfileOut($fname);
 }
Example #11
0
 /**
  * Create a redirect; fails if the title already exists; does
  * not notify RC
  *
  * @param Title $dest the destination of the redirect
  * @param string $comment the comment string describing the move
  * @return bool true on success
  * @access public
  */
 function createRedirect($dest, $comment)
 {
     if ($this->getArticleID()) {
         return false;
     }
     $fname = 'Title::createRedirect';
     $dbw =& wfGetDB(DB_MASTER);
     $article = new Article($this);
     $newid = $article->insertOn($dbw);
     $revision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => "#REDIRECT [[" . $dest->getPrefixedText() . "]]\n"));
     $revisionId = $revision->insertOn($dbw);
     $article->updateRevisionOn($dbw, $revision, 0);
     # Link table
     $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $dest->getNamespace(), 'pl_title' => $dest->getDbKey()), $fname);
     Article::onArticleCreate($this);
     return true;
 }
 /**
  * This is the meaty bit -- restores archived revisions of the given page
  * to the cur/old tables. If the page currently exists, all revisions will
  * be stuffed into old, otherwise the most recent will go into cur.
  * The deletion log will be updated with an undeletion notice.
  *
  * Returns true on success.
  *
  * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
  * @return bool
  */
 function undelete($timestamps)
 {
     global $wgUser, $wgOut, $wgLang, $wgDeferredUpdateList;
     global $wgUseSquid, $wgInternalServer, $wgLinkCache;
     global $wgDBtype;
     $fname = "doUndeleteArticle";
     $restoreAll = empty($timestamps);
     $restoreRevisions = count($timestamps);
     $dbw =& wfGetDB(DB_MASTER);
     extract($dbw->tableNames('page', 'archive'));
     # Does this page already exist? We'll have to update it...
     $article = new Article($this->title);
     $options = $wgDBtype == 'PostgreSQL' ? '' : 'FOR UPDATE';
     $page = $dbw->selectRow('page', array('page_id', 'page_latest'), array('page_namespace' => $this->title->getNamespace(), 'page_title' => $this->title->getDBkey()), $fname, $options);
     if ($page) {
         # Page already exists. Import the history, and if necessary
         # we'll update the latest revision field in the record.
         $newid = 0;
         $pageId = $page->page_id;
         $previousRevId = $page->page_latest;
         $previousTimestamp = $page->rev_timestamp;
     } else {
         # Have to create a new article...
         $newid = $article->insertOn($dbw);
         $pageId = $newid;
         $previousRevId = 0;
         $previousTimestamp = 0;
     }
     if ($restoreAll) {
         $oldones = '1';
         # All revisions...
     } else {
         $oldts = implode(',', array_map(array(&$dbw, 'addQuotes'), array_map(array(&$dbw, 'timestamp'), $timestamps)));
         $oldones = "ar_timestamp IN ( {$oldts} )";
     }
     /**
      * Restore each revision...
      */
     $result = $dbw->select('archive', array('ar_rev_id', 'ar_text', 'ar_comment', 'ar_user', 'ar_user_text', 'ar_timestamp', 'ar_minor_edit', 'ar_flags', 'ar_text_id'), array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), $fname, array('ORDER BY' => 'ar_timestamp'));
     $revision = null;
     while ($row = $dbw->fetchObject($result)) {
         $revision = new Revision(array('page' => $pageId, 'id' => $row->ar_rev_id, 'text' => Revision::getRevisionText($row, 'ar_'), 'comment' => $row->ar_comment, 'user' => $row->ar_user, 'user_text' => $row->ar_user_text, 'timestamp' => $row->ar_timestamp, 'minor_edit' => $row->ar_minor_edit, 'text_id' => $row->ar_text_id));
         $revision->insertOn($dbw);
     }
     if ($revision) {
         # FIXME: Update latest if newer as well...
         if ($newid) {
             # FIXME: update article count if changed...
             $article->updateRevisionOn($dbw, $revision, $previousRevId);
             # Finally, clean up the link tables
             $wgLinkCache = new LinkCache();
             # Select for update
             $wgLinkCache->forUpdate(true);
             # Create a dummy OutputPage to update the outgoing links
             $dummyOut = new OutputPage();
             $dummyOut->addWikiText($revision->getText());
             $u = new LinksUpdate($newid, $this->title->getPrefixedDBkey());
             array_push($wgDeferredUpdateList, $u);
             #TODO: SearchUpdate, etc.
         }
         if ($newid) {
             Article::onArticleCreate($this->title);
         } else {
             Article::onArticleEdit($this->title);
         }
     } else {
         # Something went terribly worong!
     }
     # Now that it's safely stored, take it out of the archive
     $dbw->delete('archive', array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), $fname);
     # Touch the log!
     $log = new LogPage('delete');
     if ($restoreAll) {
         $reason = '';
     } else {
         $reason = wfMsgForContent('undeletedrevisions', $restoreRevisions);
     }
     $log->addEntry('restore', $this->title, $reason);
     return true;
 }
Example #13
0
 /**
  * Move page to non-existing title.
  * @param &$nt \type{Title} the new Title
  * @param $reason \type{\string} The reason for the move
  * @param $createRedirect \type{\bool} Whether to create a redirect from the old title to the new title
  *  Ignored if the user doesn't have the suppressredirect right
  */
 private function moveToNewTitle(&$nt, $reason = '', $createRedirect = true)
 {
     global $wgUseSquid, $wgUser;
     $fname = 'MovePageForm::moveToNewTitle';
     $comment = wfMsgForContent('1movedto2', $this->getPrefixedText(), $nt->getPrefixedText());
     if ($reason) {
         $comment .= wfMsgExt('colon-separator', array('escapenoentities', 'content'));
         $comment .= $reason;
     }
     $newid = $nt->getArticleID();
     $oldid = $this->getArticleID();
     $latest = $this->getLatestRevId();
     $dbw = wfGetDB(DB_MASTER);
     $now = $dbw->timestamp();
     # Save a null revision in the page's history notifying of the move
     $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true);
     $nullRevId = $nullRevision->insertOn($dbw);
     $article = new Article($this);
     wfRunHooks('NewRevisionFromEditComplete', array($article, $nullRevision, $latest, $wgUser));
     # Rename page entry
     $dbw->update('page', array('page_touched' => $now, 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), $fname);
     $nt->resetArticleID($oldid);
     if ($createRedirect || !$wgUser->isAllowed('suppressredirect')) {
         # Insert redirect
         $mwRedir = MagicWord::get('redirect');
         $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n";
         $redirectArticle = new Article($this);
         $newid = $redirectArticle->insertOn($dbw);
         $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText));
         $redirectRevision->insertOn($dbw);
         $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0);
         wfRunHooks('NewRevisionFromEditComplete', array($redirectArticle, $redirectRevision, false, $wgUser));
         # Record the just-created redirect's linking to the page
         $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDBkey()), $fname);
         $redirectSuppressed = false;
     } else {
         $this->resetArticleID(0);
         $redirectSuppressed = true;
     }
     # Move an image if this is a file
     if ($this->getNamespace() == NS_FILE) {
         $file = wfLocalFile($this);
         if ($file->exists()) {
             $status = $file->move($nt);
             if (!$status->isOk()) {
                 $dbw->rollback();
                 return $status->getErrorsArray();
             }
         }
     }
     # Log the move
     $log = new LogPage('move');
     $log->addEntry('move', $this, $reason, array(1 => $nt->getPrefixedText(), 2 => $redirectSuppressed));
     # Purge caches as per article creation
     Article::onArticleCreate($nt);
     # Purge old title from squid
     # The new title, and links to the new title, are purged in Article::onArticleCreate()
     $this->purgeSquid();
 }
Example #14
0
 /**
  * This is the meaty bit -- restores archived revisions of the given page
  * to the cur/old tables. If the page currently exists, all revisions will
  * be stuffed into old, otherwise the most recent will go into cur.
  *
  * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
  * @param string $comment
  * @param array $fileVersions
  *
  * @return int number of revisions restored
  */
 private function undeleteRevisions($timestamps)
 {
     global $wgParser, $wgDBtype;
     $restoreAll = empty($timestamps);
     $dbw =& wfGetDB(DB_MASTER);
     extract($dbw->tableNames('page', 'archive'));
     # Does this page already exist? We'll have to update it...
     $article = new Article($this->title);
     $options = $wgDBtype == 'postgres' ? '' : 'FOR UPDATE';
     $page = $dbw->selectRow('page', array('page_id', 'page_latest'), array('page_namespace' => $this->title->getNamespace(), 'page_title' => $this->title->getDBkey()), __METHOD__, $options);
     if ($page) {
         # Page already exists. Import the history, and if necessary
         # we'll update the latest revision field in the record.
         $newid = 0;
         $pageId = $page->page_id;
         $previousRevId = $page->page_latest;
     } else {
         # Have to create a new article...
         $newid = $article->insertOn($dbw);
         $pageId = $newid;
         $previousRevId = 0;
     }
     if ($restoreAll) {
         $oldones = '1 = 1';
         # All revisions...
     } else {
         $oldts = implode(',', array_map(array(&$dbw, 'addQuotes'), array_map(array(&$dbw, 'timestamp'), $timestamps)));
         $oldones = "ar_timestamp IN ( {$oldts} )";
     }
     /**
      * Restore each revision...
      */
     $result = $dbw->select('archive', array('ar_rev_id', 'ar_text', 'ar_comment', 'ar_user', 'ar_user_text', 'ar_timestamp', 'ar_minor_edit', 'ar_flags', 'ar_text_id'), array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), __METHOD__, array('ORDER BY' => 'ar_timestamp'));
     if ($dbw->numRows($result) < count($timestamps)) {
         wfDebug(__METHOD__ . ": couldn't find all requested rows\n");
         return false;
     }
     $revision = null;
     $newRevId = $previousRevId;
     $restored = 0;
     while ($row = $dbw->fetchObject($result)) {
         if ($row->ar_text_id) {
             // Revision was deleted in 1.5+; text is in
             // the regular text table, use the reference.
             // Specify null here so the so the text is
             // dereferenced for page length info if needed.
             $revText = null;
         } else {
             // Revision was deleted in 1.4 or earlier.
             // Text is squashed into the archive row, and
             // a new text table entry will be created for it.
             $revText = Revision::getRevisionText($row, 'ar_');
         }
         $revision = new Revision(array('page' => $pageId, 'id' => $row->ar_rev_id, 'text' => $revText, 'comment' => $row->ar_comment, 'user' => $row->ar_user, 'user_text' => $row->ar_user_text, 'timestamp' => $row->ar_timestamp, 'minor_edit' => $row->ar_minor_edit, 'text_id' => $row->ar_text_id));
         $newRevId = $revision->insertOn($dbw);
         $restored++;
     }
     if ($revision) {
         # FIXME: Update latest if newer as well...
         if ($newid) {
             // Attach the latest revision to the page...
             $article->updateRevisionOn($dbw, $revision, $previousRevId);
             // Update site stats, link tables, etc
             $article->createUpdates($revision);
         }
         if ($newid) {
             Article::onArticleCreate($this->title);
         } else {
             Article::onArticleEdit($this->title);
         }
     } else {
         # Something went terribly wrong!
     }
     # Now that it's safely stored, take it out of the archive
     $dbw->delete('archive', array('ar_namespace' => $this->title->getNamespace(), 'ar_title' => $this->title->getDBkey(), $oldones), __METHOD__);
     return $restored;
 }
Example #15
0
 /**
  * Move page to non-existing title.
  *
  * @param $nt \type{Title} the new Title
  * @param $reason \type{\string} The reason for the move
  * @param $createRedirect \type{\bool} Whether to create a redirect from the old title to the new title
  *  Ignored if the user doesn't have the suppressredirect right
  */
 private function moveToNewTitle(&$nt, $reason = '', $createRedirect = true)
 {
     global $wgUser, $wgContLang;
     $comment = wfMsgForContent('1movedto2', $this->getPrefixedText(), $nt->getPrefixedText());
     if ($reason) {
         $comment .= wfMsgExt('colon-separator', array('escapenoentities', 'content'));
         $comment .= $reason;
     }
     # Truncate for whole multibyte characters. +5 bytes for ellipsis
     $comment = $wgContLang->truncate($comment, 250);
     $oldid = $this->getArticleID();
     $latest = $this->getLatestRevId();
     $dbw = wfGetDB(DB_MASTER);
     $now = $dbw->timestamp();
     # Save a null revision in the page's history notifying of the move
     $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true);
     if (!is_object($nullRevision)) {
         throw new MWException('No valid null revision produced in ' . __METHOD__);
     }
     $nullRevId = $nullRevision->insertOn($dbw);
     $article = new Article($this);
     wfRunHooks('NewRevisionFromEditComplete', array($article, $nullRevision, $latest, $wgUser));
     # Rename page entry
     $dbw->update('page', array('page_touched' => $now, 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), __METHOD__);
     $nt->resetArticleID($oldid);
     if ($createRedirect || !$wgUser->isAllowed('suppressredirect')) {
         # Insert redirect
         $mwRedir = MagicWord::get('redirect');
         $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n";
         $redirectArticle = new Article($this);
         $newid = $redirectArticle->insertOn($dbw);
         $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText));
         $redirectRevision->insertOn($dbw);
         $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0);
         wfRunHooks('NewRevisionFromEditComplete', array($redirectArticle, $redirectRevision, false, $wgUser));
         # Record the just-created redirect's linking to the page
         $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDBkey()), __METHOD__);
         $redirectSuppressed = false;
     } else {
         $this->resetArticleID(0);
         $redirectSuppressed = true;
     }
     # Log the move
     $log = new LogPage('move');
     $log->addEntry('move', $this, $reason, array(1 => $nt->getPrefixedText(), 2 => $redirectSuppressed));
     # Purge caches as per article creation
     Article::onArticleCreate($nt);
     # Purge old title from squid
     # The new title, and links to the new title, are purged in Article::onArticleCreate()
     $this->purgeSquid();
 }
Example #16
0
 /**
  * Move page to non-existing title.
  * @param Title &$nt the new Title
  */
 private function moveToNewTitle(&$nt, $reason = '')
 {
     global $wgUseSquid;
     $fname = 'MovePageForm::moveToNewTitle';
     $comment = wfMsgForContent('1movedto2', $this->getPrefixedText(), $nt->getPrefixedText());
     if ($reason) {
         $comment .= ": {$reason}";
     }
     $newid = $nt->getArticleID();
     $oldid = $this->getArticleID();
     $dbw = wfGetDB(DB_MASTER);
     $now = $dbw->timestamp();
     $linkCache =& LinkCache::singleton();
     # Save a null revision in the page's history notifying of the move
     $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true);
     $nullRevId = $nullRevision->insertOn($dbw);
     # Rename cur entry
     $dbw->update('page', array('page_touched' => $now, 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), $fname);
     $linkCache->clearLink($nt->getPrefixedDBkey());
     # Insert redirect
     $mwRedir = MagicWord::get('redirect');
     $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n";
     $redirectArticle = new Article($this);
     $newid = $redirectArticle->insertOn($dbw);
     $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText));
     $redirectRevision->insertOn($dbw);
     $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0);
     $linkCache->clearLink($this->getPrefixedDBkey());
     # Log the move
     $log = new LogPage('move');
     $log->addEntry('move', $this, $reason, array(1 => $nt->getPrefixedText()));
     # Purge caches as per article creation
     Article::onArticleCreate($nt);
     # Record the just-created redirect's linking to the page
     $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDBkey()), $fname);
     # Purge old title from squid
     # The new title, and links to the new title, are purged in Article::onArticleCreate()
     $this->purgeSquid();
 }
 function importOldRevision()
 {
     $dbw = wfGetDB(DB_MASTER);
     # Sneak a single revision into place
     $user = User::newFromName($this->getUser());
     if ($user) {
         $userId = intval($user->getId());
         $userText = $user->getName();
     } else {
         $userId = 0;
         $userText = $this->getUser();
     }
     // avoid memory leak...?
     $linkCache =& LinkCache::singleton();
     $linkCache->clear();
     $article = new Article($this->title);
     $pageId = $article->getId();
     if ($pageId == 0) {
         # must create the page...
         $pageId = $article->insertOn($dbw);
         $created = true;
     } else {
         $created = false;
         $prior = Revision::loadFromTimestamp($dbw, $this->title, $this->timestamp);
         if (!is_null($prior)) {
             // FIXME: this could fail slightly for multiple matches :P
             wfDebug(__METHOD__ . ": skipping existing revision for [[" . $this->title->getPrefixedText() . "]], timestamp " . $this->timestamp . "\n");
             return false;
         }
     }
     # FIXME: Use original rev_id optionally
     # FIXME: blah blah blah
     #if( $numrows > 0 ) {
     #	return wfMsg( "importhistoryconflict" );
     #}
     # Insert the row
     $revision = new Revision(array('page' => $pageId, 'text' => $this->getText(), 'comment' => $this->getComment(), 'user' => $userId, 'user_text' => $userText, 'timestamp' => $this->timestamp, 'minor_edit' => $this->minor));
     $revId = $revision->insertOn($dbw);
     $changed = $article->updateIfNewerOn($dbw, $revision);
     if ($created) {
         wfDebug(__METHOD__ . ": running onArticleCreate\n");
         Article::onArticleCreate($this->title);
         wfDebug(__METHOD__ . ": running create updates\n");
         $article->createUpdates($revision);
     } elseif ($changed) {
         wfDebug(__METHOD__ . ": running onArticleEdit\n");
         Article::onArticleEdit($this->title);
         wfDebug(__METHOD__ . ": running edit updates\n");
         $article->editUpdates($this->getText(), $this->getComment(), $this->minor, $this->timestamp, $revId);
     }
     return true;
 }
Example #18
0
 function importOldRevision()
 {
     $fname = "WikiImporter::importOldRevision";
     $dbw =& wfGetDB(DB_MASTER);
     # Sneak a single revision into place
     $user = User::newFromName($this->getUser());
     if ($user) {
         $userId = intval($user->getId());
         $userText = $user->getName();
     } else {
         $userId = 0;
         $userText = $this->getUser();
     }
     // avoid memory leak...?
     $linkCache =& LinkCache::singleton();
     $linkCache->clear();
     $article = new Article($this->title);
     $pageId = $article->getId();
     if ($pageId == 0) {
         # must create the page...
         $pageId = $article->insertOn($dbw);
         $created = true;
     } else {
         $created = false;
     }
     # FIXME: Check for exact conflicts
     # FIXME: Use original rev_id optionally
     # FIXME: blah blah blah
     #if( $numrows > 0 ) {
     #	return wfMsg( "importhistoryconflict" );
     #}
     # Insert the row
     $revision = new Revision(array('page' => $pageId, 'text' => $this->getText(), 'comment' => $this->getComment(), 'user' => $userId, 'user_text' => $userText, 'timestamp' => $this->timestamp, 'minor_edit' => $this->minor));
     $revId = $revision->insertOn($dbw);
     $changed = $article->updateIfNewerOn($dbw, $revision);
     if ($created) {
         wfDebug(__METHOD__ . ": running onArticleCreate\n");
         Article::onArticleCreate($this->title);
     } else {
         if ($changed) {
             wfDebug(__METHOD__ . ": running onArticleEdit\n");
             Article::onArticleEdit($this->title);
         }
     }
     if ($created || $changed) {
         wfDebug(__METHOD__ . ": running edit updates\n");
         $article->editUpdates($this->getText(), $this->getComment(), $this->minor, $this->timestamp, $revId);
     }
     return true;
 }
function FrontBackForcedArticleSaveCompleteHook(&$article, &$user, $text, $summary, $minoredit, $watchthis, $sectionanchor, &$flags, $revision, &$status, $baseRevId)
{
    global $wgLang;
    $frontMsg = wfMsgForContent('frontbackforced-front');
    $backMsg = wfMsgForContent('frontbackforced-back');
    $forcedMsg = wfMsgForContent('frontbackforced-forced');
    $myTitle = $article->getTitle()->getPrefixedDBkey();
    if (substr($myTitle, strlen($myTitle) - strlen($frontMsg), strlen($frontMsg)) == $frontMsg) {
        $frontBaseTitle = Title::newFromDBkey(substr($myTitle, 0, strlen($myTitle) - strlen($frontMsg)));
        $frontBaseTitle->invalidateCache();
        Article::onArticleCreate($frontBaseTitle);
        Article::onArticleEdit($frontBaseTitle);
    }
    if (substr($myTitle, strlen($myTitle) - strlen($backMsg), strlen($backMsg)) == $backMsg) {
        $backBaseTitle = Title::newFromDBkey(substr($myTitle, 0, strlen($myTitle) - strlen($backMsg)));
        $backBaseTitle->invalidateCache();
        Article::onArticleCreate($backBaseTitle);
        Article::onArticleEdit($backBaseTitle);
    }
    if (substr($myTitle, strlen($myTitle) - strlen($forcedMsg), strlen($forcedMsg)) == $forcedMsg) {
        $forcedBaseTitle = Title::newFromDBkey(substr($myTitle, 0, strlen($myTitle) - strlen($forcedMsg)));
        $forcedBaseTitle->invalidateCache();
        Article::onArticleCreate($forcedBaseTitle);
        Article::onArticleEdit($forcedBaseTitle);
    }
    return true;
}