public function setBits($bits)
 {
     $dbw = wfGetDB(DB_MASTER);
     // Update revision table
     $dbw->update('revision', array('rev_deleted' => $bits), array('rev_id' => $this->revision->getId(), 'rev_page' => $this->revision->getPage(), 'rev_deleted' => $this->getBits()), __METHOD__);
     if (!$dbw->affectedRows()) {
         // Concurrent fail!
         return false;
     }
     // Update recentchanges table
     $dbw->update('recentchanges', array('rc_deleted' => $bits, 'rc_patrolled' => 1), array('rc_this_oldid' => $this->revision->getId(), 'rc_timestamp' => $dbw->timestamp($this->revision->getTimestamp())), __METHOD__);
     return true;
 }
 protected function assertRevEquals(Revision $orig, Revision $rev = null)
 {
     $this->assertNotNull($rev, 'missing revision');
     $this->assertEquals($orig->getId(), $rev->getId());
     $this->assertEquals($orig->getPage(), $rev->getPage());
     $this->assertEquals($orig->getTimestamp(), $rev->getTimestamp());
     $this->assertEquals($orig->getUser(), $rev->getUser());
     $this->assertEquals($orig->getSha1(), $rev->getSha1());
 }
 /**
  * Executes the real stuff. No checks done!
  * @param User $user
  * @param Revision $revision
  * @param null|string $comment
  * @return Bool, whether the action was recorded.
  */
 public static function doReview(User $user, Revision $revision, $comment = null)
 {
     $dbw = wfGetDB(DB_MASTER);
     $table = 'translate_reviews';
     $row = array('trr_user' => $user->getId(), 'trr_page' => $revision->getPage(), 'trr_revision' => $revision->getId());
     $options = array('IGNORE');
     $dbw->insert($table, $row, __METHOD__, $options);
     if (!$dbw->affectedRows()) {
         return false;
     }
     $title = $revision->getTitle();
     $entry = new ManualLogEntry('translationreview', 'message');
     $entry->setPerformer($user);
     $entry->setTarget($title);
     $entry->setComment($comment);
     $entry->setParameters(array('4::revision' => $revision->getId()));
     $logid = $entry->insert();
     $entry->publish($logid);
     $handle = new MessageHandle($title);
     Hooks::run('TranslateEventTranslationReview', array($handle));
     return true;
 }
Esempio n. 4
0
 /**
  * Sets $this->mRedirectUrl to a correct URL if the query parameters are incorrect
  *
  * @return int The old id for the request
  */
 public function getOldIDFromRequest()
 {
     global $wgRequest;
     $this->mRedirectUrl = false;
     $oldid = $wgRequest->getIntOrNull('oldid');
     if ($oldid === null) {
         return 0;
     }
     if ($oldid !== 0) {
         # Load the given revision and check whether the page is another one.
         # In that case, update this instance to reflect the change.
         $this->mRevision = Revision::newFromId($oldid);
         if ($this->mRevision !== null) {
             // Revision title doesn't match the page title given?
             if ($this->mPage->getID() != $this->mRevision->getPage()) {
                 $function = array(get_class($this->mPage), 'newFromID');
                 $this->mPage = call_user_func($function, $this->mRevision->getPage());
             }
         }
     }
     if ($wgRequest->getVal('direction') == 'next') {
         $nextid = $this->getTitle()->getNextRevisionID($oldid);
         if ($nextid) {
             $oldid = $nextid;
             $this->mRevision = null;
         } else {
             $this->mRedirectUrl = $this->getTitle()->getFullURL('redirect=no');
         }
     } elseif ($wgRequest->getVal('direction') == 'prev') {
         $previd = $this->getTitle()->getPreviousRevisionID($oldid);
         if ($previd) {
             $oldid = $previd;
             $this->mRevision = null;
         }
     }
     return $oldid;
 }
Esempio n. 5
0
 /**
  * saveComplete -- hook
  *
  * @static
  * @access public
  *
  * @param WikiPage $oArticle,
  * @param User $User
  *
  * @author Piotr Molski (MoLi)
  * @return true
  */
 public static function saveComplete(&$oArticle, &$oUser, $text, $summary, $minor, $undef1, $undef2, &$flags, Revision $oRevision, &$status, $baseRevId)
 {
     global $wgCityId;
     wfProfileIn(__METHOD__);
     $revId = $pageId = 0;
     if (is_object($oArticle) && $oUser instanceof User) {
         # revision
         if ($oRevision instanceof Revision) {
             $revId = $oRevision->getId();
             $pageId = $oRevision->getPage();
         }
         if (empty($revId)) {
             $revId = $oArticle->getTitle()->getLatestRevID(Title::GAID_FOR_UPDATE);
         }
         # article
         if (empty($pageId) || $pageId < 0) {
             $pageId = $oArticle->getID();
         }
         if ($revId > 0 && $pageId > 0) {
             $key = isset($status->value['new']) && $status->value['new'] == 1 ? 'create' : 'edit';
             $oScribeProducer = new ScribeProducer($key, $pageId, $revId, 0, !empty($undef1) ? 1 : 0);
             if (is_object($oScribeProducer)) {
                 $oScribeProducer->send_log();
             }
         } else {
             Wikia::log(__METHOD__, "error", "Cannot send log via scribe ({$wgCityId}): revision not found for page: {$pageId}");
         }
     } else {
         $isArticle = is_object($oArticle);
         $isUser = is_object($oUser);
         Wikia::log(__METHOD__, "error", "Cannot send log via scribe ({$wgCityId}): invalid user: {$isUser}, invalid article: {$isArticle}");
     }
     wfProfileOut(__METHOD__);
     return true;
 }
Esempio n. 6
0
 /**
  * Update the revision's rev_deleted field
  * @param Revision $rev
  * @param int $bitfield new rev_deleted bitfield value
  */
 function updateRevision($rev, $bitfield)
 {
     $this->dbw->update('revision', array('rev_deleted' => $bitfield), array('rev_id' => $rev->getId(), 'rev_page' => $rev->getPage()), __METHOD__);
 }
Esempio n. 7
0
 /**
  * revisionInsertComplete
  *
  * static method called as hook
  *
  * @static
  * @access public
  *
  * @param Revision	$revision	revision object
  * @param string	$url		url to external object
  * @param string	$flags		flags for this revision
  *
  * @return true means process other hooks
  */
 public static function revisionInsertComplete(&$revision, $url, $flags)
 {
     global $wgUser, $wgCityId, $wgCommandLineMode, $wgSharedDB, $wgErrorLog, $wgMemc, $wgRequest;
     wfProfileIn(__METHOD__);
     /**
      * Do not create task when DB is locked (rt#12229)
      * Do not create task when we are in $wgCommandLineMode
      */
     $oldValue = $wgErrorLog;
     $wgErrorLog = true;
     if (!wfReadOnly() && !$wgCommandLineMode) {
         /**
          * Revision has valid Title field but sometimes not filled
          */
         $Title = $revision->getTitle();
         if (!$Title) {
             $Title = Title::newFromId($revision->getPage(), Title::GAID_FOR_UPDATE);
             $revision->setTitle($Title);
         }
         /**
          * get groups for user rt#12215
          */
         $groups = $wgUser->getEffectiveGroups();
         $invalid = array("bot" => true, "bot-global" => true, "staff" => true, "helper" => true, "sysop" => true, "bureaucrat" => true, "vstf" => true);
         $canWelcome = true;
         foreach ($groups as $group) {
             if (isset($invalid[$group]) && $invalid[$group]) {
                 $canWelcome = false;
                 Wikia::log(__METHOD__, $wgUser->getId(), "Skip welcome, user is at least in group: " . $group);
                 break;
             }
         }
         /**
          * put possible welcomer into memcached, RT#14067
          */
         if ($wgUser->getId() && self::isWelcomer($wgUser)) {
             // BugId:41817 - if ( 1 == $wgUser->getId() ) { notify Mix }
             if (1 == $wgUser->getId()) {
                 $oTo = $oFrom = new MailAddress('*****@*****.**');
                 UserMailer::send($oTo, $oFrom, 'BugId:41817 Occurrence Report', sprintf("File: %s\nLine: %s, Date: %s\nOutput: %s", __FILE__, __LINE__, date('Y-m-d H:i:s'), var_export($wgUser->getId(), true)));
             }
             $wgMemc->set(wfMemcKey("last-sysop-id"), $wgUser->getId(), 86400);
             Wikia::log(__METHOD__, $wgUser->getId(), "Store possible welcomer in memcached");
         }
         if ($Title && $canWelcome && !empty($wgSharedDB)) {
             Wikia::log(__METHOD__, "title", $Title->getFullURL());
             $welcomer = trim(wfMsgForContent("welcome-user"));
             Wikia::log(__METHOD__, "welcomer", $welcomer);
             if ($welcomer !== "@disabled" && $welcomer !== "-") {
                 /**
                  * check if talk page for wgUser exists
                  *
                  * @todo check editcount for user
                  */
                 Wikia::log(__METHOD__, "user", $wgUser->getName());
                 $talkPage = $wgUser->getUserPage()->getTalkPage();
                 if ($talkPage) {
                     $talkArticle = new Article($talkPage, 0);
                     if (!self::isPosted($talkArticle, $wgUser)) {
                         $welcomeJob = new HAWelcomeJob($Title, array("is_anon" => $wgUser->isAnon(), "user_id" => $wgUser->getId(), "user_ip" => $wgRequest->getIP(), "user_name" => $wgUser->getName()));
                         $welcomeJob->insert();
                         Wikia::log(__METHOD__, "job");
                         /**
                          * inform task manager
                          */
                         $Task = new HAWelcomeTask();
                         $taskId = $Task->createTask(array("city_id" => $wgCityId), TASK_QUEUED);
                         Wikia::log(__METHOD__, "task", $taskId);
                     } else {
                         Wikia::log(__METHOD__, "exists", sprintf("Talk page for user %s already exits", $wgUser->getName()));
                     }
                 }
             } else {
                 Wikia::log(__METHOD__, "disabled");
             }
         }
     }
     $wgErrorLog = $oldValue;
     wfProfileOut(__METHOD__);
     return true;
 }
Esempio n. 8
0
 public function execute()
 {
     $params = $this->extractRequestParams(false);
     // If any of those parameters are used, work in 'enumeration' mode.
     // Enum mode can only be used when exactly one page is provided.
     // Enumerating revisions on multiple pages make it extremely
     // difficult to manage continuations and require additional SQL indexes
     $enumRevMode = !is_null($params['user']) || !is_null($params['excludeuser']) || !is_null($params['limit']) || !is_null($params['startid']) || !is_null($params['endid']) || $params['dir'] === 'newer' || !is_null($params['start']) || !is_null($params['end']);
     $pageSet = $this->getPageSet();
     $pageCount = $pageSet->getGoodTitleCount();
     $revCount = $pageSet->getRevisionCount();
     // Optimization -- nothing to do
     if ($revCount === 0 && $pageCount === 0) {
         return;
     }
     if ($revCount > 0 && $enumRevMode) {
         $this->dieUsage('The revids= parameter may not be used with the list options (limit, startid, endid, dirNewer, start, end).', 'revids');
     }
     if ($pageCount > 1 && $enumRevMode) {
         $this->dieUsage('titles, pageids or a generator was used to supply multiple pages, but the limit, startid, endid, dirNewer, user, excludeuser, start and end parameters may only be used on a single page.', 'multpages');
     }
     if (!is_null($params['diffto'])) {
         if ($params['diffto'] == 'cur') {
             $params['diffto'] = 0;
         }
         if ((!ctype_digit($params['diffto']) || $params['diffto'] < 0) && $params['diffto'] != 'prev' && $params['diffto'] != 'next') {
             $this->dieUsage('rvdiffto must be set to a non-negative number, "prev", "next" or "cur"', 'diffto');
         }
         // Check whether the revision exists and is readable,
         // DifferenceEngine returns a rather ambiguous empty
         // string if that's not the case
         if ($params['diffto'] != 0) {
             $difftoRev = Revision::newFromID($params['diffto']);
             if (!$difftoRev) {
                 $this->dieUsageMsg(array('nosuchrevid', $params['diffto']));
             }
             if (!$difftoRev->userCan(Revision::DELETED_TEXT)) {
                 $this->setWarning("Couldn't diff to r{$difftoRev->getID()}: content is hidden");
                 $params['diffto'] = null;
             }
         }
     }
     $this->addTables('revision');
     $this->addFields(Revision::selectFields());
     $this->addTables('page');
     $this->addWhere('page_id = rev_page');
     $prop = array_flip($params['prop']);
     // Optional fields
     $this->fld_ids = isset($prop['ids']);
     // $this->addFieldsIf('rev_text_id', $this->fld_ids); // should this be exposed?
     $this->fld_flags = isset($prop['flags']);
     $this->fld_timestamp = isset($prop['timestamp']);
     $this->fld_comment = isset($prop['comment']);
     $this->fld_size = isset($prop['size']);
     $this->fld_user = isset($prop['user']);
     $this->token = $params['token'];
     $this->diffto = $params['diffto'];
     if (!is_null($this->token) || $pageCount > 0) {
         $this->addFields(Revision::selectPageFields());
     }
     if (isset($prop['content'])) {
         // For each page we will request, the user must have read rights for that page
         foreach ($pageSet->getGoodTitles() as $title) {
             if (!$title->userCanRead()) {
                 $this->dieUsage('The current user is not allowed to read ' . $title->getPrefixedText(), 'accessdenied');
             }
         }
         $this->addTables('text');
         $this->addWhere('rev_text_id=old_id');
         $this->addFields('old_id');
         $this->addFields(Revision::selectTextFields());
         $this->fld_content = true;
         $this->expandTemplates = $params['expandtemplates'];
         $this->generateXML = $params['generatexml'];
         if (isset($params['section'])) {
             $this->section = $params['section'];
         } else {
             $this->section = false;
         }
     }
     $userMax = $this->fld_content ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1;
     $botMax = $this->fld_content ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2;
     $limit = $params['limit'];
     if ($limit == 'max') {
         $limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
         $this->getResult()->addValue('limits', $this->getModuleName(), $limit);
     }
     if ($enumRevMode) {
         // This is mostly to prevent parameter errors (and optimize SQL?)
         if (!is_null($params['startid']) && !is_null($params['start'])) {
             $this->dieUsage('start and startid cannot be used together', 'badparams');
         }
         if (!is_null($params['endid']) && !is_null($params['end'])) {
             $this->dieUsage('end and endid cannot be used together', 'badparams');
         }
         if (!is_null($params['user']) && !is_null($params['excludeuser'])) {
             $this->dieUsage('user and excludeuser cannot be used together', 'badparams');
         }
         // This code makes an assumption that sorting by rev_id and rev_timestamp produces
         // the same result. This way users may request revisions starting at a given time,
         // but to page through results use the rev_id returned after each page.
         // Switching to rev_id removes the potential problem of having more than
         // one row with the same timestamp for the same page.
         // The order needs to be the same as start parameter to avoid SQL filesort.
         if (is_null($params['startid']) && is_null($params['endid'])) {
             $this->addWhereRange('rev_timestamp', $params['dir'], $params['start'], $params['end']);
         } else {
             $this->addWhereRange('rev_id', $params['dir'], $params['startid'], $params['endid']);
             // One of start and end can be set
             // If neither is set, this does nothing
             $this->addWhereRange('rev_timestamp', $params['dir'], $params['start'], $params['end'], false);
         }
         // must manually initialize unset limit
         if (is_null($limit)) {
             $limit = 10;
         }
         $this->validateLimit('limit', $limit, 1, $userMax, $botMax);
         // There is only one ID, use it
         $this->addWhereFld('rev_page', reset(array_keys($pageSet->getGoodTitles())));
         if (!is_null($params['user'])) {
             $this->addWhereFld('rev_user_text', $params['user']);
         } elseif (!is_null($params['excludeuser'])) {
             $this->addWhere('rev_user_text != ' . $this->getDB()->addQuotes($params['excludeuser']));
         }
         if (!is_null($params['user']) || !is_null($params['excludeuser'])) {
             // Paranoia: avoid brute force searches (bug 17342)
             $this->addWhere('rev_deleted & ' . Revision::DELETED_USER . ' = 0');
         }
     } elseif ($revCount > 0) {
         $max = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
         $revs = $pageSet->getRevisionIDs();
         if (self::truncateArray($revs, $max)) {
             $this->setWarning("Too many values supplied for parameter 'revids': the limit is {$max}");
         }
         // Get all revision IDs
         $this->addWhereFld('rev_id', array_keys($revs));
         if (!is_null($params['continue'])) {
             $this->addWhere("rev_id >= '" . intval($params['continue']) . "'");
         }
         $this->addOption('ORDER BY', 'rev_id');
         // assumption testing -- we should never get more then $revCount rows.
         $limit = $revCount;
     } elseif ($pageCount > 0) {
         $max = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
         $titles = $pageSet->getGoodTitles();
         if (self::truncateArray($titles, $max)) {
             $this->setWarning("Too many values supplied for parameter 'titles': the limit is {$max}");
         }
         // When working in multi-page non-enumeration mode,
         // limit to the latest revision only
         $this->addWhere('page_id=rev_page');
         $this->addWhere('page_latest=rev_id');
         // Get all page IDs
         $this->addWhereFld('page_id', array_keys($titles));
         // Every time someone relies on equality propagation, god kills a kitten :)
         $this->addWhereFld('rev_page', array_keys($titles));
         if (!is_null($params['continue'])) {
             $cont = explode('|', $params['continue']);
             if (count($cont) != 2) {
                 $this->dieUsage("Invalid continue param. You should pass the original " . "value returned by the previous query", "_badcontinue");
             }
             $pageid = intval($cont[0]);
             $revid = intval($cont[1]);
             $this->addWhere("rev_page > '{$pageid}' OR " . "(rev_page = '{$pageid}' AND " . "rev_id >= '{$revid}')");
         }
         $this->addOption('ORDER BY', 'rev_page, rev_id');
         // assumption testing -- we should never get more then $pageCount rows.
         $limit = $pageCount;
     } else {
         ApiBase::dieDebug(__METHOD__, 'param validation?');
     }
     $this->addOption('LIMIT', $limit + 1);
     $data = array();
     $count = 0;
     $res = $this->select(__METHOD__);
     $db = $this->getDB();
     while ($row = $db->fetchObject($res)) {
         if (++$count > $limit) {
             // We've reached the one extra which shows that there are additional pages to be had. Stop here...
             if (!$enumRevMode) {
                 ApiBase::dieDebug(__METHOD__, 'Got more rows then expected');
             }
             // bug report
             $this->setContinueEnumParameter('startid', intval($row->rev_id));
             break;
         }
         $revision = new Revision($row);
         //
         $fit = $this->addPageSubItem($revision->getPage(), $this->extractRowInfo($revision), 'rev');
         if (!$fit) {
             if ($enumRevMode) {
                 $this->setContinueEnumParameter('startid', intval($row->rev_id));
             } else {
                 if ($revCount > 0) {
                     $this->setContinueEnumParameter('continue', intval($row->rev_id));
                 } else {
                     $this->setContinueEnumParameter('continue', intval($row->rev_page) . '|' . intval($row->rev_id));
                 }
             }
             break;
         }
     }
     $db->freeResult($res);
 }
 /**
  * Page moving and page protection (and possibly other things) creates null
  * revisions. These revisions re-use the previous text already stored in
  * the database. Those however do not trigger re-parsing of the page and
  * thus the ready tag is not updated. This watches for new revisions,
  * checks if they reuse existing text, checks whether the parent version
  * is the latest version and has a ready tag. If that is the case,
  * also adds a ready tag for the new revision (which is safe, because
  * the text hasn't changed). The interface will say that there has been
  * a change, but shows no change in the content. This lets the user to
  * update the translation pages in the case, the non-text changes affect
  * the rendering of translation pages. I'm not aware of any such cases
  * at the moment.
  * Hook: RevisionInsertComplete
  * @since 2012-05-08
  */
 public static function updateTranstagOnNullRevisions(Revision $rev, $text, $flags)
 {
     $title = $rev->getTitle();
     $newRevId = $rev->getId();
     $oldRevId = $rev->getParentId();
     $newTextId = $rev->getTextId();
     /* This hook doesn't provide any way to detech null revisions
      * without extra query */
     $dbw = wfGetDB(DB_MASTER);
     $table = 'revision';
     $field = 'rev_text_id';
     $conds = array('rev_page' => $rev->getPage(), 'rev_id' => $oldRevId);
     // FIXME: optimize away this query. Bug T38588.
     $oldTextId = $dbw->selectField($table, $field, $conds, __METHOD__);
     if (strval($newTextId) !== strval($oldTextId)) {
         // Not a null revision, bail out.
         return true;
     }
     $page = TranslatablePage::newFromTitle($title);
     if ($page->getReadyTag() === $oldRevId) {
         $page->addReadyTag($newRevId);
     }
     return true;
 }
Esempio n. 10
0
 /**
  * revisionInsertComplete
  *
  * static method called as hook
  *
  * @static
  * @access public
  *
  * @param Revision	$revision	revision object
  * @param string	$url		url to external object
  * @param string	$flags		flags for this revision
  *
  * @return true means process other hooks
  */
 public static function revisionInsertComplete(&$revision, $url, $flags)
 {
     global $wgUser, $wgCityId, $wgCommandLineMode, $wgSharedDB, $wgErrorLog, $wgMemc, $wgRequest;
     //do nothing if the user clicked 'undo'
     if ($wgRequest->getVal('wpUndoEdit')) {
         return true;
     }
     wfProfileIn(__METHOD__);
     /* first edit? */
     //if (User::edits($wgUser->getID()) == 1) {
     /**
      * Do not create task when DB is locked (rt#12229)
      * Do not create task when we are in $wgCommandLineMode
      */
     $oldValue = $wgErrorLog;
     $wgErrorLog = true;
     if (!wfReadOnly() && !$wgCommandLineMode) {
         wfLoadExtensionMessages("HAWelcome");
         /**
          * Revision has valid Title field but sometimes not filled
          */
         $Title = $revision->getTitle();
         if (!$Title) {
             $Title = Title::newFromId($revision->getPage(), GAID_FOR_UPDATE);
             $revision->setTitle($Title);
         }
         /**
          * get groups for user rt#12215
          */
         $groups = $wgUser->getEffectiveGroups();
         $invalid = array("bot" => true, "staff" => true, "helper" => true, "sysop" => true, "bureaucrat" => true, "vstf" => true);
         $canWelcome = true;
         foreach ($groups as $group) {
             if (isset($invalid[$group]) && $invalid[$group]) {
                 $canWelcome = false;
                 break;
             }
         }
         /**
          * put possible welcomer into memcached, RT#14067
          */
         if ($wgUser->getId() && self::isWelcomer($wgUser)) {
             //$wgMemc->set( wfMemcKey( "last-sysop-id" ), $wgUser->getId(), 86400 );
             $wgMemc->set(wfMemcKey("last-sysop-id"), $wgUser->getId(), 3600);
         }
         if ($Title && $canWelcome && !empty($wgSharedDB)) {
             $welcomer = trim(wfMsgForContent("welcome-user"));
             if ($welcomer !== "@disabled" && $welcomer !== "-") {
                 /**
                  * check if talk page for wgUser exists
                  *
                  * @todo check editcount for user
                  */
                 $talkPage = $wgUser->getUserPage()->getTalkPage();
                 if ($talkPage) {
                     $talkArticle = new Article($talkPage, 0);
                     if (!$talkArticle->exists()) {
                         //run the talk page stuff
                         self::runEditThanks($Title);
                     }
                 }
             }
         }
     }
     //}
     $wgErrorLog = $oldValue;
     wfProfileOut(__METHOD__);
     return true;
 }
 /**
  * Check if a user reverted himself to the stable version
  */
 protected static function isSelfRevertToStable(Revision $rev, $srev, $baseRevId, $user)
 {
     if (!$srev || $baseRevId != $srev->getRevId()) {
         return false;
         // user reports they are not the same
     }
     $dbw = wfGetDB(DB_MASTER);
     # Such a revert requires 1+ revs between it and the stable
     $revertedRevs = $dbw->selectField('revision', '1', array('rev_page' => $rev->getPage(), 'rev_id > ' . intval($baseRevId), 'rev_id < ' . intval($rev->getId()), 'rev_user_text' => $user->getName()), __METHOD__);
     if (!$revertedRevs) {
         return false;
         // can't be a revert
     }
     # Check that this user is ONLY reverting his/herself.
     $otherUsers = $dbw->selectField('revision', '1', array('rev_page' => $rev->getPage(), 'rev_id > ' . intval($baseRevId), 'rev_user_text != ' . $dbw->addQuotes($user->getName())), __METHOD__);
     if ($otherUsers) {
         return false;
         // only looking for self-reverts
     }
     # Confirm the text because we can't trust this user.
     return $rev->getSha1() === $srev->getRevision()->getSha1();
 }
Esempio n. 12
0
 public function execute()
 {
     $params = $this->extractRequestParams(false);
     // If any of those parameters are used, work in 'enumeration' mode.
     // Enum mode can only be used when exactly one page is provided.
     // Enumerating revisions on multiple pages make it extremely
     // difficult to manage continuations and require additional SQL indexes
     $enumRevMode = !is_null($params['user']) || !is_null($params['excludeuser']) || !is_null($params['limit']) || !is_null($params['startid']) || !is_null($params['endid']) || $params['dir'] === 'newer' || !is_null($params['start']) || !is_null($params['end']);
     $pageSet = $this->getPageSet();
     $pageCount = $pageSet->getGoodTitleCount();
     $revCount = $pageSet->getRevisionCount();
     // Optimization -- nothing to do
     if ($revCount === 0 && $pageCount === 0) {
         return;
     }
     if ($revCount > 0 && $enumRevMode) {
         $this->dieUsage('The revids= parameter may not be used with the list options (limit, startid, endid, dirNewer, start, end).', 'revids');
     }
     if ($pageCount > 1 && $enumRevMode) {
         $this->dieUsage('titles, pageids or a generator was used to supply multiple pages, but the limit, startid, endid, dirNewer, user, excludeuser, start and end parameters may only be used on a single page.', 'multpages');
     }
     $this->addTables('revision');
     $this->addFields(Revision::selectFields());
     $this->addTables('page');
     $this->addWhere('page_id = rev_page');
     $prop = array_flip($params['prop']);
     // Optional fields
     $this->fld_ids = isset($prop['ids']);
     // $this->addFieldsIf('rev_text_id', $this->fld_ids); // should this be exposed?
     $this->fld_flags = isset($prop['flags']);
     $this->fld_timestamp = isset($prop['timestamp']);
     $this->fld_comment = isset($prop['comment']);
     $this->fld_size = isset($prop['size']);
     $this->fld_user = isset($prop['user']);
     $this->token = $params['token'];
     if (!is_null($this->token) || $pageCount > 0) {
         $this->addFields(Revision::selectPageFields());
     }
     if (isset($prop['content'])) {
         // For each page we will request, the user must have read rights for that page
         foreach ($pageSet->getGoodTitles() as $title) {
             if (!$title->userCanRead()) {
                 $this->dieUsage('The current user is not allowed to read ' . $title->getPrefixedText(), 'accessdenied');
             }
         }
         $this->addTables('text');
         $this->addWhere('rev_text_id=old_id');
         $this->addFields('old_id');
         $this->addFields(Revision::selectTextFields());
         $this->fld_content = true;
         $this->expandTemplates = $params['expandtemplates'];
         $this->generateXML = $params['generatexml'];
         if (isset($params['section'])) {
             $this->section = $params['section'];
         } else {
             $this->section = false;
         }
     }
     $userMax = $this->fld_content ? ApiBase::LIMIT_SML1 : ApiBase::LIMIT_BIG1;
     $botMax = $this->fld_content ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_BIG2;
     $limit = $params['limit'];
     if ($limit == 'max') {
         $limit = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
         $this->getResult()->addValue('limits', $this->getModuleName(), $limit);
     }
     if ($enumRevMode) {
         // This is mostly to prevent parameter errors (and optimize SQL?)
         if (!is_null($params['startid']) && !is_null($params['start'])) {
             $this->dieUsage('start and startid cannot be used together', 'badparams');
         }
         if (!is_null($params['endid']) && !is_null($params['end'])) {
             $this->dieUsage('end and endid cannot be used together', 'badparams');
         }
         if (!is_null($params['user']) && !is_null($params['excludeuser'])) {
             $this->dieUsage('user and excludeuser cannot be used together', 'badparams');
         }
         // This code makes an assumption that sorting by rev_id and rev_timestamp produces
         // the same result. This way users may request revisions starting at a given time,
         // but to page through results use the rev_id returned after each page.
         // Switching to rev_id removes the potential problem of having more than
         // one row with the same timestamp for the same page.
         // The order needs to be the same as start parameter to avoid SQL filesort.
         if (is_null($params['startid']) && is_null($params['endid'])) {
             $this->addWhereRange('rev_timestamp', $params['dir'], $params['start'], $params['end']);
         } else {
             $this->addWhereRange('rev_id', $params['dir'], $params['startid'], $params['endid']);
         }
         // must manually initialize unset limit
         if (is_null($limit)) {
             $limit = 10;
         }
         $this->validateLimit('limit', $limit, 1, $userMax, $botMax);
         // There is only one ID, use it
         $this->addWhereFld('rev_page', current(array_keys($pageSet->getGoodTitles())));
         if (!is_null($params['user'])) {
             $this->addWhereFld('rev_user_text', $params['user']);
         } elseif (!is_null($params['excludeuser'])) {
             $this->addWhere('rev_user_text != ' . $this->getDB()->addQuotes($params['excludeuser']));
         }
     } elseif ($revCount > 0) {
         $max = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
         $revs = $pageSet->getRevisionIDs();
         if (self::truncateArray($revs, $max)) {
             $this->setWarning("Too many values supplied for parameter 'revids': the limit is {$max}");
         }
         // Get all revision IDs
         $this->addWhereFld('rev_id', array_keys($revs));
         // assumption testing -- we should never get more then $revCount rows.
         $limit = $revCount;
     } elseif ($pageCount > 0) {
         $max = $this->getMain()->canApiHighLimits() ? $botMax : $userMax;
         $titles = $pageSet->getGoodTitles();
         if (self::truncateArray($titles, $max)) {
             $this->setWarning("Too many values supplied for parameter 'titles': the limit is {$max}");
         }
         // When working in multi-page non-enumeration mode,
         // limit to the latest revision only
         $this->addWhere('page_id=rev_page');
         $this->addWhere('page_latest=rev_id');
         // Get all page IDs
         $this->addWhereFld('page_id', array_keys($titles));
         // assumption testing -- we should never get more then $pageCount rows.
         $limit = $pageCount;
     } else {
         ApiBase::dieDebug(__METHOD__, 'param validation?');
     }
     $this->addOption('LIMIT', $limit + 1);
     $data = array();
     $count = 0;
     $res = $this->select(__METHOD__);
     $db = $this->getDB();
     while ($row = $db->fetchObject($res)) {
         if (++$count > $limit) {
             // We've reached the one extra which shows that there are additional pages to be had. Stop here...
             if (!$enumRevMode) {
                 ApiBase::dieDebug(__METHOD__, 'Got more rows then expected');
             }
             // bug report
             $this->setContinueEnumParameter('startid', intval($row->rev_id));
             break;
         }
         $revision = new Revision($row);
         $this->getResult()->addValue(array('query', 'pages', $revision->getPage(), 'revisions'), null, $this->extractRowInfo($revision));
     }
     $db->freeResult($res);
     // Ensure that all revisions are shown as '<rev>' elements
     $result = $this->getResult();
     if ($result->getIsRawMode()) {
         $data =& $result->getData();
         foreach ($data['query']['pages'] as &$page) {
             if (is_array($page) && array_key_exists('revisions', $page)) {
                 $result->setIndexedTagName($page['revisions'], 'rev');
             }
         }
     }
 }