protected function getLoggedActionsCount()
 {
     $excludedLogTypes = array('patrol');
     $excludedLogTypes = array_map(array($this->db, 'addQuotes'), $excludedLogTypes);
     $excludedLogTypes = "NOT log_type IN (" . implode(',', $excludedLogTypes) . ")";
     $value = $this->db->selectField('logging', 'count(*)', array($excludedLogTypes), __METHOD__);
     if (is_numeric($value)) {
         $value = max(0, $value - 6);
     }
     return $value;
 }
Example #2
0
 private function addCoreDBData()
 {
     if ($this->db->getType() == 'oracle') {
         # Insert 0 user to prevent FK violations
         # Anonymous user
         if (!$this->db->selectField('user', '1', ['user_id' => 0])) {
             $this->db->insert('user', ['user_id' => 0, 'user_name' => 'Anonymous'], __METHOD__, ['IGNORE']);
         }
         # Insert 0 page to prevent FK violations
         # Blank page
         if (!$this->db->selectField('page', '1', ['page_id' => 0])) {
             $this->db->insert('page', ['page_id' => 0, 'page_namespace' => 0, 'page_title' => ' ', 'page_restrictions' => null, 'page_is_redirect' => 0, 'page_is_new' => 0, 'page_random' => 0, 'page_touched' => $this->db->timestamp(), 'page_latest' => 0, 'page_len' => 0], __METHOD__, ['IGNORE']);
         }
     }
     User::resetIdByNameCache();
     // Make sysop user
     $user = static::getTestSysop()->getUser();
     // Make 1 page with 1 revision
     $page = WikiPage::factory(Title::newFromText('UTPage'));
     if ($page->getId() == 0) {
         $page->doEditContent(new WikitextContent('UTContent'), 'UTPageSummary', EDIT_NEW, false, $user);
         // doEditContent() probably started the session via
         // User::loadFromSession(). Close it now.
         if (session_id() !== '') {
             session_write_close();
             session_id('');
         }
     }
 }
Example #3
0
 /**
  * Update CategoryLinks collation
  */
 protected function doCollationUpdate()
 {
     global $wgCategoryCollation;
     if ($this->db->fieldExists('categorylinks', 'cl_collation', __METHOD__)) {
         if ($this->db->selectField('categorylinks', 'COUNT(*)', 'cl_collation != ' . $this->db->addQuotes($wgCategoryCollation), __METHOD__) == 0) {
             $this->output("...collations up-to-date.\n");
             return;
         }
         $this->output("Updating category collations...");
         $task = $this->maintenance->runChild('UpdateCollation');
         $task->execute();
         $this->output("...done.\n");
     }
 }
Example #4
0
 function buildTable($table, $key, $callback)
 {
     $count = $this->dbw->selectField($table, 'count(*)', '', __METHOD__);
     $this->init($count, $table);
     $this->output("Processing {$table}...\n");
     $result = $this->getDB(DB_REPLICA)->select($table, '*', [], __METHOD__);
     foreach ($result as $row) {
         $update = call_user_func($callback, $row, null);
         if ($update) {
             $this->progress(1);
         } else {
             $this->progress(0);
         }
     }
     $this->output("Finished {$table}... {$this->updated} of {$this->processed} rows updated\n");
 }
Example #5
0
 public static function setAvatar($user)
 {
     global $wgVanillaDB;
     $fname = "Vanilla::setAvatar";
     wfProfileIn($fname);
     $db = new Database($wgVanillaDB['host'], $wgVanillaDB['user'], $wgVanillaDB['password'], $wgVanillaDB['dbname']);
     // get vanilla user id
     $vid = $db->selectField('GDN_UserAuthentication', array('UserID'), array('ForeignUserKey' => $user->getID()));
     if (!$vid) {
         return false;
     }
     $updates = array("Photo" => Avatar::getAvatarURL($user->getName()));
     $opts = array('UserID' => $vid);
     $db->update('GDN_User', $updates, $opts);
     wfDebug("Vanilla: Updating avatar " . print_r($updates, true) . print_r($opts, true) . "\n");
     wfProfileOut($fname);
     return true;
 }
Example #6
0
 function updateRemote()
 {
     global $wgUser, $wgVanillaDB;
     try {
         $db = new Database($wgVanillaDB['host'], $wgVanillaDB['user'], $wgVanillaDB['password'], $wgVanillaDB['dbname']);
         $oldignore = $db->ignoreErrors(true);
         // get vanilla user id
         $vid = $db->selectField('GDN_UserAuthentication', array('UserID'), array('ForeignUserKey' => $wgUser->getID()));
         if (!$vid) {
             return true;
         }
         $photo = Avatar::getAvatarURL($wgUser->getName());
         $updates = array("Photo" => $photo, "Email" => $wgUser->getEmail());
         if (in_array('bureaucrat', $wgUser->getGroups())) {
             $updates["Admin"] = 1;
         } else {
             $updates["Admin"] = 0;
         }
         $opts = array('UserID' => $vid);
         $db->update('GDN_User', $updates, $opts);
         if (self::isUserBlocked()) {
             $db->update('GDN_UserRole', array('RoleID = 1'), $opts);
         } else {
             if (in_array('bureaucrat', $wgUser->getGroups())) {
                 $db->update('GDN_UserRole', array('RoleID = 16'), $opts);
             } else {
                 if (in_array('sysop', $wgUser->getGroups())) {
                     $db->update("GDN_User", array('Permissions' => 'a:14:{i:0;s:19:"Garden.SignIn.Allow";i:1;s:22:"Garden.Activity.Delete";i:2;s:25:"Vanilla.Categories.Manage";i:3;s:19:"Vanilla.Spam.Manage";s:24:"Vanilla.Discussions.View";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:23:"Vanilla.Discussions.Add";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:24:"Vanilla.Discussions.Edit";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:28:"Vanilla.Discussions.Announce";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:24:"Vanilla.Discussions.Sink";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:25:"Vanilla.Discussions.Close";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:26:"Vanilla.Discussions.Delete";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:20:"Vanilla.Comments.Add";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:21:"Vanilla.Comments.Edit";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:23:"Vanilla.Comments.Delete";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}}'), $opts);
                     $db->update('GDN_UserRole', array('RoleID = 32'), $opts);
                 } else {
                     $db->update("GDN_User", array('Permissions' => 'a:4:{i:0;s:19:"Garden.SignIn.Allow";s:24:"Vanilla.Discussions.View";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:23:"Vanilla.Discussions.Add";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}s:20:"Vanilla.Comments.Add";a:6:{i:0;s:1:"1";i:1;s:1:"4";i:2;s:1:"5";i:3;s:1:"7";i:4;s:1:"8";i:5;s:1:"9";}}'), $opts);
                     $db->update('GDN_UserRole', array('RoleID = 8'), $opts);
                     print $db->lastQuery();
                 }
             }
         }
         $db->ignoreErrors($oldignore);
     } catch (Exception $e) {
         print "oops {$e->getMessage()}\n";
     }
     return true;
 }
Example #7
0
 /**
  * Copy all rows from $srcTable to $dstTable
  * @param string $srcTable
  * @param string $dstTable
  */
 function sync($srcTable, $dstTable)
 {
     $batchSize = 1000;
     $minTs = $this->dbw->selectField($srcTable, 'MIN(log_timestamp)', false, __METHOD__);
     $minTsUnix = wfTimestamp(TS_UNIX, $minTs);
     $numRowsCopied = 0;
     while (true) {
         $maxTs = $this->dbw->selectField($srcTable, 'MAX(log_timestamp)', false, __METHOD__);
         $copyPos = $this->dbw->selectField($dstTable, 'MAX(log_timestamp)', false, __METHOD__);
         $maxTsUnix = wfTimestamp(TS_UNIX, $maxTs);
         $copyPosUnix = wfTimestamp(TS_UNIX, $copyPos);
         if ($copyPos === null) {
             $percent = 0;
         } else {
             $percent = ($copyPosUnix - $minTsUnix) / ($maxTsUnix - $minTsUnix) * 100;
         }
         printf("%s  %.2f%%\n", $copyPos, $percent);
         # Handle all entries with timestamp equal to $copyPos
         if ($copyPos !== null) {
             $numRowsCopied += $this->copyExactMatch($srcTable, $dstTable, $copyPos);
         }
         # Now copy a batch of rows
         if ($copyPos === null) {
             $conds = false;
         } else {
             $conds = ['log_timestamp > ' . $this->dbw->addQuotes($copyPos)];
         }
         $srcRes = $this->dbw->select($srcTable, '*', $conds, __METHOD__, ['LIMIT' => $batchSize, 'ORDER BY' => 'log_timestamp']);
         if (!$srcRes->numRows()) {
             # All done
             break;
         }
         $batch = [];
         foreach ($srcRes as $srcRow) {
             $batch[] = (array) $srcRow;
         }
         $this->dbw->insert($dstTable, $batch, __METHOD__);
         $numRowsCopied += count($batch);
         wfWaitForSlaves();
     }
     echo "Copied {$numRowsCopied} rows\n";
 }
Example #8
0
 /**
  * Get previous revision Id for this page_id
  * This is used to populate rev_parent_id on save
  * @param Database $db
  * @return int
  */
 private function getPreviousRevisionId($db)
 {
     if (is_null($this->mPage)) {
         return 0;
     }
     # Use page_latest if ID is not given
     if (!$this->mId) {
         $prevId = $db->selectField('page', 'page_latest', array('page_id' => $this->mPage), __METHOD__);
     } else {
         $prevId = $db->selectField('revision', 'rev_id', array('rev_page' => $this->mPage, 'rev_id < ' . $this->mId), __METHOD__, array('ORDER BY' => 'rev_id DESC'));
     }
     return intval($prevId);
 }
Example #9
0
 /**
  * Tries to get the revision text for a revision id.
  * Export transformations are applied if the content model can is given or can be
  * determined from the database.
  *
  * Upon errors, retries (Up to $this->maxFailures tries each call).
  * If still no good revision get could be found even after this retrying, "" is returned.
  * If no good revision text could be returned for
  * $this->maxConsecutiveFailedTextRetrievals consecutive calls to getText, MWException
  * is thrown.
  *
  * @param string $id The revision id to get the text for
  * @param string|bool|null $model The content model used to determine
  *  applicable export transformations.
  *  If $model is null, it will be determined from the database.
  * @param string|null $format The content format used when applying export transformations.
  *
  * @throws MWException
  * @return string The revision text for $id, or ""
  */
 function getText($id, $model = null, $format = null)
 {
     global $wgContentHandlerUseDB;
     $prefetchNotTried = true;
     // Whether or not we already tried to get the text via prefetch.
     $text = false;
     // The candidate for a good text. false if no proper value.
     $failures = 0;
     // The number of times, this invocation of getText already failed.
     // The number of times getText failed without yielding a good text in between.
     static $consecutiveFailedTextRetrievals = 0;
     $this->fetchCount++;
     // To allow to simply return on success and do not have to worry about book keeping,
     // we assume, this fetch works (possible after some retries). Nevertheless, we koop
     // the old value, so we can restore it, if problems occur (See after the while loop).
     $oldConsecutiveFailedTextRetrievals = $consecutiveFailedTextRetrievals;
     $consecutiveFailedTextRetrievals = 0;
     if ($model === null && $wgContentHandlerUseDB) {
         $row = $this->db->selectRow('revision', ['rev_content_model', 'rev_content_format'], ['rev_id' => $this->thisRev], __METHOD__);
         if ($row) {
             $model = $row->rev_content_model;
             $format = $row->rev_content_format;
         }
     }
     if ($model === null || $model === '') {
         $model = false;
     }
     while ($failures < $this->maxFailures) {
         // As soon as we found a good text for the $id, we will return immediately.
         // Hence, if we make it past the try catch block, we know that we did not
         // find a good text.
         try {
             // Step 1: Get some text (or reuse from previous iteratuon if checking
             //         for plausibility failed)
             // Trying to get prefetch, if it has not been tried before
             if ($text === false && isset($this->prefetch) && $prefetchNotTried) {
                 $prefetchNotTried = false;
                 $tryIsPrefetch = true;
                 $text = $this->prefetch->prefetch(intval($this->thisPage), intval($this->thisRev));
                 if ($text === null) {
                     $text = false;
                 }
                 if (is_string($text) && $model !== false) {
                     // Apply export transformation to text coming from an old dump.
                     // The purpose of this transformation is to convert up from legacy
                     // formats, which may still be used in the older dump that is used
                     // for pre-fetching. Applying the transformation again should not
                     // interfere with content that is already in the correct form.
                     $text = $this->exportTransform($text, $model, $format);
                 }
             }
             if ($text === false) {
                 // Fallback to asking the database
                 $tryIsPrefetch = false;
                 if ($this->spawn) {
                     $text = $this->getTextSpawned($id);
                 } else {
                     $text = $this->getTextDb($id);
                 }
                 if ($text !== false && $model !== false) {
                     // Apply export transformation to text coming from the database.
                     // Prefetched text should already have transformations applied.
                     $text = $this->exportTransform($text, $model, $format);
                 }
                 // No more checks for texts from DB for now.
                 // If we received something that is not false,
                 // We treat it as good text, regardless of whether it actually is or is not
                 if ($text !== false) {
                     return $text;
                 }
             }
             if ($text === false) {
                 throw new MWException("Generic error while obtaining text for id " . $id);
             }
             // We received a good candidate for the text of $id via some method
             // Step 2: Checking for plausibility and return the text if it is
             //         plausible
             $revID = intval($this->thisRev);
             if (!isset($this->db)) {
                 throw new MWException("No database available");
             }
             if ($model !== CONTENT_MODEL_WIKITEXT) {
                 $revLength = strlen($text);
             } else {
                 $revLength = $this->db->selectField('revision', 'rev_len', ['rev_id' => $revID]);
             }
             if (strlen($text) == $revLength) {
                 if ($tryIsPrefetch) {
                     $this->prefetchCount++;
                 }
                 return $text;
             }
             $text = false;
             throw new MWException("Received text is unplausible for id " . $id);
         } catch (Exception $e) {
             $msg = "getting/checking text " . $id . " failed (" . $e->getMessage() . ")";
             if ($failures + 1 < $this->maxFailures) {
                 $msg .= " (Will retry " . ($this->maxFailures - $failures - 1) . " more times)";
             }
             $this->progress($msg);
         }
         // Something went wrong; we did not a text that was plausible :(
         $failures++;
         // A failure in a prefetch hit does not warrant resetting db connection etc.
         if (!$tryIsPrefetch) {
             // After backing off for some time, we try to reboot the whole process as
             // much as possible to not carry over failures from one part to the other
             // parts
             sleep($this->failureTimeout);
             try {
                 $this->rotateDb();
                 if ($this->spawn) {
                     $this->closeSpawn();
                     $this->openSpawn();
                 }
             } catch (Exception $e) {
                 $this->progress("Rebooting getText infrastructure failed (" . $e->getMessage() . ")" . " Trying to continue anyways");
             }
         }
     }
     // Retirieving a good text for $id failed (at least) maxFailures times.
     // We abort for this $id.
     // Restoring the consecutive failures, and maybe aborting, if the dump
     // is too broken.
     $consecutiveFailedTextRetrievals = $oldConsecutiveFailedTextRetrievals + 1;
     if ($consecutiveFailedTextRetrievals > $this->maxConsecutiveFailedTextRetrievals) {
         throw new MWException("Graceful storage failure");
     }
     return "";
 }