protected function makeRevision($props = null) { if ($props === null) { $props = []; } if (!isset($props['content']) && !isset($props['text'])) { $props['text'] = 'Lorem Ipsum'; } if (!isset($props['comment'])) { $props['comment'] = 'just a test'; } if (!isset($props['page'])) { $props['page'] = $this->the_page->getId(); } $rev = new Revision($props); $dbw = wfGetDB(DB_MASTER); $rev->insertOn($dbw); return $rev; }
/** * 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(); }
$u->saveSettings(); $u->addGroup("sysop"); $u->addGroup("bureaucrat"); print "<li>Created sysop account <tt>" . htmlspecialchars($conf->SysopName) . "</tt>.</li>\n"; } else { print "<li>Could not create user - already exists!</li>\n"; } } } else { print "<li>Skipped sysop account creation, no name given.</li>\n"; } $titleobj = Title::newFromText(wfMsgNoDB("mainpage")); $article = new Article($titleobj); $newid = $article->insertOn($wgDatabase); $revision = new Revision(array('page' => $newid, 'text' => wfMsg('mainpagetext') . "\n\n" . wfMsgNoTrans('mainpagedocfooter'), 'comment' => '', 'user' => 0, 'user_text' => 'MediaWiki default')); $revid = $revision->insertOn($wgDatabase); $article->updateRevisionOn($wgDatabase, $revision); } /* Write out the config file now that all is well */ print "<li style=\"list-style: none\">\n"; print "<p>Creating LocalSettings.php...</p>\n\n"; $localSettings = "<" . "?php{$endl}{$local}"; // Fix up a common line-ending problem (due to CVS on Windows) $localSettings = str_replace("\r\n", "\n", $localSettings); $f = fopen("LocalSettings.php", 'xt'); if ($f == false) { print "</li>\n"; dieout("<p>Couldn't write out LocalSettings.php. Check that the directory permissions are correct and that there isn't already a file of that name here...</p>\n" . "<p>Here's the file that would have been written, try to paste it into place manually:</p>\n" . "<pre>\n" . htmlspecialchars($localSettings) . "</pre>\n"); } if (fwrite($f, $localSettings)) { fclose($f);
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 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); }
function merge() { global $wgOut, $wgUser; # Get the titles directly from the IDs, in case the target page params # were spoofed. The queries are done based on the IDs, so it's best to # keep it consistent... $targetTitle = Title::newFromID($this->mTargetID); $destTitle = Title::newFromID($this->mDestID); if (is_null($targetTitle) || is_null($destTitle)) { return false; } // validate these if ($targetTitle->getArticleId() == $destTitle->getArticleId()) { return false; } # Verify that this timestamp is valid # Must be older than the destination page $dbw = wfGetDB(DB_MASTER); # Get timestamp into DB format $this->mTimestamp = $this->mTimestamp ? $dbw->timestamp($this->mTimestamp) : ''; # Max timestamp should be min of destination page $maxtimestamp = $dbw->selectField('revision', 'MIN(rev_timestamp)', array('rev_page' => $this->mDestID), __METHOD__); # Destination page must exist with revisions if (!$maxtimestamp) { $wgOut->addWikiMsg('mergehistory-fail'); return false; } # Get the latest timestamp of the source $lasttimestamp = $dbw->selectField(array('page', 'revision'), 'rev_timestamp', array('page_id' => $this->mTargetID, 'page_latest = rev_id'), __METHOD__); # $this->mTimestamp must be older than $maxtimestamp if ($this->mTimestamp >= $maxtimestamp) { $wgOut->addWikiMsg('mergehistory-fail'); return false; } # Update the revisions if ($this->mTimestamp) { $timewhere = "rev_timestamp <= {$this->mTimestamp}"; $TimestampLimit = wfTimestamp(TS_MW, $this->mTimestamp); } else { $timewhere = "rev_timestamp <= {$maxtimestamp}"; $TimestampLimit = wfTimestamp(TS_MW, $lasttimestamp); } # Do the moving... $dbw->update('revision', array('rev_page' => $this->mDestID), array('rev_page' => $this->mTargetID, $timewhere), __METHOD__); $count = $dbw->affectedRows(); # Make the source page a redirect if no revisions are left $haveRevisions = $dbw->selectField('revision', 'rev_timestamp', array('rev_page' => $this->mTargetID), __METHOD__, array('FOR UPDATE')); if (!$haveRevisions) { if ($this->mComment) { $comment = wfMsgForContent('mergehistory-comment', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $this->mComment); } else { $comment = wfMsgForContent('mergehistory-autocomment', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText()); } $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $destTitle->getPrefixedText() . "]]\n"; $redirectArticle = new Article($targetTitle); $redirectRevision = new Revision(array('page' => $this->mTargetID, 'comment' => $comment, 'text' => $redirectText)); $redirectRevision->insertOn($dbw); $redirectArticle->updateRevisionOn($dbw, $redirectRevision); # 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' => $this->mDestID), __METHOD__); $dbw->insert('pagelinks', array('pl_from' => $this->mDestID, 'pl_namespace' => $destTitle->getNamespace(), 'pl_title' => $destTitle->getDBkey()), __METHOD__); } else { $targetTitle->invalidateCache(); // update histories } $destTitle->invalidateCache(); // update histories # Check if this did anything if (!$count) { $wgOut->addWikiMsg('mergehistory-fail'); return false; } # Update our logs $log = new LogPage('merge'); $log->addEntry('merge', $targetTitle, $this->mComment, array($destTitle->getPrefixedText(), $TimestampLimit)); $wgOut->addHTML(wfMsgExt('mergehistory-success', array('parseinline'), $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $count)); wfRunHooks('ArticleMergeComplete', array($targetTitle, $destTitle)); 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 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; }
/** * 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(); }
/** * Actually attempt the history move * * @todo if all versions of page A are moved to B and then a user * tries to do a reverse-merge via the "unmerge" log link, then page * A will still be a redirect (as it was after the original merge), * though it will have the old revisions back from before (as expected). * The user may have to "undo" the redirect manually to finish the "unmerge". * Maybe this should delete redirects at the source page of merges? * * @param User $user * @param string $reason * @return Status status of the history merge */ public function merge(User $user, $reason = '') { $status = new Status(); // Check validity and permissions required for merge $validCheck = $this->isValidMerge(); // Check this first to check for null pages if (!$validCheck->isOK()) { return $validCheck; } $permCheck = $this->checkPermissions($user, $reason); if (!$permCheck->isOK()) { return $permCheck; } $this->dbw->update('revision', array('rev_page' => $this->dest->getArticleID()), array('rev_page' => $this->source->getArticleID(), $this->timeWhere), __METHOD__); // Check if this did anything $this->revisionsMerged = $this->dbw->affectedRows(); if ($this->revisionsMerged < 1) { $status->fatal('mergehistory-fail-no-change'); return $status; } // Make the source page a redirect if no revisions are left $haveRevisions = $this->dbw->selectField('revision', 'rev_timestamp', array('rev_page' => $this->source->getArticleID()), __METHOD__, array('FOR UPDATE')); if (!$haveRevisions) { if ($reason) { $reason = wfMessage('mergehistory-comment', $this->source->getPrefixedText(), $this->dest->getPrefixedText(), $reason)->inContentLanguage()->text(); } else { $reason = wfMessage('mergehistory-autocomment', $this->source->getPrefixedText(), $this->dest->getPrefixedText())->inContentLanguage()->text(); } $contentHandler = ContentHandler::getForTitle($this->source); $redirectContent = $contentHandler->makeRedirectContent($this->dest, wfMessage('mergehistory-redirect-text')->inContentLanguage()->plain()); if ($redirectContent) { $redirectPage = WikiPage::factory($this->source); $redirectRevision = new Revision(array('title' => $this->source, 'page' => $this->source->getArticleID(), 'comment' => $reason, 'content' => $redirectContent)); $redirectRevision->insertOn($this->dbw); $redirectPage->updateRevisionOn($this->dbw, $redirectRevision); // Now, we record the link from the redirect to the new title. // It should have no other outgoing links... $this->dbw->delete('pagelinks', array('pl_from' => $this->dest->getArticleID()), __METHOD__); $this->dbw->insert('pagelinks', array('pl_from' => $this->dest->getArticleID(), 'pl_from_namespace' => $this->dest->getNamespace(), 'pl_namespace' => $this->dest->getNamespace(), 'pl_title' => $this->dest->getDBkey()), __METHOD__); } else { // Warning if we couldn't create the redirect $status->warning('mergehistory-warning-redirect-not-created'); } } else { $this->source->invalidateCache(); // update histories } $this->dest->invalidateCache(); // update histories // Update our logs $logEntry = new ManualLogEntry('merge', 'merge'); $logEntry->setPerformer($user); $logEntry->setComment($reason); $logEntry->setTarget($this->source); $logEntry->setParameters(array('4::dest' => $this->dest->getPrefixedText(), '5::mergepoint' => $this->timestampLimit->getTimestamp(TS_MW))); $logId = $logEntry->insert(); $logEntry->publish($logId); Hooks::run('ArticleMergeComplete', array($this->source, $this->dest)); return $status; }
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; }
/** * Actually attempt the history move * * @todo if all versions of page A are moved to B and then a user * tries to do a reverse-merge via the "unmerge" log link, then page * A will still be a redirect (as it was after the original merge), * though it will have the old revisions back from before (as expected). * The user may have to "undo" the redirect manually to finish the "unmerge". * Maybe this should delete redirects at the target page of merges? * * @return bool Success */ function merge() { # Get the titles directly from the IDs, in case the target page params # were spoofed. The queries are done based on the IDs, so it's best to # keep it consistent... $targetTitle = Title::newFromID($this->mTargetID); $destTitle = Title::newFromID($this->mDestID); if (is_null($targetTitle) || is_null($destTitle)) { return false; // validate these } if ($targetTitle->getArticleID() == $destTitle->getArticleID()) { return false; } # Verify that this timestamp is valid # Must be older than the destination page $dbw = wfGetDB(DB_MASTER); # Get timestamp into DB format $this->mTimestamp = $this->mTimestamp ? $dbw->timestamp($this->mTimestamp) : ''; # Max timestamp should be min of destination page $maxtimestamp = $dbw->selectField('revision', 'MIN(rev_timestamp)', array('rev_page' => $this->mDestID), __METHOD__); # Destination page must exist with revisions if (!$maxtimestamp) { $this->getOutput()->addWikiMsg('mergehistory-fail'); return false; } # Get the latest timestamp of the source $lasttimestamp = $dbw->selectField(array('page', 'revision'), 'rev_timestamp', array('page_id' => $this->mTargetID, 'page_latest = rev_id'), __METHOD__); # $this->mTimestamp must be older than $maxtimestamp if ($this->mTimestamp >= $maxtimestamp) { $this->getOutput()->addWikiMsg('mergehistory-fail'); return false; } # Get the timestamp pivot condition if ($this->mTimestamp) { $timewhere = "rev_timestamp <= {$this->mTimestamp}"; $timestampLimit = wfTimestamp(TS_MW, $this->mTimestamp); } else { $timewhere = "rev_timestamp <= {$maxtimestamp}"; $timestampLimit = wfTimestamp(TS_MW, $lasttimestamp); } # Check that there are not too many revisions to move $limit = 5000; // avoid too much slave lag $count = $dbw->selectRowCount('revision', '1', array('rev_page' => $this->mTargetID, $timewhere), __METHOD__, array('LIMIT' => $limit + 1)); if ($count > $limit) { $this->getOutput()->addWikiMsg('mergehistory-fail-toobig'); return false; } # Do the moving... $dbw->update('revision', array('rev_page' => $this->mDestID), array('rev_page' => $this->mTargetID, $timewhere), __METHOD__); $count = $dbw->affectedRows(); # Make the source page a redirect if no revisions are left $haveRevisions = $dbw->selectField('revision', 'rev_timestamp', array('rev_page' => $this->mTargetID), __METHOD__, array('FOR UPDATE')); if (!$haveRevisions) { if ($this->mComment) { $comment = $this->msg('mergehistory-comment', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $this->mComment)->inContentLanguage()->text(); } else { $comment = $this->msg('mergehistory-autocomment', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText())->inContentLanguage()->text(); } $contentHandler = ContentHandler::getForTitle($targetTitle); $redirectContent = $contentHandler->makeRedirectContent($destTitle); if ($redirectContent) { $redirectPage = WikiPage::factory($targetTitle); $redirectRevision = new Revision(array('title' => $targetTitle, 'page' => $this->mTargetID, 'comment' => $comment, 'content' => $redirectContent)); $redirectRevision->insertOn($dbw); $redirectPage->updateRevisionOn($dbw, $redirectRevision); # 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' => $this->mDestID), __METHOD__); $dbw->insert('pagelinks', array('pl_from' => $this->mDestID, 'pl_from_namespace' => $destTitle->getNamespace(), 'pl_namespace' => $destTitle->getNamespace(), 'pl_title' => $destTitle->getDBkey()), __METHOD__); } else { // would be nice to show a warning if we couldn't create a redirect } } else { $targetTitle->invalidateCache(); // update histories } $destTitle->invalidateCache(); // update histories # Check if this did anything if (!$count) { $this->getOutput()->addWikiMsg('mergehistory-fail'); return false; } # Update our logs $log = new LogPage('merge'); $log->addEntry('merge', $targetTitle, $this->mComment, array($destTitle->getPrefixedText(), $timestampLimit), $this->getUser()); # @todo message should use redirect=no $this->getOutput()->addWikiMsg('mergehistory-success', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $count); wfRunHooks('ArticleMergeComplete', array($targetTitle, $destTitle)); return true; }
/** * 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(); }
/** * 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; }
/** * 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; }
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; }
$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++; } // 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) {
/** * 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; if ($nt->exists()) { $moveOverRedirect = true; $logType = 'move_redir'; } else { $moveOverRedirect = false; $logType = 'move'; } $redirectSuppressed = !$createRedirect && $wgUser->isAllowed('suppressredirect'); $logEntry = new ManualLogEntry('move', $logType); $logEntry->setPerformer($wgUser); $logEntry->setTarget($this); $logEntry->setComment($reason); $logEntry->setParameters(array('4::target' => $nt->getPrefixedText(), '5::noredir' => $redirectSuppressed ? '1' : '0')); $formatter = LogFormatter::newFromEntry($logEntry); $formatter->setContext(RequestContext::newExtraneousContext($this)); $comment = $formatter->getPlainActionText(); 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); $newpage = WikiPage::factory($nt); if ($moveOverRedirect) { $newid = $nt->getArticleID(); # 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__); $newpage->doDeleteUpdates($newid); } # 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); # Change the name of the target page: $dbw->update('page', array('page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey()), array('page_id' => $oldid), __METHOD__); $this->resetArticleID(0); $nt->resetArticleID($oldid); $newpage->updateRevisionOn($dbw, $nullRevision); wfRunHooks('NewRevisionFromEditComplete', array($newpage, $nullRevision, $latest, $wgUser)); $newpage->doEditUpdates($nullRevision, $wgUser, array('changed' => false)); if (!$moveOverRedirect) { WikiPage::onArticleCreate($nt); } # Recreate the redirect, this time in the other direction. if ($redirectSuppressed) { WikiPage::onArticleDelete($this); } else { $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n"; $redirectArticle = WikiPage::factory($this); $newid = $redirectArticle->insertOn($dbw); if ($newid) { // sanity $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)); $redirectArticle->doEditUpdates($redirectRevision, $wgUser, array('created' => true)); } } # Log the move $logid = $logEntry->insert(); $logEntry->publish($logid); }
/** * Edit an article without doing all that other stuff * The article must already exist; link tables etc * are not updated, caches are not flushed. * * @param $text String: text submitted * @param $comment String: comment submitted * @param $minor Boolean: whereas it's a minor modification */ public function quickEdit($text, $comment = '', $minor = 0) { wfProfileIn(__METHOD__); $dbw = wfGetDB(DB_MASTER); $revision = new Revision(array('page' => $this->getId(), 'text' => $text, 'comment' => $comment, 'minor_edit' => $minor ? 1 : 0)); $revision->insertOn($dbw); $this->updateRevisionOn($dbw, $revision); global $wgUser; wfRunHooks('NewRevisionFromEditComplete', array($this, $revision, false, $wgUser)); wfProfileOut(__METHOD__); }
protected function _createMainPageForWiki() { $db = $this->getDatabase(); $titleobj = Title::newFromText(wfMessage('mainpage')->inContentLanguage()->useDatabase(false)->plain()); $article = new Article($titleobj); $newid = $article->insertOn($db); $revision = new Revision(array('page' => $newid, 'text' => wfMsgForContent('farmernewwikimainpage'), 'comment' => '', 'user' => 0, 'user_text' => 'MediaWiki default')); $revid = $revision->insertOn($db); $article->updateRevisionOn($db, $revision); // site_stats table entry $db->insert('site_stats', array('ss_row_id' => 1, 'ss_total_views' => 0, 'ss_total_edits' => 0, 'ss_good_articles' => 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...? global $wgLinkCache; $wgLinkCache->clear(); $article = new Article($this->title); $pageId = $article->getId(); if ($pageId == 0) { # must create the page... $pageId = $article->insertOn($dbw); } # 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); $article->updateIfNewerOn($dbw, $revision); return true; }
/** * Edit an article without doing all that other stuff * The article must already exist; link tables etc * are not updated, caches are not flushed. * * @param string $text text submitted * @param string $comment comment submitted * @param bool $minor whereas it's a minor modification */ function quickEdit($text, $comment = '', $minor = 0) { wfProfileIn(__METHOD__); $dbw =& wfGetDB(DB_MASTER); $dbw->begin(); $revision = new Revision(array('page' => $this->getId(), 'text' => $text, 'comment' => $comment, 'minor_edit' => $minor ? 1 : 0)); $revision->insertOn($dbw); $this->updateRevisionOn($dbw, $revision); $dbw->commit(); wfProfileOut(__METHOD__); }
/** * 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(); }
/** * @param int $pageId page id to insert the revision for * @return int ID of inserted revisions * @throws MWException */ private function insertEmptyRevision($pageId) { $revision = new Revision(['page' => $pageId, 'comment' => self::EMPTY_EDIT_SUMMARY, 'minor_edit' => true, 'text' => '', 'user' => $this->user->getId(), 'user_text' => $this->user->getName(), 'timestamp' => wfTimestampNow()]); return $revision->insertOn($this->dbw); }
/** * @param Content $content Pre-save transform content * @param integer $flags * @param User $user * @param string $summary * @param array $meta * @return Status * @throws DBUnexpectedError * @throws Exception * @throws FatalError * @throws MWException */ private function doCreate(Content $content, $flags, User $user, $summary, array $meta) { global $wgUseRCPatrol, $wgUseNPPatrol; $status = Status::newGood(['new' => true, 'revision' => null]); $now = wfTimestampNow(); $newsize = $content->getSize(); $prepStatus = $content->prepareSave($this, $flags, $meta['oldId'], $user); $status->merge($prepStatus); if (!$status->isOK()) { return $status; } $dbw = wfGetDB(DB_MASTER); $dbw->startAtomic(__METHOD__); // Add the page record unless one already exists for the title $newid = $this->insertOn($dbw); if ($newid === false) { $dbw->endAtomic(__METHOD__); // nothing inserted $status->fatal('edit-already-exists'); return $status; // nothing done } // At this point we are now comitted to returning an OK // status unless some DB query error or other exception comes up. // This way callers don't have to call rollback() if $status is bad // unless they actually try to catch exceptions (which is rare). // @TODO: pass content object?! $revision = new Revision(['page' => $newid, 'title' => $this->mTitle, 'comment' => $summary, 'minor_edit' => $meta['minor'], 'text' => $meta['serialized'], 'len' => $newsize, 'user' => $user->getId(), 'user_text' => $user->getName(), 'timestamp' => $now, 'content_model' => $content->getModel(), 'content_format' => $meta['serialFormat']]); // Save the revision text... $revisionId = $revision->insertOn($dbw); // Update the page record with revision data if (!$this->updateRevisionOn($dbw, $revision, 0)) { throw new MWException("Failed to update page row to use new revision."); } Hooks::run('NewRevisionFromEditComplete', [$this, $revision, false, $user]); // Update recentchanges if (!($flags & EDIT_SUPPRESS_RC)) { // Mark as patrolled if the user can do so $patrolled = ($wgUseRCPatrol || $wgUseNPPatrol) && !count($this->mTitle->getUserPermissionsErrors('autopatrol', $user)); // Add RC row to the DB RecentChange::notifyNew($now, $this->mTitle, $revision->isMinor(), $user, $summary, $meta['bot'], '', $newsize, $revisionId, $patrolled, $meta['tags']); } $user->incEditCount(); $dbw->endAtomic(__METHOD__); $this->mTimestamp = $now; // Return the new revision to the caller $status->value['revision'] = $revision; // Do secondary updates once the main changes have been committed... DeferredUpdates::addUpdate(new AtomicSectionUpdate($dbw, __METHOD__, function () use($revision, &$user, $content, $summary, &$flags, $meta, &$status) { // Update links, etc. $this->doEditUpdates($revision, $user, ['created' => true]); // Trigger post-create hook $params = [&$this, &$user, $content, $summary, $flags & EDIT_MINOR, null, null, &$flags, $revision]; ContentHandler::runLegacyHooks('ArticleInsertComplete', $params, '1.21'); Hooks::run('PageContentInsertComplete', $params); // Trigger post-save hook $params = array_merge($params, [&$status, $meta['baseRevId']]); ContentHandler::runLegacyHooks('ArticleSaveComplete', $params, '1.21'); Hooks::run('PageContentSaveComplete', $params); }), DeferredUpdates::PRESEND); return $status; }
/** * Move page to a title which is either a redirect to the * source page or nonexistent * * @param Title $nt The page to move to, which should be a redirect or nonexistent * @param string $reason The reason for the move * @param bool $createRedirect Whether to leave a redirect at the old title. Does not check * if the user has the suppressredirect right * @throws MWException */ private function moveToInternal(&$nt, $reason = '', $createRedirect = true) { global $wgUser, $wgContLang; if ($nt->exists()) { $moveOverRedirect = true; $logType = 'move_redir'; } else { $moveOverRedirect = false; $logType = 'move'; } if ($createRedirect) { if ($this->getNamespace() == NS_CATEGORY && !wfMessage('category-move-redirect-override')->inContentLanguage()->isDisabled()) { $redirectContent = new WikitextContent(wfMessage('category-move-redirect-override')->params($nt->getPrefixedText())->inContentLanguage()->plain()); } else { $contentHandler = ContentHandler::getForTitle($this); $redirectContent = $contentHandler->makeRedirectContent($nt, wfMessage('move-redirect-text')->inContentLanguage()->plain()); } // NOTE: If this page's content model does not support redirects, $redirectContent will be null. } else { $redirectContent = null; } // bug 57084: log_page should be the ID of the *moved* page $oldid = $this->getArticleID(); $logTitle = clone $this; $logEntry = new ManualLogEntry('move', $logType); $logEntry->setPerformer($wgUser); $logEntry->setTarget($logTitle); $logEntry->setComment($reason); $logEntry->setParameters(array('4::target' => $nt->getPrefixedText(), '5::noredir' => $redirectContent ? '0' : '1')); $formatter = LogFormatter::newFromEntry($logEntry); $formatter->setContext(RequestContext::newExtraneousContext($this)); $comment = $formatter->getPlainActionText(); if ($reason) { $comment .= wfMessage('colon-separator')->inContentLanguage()->text() . $reason; } # Truncate for whole multibyte characters. $comment = $wgContLang->truncate($comment, 255); $dbw = wfGetDB(DB_MASTER); $newpage = WikiPage::factory($nt); if ($moveOverRedirect) { $newid = $nt->getArticleID(); $newcontent = $newpage->getContent(); # 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__); $newpage->doDeleteUpdates($newid, $newcontent); } # Save a null revision in the page's history notifying of the move $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true, $wgUser); if (!is_object($nullRevision)) { throw new MWException('No valid null revision produced in ' . __METHOD__); } $nullRevision->insertOn($dbw); # Change the name of the target page: $dbw->update('page', array('page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey()), array('page_id' => $oldid), __METHOD__); // clean up the old title before reset article id - bug 45348 if (!$redirectContent) { WikiPage::onArticleDelete($this); } $this->resetArticleID(0); // 0 == non existing $nt->resetArticleID($oldid); $newpage->loadPageData(WikiPage::READ_LOCKING); // bug 46397 $newpage->updateRevisionOn($dbw, $nullRevision); wfRunHooks('NewRevisionFromEditComplete', array($newpage, $nullRevision, $nullRevision->getParentId(), $wgUser)); $newpage->doEditUpdates($nullRevision, $wgUser, array('changed' => false)); if (!$moveOverRedirect) { WikiPage::onArticleCreate($nt); } # Recreate the redirect, this time in the other direction. if ($redirectContent) { $redirectArticle = WikiPage::factory($this); $redirectArticle->loadFromRow(false, WikiPage::READ_LOCKING); // bug 46397 $newid = $redirectArticle->insertOn($dbw); if ($newid) { // sanity $this->resetArticleID($newid); $redirectRevision = new Revision(array('title' => $this, 'page' => $newid, 'user_text' => $wgUser->getName(), 'user' => $wgUser->getId(), 'comment' => $comment, 'content' => $redirectContent)); $redirectRevision->insertOn($dbw); $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0); wfRunHooks('NewRevisionFromEditComplete', array($redirectArticle, $redirectRevision, false, $wgUser)); $redirectArticle->doEditUpdates($redirectRevision, $wgUser, array('created' => true)); } } # Log the move $logid = $logEntry->insert(); $logEntry->publish($logid); }
/** * @return bool */ 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(); $userObj = $user; } else { $userId = 0; $userText = $this->getUser(); $userObj = new User(); } // avoid memory leak...? Title::clearCaches(); $page = WikiPage::factory($this->title); $page->loadPageData('fromdbmaster'); if (!$page->exists()) { # must create the page... $pageId = $page->insertOn($dbw); $created = true; $oldcountable = null; } else { $pageId = $page->getId(); $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) { // @todo FIXME: This could fail slightly for multiple matches :P wfDebug(__METHOD__ . ": skipping existing revision for [[" . $this->title->getPrefixedText() . "]], timestamp " . $this->timestamp . "\n"); return false; } } # @todo FIXME: Use original rev_id optionally (better for backups) # Insert the row $revision = new Revision(array('title' => $this->title, 'page' => $pageId, 'content_model' => $this->getModel(), 'content_format' => $this->getFormat(), 'text' => $this->getContent()->serialize($this->getFormat()), 'comment' => $this->getComment(), 'user' => $userId, 'user_text' => $userText, 'timestamp' => $this->timestamp, 'minor_edit' => $this->minor)); $revision->insertOn($dbw); $changed = $page->updateIfNewerOn($dbw, $revision); if ($changed !== false && !$this->mNoUpdates) { wfDebug(__METHOD__ . ": running updates\n"); // countable/oldcountable stuff is handled in WikiImporter::finishImportPage $page->doEditUpdates($revision, $userObj, array('created' => $created, 'oldcountable' => 'no-change')); } return true; }
/** * Edit an article without doing all that other stuff * The article must already exist; link tables etc * are not updated, caches are not flushed. * * @param Content $content Content submitted * @param User $user The relevant user * @param string $comment Comment submitted * @param bool $minor Whereas it's a minor modification * @param string $serialFormat Format for storing the content in the database */ public function doQuickEditContent(Content $content, User $user, $comment = '', $minor = false, $serialFormat = null) { $serialized = $content->serialize($serialFormat); $dbw = wfGetDB(DB_MASTER); $revision = new Revision(array('title' => $this->getTitle(), 'page' => $this->getId(), 'user_text' => $user->getName(), 'user' => $user->getId(), 'text' => $serialized, 'length' => $content->getSize(), 'comment' => $comment, 'minor_edit' => $minor ? 1 : 0)); // XXX: set the content object? $revision->insertOn($dbw); $this->updateRevisionOn($dbw, $revision); Hooks::run('NewRevisionFromEditComplete', array($this, $revision, false, $user)); }
/** * Edit an article without doing all that other stuff * The article must already exist; link tables etc * are not updated, caches are not flushed. * * @param Content $content Content submitted * @param User $user The relevant user * @param string $comment comment submitted * @param string $serialisation_format Format for storing the content in the database * @param bool $minor Whereas it's a minor modification */ public function doQuickEditContent( Content $content, User $user, $comment = '', $minor = false, $serialisation_format = null ) { wfProfileIn( __METHOD__ ); $serialized = $content->serialize( $serialisation_format ); $dbw = wfGetDB( DB_MASTER ); $revision = new Revision( array( 'title' => $this->getTitle(), // for determining the default content model 'page' => $this->getId(), 'text' => $serialized, 'length' => $content->getSize(), 'comment' => $comment, 'minor_edit' => $minor ? 1 : 0, ) ); // XXX: set the content object? $revision->insertOn( $dbw ); $this->updateRevisionOn( $dbw, $revision ); wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) ); wfProfileOut( __METHOD__ ); }
/** * @return bool */ function importOldRevision() { $dbw = wfGetDB(DB_MASTER); # Sneak a single revision into place $user = $this->getUserObj() ?: User::newFromName($this->getUser()); if ($user) { $userId = intval($user->getId()); $userText = $user->getName(); } else { $userId = 0; $userText = $this->getUser(); $user = new User(); } // avoid memory leak...? Title::clearCaches(); $page = WikiPage::factory($this->title); $page->loadPageData('fromdbmaster'); if (!$page->exists()) { // must create the page... $pageId = $page->insertOn($dbw); $created = true; $oldcountable = null; } else { $pageId = $page->getId(); $created = false; $prior = $dbw->selectField('revision', '1', ['rev_page' => $pageId, 'rev_timestamp' => $dbw->timestamp($this->timestamp), 'rev_user_text' => $userText, 'rev_comment' => $this->getComment()], __METHOD__); if ($prior) { // @todo FIXME: This could fail slightly for multiple matches :P wfDebug(__METHOD__ . ": skipping existing revision for [[" . $this->title->getPrefixedText() . "]], timestamp " . $this->timestamp . "\n"); return false; } } if (!$pageId) { // This seems to happen if two clients simultaneously try to import the // same page wfDebug(__METHOD__ . ': got invalid $pageId when importing revision of [[' . $this->title->getPrefixedText() . ']], timestamp ' . $this->timestamp . "\n"); return false; } // Select previous version to make size diffs correct // @todo This assumes that multiple revisions of the same page are imported // in order from oldest to newest. $prevId = $dbw->selectField('revision', 'rev_id', ['rev_page' => $pageId, 'rev_timestamp <= ' . $dbw->addQuotes($dbw->timestamp($this->timestamp))], __METHOD__, ['ORDER BY' => ['rev_timestamp DESC', 'rev_id DESC']]); # @todo FIXME: Use original rev_id optionally (better for backups) # Insert the row $revision = new Revision(['title' => $this->title, 'page' => $pageId, 'content_model' => $this->getModel(), 'content_format' => $this->getFormat(), 'text' => $this->getContent()->serialize($this->getFormat()), 'comment' => $this->getComment(), 'user' => $userId, 'user_text' => $userText, 'timestamp' => $this->timestamp, 'minor_edit' => $this->minor, 'parent_id' => $prevId]); $revision->insertOn($dbw); $changed = $page->updateIfNewerOn($dbw, $revision); if ($changed !== false && !$this->mNoUpdates) { wfDebug(__METHOD__ . ": running updates\n"); // countable/oldcountable stuff is handled in WikiImporter::finishImportPage $page->doEditUpdates($revision, $user, ['created' => $created, 'oldcountable' => 'no-change']); } return true; }