28use Wikimedia\Minify\CSSMin;
31use Wikimedia\Timestamp\ConvertibleTimestamp;
58 protected $origin = self::ORIGIN_USER_SITEWIDE;
92 if ( $options ===
null ) {
96 foreach ( $options as $member => $option ) {
102 $this->{$member} = $option;
131 foreach ( $this->scripts as $script ) {
132 $pages[$script] = [
'type' =>
'script' ];
137 foreach ( $this->styles as $style ) {
138 $pages[$style] = [
'type' =>
'style' ];
179 $pageStore = MediaWikiServices::getInstance()->getPageStore();
180 $title = $pageStore->getPageByText( $titleText );
190 $handler =
$content->getContentHandler();
199 return $content->serialize( $format );
214 $content = $overrideCallback ? call_user_func( $overrideCallback, $page ) :
null;
218 'Bad content override for "{title}" in ' . __METHOD__,
219 [
'title' => (
string)$page ]
224 $revision = MediaWikiServices::getInstance()
225 ->getRevisionLookup()
226 ->getKnownCurrentRevision( $page );
230 $content = $revision->getContent( SlotRecord::MAIN, RevisionRecord::RAW );
234 'Failed to load content of JS/CSS page "{title}" in ' . __METHOD__,
235 [
'title' => (
string)$page ]
242 if ( $maxRedirects ===
null ) {
243 $maxRedirects = $this->
getConfig()->get(
'MaxRedirects' ) ?: 0;
245 if ( $maxRedirects > 0 ) {
246 $newTitle =
$content->getRedirectTarget();
247 return $newTitle ? $this->
getContentObj( $newTitle, $context, $maxRedirects - 1 ) :
null;
260 if ( $overrideCallback && $this->
getSource() ===
'local' ) {
261 foreach ( $this->
getPages( $context ) as $page => $info ) {
262 $title = Title::newFromText( $page );
263 if (
$title && call_user_func( $overrideCallback,
$title ) !==
null ) {
269 return parent::shouldEmbedModule( $context );
278 foreach ( $this->
getPages( $context ) as $titleText => $options ) {
279 if ( $options[
'type'] !==
'script' ) {
282 $script = $this->
getContent( $titleText, $context );
283 if ( strval( $script ) !==
'' ) {
297 foreach ( $this->
getPages( $context ) as $titleText => $options ) {
298 if ( $options[
'type'] !==
'style' ) {
301 $media = $options[
'media'] ??
'all';
302 $style = $this->
getContent( $titleText, $context );
303 if ( strval( $style ) ===
'' ) {
306 if ( $this->
getFlip( $context ) ) {
307 $style = CSSJanus::transform( $style,
true,
false );
309 $remoteDir = $this->
getConfig()->get(
'ScriptPath' );
310 if ( $remoteDir ===
'' ) {
320 [ CSSMin::class,
'remap' ],
321 [ $style,
false, $remoteDir,
true ]
323 if ( !isset(
$styles[$media] ) ) {
351 $summary = parent::getDefinitionSummary( $context );
353 'pages' => $this->
getPages( $context ),
372 if ( $this->
getGroup() ===
'user' ) {
373 foreach ( $revisions as $revision ) {
374 if ( $revision[
'page_len'] > 0 ) {
385 return count( $revisions ) === 0;
389 $this->titleInfo[$batchKey] = $titleInfo;
394 return "{$title->getNamespace()}:{$title->getDBkey()}";
405 $pageNames = array_keys( $this->
getPages( $context ) );
407 $batchKey = implode(
'|', $pageNames );
408 if ( !isset( $this->titleInfo[$batchKey] ) ) {
409 $this->titleInfo[$batchKey] = static::fetchTitleInfo(
$dbr, $pageNames, __METHOD__ );
416 if ( $overrideCallback ) {
417 foreach ( $pageNames as $page ) {
418 $title = Title::newFromText( $page );
423 'page_latest' =>
'TBD',
424 'page_touched' => ConvertibleTimestamp::now( TS_MW ),
441 $linkBatchFactory = MediaWikiServices::getInstance()->getLinkBatchFactory();
442 $batch = $linkBatchFactory->newLinkBatch();
443 foreach ( $pages as $titleText ) {
444 $title = Title::newFromText( $titleText );
450 if ( !$batch->isEmpty() ) {
453 [
'page_namespace',
'page_title',
'page_touched',
'page_len',
'page_latest' ],
454 $batch->constructSet(
'page', $db ),
457 foreach (
$res as $row ) {
462 'page_len' => $row->page_len,
463 'page_latest' => $row->page_latest,
464 'page_touched' => $row->page_touched,
486 foreach ( $moduleNames as
$name ) {
487 $module = $rl->getModule( $name );
488 if ( $module instanceof
self ) {
489 $mDB = $module->getDB();
491 if ( $mDB->getDomainID() === $db->
getDomainID() ) {
492 $wikiModules[] = $module;
493 $allPages += $module->getPages( $context );
498 if ( !$wikiModules ) {
503 $pageNames = array_keys( $allPages );
505 $hash = sha1( implode(
'|', $pageNames ) );
508 $func = [ static::class,
'fetchTitleInfo' ];
511 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
512 $allInfo =
$cache->getWithSetCallback(
515 static function ( $curVal, &$ttl, array &$setOpts ) use ( $func, $pageNames, $db, $fname ) {
516 $setOpts += Database::getCacheSetOptions( $db );
518 return call_user_func( $func, $db, $pageNames, $fname );
526 foreach ( $wikiModules as $wikiModule ) {
527 $pages = $wikiModule->getPages( $context );
530 foreach ( $pages as $pageName => $unused ) {
531 $title = Title::newFromText( $pageName );
533 $intersect[ self::makeTitleKey(
$title ) ] = 1;
536 $rl->getLogger()->info(
537 'Invalid wiki page title "{title}" in ' . __METHOD__,
538 [
'title' => $pageName ]
542 $info = array_intersect_key( $allInfo, $intersect );
543 $pageNames = array_keys( $pages );
545 $batchKey = implode(
'|', $pageNames );
546 $wikiModule->setTitleInfo( $batchKey, $info );
572 $oldModel = $old->
getSlot( SlotRecord::MAIN, RevisionRecord::RAW )->getModel();
573 if ( in_array( $oldModel, $models ) ) {
578 if ( !$purge && $new ) {
579 $newModel = $new->
getSlot( SlotRecord::MAIN, RevisionRecord::RAW )->getModel();
580 if ( in_array( $newModel, $models ) ) {
586 $title = Title::castFromPageIdentity( $page );
587 $purge = (
$title->isSiteConfigPage() ||
$title->isUserConfigPage() );
591 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
592 $key =
$cache->makeGlobalKey(
'resourceloader-titleinfo', $domain );
593 $cache->touchCheckKey( $key );
605 return ( $this->styles && !$this->scripts ) ? self::LOAD_STYLES : self::LOAD_GENERAL;
const CONTENT_FORMAT_JAVASCRIPT
For JS pages.
const CONTENT_FORMAT_CSS
For CSS pages.
const CONTENT_MODEL_JAVASCRIPT
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
static call( $callable, array $args=[], $ttl=3600)
Shortcut method for creating a MemoizedCallable and invoking it with the specified arguments.
Context object that contains information about the state of a specific ResourceLoader web request.
getContentOverrideCallback()
Return the replaced-content mapping callback.
Abstraction for ResourceLoader modules, with name registration and maxage functionality.
getDependencies(ResourceLoaderContext $context=null)
Get a list of modules this module depends on.
validateScriptFile( $fileName, $contents)
Validate a user-provided JavaScript blob.
getFlip(ResourceLoaderContext $context)
string null $name
Module name.
getSource()
Get the source of this module.
Abstraction for ResourceLoader modules which pull from wiki pages.
array $titleInfo
In-process cache for title info, structured as an array [ <batchKey> // Pipe-separated list of sorted...
getTitleInfo(ResourceLoaderContext $context)
Get the information about the wiki pages for a given context.
getDB()
Get the Database handle used for computing the module version.
static invalidateModuleCache(PageIdentity $page, ?RevisionRecord $old, ?RevisionRecord $new, string $domain)
Clear the preloadTitleInfo() cache for all wiki modules on this wiki on page change if it was a JS or...
__construct(array $options=null)
static preloadTitleInfo(ResourceLoaderContext $context, IDatabase $db, array $moduleNames)
enableModuleContentVersion()
Disable module content versioning.
getPages(ResourceLoaderContext $context)
Subclasses should return an associative array of resources in the module.
shouldEmbedModule(ResourceLoaderContext $context)
static fetchTitleInfo(IDatabase $db, array $pages, $fname=__METHOD__)
static makeTitleKey(LinkTarget $title)
getDefinitionSummary(ResourceLoaderContext $context)
setTitleInfo( $batchKey, array $titleInfo)
array $scripts
List of page names that contain JavaScript.
getStyles(ResourceLoaderContext $context)
isKnownEmpty(ResourceLoaderContext $context)
getGroup()
Get group name.
string null $group
Group of module.
string $origin
Origin defaults to users with sitewide authority.
getContent( $titleText, ResourceLoaderContext $context)
getContentObj(PageIdentity $page, ResourceLoaderContext $context, $maxRedirects=null)
getScript(ResourceLoaderContext $context)
array $styles
List of page names that contain CSS.
static makeComment( $text)
Generate a CSS or JS comment block.
Represents a page (or page fragment) title within MediaWiki.
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
Base interface for content objects.
Interface for objects (potentially) representing an editable wiki page.