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; }
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(''); } } }
/** * 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"); } }
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"); }
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; }
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; }
/** * 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"; }
/** * 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); }
/** * 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 ""; }