resourceloader: Add/change ResourceLoaderModifyEmbeddedSourceUrls hook

We've discovered some new requirements.

Follow-up to 31f614f732.
The hook was not in a release yet, so we can rename it.

Bug: T371530
Change-Id: I82d8ae69c27a38c45eab5d19c063f0b9515b8ec8
This commit is contained in:
Bartosz Dziewoński 2024-09-27 19:43:25 +02:00
parent 1ec2185a55
commit 531ba3aad0
10 changed files with 77 additions and 53 deletions

View file

@ -120,7 +120,7 @@ For notes on 1.42.x and older releases, see HISTORY.
which takes two timestamps and a precision in order to calculate a more
accurate text representation of duration.
* Added an interactive mode to the install.php maintenance script.
* The ResourceLoaderModifyStartupSourceUrls hook was added.
* The ResourceLoaderModifyEmbeddedSourceUrls hook was added.
* The AuthManagerFilterProviders hook was added.
* The AuthManagerVerifyAuthentication hook was added.
* The OutputPageRenderCategoryLink hook was added, as a replacement for the

View file

@ -2131,7 +2131,7 @@ $wgAutoloadLocalClasses = [
'MediaWiki\\ResourceLoader\\Hook\\ResourceLoaderForeignApiModulesHook' => __DIR__ . '/includes/ResourceLoader/Hook/ResourceLoaderForeignApiModulesHook.php',
'MediaWiki\\ResourceLoader\\Hook\\ResourceLoaderGetConfigVarsHook' => __DIR__ . '/includes/ResourceLoader/Hook/ResourceLoaderGetConfigVarsHook.php',
'MediaWiki\\ResourceLoader\\Hook\\ResourceLoaderJqueryMsgModuleMagicWordsHook' => __DIR__ . '/includes/ResourceLoader/Hook/ResourceLoaderJqueryMsgModuleMagicWordsHook.php',
'MediaWiki\\ResourceLoader\\Hook\\ResourceLoaderModifyStartupSourceUrlsHook' => __DIR__ . '/includes/ResourceLoader/Hook/ResourceLoaderModifyStartupSourceUrlsHook.php',
'MediaWiki\\ResourceLoader\\Hook\\ResourceLoaderModifyEmbeddedSourceUrlsHook' => __DIR__ . '/includes/ResourceLoader/Hook/ResourceLoaderModifyEmbeddedSourceUrlsHook.php',
'MediaWiki\\ResourceLoader\\Hook\\ResourceLoaderRegisterModulesHook' => __DIR__ . '/includes/ResourceLoader/Hook/ResourceLoaderRegisterModulesHook.php',
'MediaWiki\\ResourceLoader\\Hook\\ResourceLoaderSiteModulePagesHook' => __DIR__ . '/includes/ResourceLoader/Hook/ResourceLoaderSiteModulePagesHook.php',
'MediaWiki\\ResourceLoader\\Hook\\ResourceLoaderSiteStylesModulePagesHook' => __DIR__ . '/includes/ResourceLoader/Hook/ResourceLoaderSiteStylesModulePagesHook.php',

View file

@ -0,0 +1,33 @@
<?php
namespace MediaWiki\ResourceLoader\Hook;
/**
* This is a hook handler interface, see docs/Hooks.md.
* Use the hook name "ResourceLoaderModifyEmbeddedSourceUrls" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup ResourceLoaderHooks
*/
interface ResourceLoaderModifyEmbeddedSourceUrlsHook {
/**
* Allow modifying source URLs (i.e. URLs to load.php, see {@link ResourceLoader::getSources()})
* when they are used for output that may be embedded in the page HTML, rather than referenced
* using `<link>` etc., and thus the URL will be expanded relative to index.php URLs, rather than
* other load.php URLs.
*
* The hook must not add or remove sources, and calling the new URL should have a roughly similar
* outcome to calling the old URL. It is mainly intended to support serving index.php and load.php
* from different domains.
*
* This hook is currently called from StartUpModule and ImageModule.
*
* @since 1.43
*
* @param string[] &$urls An array of source name => URL; the URL might be relative.
* @return void This hook must not abort, it must return no value
*/
public function onResourceLoaderModifyEmbeddedSourceUrls( array &$urls ): void;
}

View file

@ -1,35 +0,0 @@
<?php
namespace MediaWiki\ResourceLoader\Hook;
use MediaWiki\ResourceLoader\Context;
/**
* This is a hook handler interface, see docs/Hooks.md.
* Use the hook name "ResourceLoaderForeignApiModules" to register handlers implementing this interface.
*
* @stable to implement
* @ingroup ResourceLoaderHooks
*/
interface ResourceLoaderModifyStartupSourceUrlsHook {
/**
* Allow modifying source URLs (i.e. URLs to load.php, see {@link ResourceLoader::getSources()})
* before they get embedded in the JS generated for the startup module.
*
* The hook must not add or remove sources, and calling the new URL should have a roughly
* similar outcome to calling the old URL. It is mainly intended to preserve URL modifications
* that might affect the code generated for the modules (e.g. when load.php?modules=startup is
* called on the mobile site, it should generate source URLs which also use the mobile site).
*
* This hook is called from StartUpModule.
*
* @since 1.43
*
* @param string[] &$urls An array of source name => URL; the URL might be relative.
* @param Context $context
* @return void This hook must not abort, it must return no value
*/
public function onResourceLoaderModifyStartupSourceUrls( array &$urls, Context $context ): void;
}

View file

@ -13,7 +13,7 @@ use MediaWiki\HookContainer\HookContainer;
class HookRunner implements
\MediaWiki\ResourceLoader\Hook\ResourceLoaderExcludeUserOptionsHook,
\MediaWiki\ResourceLoader\Hook\ResourceLoaderForeignApiModulesHook,
\MediaWiki\ResourceLoader\Hook\ResourceLoaderModifyStartupSourceUrlsHook,
\MediaWiki\ResourceLoader\Hook\ResourceLoaderModifyEmbeddedSourceUrlsHook,
\MediaWiki\ResourceLoader\Hook\ResourceLoaderRegisterModulesHook,
\MediaWiki\ResourceLoader\Hook\ResourceLoaderSiteModulePagesHook,
\MediaWiki\ResourceLoader\Hook\ResourceLoaderSiteStylesModulePagesHook,
@ -43,10 +43,10 @@ class HookRunner implements
);
}
public function onResourceLoaderModifyStartupSourceUrls( array &$urls, Context $context ): void {
public function onResourceLoaderModifyEmbeddedSourceUrls( array &$urls ): void {
$this->container->run(
'ResourceLoaderModifyStartupSourceUrls',
[ &$urls, $context ],
'ResourceLoaderModifyEmbeddedSourceUrls',
[ &$urls ],
[ 'abortable' => false ]
);
}

View file

@ -20,6 +20,7 @@
*/
namespace MediaWiki\ResourceLoader;
use DomainException;
use InvalidArgumentException;
use Wikimedia\Minify\CSSMin;
@ -335,7 +336,14 @@ class ImageModule extends Module {
// Build CSS rules
$rules = [];
$script = $context->getResourceLoader()->getLoadScript( $this->getSource() );
$sources = $oldSources = $context->getResourceLoader()->getSources();
$this->getHookRunner()->onResourceLoaderModifyEmbeddedSourceUrls( $sources );
if ( array_keys( $sources ) !== array_keys( $oldSources ) ) {
throw new DomainException( 'ResourceLoaderModifyEmbeddedSourceUrls hook must not add or remove sources' );
}
$script = $sources[ $this->getSource() ];
$selectors = $this->getSelectors();
foreach ( $this->getImages( $context ) as $name => $image ) {

View file

@ -254,9 +254,9 @@ class StartUpModule extends Module {
// Register sources
$sources = $oldSources = $resourceLoader->getSources();
$this->getHookRunner()->onResourceLoaderModifyStartupSourceUrls( $sources, $context );
$this->getHookRunner()->onResourceLoaderModifyEmbeddedSourceUrls( $sources );
if ( array_keys( $sources ) !== array_keys( $oldSources ) ) {
throw new DomainException( 'ResourceLoaderModifyStartupSourceUrls hook must not add or remove sources' );
throw new DomainException( 'ResourceLoaderModifyEmbeddedSourceUrls hook must not add or remove sources' );
}
$out = ResourceLoader::makeLoaderSourcesScript( $context, $sources );

View file

@ -2,6 +2,8 @@
namespace MediaWiki\Tests\ResourceLoader;
use MediaWiki\HookContainer\HookContainer;
use MediaWiki\HookContainer\StaticHookRegistry;
use MediaWiki\Request\FauxRequest;
use MediaWiki\ResourceLoader\Context;
use MediaWiki\ResourceLoader\FilePath;
@ -159,6 +161,10 @@ class ImageModuleTest extends ResourceLoaderTestCase {
* skin attributes.
*/
public function testResourceLoaderFilePath() {
$hookContainer = new HookContainer(
new StaticHookRegistry(),
$this->getServiceContainer()->getObjectFactory()
);
$basePath = __DIR__ . '/../../data/blahblah';
$filePath = __DIR__ . '/../../data/rlfilepath';
$testModule = new ImageModule( [
@ -176,6 +182,7 @@ class ImageModuleTest extends ResourceLoaderTestCase {
],
] );
$testModule->setName( 'testModule' );
$testModule->setHookContainer( $hookContainer );
$expectedModule = new ImageModule( [
'localBasePath' => $filePath,
'remoteBasePath' => 'rlfilepath',
@ -191,6 +198,7 @@ class ImageModuleTest extends ResourceLoaderTestCase {
],
] );
$expectedModule->setName( 'testModule' );
$expectedModule->setHookContainer( $hookContainer );
$context = $this->getResourceLoaderContext();
$this->assertEquals(
@ -208,6 +216,10 @@ class ImageModuleTest extends ResourceLoaderTestCase {
$module,
__DIR__ . '/../../data/resourceloader'
);
$module->setHookContainer( new HookContainer(
new StaticHookRegistry(),
$this->getServiceContainer()->getObjectFactory()
) );
$styles = $module->getStyles( $this->getResourceLoaderContext() );
$this->assertEquals( $expected, $styles['all'] );
}

View file

@ -2,6 +2,8 @@
namespace MediaWiki\Tests\ResourceLoader;
use MediaWiki\HookContainer\HookContainer;
use MediaWiki\HookContainer\StaticHookRegistry;
use MediaWiki\Registration\ExtensionRegistry;
use MediaWiki\ResourceLoader\OOUIImageModule;
use MediaWiki\Tests\Unit\DummyServicesTrait;
@ -20,6 +22,10 @@ class OOUIImageModuleTest extends ResourceLoaderTestCase {
'name' => 'icons',
'rootPath' => 'tests/phpunit/data/resourceloader/oouiimagemodule',
] );
$module->setHookContainer( new HookContainer(
new StaticHookRegistry(),
$this->getServiceContainer()->getObjectFactory()
) );
// Pretend that 'fakemonobook' is a real skin using the Apex theme
$skinFactory = new SkinFactory( $this->getDummyObjectFactory(), [] );

View file

@ -657,7 +657,7 @@ mw.loader.register([
* @dataProvider provideGetModuleRegistrations
*/
public function testGetModuleRegistrations( $case ) {
$this->clearHook( 'ResourceLoaderModifyStartupSourceUrls' );
$this->clearHook( 'ResourceLoaderModifyEmbeddedSourceUrls' );
$extraQuery = $case['extraQuery'] ?? [];
$context = $this->getResourceLoaderContext( $extraQuery );
@ -729,7 +729,7 @@ mw.loader.register([
* @dataProvider provideGetModuleRegistrationsProduction
*/
public function testGetModuleRegistrationsProduction( array $case ) {
$this->clearHook( 'ResourceLoaderModifyStartupSourceUrls' );
$this->clearHook( 'ResourceLoaderModifyEmbeddedSourceUrls' );
$context = $this->getResourceLoaderContext( [ 'debug' => 'false' ] );
$rl = $context->getResourceLoader();
@ -749,8 +749,8 @@ mw.loader.register([
}
public function testGetModuleRegistrations_hook() {
$this->clearHook( 'ResourceLoaderModifyStartupSourceUrls' );
$this->setTemporaryHook( 'ResourceLoaderModifyStartupSourceUrls', function ( &$urls, $context ) {
$this->clearHook( 'ResourceLoaderModifyEmbeddedSourceUrls' );
$this->setTemporaryHook( 'ResourceLoaderModifyEmbeddedSourceUrls', function ( &$urls ) {
$urlUtils = $this->getServiceContainer()->getUrlUtils();
$urls['local'] = $urlUtils->expand( $urls['local'] );
} );
@ -794,7 +794,7 @@ mw.loader.register([]);';
* @dataProvider provideRegistrations
*/
public function testRegistrationsMinified( $modules ) {
$this->clearHook( 'ResourceLoaderModifyStartupSourceUrls' );
$this->clearHook( 'ResourceLoaderModifyEmbeddedSourceUrls' );
$context = $this->getResourceLoaderContext( [
'debug' => 'false',
@ -822,7 +822,7 @@ mw.loader.register([]);';
* @dataProvider provideRegistrations
*/
public function testRegistrationsUnminified( $modules ) {
$this->clearHook( 'ResourceLoaderModifyStartupSourceUrls' );
$this->clearHook( 'ResourceLoaderModifyEmbeddedSourceUrls' );
$context = $this->getResourceLoaderContext( [
'debug' => 'true',
@ -861,7 +861,7 @@ mw.loader.register([
}
public function testGetVersionHash_varyConfig() {
$this->clearHook( 'ResourceLoaderModifyStartupSourceUrls' );
$this->clearHook( 'ResourceLoaderModifyEmbeddedSourceUrls' );
$context = $this->getResourceLoaderContext();
$module = new StartUpModule();
@ -881,7 +881,7 @@ mw.loader.register([
}
public function testGetVersionHash_varyModule() {
$this->clearHook( 'ResourceLoaderModifyStartupSourceUrls' );
$this->clearHook( 'ResourceLoaderModifyEmbeddedSourceUrls' );
$context1 = $this->getResourceLoaderContext( [
'debug' => 'false',
@ -939,7 +939,7 @@ mw.loader.register([
}
public function testGetVersionHash_varyDeps() {
$this->clearHook( 'ResourceLoaderModifyStartupSourceUrls' );
$this->clearHook( 'ResourceLoaderModifyEmbeddedSourceUrls' );
$context = $this->getResourceLoaderContext( [ 'debug' => 'false' ] );
$rl = $context->getResourceLoader();