mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-12 01:09:20 +00:00
[dev] add skin version query parameter override
As described in the readme but not implemented until now, this patch enables the skin version to be specified as a URL query parameter. This is useful for testing both skin versions during development and on wiki, as well as enabling sharing URLs with a specific skin (Vector) and skin version (1 or 2). Obtaining the actual skin version requires tying together three input sources, WebRequest, User, and Config. It seems simple but it'd be easy to botch. For this reason, a helper class to correctly interrogate them and tests are provided. Bug: T244481 Change-Id: I52d80942b4270c008d4e45050589ed9220255a50
This commit is contained in:
parent
b80ad85bb1
commit
d1072d0fdf
|
@ -28,7 +28,8 @@ URL query parameters
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
- `useskinversion`: Like `useskin` but for overriding the Vector skin version
|
- `useskinversion`: Like `useskin` but for overriding the Vector skin version
|
||||||
user preference and configuration.
|
user preference and configuration. E.g.,
|
||||||
|
http://localhost:8181?useskin=vector&useskinversion=2.
|
||||||
|
|
||||||
Skin preferences
|
Skin preferences
|
||||||
----------------
|
----------------
|
||||||
|
|
|
@ -72,6 +72,13 @@ final class Constants {
|
||||||
*/
|
*/
|
||||||
public const REQUIREMENT_FULLY_INITIALISED = 'FullyInitialised';
|
public const REQUIREMENT_FULLY_INITIALISED = 'FullyInitialised';
|
||||||
|
|
||||||
|
// These are used for query parameters.
|
||||||
|
/**
|
||||||
|
* Override the skin version user preference and site Config. See readme.
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public const QUERY_PARAM_SKIN_VERSION = 'useskinversion';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is for namespacing constants only. Forbid construction.
|
* This class is for namespacing constants only. Forbid construction.
|
||||||
* @throws FatalError
|
* @throws FatalError
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
* @file
|
* @file
|
||||||
* @ingroup Skins
|
* @ingroup Skins
|
||||||
*/
|
*/
|
||||||
use Vector\Constants;
|
use Vector\SkinVersionLookup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skin subclass for Vector
|
* Skin subclass for Vector
|
||||||
|
@ -36,6 +36,21 @@ class SkinVector extends SkinTemplate {
|
||||||
|
|
||||||
private $responsiveMode = false;
|
private $responsiveMode = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var SkinVersionLookup
|
||||||
|
*/
|
||||||
|
private $skinVersionLookup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function __construct( $skinname = null ) {
|
||||||
|
parent::__construct( $skinname );
|
||||||
|
|
||||||
|
$this->skinVersionLookup =
|
||||||
|
new SkinVersionLookup( $this->getRequest(), $this->getUser(), $this->getConfig() );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the responsive mode
|
* Enables the responsive mode
|
||||||
*/
|
*/
|
||||||
|
@ -67,7 +82,8 @@ class SkinVector extends SkinTemplate {
|
||||||
public function getDefaultModules() {
|
public function getDefaultModules() {
|
||||||
$modules = parent::getDefaultModules();
|
$modules = parent::getDefaultModules();
|
||||||
// add vector skin styles and vector module
|
// add vector skin styles and vector module
|
||||||
$module = $this->isLegacy() ? 'skins.vector.styles.legacy' : 'skins.vector.styles';
|
$module = $this->skinVersionLookup->isLegacy()
|
||||||
|
? 'skins.vector.styles.legacy' : 'skins.vector.styles';
|
||||||
$modules['styles']['skin'][] = $module;
|
$modules['styles']['skin'][] = $module;
|
||||||
$modules['core'][] = 'skins.vector.js';
|
$modules['core'][] = 'skins.vector.js';
|
||||||
|
|
||||||
|
@ -85,9 +101,7 @@ class SkinVector extends SkinTemplate {
|
||||||
*/
|
*/
|
||||||
protected function setupTemplate( $classname ) {
|
protected function setupTemplate( $classname ) {
|
||||||
$tp = new TemplateParser( __DIR__ . '/templates' );
|
$tp = new TemplateParser( __DIR__ . '/templates' );
|
||||||
$vectorTemplate = new VectorTemplate( $this->getConfig(), $tp, $this->isLegacy() );
|
return new VectorTemplate( $this->getConfig(), $tp, $this->skinVersionLookup->isLegacy() );
|
||||||
|
|
||||||
return $vectorTemplate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,15 +112,4 @@ class SkinVector extends SkinTemplate {
|
||||||
public function shouldPreloadLogo() {
|
public function shouldPreloadLogo() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the legacy skin is being used.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function isLegacy() {
|
|
||||||
// Note: This will be replaced with FeatureManager when it is ready.
|
|
||||||
return $this->getUser()->getOption( Constants::PREF_KEY_SKIN_VERSION )
|
|
||||||
=== Constants::SKIN_VERSION_LEGACY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
109
includes/SkinVersionLookup.php
Normal file
109
includes/SkinVersionLookup.php
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @since 1.35
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Vector;
|
||||||
|
|
||||||
|
use Config;
|
||||||
|
use User;
|
||||||
|
use WebRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given initial dependencies, retrieve the current skin version. This class does no parsing, just
|
||||||
|
* the lookup.
|
||||||
|
*
|
||||||
|
* Skin version is evaluated in the following order:
|
||||||
|
*
|
||||||
|
* - useskinversion URL query parameter override. See readme.
|
||||||
|
*
|
||||||
|
* - User preference. The User object for new and existing accounts are updated by hook according to
|
||||||
|
* VectorDefaultSkinVersionForNewAccounts and VectorDefaultSkinVersionForExistingAccounts. See
|
||||||
|
* Hooks and skin.json.
|
||||||
|
*
|
||||||
|
* If the skin version is evaluated prior to User preference hook invocations, an incorrect
|
||||||
|
* version may be returned as only query parameter and site configuration will be known.
|
||||||
|
*
|
||||||
|
* - Site configuration default. The default is controlled by VectorDefaultSkinVersion. This is used
|
||||||
|
* for anonymous users and as a fallback configuration. See skin.json.
|
||||||
|
*
|
||||||
|
* @unstable
|
||||||
|
*
|
||||||
|
* @package Vector
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class SkinVersionLookup {
|
||||||
|
/**
|
||||||
|
* @var WebRequest
|
||||||
|
*/
|
||||||
|
private $request;
|
||||||
|
/**
|
||||||
|
* @var User
|
||||||
|
*/
|
||||||
|
private $user;
|
||||||
|
/**
|
||||||
|
* @var Config
|
||||||
|
*/
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This constructor accepts all dependencies needed to obtain the skin version. The dependencies
|
||||||
|
* are lazily evaluated, not cached, meaning they always return the current results.
|
||||||
|
*
|
||||||
|
* @param WebRequest $request
|
||||||
|
* @param User $user
|
||||||
|
* @param Config $config
|
||||||
|
*/
|
||||||
|
public function __construct( WebRequest $request, User $user, Config $config ) {
|
||||||
|
$this->request = $request;
|
||||||
|
$this->user = $user;
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the legacy skin is being used.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \ConfigException
|
||||||
|
*/
|
||||||
|
public function isLegacy() {
|
||||||
|
return $this->getVersion() === Constants::SKIN_VERSION_LEGACY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The skin version as a string. E.g., `Constants::SKIN_VERSION_LEGACY`,
|
||||||
|
* `Constants::SKIN_VERSION_LATEST`, or maybe 'beta'. Note: it's likely someone will put arbitrary
|
||||||
|
* strings in the query parameter which means this function returns those strings as is.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \ConfigException
|
||||||
|
*/
|
||||||
|
public function getVersion() {
|
||||||
|
// Obtain the skin version from the `useskinversion` URL query parameter override, the user
|
||||||
|
// preference, or the configured default.
|
||||||
|
return (string)$this->request->getVal(
|
||||||
|
Constants::QUERY_PARAM_SKIN_VERSION,
|
||||||
|
$this->user->getOption(
|
||||||
|
Constants::PREF_KEY_SKIN_VERSION,
|
||||||
|
$this->config->get( Constants::CONFIG_KEY_DEFAULT_SKIN_VERSION )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@
|
||||||
"AutoloadClasses": {
|
"AutoloadClasses": {
|
||||||
"Vector\\Constants": "includes/Constants.php",
|
"Vector\\Constants": "includes/Constants.php",
|
||||||
"Vector\\Hooks": "includes/Hooks.php",
|
"Vector\\Hooks": "includes/Hooks.php",
|
||||||
|
"Vector\\SkinVersionLookup": "includes/SkinVersionLookup.php",
|
||||||
"SkinVector": "includes/SkinVector.php",
|
"SkinVector": "includes/SkinVector.php",
|
||||||
"VectorTemplate": "includes/VectorTemplate.php"
|
"VectorTemplate": "includes/VectorTemplate.php"
|
||||||
},
|
},
|
||||||
|
|
133
tests/phpunit/integration/SkinVersionLookupTest.php
Normal file
133
tests/phpunit/integration/SkinVersionLookupTest.php
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @since 1.35
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Vector\SkinVersionLookup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group Vector
|
||||||
|
* @coversDefaultClass \Vector\SkinVersionLookup
|
||||||
|
*/
|
||||||
|
class SkinVersionLookupTest extends \MediaWikiTestCase {
|
||||||
|
/**
|
||||||
|
* @covers ::isLegacy
|
||||||
|
* @covers ::getVersion
|
||||||
|
*/
|
||||||
|
public function testRequest() {
|
||||||
|
$request = $this->getMockBuilder( \WebRequest::class )->getMock();
|
||||||
|
$request
|
||||||
|
->expects( $this->exactly( 2 ) )
|
||||||
|
->method( 'getVal' )
|
||||||
|
->with( $this->anything(), $this->equalTo( '1' ) )
|
||||||
|
->willReturn( 'beta' );
|
||||||
|
|
||||||
|
$user = $this->createMock( \User::class );
|
||||||
|
$user
|
||||||
|
->expects( $this->exactly( 2 ) )
|
||||||
|
->method( 'getOption' )
|
||||||
|
->with( $this->anything(), $this->equalTo( '2' ) )
|
||||||
|
->willReturn( '1' );
|
||||||
|
|
||||||
|
$config = new HashConfig( [ 'VectorDefaultSkinVersion' => '2' ] );
|
||||||
|
|
||||||
|
$skinVersionLookup = new SkinVersionLookup( $request, $user, $config );
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
$skinVersionLookup->getVersion(),
|
||||||
|
'beta',
|
||||||
|
'Query parameter is the first priority.'
|
||||||
|
);
|
||||||
|
$this->assertSame(
|
||||||
|
$skinVersionLookup->isLegacy(),
|
||||||
|
false,
|
||||||
|
'Version is non-legacy.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::getVersion
|
||||||
|
* @covers ::isLegacy
|
||||||
|
*/
|
||||||
|
public function testUserPreference() {
|
||||||
|
$request = $this->getMockBuilder( \WebRequest::class )->getMock();
|
||||||
|
$request
|
||||||
|
->expects( $this->exactly( 2 ) )
|
||||||
|
->method( 'getVal' )
|
||||||
|
->with( $this->anything(), $this->equalTo( '1' ) )
|
||||||
|
->willReturn( '1' );
|
||||||
|
|
||||||
|
$user = $this->createMock( \User::class );
|
||||||
|
$user
|
||||||
|
->expects( $this->exactly( 2 ) )
|
||||||
|
->method( 'getOption' )
|
||||||
|
->with( $this->anything(), $this->equalTo( '2' ) )
|
||||||
|
->willReturn( '1' );
|
||||||
|
|
||||||
|
$config = new HashConfig( [ 'VectorDefaultSkinVersion' => '2' ] );
|
||||||
|
|
||||||
|
$skinVersionLookup = new SkinVersionLookup( $request, $user, $config );
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
$skinVersionLookup->getVersion(),
|
||||||
|
'1',
|
||||||
|
'User preference is the second priority.'
|
||||||
|
);
|
||||||
|
$this->assertSame(
|
||||||
|
$skinVersionLookup->isLegacy(),
|
||||||
|
true,
|
||||||
|
'Version is legacy.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers ::getVersion
|
||||||
|
* @covers ::isLegacy
|
||||||
|
*/
|
||||||
|
public function testConfig() {
|
||||||
|
$request = $this->getMockBuilder( \WebRequest::class )->getMock();
|
||||||
|
$request
|
||||||
|
->expects( $this->exactly( 2 ) )
|
||||||
|
->method( 'getVal' )
|
||||||
|
->with( $this->anything(), $this->equalTo( '2' ) )
|
||||||
|
->willReturn( '2' );
|
||||||
|
|
||||||
|
$user = $this->createMock( \User::class );
|
||||||
|
$user
|
||||||
|
->expects( $this->exactly( 2 ) )
|
||||||
|
->method( 'getOption' )
|
||||||
|
->with( $this->anything(), $this->equalTo( '2' ) )
|
||||||
|
->willReturn( '2' );
|
||||||
|
|
||||||
|
$config = new HashConfig( [ 'VectorDefaultSkinVersion' => '2' ] );
|
||||||
|
|
||||||
|
$skinVersionLookup = new SkinVersionLookup( $request, $user, $config );
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
$skinVersionLookup->getVersion(),
|
||||||
|
'2',
|
||||||
|
'Config is the third priority.'
|
||||||
|
);
|
||||||
|
$this->assertSame(
|
||||||
|
$skinVersionLookup->isLegacy(),
|
||||||
|
false,
|
||||||
|
'Version is non-legacy.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue