/** * Load a revision based on a known page ID and current revision ID from the DB * * This method allows for the use of caching, though accessing anything that normally * requires permission checks (aside from the text) will trigger a small DB lookup. * The title will also be lazy loaded, though setTitle() can be used to preload it. * * @param IDatabase $db * @param int $pageId Page ID * @param int $revId Known current revision of this page * @return Revision|bool Returns false if missing * @since 1.28 */ public static function newKnownCurrent(IDatabase $db, $pageId, $revId) { $cache = MediaWikiServices::getInstance()->getMainWANObjectCache(); return $cache->getWithSetCallback($cache->makeGlobalKey('revision', $db->getWikiID(), $pageId, $revId), $cache::TTL_WEEK, function ($curValue, &$ttl, array &$setOpts) use($db, $pageId, $revId) { $setOpts += Database::getCacheSetOptions($db); $rev = Revision::loadFromPageId($db, $pageId, $revId); // Reflect revision deletion and user renames if ($rev) { $rev->mTitle = null; // mutable; lazy-load $rev->mRefreshMutableFields = true; } return $rev ?: false; // don't cache negatives }); }
/** * @since 1.28 * @param ResourceLoaderContext $context * @param IDatabase $db * @param string[] $moduleNames */ public static function preloadTitleInfo(ResourceLoaderContext $context, IDatabase $db, array $moduleNames) { $rl = $context->getResourceLoader(); // getDB() can be overridden to point to a foreign database. // For now, only preload local. In the future, we could preload by wikiID. $allPages = []; /** @var ResourceLoaderWikiModule[] $wikiModules */ $wikiModules = []; foreach ($moduleNames as $name) { $module = $rl->getModule($name); if ($module instanceof self) { $mDB = $module->getDB(); // Subclasses may disable getDB and implement getTitleInfo differently if ($mDB && $mDB->getWikiID() === $db->getWikiID()) { $wikiModules[] = $module; $allPages += $module->getPages($context); } } } $pageNames = array_keys($allPages); sort($pageNames); $hash = sha1(implode('|', $pageNames)); // Avoid Zend bug where "static::" does not apply LSB in the closure $func = [static::class, 'fetchTitleInfo']; $fname = __METHOD__; $cache = ObjectCache::getMainWANInstance(); $allInfo = $cache->getWithSetCallback($cache->makeGlobalKey('resourceloader', 'titleinfo', $db->getWikiID(), $hash), $cache::TTL_HOUR, function ($curVal, &$ttl, array &$setOpts) use($func, $pageNames, $db, $fname) { $setOpts += Database::getCacheSetOptions($db); return call_user_func($func, $db, $pageNames, $fname); }, ['checkKeys' => [$cache->makeGlobalKey('resourceloader', 'titleinfo', $db->getWikiID())]]); foreach ($wikiModules as $wikiModule) { $pages = $wikiModule->getPages($context); // Before we intersect, map the names to canonical form (T145673). $intersect = []; foreach ($pages as $page => $unused) { $title = Title::newFromText($page); if ($title) { $intersect[$title->getPrefixedText()] = 1; } else { // Page name may be invalid if user-provided (e.g. gadgets) $rl->getLogger()->info('Invalid wiki page title "{title}" in ' . __METHOD__, ['title' => $page]); } } $info = array_intersect_key($allInfo, $intersect); $pageNames = array_keys($pages); sort($pageNames); $key = implode('|', $pageNames); $wikiModule->setTitleInfo($key, $info); } }