public function execute()
 {
     $dbw = CentralAuthUser::getCentralDB();
     $databaseUpdates = new UsersToRenameDatabaseUpdates($dbw);
     // CentralAuthUser::chooseHomeWiki is expensive and called
     // multiple times, so lets cache it.
     $cache = new MapCacheLRU($this->mBatchSize);
     do {
         $rows = $this->doQuery();
         $insertRows = array();
         foreach ($rows as $row) {
             $this->lName = $row->name;
             $this->lWiki = $row->wiki;
             if ($cache->has($row->name)) {
                 $attachableWikis = $cache->get($row->name);
             } else {
                 $ca = new CentralAuthUser($row->name);
                 $attachableWikis = array();
                 $unattached = $ca->queryUnattached();
                 if ($ca->exists()) {
                     $home = $ca->getHomeWiki();
                     $attachableWikis[] = $home;
                     foreach ($unattached as $wiki => $info) {
                         if ($ca->getEmailAuthenticationTimestamp() && $info['email'] === $ca->getEmail() && !is_null($info['emailAuthenticated'])) {
                             $attachableWikis[] = $wiki;
                         }
                     }
                 } else {
                     $home = $ca->chooseHomeWiki($unattached);
                     $attachableWikis[] = $home;
                     if ($unattached[$home]['email'] && isset($unattached[$home]['emailAuthenticated'])) {
                         foreach ($unattached as $wiki => $info) {
                             if ($wiki !== $home && $unattached[$home]['email'] === $info['email'] && isset($info['emailAuthenticated'])) {
                                 $attachableWikis[] = $wiki;
                             }
                         }
                     }
                 }
                 $cache->set($row->name, $attachableWikis);
             }
             if (!in_array($row->wiki, $attachableWikis)) {
                 // Unattached account which is not attachable,
                 // so they're getting renamed :(
                 $this->output("{$row->name}@{$row->wiki} is going to be renamed.\n");
                 $insertRows[] = (array) $row;
             }
         }
         $databaseUpdates->batchInsert($insertRows);
         $count = $dbw->affectedRows();
         $this->output("Inserted {$count} users who we will rename\n");
         $this->output("Waiting for slaves...\n");
         CentralAuthUser::waitForSlaves();
     } while ($count !== 0);
 }
Esempio n. 2
0
 /**
  * Get an array of language names, indexed by code.
  * @param null|string $inLanguage Code of language in which to return the names
  *		Use null for autonyms (native names)
  * @param string $include One of:
  *		'all' all available languages
  *		'mw' only if the language is defined in MediaWiki or wgExtraLanguageNames (default)
  *		'mwfile' only if the language is in 'mw' *and* has a message file
  * @return array Language code => language name
  * @since 1.20
  */
 public static function fetchLanguageNames($inLanguage = null, $include = 'mw')
 {
     $cacheKey = $inLanguage === null ? 'null' : $inLanguage;
     $cacheKey .= ":{$include}";
     if (self::$languageNameCache === null) {
         self::$languageNameCache = new MapCacheLRU(20);
     }
     if (self::$languageNameCache->has($cacheKey)) {
         $ret = self::$languageNameCache->get($cacheKey);
     } else {
         $ret = self::fetchLanguageNamesUncached($inLanguage, $include);
         self::$languageNameCache->set($cacheKey, $ret);
     }
     return $ret;
 }
Esempio n. 3
0
 /**
  * Get the grammar transformations data for the language.
  * Used like grammar forms, with {{GRAMMAR}} and cases,
  * but uses pairs of regexes and replacements instead of code.
  *
  * @return array[] Array of grammar transformations.
  * @throws MWException
  * @since 1.28
  */
 public function getGrammarTransformations()
 {
     $languageCode = $this->getCode();
     if (self::$grammarTransformations === null) {
         self::$grammarTransformations = new MapCacheLRU(10);
     }
     if (self::$grammarTransformations->has($languageCode)) {
         return self::$grammarTransformations->get($languageCode);
     }
     $data = [];
     $grammarDataFile = __DIR__ . "/data/grammarTransformations/{$languageCode}.json";
     if (is_readable($grammarDataFile)) {
         $data = FormatJson::decode(file_get_contents($grammarDataFile), true);
         if ($data === null) {
             throw new MWException("Invalid grammar data for \"{$languageCode}\".");
         }
         self::$grammarTransformations->set($languageCode, $data);
     }
     return $data;
 }
Esempio n. 4
0
 /**
  * Fetch the current revision of a given title. Note that the revision
  * (and even the title) may not exist in the database, so everything
  * contributing to the output of the parser should use this method
  * where possible, rather than getting the revisions themselves. This
  * method also caches its results, so using it benefits performance.
  *
  * @since 1.24
  * @param Title $title
  * @return Revision
  */
 public function fetchCurrentRevisionOfTitle($title)
 {
     $cacheKey = $title->getPrefixedDBkey();
     if (!$this->currentRevisionCache) {
         $this->currentRevisionCache = new MapCacheLRU(100);
     }
     if (!$this->currentRevisionCache->has($cacheKey)) {
         $this->currentRevisionCache->set($cacheKey, call_user_func($this->mOptions->getCurrentRevisionCallback(), $title, $this));
     }
     return $this->currentRevisionCache->get($cacheKey);
 }
 /**
  * Clears cache
  */
 public function clear()
 {
     $this->mGoodLinks->clear();
     $this->mBadLinks->clear();
 }
Esempio n. 6
0
 /**
  * Fetched the current revision of the given title and return this.
  * Will increment the expensive function count and
  * add a template link to get the value refreshed on changes.
  * For a given title, which is equal to the current parser title,
  * the revision object from the parser is used, when that is the current one
  *
  * @param Parser $parser
  * @param Title $title
  * @return Revision
  * @since 1.23
  */
 private static function getCachedRevisionObject($parser, $title = null)
 {
     static $cache = null;
     if ($cache == null) {
         $cache = new MapCacheLRU(50);
     }
     if (is_null($title)) {
         return null;
     }
     // Use the revision from the parser itself, when param is the current page
     // and the revision is the current one
     if ($title->equals($parser->getTitle())) {
         $parserRev = $parser->getRevisionObject();
         if ($parserRev && $parserRev->isCurrent()) {
             // force reparse after edit with vary-revision flag
             $parser->getOutput()->setFlag('vary-revision');
             wfDebug(__METHOD__ . ": use current revision from parser, setting vary-revision...\n");
             return $parserRev;
         }
     }
     // Normalize name for cache
     $page = $title->getPrefixedDBkey();
     if ($cache->has($page)) {
         // cache contains null values
         return $cache->get($page);
     }
     if ($parser->incrementExpensiveFunctionCount()) {
         $rev = Revision::newFromTitle($title, false, Revision::READ_NORMAL);
         $pageID = $rev ? $rev->getPage() : 0;
         $revID = $rev ? $rev->getId() : 0;
         $cache->set($page, $rev);
         // maybe null
         // Register dependency in templatelinks
         $parser->getOutput()->addTemplate($title, $pageID, $revID);
         return $rev;
     }
     $cache->set($page, null);
     return null;
 }
Esempio n. 7
0
 /**
  * Lazy-load the revision's text.
  * Currently hardcoded to the 'text' table storage engine.
  *
  * @return string|bool The revision's text, or false on failure
  */
 protected function loadText()
 {
     // Caching may be beneficial for massive use of external storage
     global $wgRevisionCacheExpiry;
     static $processCache = null;
     if (!$processCache) {
         $processCache = new MapCacheLRU(10);
     }
     $cache = ObjectCache::getMainWANInstance();
     $textId = $this->getTextId();
     $key = wfMemcKey('revisiontext', 'textid', $textId);
     if ($wgRevisionCacheExpiry) {
         if ($processCache->has($key)) {
             return $processCache->get($key);
         }
         $text = $cache->get($key);
         if (is_string($text)) {
             $processCache->set($key, $text);
             return $text;
         }
     }
     // If we kept data for lazy extraction, use it now...
     if ($this->mTextRow !== null) {
         $row = $this->mTextRow;
         $this->mTextRow = null;
     } else {
         $row = null;
     }
     if (!$row) {
         // Text data is immutable; check slaves first.
         $dbr = wfGetDB(DB_SLAVE);
         $row = $dbr->selectRow('text', ['old_text', 'old_flags'], ['old_id' => $textId], __METHOD__);
     }
     // Fallback to the master in case of slave lag. Also use FOR UPDATE if it was
     // used to fetch this revision to avoid missing the row due to REPEATABLE-READ.
     $forUpdate = $this->mQueryFlags & self::READ_LOCKING == self::READ_LOCKING;
     if (!$row && ($forUpdate || wfGetLB()->getServerCount() > 1)) {
         $dbw = wfGetDB(DB_MASTER);
         $row = $dbw->selectRow('text', ['old_text', 'old_flags'], ['old_id' => $textId], __METHOD__, $forUpdate ? ['FOR UPDATE'] : []);
     }
     if (!$row) {
         wfDebugLog('Revision', "No text row with ID '{$textId}' (revision {$this->getId()}).");
     }
     $text = self::getRevisionText($row);
     if ($row && $text === false) {
         wfDebugLog('Revision', "No blob for text row '{$textId}' (revision {$this->getId()}).");
     }
     # No negative caching -- negative hits on text rows may be due to corrupted slave servers
     if ($wgRevisionCacheExpiry && $text !== false) {
         $processCache->set($key, $text);
         $cache->set($key, $text, $wgRevisionCacheExpiry);
     }
     return $text;
 }