Пример #1
0
 /**
  * Do some database updates after deletion
  *
  * @param int $id The page_id value of the page being deleted
  * @param Content|null $content Optional page content to be used when determining
  *   the required updates. This may be needed because $this->getContent()
  *   may already return null when the page proper was deleted.
  * @param Revision|null $revision The latest page revision
  */
 public function doDeleteUpdates($id, Content $content = null, Revision $revision = null)
 {
     try {
         $countable = $this->isCountable();
     } catch (Exception $ex) {
         // fallback for deleting broken pages for which we cannot load the content for
         // some reason. Note that doDeleteArticleReal() already logged this problem.
         $countable = false;
     }
     // Update site status
     DeferredUpdates::addUpdate(new SiteStatsUpdate(0, 1, -(int) $countable, -1));
     // Delete pagelinks, update secondary indexes, etc
     $updates = $this->getDeletionUpdates($content);
     foreach ($updates as $update) {
         DeferredUpdates::addUpdate($update);
     }
     // Reparse any pages transcluding this page
     LinksUpdate::queueRecursiveJobsForTable($this->mTitle, 'templatelinks');
     // Reparse any pages including this image
     if ($this->mTitle->getNamespace() == NS_FILE) {
         LinksUpdate::queueRecursiveJobsForTable($this->mTitle, 'imagelinks');
     }
     // Clear caches
     WikiPage::onArticleDelete($this->mTitle);
     ResourceLoaderWikiModule::invalidateModuleCache($this->mTitle, $revision, null, wfWikiID());
     // Reset this object and the Title object
     $this->loadFromRow(false, self::READ_LATEST);
     // Search engine
     DeferredUpdates::addUpdate(new SearchUpdate($id, $this->mTitle));
 }
Пример #2
0
 /**
  * Updates page_touched for this page; called from LinksUpdate.php
  *
  * @param string $purgeTime [optional] TS_MW timestamp
  * @return bool True if the update succeeded
  */
 public function invalidateCache($purgeTime = null)
 {
     if (wfReadOnly()) {
         return false;
     } elseif ($this->mArticleID === 0) {
         return true;
         // avoid gap locking if we know it's not there
     }
     $dbw = wfGetDB(DB_MASTER);
     $dbw->onTransactionPreCommitOrIdle(function () {
         ResourceLoaderWikiModule::invalidateModuleCache($this, null, null, wfWikiID());
     });
     $conds = $this->pageCond();
     DeferredUpdates::addUpdate(new AutoCommitUpdate($dbw, __METHOD__, function (IDatabase $dbw, $fname) use($conds, $purgeTime) {
         $dbTimestamp = $dbw->timestamp($purgeTime ?: time());
         $dbw->update('page', ['page_touched' => $dbTimestamp], $conds + ['page_touched < ' . $dbw->addQuotes($dbTimestamp)], $fname);
         MediaWikiServices::getInstance()->getLinkCache()->invalidateTitle($this);
     }), DeferredUpdates::PRESEND);
     return true;
 }
 /**
  * @covers ResourceLoaderWikiModule::getGroup
  * @dataProvider provideGetGroup
  */
 public function testGetGroup($params, $expected)
 {
     $module = new ResourceLoaderWikiModule($params);
     $this->assertEquals($expected, $module->getGroup());
 }
 protected function getResourceName($title, $titleText, $options)
 {
     if (isset($options['originalName'])) {
         return $options['originalName'];
     }
     if ($title instanceof GlobalTitle) {
         $name = "[city_id=" . $title->getCityId() . "]:";
         $name .= isset($options['title']) ? $options['title'] : $titleText;
         return $name;
     } else {
         return parent::getResourceName($title, $titleText, $options);
     }
 }
Пример #5
0
 /**
  * Call this to freeze the module queue and JS config and create a formatter.
  *
  * Depending on the Skin, this may get lazy-initialised in either headElement() or
  * getBottomScripts(). See SkinTemplate::prepareQuickTemplate(). Calling this too early may
  * cause unexpected side-effects since disallowUserJs() may be called at any time to change
  * the module filters retroactively. Skins and extension hooks may also add modules until very
  * late in the request lifecycle.
  *
  * @return ResourceLoaderClientHtml
  */
 public function getRlClient()
 {
     if (!$this->rlClient) {
         $context = $this->getRlClientContext();
         $rl = $this->getResourceLoader();
         $this->addModules(['user.options', 'user.tokens']);
         $this->addModuleStyles(['site.styles', 'noscript', 'user.styles', 'user.cssprefs']);
         $this->getSkin()->setupSkinUserCss($this);
         // Prepare exempt modules for buildExemptModules()
         $exemptGroups = ['site' => [], 'noscript' => [], 'private' => [], 'user' => []];
         $exemptStates = [];
         $moduleStyles = $this->getModuleStyles(true);
         // Preload getTitleInfo for isKnownEmpty calls below and in ResourceLoaderClientHtml
         // Separate user-specific batch for improved cache-hit ratio.
         $userBatch = ['user.styles', 'user'];
         $siteBatch = array_diff($moduleStyles, $userBatch);
         $dbr = wfGetDB(DB_REPLICA);
         ResourceLoaderWikiModule::preloadTitleInfo($context, $dbr, $siteBatch);
         ResourceLoaderWikiModule::preloadTitleInfo($context, $dbr, $userBatch);
         // Filter out modules handled by buildExemptModules()
         $moduleStyles = array_filter($moduleStyles, function ($name) use($rl, $context, &$exemptGroups, &$exemptStates) {
             $module = $rl->getModule($name);
             if ($module) {
                 if ($name === 'user.styles' && $this->isUserCssPreview()) {
                     $exemptStates[$name] = 'ready';
                     // Special case in buildExemptModules()
                     return false;
                 }
                 $group = $module->getGroup();
                 if (isset($exemptGroups[$group])) {
                     $exemptStates[$name] = 'ready';
                     if (!$module->isKnownEmpty($context)) {
                         // E.g. Don't output empty <styles>
                         $exemptGroups[$group][] = $name;
                     }
                     return false;
                 }
             }
             return true;
         });
         $this->rlExemptStyleModules = $exemptGroups;
         $isUserModuleFiltered = !$this->filterModules(['user']);
         // If this page filters out 'user', makeResourceLoaderLink will drop it.
         // Avoid indefinite "loading" state or untrue "ready" state (T145368).
         if (!$isUserModuleFiltered) {
             // Manually handled by getBottomScripts()
             $userModule = $rl->getModule('user');
             $userState = $userModule->isKnownEmpty($context) && !$this->isUserJsPreview() ? 'ready' : 'loading';
             $this->rlUserModuleState = $exemptStates['user'] = $userState;
         }
         $rlClient = new ResourceLoaderClientHtml($context, $this->getTarget());
         $rlClient->setConfig($this->getJSVars());
         $rlClient->setModules($this->getModules(true));
         $rlClient->setModuleStyles($moduleStyles);
         $rlClient->setModuleScripts($this->getModuleScripts(true));
         $rlClient->setExemptStates($exemptStates);
         $this->rlClient = $rlClient;
     }
     return $this->rlClient;
 }
Пример #6
0
 /**
  * Load information stored in the database about modules.
  *
  * This method grabs modules dependencies from the database and updates modules
  * objects.
  *
  * This is not inside the module code because it is much faster to
  * request all of the information at once than it is to have each module
  * requests its own information. This sacrifice of modularity yields a substantial
  * performance improvement.
  *
  * @param array $moduleNames List of module names to preload information for
  * @param ResourceLoaderContext $context Context to load the information within
  */
 public function preloadModuleInfo(array $moduleNames, ResourceLoaderContext $context)
 {
     if (!$moduleNames) {
         // Or else Database*::select() will explode, plus it's cheaper!
         return;
     }
     $dbr = wfGetDB(DB_REPLICA);
     $skin = $context->getSkin();
     $lang = $context->getLanguage();
     // Batched version of ResourceLoaderModule::getFileDependencies
     $vary = "{$skin}|{$lang}";
     $res = $dbr->select('module_deps', ['md_module', 'md_deps'], ['md_module' => $moduleNames, 'md_skin' => $vary], __METHOD__);
     // Prime in-object cache for file dependencies
     $modulesWithDeps = [];
     foreach ($res as $row) {
         $module = $this->getModule($row->md_module);
         if ($module) {
             $module->setFileDependencies($context, ResourceLoaderModule::expandRelativePaths(FormatJson::decode($row->md_deps, true)));
             $modulesWithDeps[] = $row->md_module;
         }
     }
     // Register the absence of a dependency row too
     foreach (array_diff($moduleNames, $modulesWithDeps) as $name) {
         $module = $this->getModule($name);
         if ($module) {
             $this->getModule($name)->setFileDependencies($context, []);
         }
     }
     // Batched version of ResourceLoaderWikiModule::getTitleInfo
     ResourceLoaderWikiModule::preloadTitleInfo($context, $dbr, $moduleNames);
     // Prime in-object cache for message blobs for modules with messages
     $modules = [];
     foreach ($moduleNames as $name) {
         $module = $this->getModule($name);
         if ($module && $module->getMessages()) {
             $modules[$name] = $module;
         }
     }
     $store = $this->getMessageBlobStore();
     $blobs = $store->getBlobs($modules, $lang);
     foreach ($blobs as $name => $blob) {
         $modules[$name]->setMessageBlob($blob, $lang);
     }
 }