3use Wikimedia\TestingAccessWrapper;
25 $outputPage->addMeta(
'http:expires',
'0' );
26 $outputPage->addMeta(
'keywords',
'first' );
27 $outputPage->addMeta(
'keywords',
'second' );
28 $outputPage->addMeta(
'og:title',
'Ta-duh' );
31 [
'http:expires',
'0' ],
32 [
'keywords',
'first' ],
33 [
'keywords',
'second' ],
34 [
'og:title',
'Ta-duh' ],
36 $this->assertSame( $expected, $outputPage->getMetaTags() );
38 $links = $outputPage->getHeadLinksArray();
39 $this->assertContains(
'<meta http-equiv="expires" content="0"/>', $links );
40 $this->assertContains(
'<meta name="keywords" content="first"/>', $links );
41 $this->assertContains(
'<meta name="keywords" content="second"/>', $links );
42 $this->assertContains(
'<meta property="og:title" content="Ta-duh"/>', $links );
43 $this->assertArrayNotHasKey(
'meta-robots', $links );
53 $outputPage->setIndexPolicy(
'noindex' );
54 $outputPage->setFollowPolicy(
'nofollow' );
56 $links = $outputPage->getHeadLinksArray();
57 $this->assertContains(
'<meta name="robots" content="noindex,nofollow"/>', $links );
76 if ( isset(
$args[
'printableQuery'] ) ) {
77 $queryData[
'printable'] =
$args[
'printableQuery'];
80 if ( isset(
$args[
'handheldQuery'] ) ) {
81 $queryData[
'handheld'] =
$args[
'handheldQuery'];
84 $fauxRequest =
new FauxRequest( $queryData,
false );
86 'wgRequest' => $fauxRequest,
89 $actualReturn = OutputPage::transformCssMedia(
$args[
'media'] );
90 $this->assertSame(
$args[
'expectedReturn'], $actualReturn,
$args[
'message'] );
99 'printableQuery' =>
'1',
101 'expectedReturn' =>
null,
102 'message' =>
'On printable request, screen returns null'
106 'printableQuery' =>
'1',
107 'media' => self::SCREEN_MEDIA_QUERY,
108 'expectedReturn' =>
null,
109 'message' =>
'On printable request, screen media query returns null'
113 'printableQuery' =>
'1',
114 'media' => self::SCREEN_ONLY_MEDIA_QUERY,
115 'expectedReturn' =>
null,
116 'message' =>
'On printable request, screen media query with only returns null'
120 'printableQuery' =>
'1',
122 'expectedReturn' =>
'',
123 'message' =>
'On printable request, media print returns empty string'
134 'expectedReturn' =>
'screen',
135 'message' =>
'On screen request, screen media type is preserved'
139 'media' =>
'handheld',
140 'expectedReturn' =>
'handheld',
141 'message' =>
'On screen request, handheld media type is preserved'
145 'media' => self::SCREEN_MEDIA_QUERY,
146 'expectedReturn' => self::SCREEN_MEDIA_QUERY,
147 'message' =>
'On screen request, screen media query is preserved.'
151 'media' => self::SCREEN_ONLY_MEDIA_QUERY,
152 'expectedReturn' => self::SCREEN_ONLY_MEDIA_QUERY,
153 'message' =>
'On screen request, screen media query with only is preserved.'
158 'expectedReturn' =>
'print',
159 'message' =>
'On screen request, print media type is preserved'
169 'handheldQuery' =>
'1',
170 'media' =>
'handheld',
171 'expectedReturn' =>
'',
172 'message' =>
'On request with handheld querystring and media is handheld, returns empty string'
176 'handheldQuery' =>
'1',
178 'expectedReturn' =>
null,
179 'message' =>
'On request with handheld querystring and media is screen, returns null'
184 $baseDir = dirname( __DIR__ ) .
'/data/media';
188 'baseDir' => $baseDir,
'basePath' =>
'/w',
194 'baseDir' => $baseDir,
'basePath' =>
'/w',
200 'baseDir' => $baseDir,
'basePath' =>
'/w',
205 'baseDir' => $baseDir,
'basePath' =>
'/w',
211 'baseDir' => $baseDir,
'basePath' =>
'/w',
212 '//example.org/w/test.jpg'
215 'baseDir' => $baseDir,
'basePath' =>
'/w',
216 'https://example.org/w/test.jpg'
220 'baseDir' => $baseDir,
'basePath' =>
'/w',
221 'https://example.org/files/test.jpg'
224 'baseDir' => $baseDir,
'basePath' =>
'/w',
225 '//example.org/files/test.jpg'
229 'baseDir' => $baseDir,
'basePath' =>
'',
230 'https://example.org/files/test.jpg'
233 'baseDir' => $baseDir,
'basePath' =>
'',
235 '//example.org/files/test.jpg'
239 'baseDir' => dirname( $baseDir ),
'basePath' =>
'',
240 'uploadDir' => $baseDir,
'uploadPath' =>
'/images',
242 '/images/test.jpg?edcf2'
253 $uploadPath =
null, $path =
null, $expected =
null
255 if ( $path ===
null ) {
258 $expected = $uploadPath;
259 $uploadDir =
"$baseDir/images";
260 $uploadPath =
"$basePath/images";
265 'UploadDirectory' => $uploadDir,
266 'UploadPath' => $uploadPath,
269 Wikimedia\suppressWarnings();
270 $actual = OutputPage::transformResourcePath( $conf, $path );
271 Wikimedia\restoreWarnings();
273 $this->assertEquals( $expected ?:
$path, $actual );
282 "<script>(window.RLQ=window.RLQ||[]).push(function(){"
283 .
'mw.loader.load("http://127.0.0.1:8080/w/load.php?debug=false\u0026lang=en\u0026modules=test.foo\u0026only=scripts\u0026skin=fallback");'
290 '<link rel="stylesheet" href="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.bar%2Cbaz%2Cfoo&only=styles&skin=fallback"/>'
295 "<script>(window.RLQ=window.RLQ||[]).push(function(){"
296 .
"mw.test.baz({token:123});\nmw.loader.state({\"test.quux\":\"ready\"});"
311 'wgResourceLoaderDebug' =>
false,
312 'wgLoadScript' =>
'http://127.0.0.1:8080/w/load.php',
314 $class =
new ReflectionClass( OutputPage::class );
315 $method = $class->getMethod(
'makeResourceLoaderLink' );
316 $method->setAccessible(
true );
318 $ctx->setSkin( SkinFactory::getDefaultInstance()->makeSkin(
'fallback' ) );
319 $ctx->setLanguage(
'en' );
321 $rl =
$out->getResourceLoader();
325 'script' =>
'mw.test.foo( { a: true } );',
326 'styles' =>
'.mw-test-foo { content: "style"; }',
329 'script' =>
'mw.test.bar( { a: true } );',
330 'styles' =>
'.mw-test-bar { content: "style"; }',
333 'script' =>
'mw.test.baz( { a: true } );',
334 'styles' =>
'.mw-test-baz { content: "style"; }',
337 'script' =>
'mw.test.baz( { token: 123 } );',
338 'styles' =>
'/* pref-animate=off */ .mw-icon { transition: none; }',
339 'group' =>
'private',
342 $links = $method->invokeArgs(
$out,
$args );
343 $actualHtml = strval( $links );
344 $this->assertEquals( $expectedHtml, $actualHtml );
351 'exemptStyleModules' => [],
352 '<meta name="ResourceLoaderDynamicStyles" content=""/>',
355 'exemptStyleModules' => [
'site' => [],
'noscript' => [],
'private' => [],
'user' => [] ],
356 '<meta name="ResourceLoaderDynamicStyles" content=""/>',
358 'default logged-out' => [
359 'exemptStyleModules' => [
'site' => [
'site.styles' ] ],
360 '<meta name="ResourceLoaderDynamicStyles" content=""/>' .
"\n" .
361 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=en&modules=site.styles&only=styles&skin=fallback"/>',
363 'default logged-in' => [
364 'exemptStyleModules' => [
'site' => [
'site.styles' ],
'user' => [
'user.styles' ] ],
365 '<meta name="ResourceLoaderDynamicStyles" content=""/>' .
"\n" .
366 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=en&modules=site.styles&only=styles&skin=fallback"/>' .
"\n" .
367 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=en&modules=user.styles&only=styles&skin=fallback&version=1e9z0ox"/>',
369 'custom modules' => [
370 'exemptStyleModules' => [
371 'site' => [
'site.styles',
'example.site.a',
'example.site.b' ],
372 'user' => [
'user.styles',
'example.user' ],
374 '<meta name="ResourceLoaderDynamicStyles" content=""/>' .
"\n" .
375 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=en&modules=example.site.a%2Cb&only=styles&skin=fallback"/>' .
"\n" .
376 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=en&modules=site.styles&only=styles&skin=fallback"/>' .
"\n" .
377 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=en&modules=example.user&only=styles&skin=fallback&version=0a56zyi"/>' .
"\n" .
378 '<link rel="stylesheet" href="/w/load.php?debug=false&lang=en&modules=user.styles&only=styles&skin=fallback&version=1e9z0ox"/>',
390 'wgResourceLoaderDebug' =>
false,
391 'wgLoadScript' =>
'/w/load.php',
394 'wgCacheEpoch' =>
'20140101000000',
399 $ctx->setSkin( SkinFactory::getDefaultInstance()->makeSkin(
'fallback' ) );
400 $ctx->setLanguage(
'en' );
401 $outputPage = $this->getMockBuilder( OutputPage::class )
402 ->setConstructorArgs( [ $ctx ] )
403 ->setMethods( [
'isUserCssPreview',
'buildCssLinksArray' ] )
405 $outputPage->expects( $this->
any() )
406 ->method(
'isUserCssPreview' )
407 ->willReturn(
false );
408 $outputPage->expects( $this->
any() )
409 ->method(
'buildCssLinksArray' )
411 $rl = $outputPage->getResourceLoader();
421 $outputPage = TestingAccessWrapper::newFromObject( $outputPage );
422 $outputPage->rlExemptStyleModules = $exemptStyleModules;
425 strval( $outputPage->buildExemptModules() )
437 $outputPage = $this->getMockBuilder( OutputPage::class )
439 ->setMethods( [
'getCacheVaryCookies' ] )
441 $outputPage->expects( $this->
any() )
442 ->method(
'getCacheVaryCookies' )
443 ->will( $this->returnValue( [] ) );
444 TestingAccessWrapper::newFromObject( $outputPage )->mVaryHeader = [];
446 foreach ( $calls as $call ) {
447 call_user_func_array( [ $outputPage,
'addVaryHeader' ], $call );
449 $this->assertEquals( $vary, $outputPage->getVaryHeader(),
'Vary:' );
450 $this->assertEquals( $key, $outputPage->getKeyHeader(),
'Key:' );
466 [
'Accept-Language' ],
469 'Vary: Cookie, Accept-Language',
470 'Key: Cookie,Accept-Language',
474 [
'Cookie', [
'param=phpsessid' ] ],
475 [
'Accept-Language', [
'substr=en' ] ],
477 'Vary: Cookie, Accept-Language',
478 'Key: Cookie;param=phpsessid,Accept-Language;substr=en',
482 [
'Cookie', [
'param=phpsessid',
'param=userId' ] ],
485 'Key: Cookie;param=phpsessid;param=userId',
489 [
'Cookie', [
'param=phpsessid' ] ],
490 [
'Cookie', [
'param=phpsessid' ] ],
491 [
'Accept-Language', [
'substr=en',
'substr=en' ] ],
493 'Vary: Cookie, Accept-Language',
494 'Key: Cookie;param=phpsessid,Accept-Language;substr=en',
498 [
'Cookie', [
'param=phpsessid' ] ],
499 [
'Cookie', [
'param=userId' ] ],
502 'Key: Cookie;param=phpsessid;param=userId',
517 $this->assertFalse( $outputPage->haveCacheVaryCookies() );
521 $this->assertFalse( $outputPage->haveCacheVaryCookies() );
524 $request->setCookie(
'Token',
'123' );
525 $this->assertTrue( $outputPage->haveCacheVaryCookies() );
533 $fakeResultWrapper =
new FakeResultWrapper( [
536 'page_title' =>
'Test'
539 'page_title' =>
'Test2'
542 $outputPage = $this->getMockBuilder( OutputPage::class )
544 ->setMethods( [
'addCategoryLinksToLBAndGetResult' ] )
546 $outputPage->expects( $this->
any() )
547 ->method(
'addCategoryLinksToLBAndGetResult' )
548 ->will( $this->returnValue( $fakeResultWrapper ) );
550 $outputPage->addCategoryLinks( [
554 $this->assertEquals( [ 0 =>
'Test',
'1' =>
'Test2' ], $outputPage->getCategories() );
555 $this->assertEquals( [ 0 =>
'Test2' ], $outputPage->getCategories(
'normal' ) );
556 $this->assertEquals( [ 0 =>
'Test' ], $outputPage->getCategories(
'hidden' ) );
567 foreach ( $headers as
$header ) {
568 $outputPage->addLinkHeader(
$header );
571 $this->assertEquals( $result, $outputPage->getLinkHeader() );
581 [
'<https://foo/bar.jpg>;rel=preload;as=image' ],
582 'Link: <https://foo/bar.jpg>;rel=preload;as=image',
585 [
'<https://foo/bar.jpg>;rel=preload;as=image',
'<https://foo/baz.jpg>;rel=preload;as=image' ],
586 'Link: <https://foo/bar.jpg>;rel=preload;as=image,<https://foo/baz.jpg>;rel=preload;as=image',
600 $out = TestingAccessWrapper::newFromObject( $this->
newInstance( $config ) );
601 $out->addLogoPreloadLinkHeaders();
603 $this->assertEquals( $result,
$out->getLinkHeader() );
610 'ResourceBasePath' =>
'/w',
611 'Logo' =>
'/img/default.png',
613 '1.5x' =>
'/img/one-point-five.png',
614 '2x' =>
'/img/two-x.png',
617 'Link: </img/default.png>;rel=preload;as=image;media=' .
618 'not all and (min-resolution: 1.5dppx),' .
619 '</img/one-point-five.png>;rel=preload;as=image;media=' .
620 '(min-resolution: 1.5dppx) and (max-resolution: 1.999999dppx),' .
621 '</img/two-x.png>;rel=preload;as=image;media=(min-resolution: 2dppx)'
625 'ResourceBasePath' =>
'/w',
626 'Logo' =>
'/img/default.png',
629 'Link: </img/default.png>;rel=preload;as=image'
633 'ResourceBasePath' =>
'/w',
634 'Logo' =>
'/img/default.png',
636 '2x' =>
'/img/two-x.png',
639 'Link: </img/default.png>;rel=preload;as=image;media=' .
640 'not all and (min-resolution: 2dppx),' .
641 '</img/two-x.png>;rel=preload;as=image;media=(min-resolution: 2dppx)'
645 'ResourceBasePath' =>
'/w',
646 'Logo' =>
'/img/default.png',
648 'svg' =>
'/img/vector.svg',
651 'Link: </img/vector.svg>;rel=preload;as=image'
656 'ResourceBasePath' =>
'/w',
657 'Logo' =>
'/w/test.jpg',
659 'UploadPath' =>
'/w/images',
661 'Link: </w/test.jpg?edcf2>;rel=preload;as=image',
662 'baseDir' => dirname( __DIR__ ) .
'/data/media',
674 'AppleTouchIcon' =>
false,
675 'DisableLangConversion' =>
true,
676 'EnableAPI' =>
false,
677 'EnableCanonicalServerLink' =>
false,
680 'LanguageCode' =>
false,
681 'ReferrerPolicy' =>
false,
682 'RightsPage' =>
false,
683 'RightsUrl' =>
false,
684 'UniversalEditButton' =>
false,
they could even be mouse clicks or menu items whatever suits your program You should also get your if any
WebRequest clone which takes values from a provided array.
A Config instance which stores all settings as a member variable.
This class generates message blobs for use by ResourceLoader modules.
MessageBlobStore that doesn't do anything.
clear()
Invalidate cache keys for all known modules.
updateMessage( $key)
Invalidate cache keys for modules using this message key.
updateModule( $name, ResourceLoaderModule $module, $lang)
testGetCategories()
OutputPage::addCategoryLinks OutputPage::getCategories.
testRobotsPolicies()
OutputPage::setIndexPolicy OutputPage::setFollowPolicy OutputPage::getHeadLinksArray.
const SCREEN_ONLY_MEDIA_QUERY
testMetaTags()
OutputPage::addMeta OutputPage::getMetaTags OutputPage::getHeadLinksArray.
testHaveCacheVaryCookies()
OutputPage::haveCacheVaryCookies.
testTransformResourcePath( $baseDir, $basePath, $uploadDir=null, $uploadPath=null, $path=null, $expected=null)
provideTransformFilePath OutputPage::transformFilePath OutputPage::transformResourcePath
testHandheld()
Tests handheld behavior OutputPage::transformCssMedia.
testPreloadLinkHeaders( $config, $result, $baseDir=null)
providePreloadLinkHeaders OutputPage::addLogoPreloadLinkHeaders ResourceLoaderSkinModule::getLogo
static provideTransformFilePath()
testMakeResourceLoaderLink( $args, $expectedHtml)
See ResourceLoaderClientHtmlTest for full coverage.
static provideMakeResourceLoaderLink()
assertTransformCssMediaCase( $args)
Tests a particular case of transformCssMedia, using the given input, globals, expected return,...
testLinkHeaders( $headers, $result)
provideLinkHeaders OutputPage::addLinkHeader OutputPage::getLinkHeader
testScreenRequests()
Tests screen requests, without either query parameter set OutputPage::transformCssMedia.
testPrintRequests()
Tests print requests OutputPage::transformCssMedia.
providePreloadLinkHeaders()
testVaryHeaders( $calls, $vary, $key)
provideVaryHeaders OutputPage::addVaryHeader OutputPage::getVaryHeader OutputPage::getKeyHeader
static provideBuildExemptModules()
testBuildExemptModules(array $exemptStyleModules, $expect)
provideBuildExemptModules OutputPage::buildExemptModules
This class should be covered by a general architecture document which does not exist as of January 20...
Group all the pieces relevant to the context of a request into one instance.
Abstraction for ResourceLoader modules, with name registration and maxage functionality.
Dynamic JavaScript and CSS resource loading system.
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on $request
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output $out
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext such as when responding to a resource loader request or generating HTML output & $resourceLoader
processing should stop and the error should be shown to the user * false
if(!isset( $args[0])) $lang