mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-30 18:35:44 +00:00
Merge "Vector is split into 2 skins"
This commit is contained in:
commit
84ed8343c2
|
@ -3,6 +3,7 @@
|
|||
"authors": []
|
||||
},
|
||||
"skinname-vector": "Vector",
|
||||
"skinname-vector-2022": "Vector 2022",
|
||||
"vector-skin-desc": "Modern version of MonoBook with fresh look and many usability improvements",
|
||||
"prefs-vector-enable-vector-1-label": "Use Legacy Vector",
|
||||
"prefs-vector-enable-vector-1-help": "Over the next few years, we will be gradually updating the Vector skin. Legacy Vector will allow you to view the old version of Vector (as of December 2019). To learn more about the updates, go to our [[mw:Reading/Web/Desktop_Improvements|project page]].",
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
]
|
||||
},
|
||||
"skinname-vector": "{{name}}",
|
||||
"skinname-vector-2022": "{{name}}",
|
||||
"vector-skin-desc": "{{desc|what=skin|name=Vector|url=https://www.mediawiki.org/wiki/Skin:Vector}}",
|
||||
"prefs-vector-enable-vector-1-label": "Label for the checkbox to force Legacy Vector operation accessible via Special:Preferences. When this checkbox is enabled, the December 2019 of Vector is used. When this checkbox is disabled, the actively developed version of Vector is used instead.",
|
||||
"prefs-vector-enable-vector-1-help": "Detail explaining the operation of the prefs-vector-enable-vector-1-label checkbox.",
|
||||
|
|
|
@ -14,7 +14,13 @@ final class Constants {
|
|||
* This is tightly coupled to the ConfigRegistry field in skin.json.
|
||||
* @var string
|
||||
*/
|
||||
public const SKIN_NAME = 'vector';
|
||||
public const SKIN_NAME_MODERN = 'vector-2022';
|
||||
|
||||
/**
|
||||
* This is tightly coupled to the ConfigRegistry field in skin.json.
|
||||
* @var string
|
||||
*/
|
||||
public const SKIN_NAME_LEGACY = 'vector';
|
||||
|
||||
// These are tightly coupled to PREF_KEY_SKIN_VERSION and skin.json's configs. See skin.json for
|
||||
// documentation.
|
||||
|
@ -69,6 +75,11 @@ final class Constants {
|
|||
public const CONFIG_KEY_DEFAULT_SIDEBAR_VISIBLE_FOR_ANONYMOUS_USER =
|
||||
'VectorDefaultSidebarVisibleForAnonymousUser';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const PREF_KEY_SKIN = 'skin';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
|
|
@ -10,7 +10,6 @@ use ResourceLoaderContext;
|
|||
use RuntimeException;
|
||||
use Skin;
|
||||
use SkinTemplate;
|
||||
use SkinVector;
|
||||
use Title;
|
||||
use User;
|
||||
use Vector\HTMLForm\Fields\HTMLLegacySkinVersionField;
|
||||
|
@ -24,6 +23,19 @@ use Vector\HTMLForm\Fields\HTMLLegacySkinVersionField;
|
|||
* @internal
|
||||
*/
|
||||
class Hooks {
|
||||
/**
|
||||
* Checks if the current skin is a variant of Vector
|
||||
*
|
||||
* @param string $skinName
|
||||
* @return bool
|
||||
*/
|
||||
private static function isVectorSkin( string $skinName ): bool {
|
||||
return (
|
||||
$skinName === Constants::SKIN_NAME_LEGACY ||
|
||||
$skinName === Constants::SKIN_NAME_MODERN
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Config $config
|
||||
* @return array
|
||||
|
@ -355,7 +367,8 @@ class Hooks {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add Vector preferences to the user's Special:Preferences page directly underneath skins.
|
||||
* Add Vector preferences to the user's Special:Preferences page directly underneath skins
|
||||
* provided that $wgVectorSkinMigrationMode is not enabled.
|
||||
*
|
||||
* @param User $user User whose preferences are being modified.
|
||||
* @param array[] &$prefs Preferences description array, to be fed to a HTMLForm object.
|
||||
|
@ -366,6 +379,16 @@ class Hooks {
|
|||
return;
|
||||
}
|
||||
|
||||
// If migration mode was enabled, and the skin version is set to modern,
|
||||
// switch over the skin.
|
||||
if ( self::isMigrationMode() && !self::isSkinVersionLegacy() ) {
|
||||
MediaWikiServices::getInstance()->getUserOptionsManager()->setOption(
|
||||
$user,
|
||||
Constants::PREF_KEY_SKIN,
|
||||
Constants::SKIN_NAME_MODERN
|
||||
);
|
||||
}
|
||||
|
||||
// Preferences to add.
|
||||
$vectorPrefs = [
|
||||
Constants::PREF_KEY_SKIN_VERSION => [
|
||||
|
@ -380,7 +403,9 @@ class Hooks {
|
|||
'default' => self::isSkinVersionLegacy(),
|
||||
// Only show this section when the Vector skin is checked. The JavaScript client also uses
|
||||
// this state to determine whether to show or hide the whole section.
|
||||
'hide-if' => [ '!==', 'wpskin', Constants::SKIN_NAME ],
|
||||
// If migration mode is enabled, the section is always hidden.
|
||||
'hide-if' => self::isMigrationMode() ? [ '!==', 'wpskin', '0' ] :
|
||||
[ '!==', 'wpskin', Constants::SKIN_NAME_LEGACY ],
|
||||
],
|
||||
Constants::PREF_KEY_SIDEBAR_VISIBLE => [
|
||||
'type' => 'api',
|
||||
|
@ -389,7 +414,9 @@ class Hooks {
|
|||
];
|
||||
|
||||
// Seek the skin preference section to add Vector preferences just below it.
|
||||
$skinSectionIndex = array_search( 'skin', array_keys( $prefs ) );
|
||||
$skinSectionIndex = array_search(
|
||||
Constants::PREF_KEY_SKIN, array_keys( $prefs )
|
||||
);
|
||||
if ( $skinSectionIndex !== false ) {
|
||||
// Skin preference section found. Inject Vector skin-specific preferences just below it.
|
||||
// This pattern can be found in Popups too. See T246162.
|
||||
|
@ -408,25 +435,41 @@ class Hooks {
|
|||
* presentation of skin version to a version string. That is, a single preference change by the
|
||||
* user may trigger two writes: a boolean followed by a string.
|
||||
*
|
||||
* @param array $formData Form data submitted by user
|
||||
* @param array &$formData Form data submitted by user
|
||||
* @param HTMLForm $form A preferences form
|
||||
* @param User $user Logged-in user
|
||||
* @param bool &$result Variable defining is form save successful
|
||||
* @param array $oldPreferences
|
||||
*/
|
||||
public static function onPreferencesFormPreSave(
|
||||
array $formData,
|
||||
array &$formData,
|
||||
HTMLForm $form,
|
||||
User $user,
|
||||
&$result,
|
||||
$oldPreferences
|
||||
) {
|
||||
$isVectorEnabled = ( $formData[ 'skin' ] ?? '' ) === Constants::SKIN_NAME;
|
||||
$userManager = MediaWikiServices::getInstance()->getUserOptionsManager();
|
||||
$skinVersion = $formData[ Constants::PREF_KEY_SKIN_VERSION ] ?? '';
|
||||
$skin = $formData[ Constants::PREF_KEY_SKIN ] ?? '';
|
||||
$isVectorEnabled = self::isVectorSkin( $skin );
|
||||
|
||||
if (
|
||||
self::isMigrationMode() &&
|
||||
$skin === Constants::SKIN_NAME_LEGACY &&
|
||||
$skinVersion === Constants::SKIN_VERSION_LATEST
|
||||
) {
|
||||
// Mismatch between skin and version. Use skin.
|
||||
$userManager->setOption(
|
||||
$user,
|
||||
Constants::PREF_KEY_SKIN_VERSION,
|
||||
Constants::SKIN_VERSION_LEGACY
|
||||
);
|
||||
}
|
||||
|
||||
if ( !$isVectorEnabled && array_key_exists( Constants::PREF_KEY_SKIN_VERSION, $oldPreferences ) ) {
|
||||
// The setting was cleared. However, this is likely because a different skin was chosen and
|
||||
// the skin version preference was hidden.
|
||||
MediaWikiServices::getInstance()->getUserOptionsManager()->setOption(
|
||||
$userManager->setOption(
|
||||
$user,
|
||||
Constants::PREF_KEY_SKIN_VERSION,
|
||||
$oldPreferences[ Constants::PREF_KEY_SKIN_VERSION ]
|
||||
|
@ -434,6 +477,15 @@ class Hooks {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether we can start migrating users to use skin preference.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function isMigrationMode(): bool {
|
||||
return self::getConfig( 'VectorSkinMigrationMode' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Called one time when initializing a users preferences for a newly created account.
|
||||
*
|
||||
|
@ -442,13 +494,24 @@ class Hooks {
|
|||
*/
|
||||
public static function onLocalUserCreated( User $user, $isAutoCreated ) {
|
||||
$default = self::getConfig( Constants::CONFIG_KEY_DEFAULT_SKIN_VERSION_FOR_NEW_ACCOUNTS );
|
||||
$optionsManager = MediaWikiServices::getInstance()->getUserOptionsManager();
|
||||
// Permanently set the default preference. The user can later change this preference, however,
|
||||
// self::onLocalUserCreated() will not be executed for that account again.
|
||||
MediaWikiServices::getInstance()->getUserOptionsManager()->setOption(
|
||||
$optionsManager->setOption(
|
||||
$user,
|
||||
Constants::PREF_KEY_SKIN_VERSION,
|
||||
$default
|
||||
);
|
||||
|
||||
// Also set the skin key if migration mode is enabled.
|
||||
if ( self::isMigrationMode() ) {
|
||||
$optionsManager->setOption(
|
||||
$user,
|
||||
Constants::PREF_KEY_SKIN,
|
||||
$default === Constants::SKIN_VERSION_LEGACY ?
|
||||
Constants::SKIN_NAME_LEGACY : Constants::SKIN_NAME_MODERN
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -460,7 +523,8 @@ class Hooks {
|
|||
* @param string[] &$bodyAttrs
|
||||
*/
|
||||
public static function onOutputPageBodyAttributes( OutputPage $out, Skin $sk, &$bodyAttrs ) {
|
||||
if ( !$sk instanceof SkinVector ) {
|
||||
$skinName = $out->getSkin()->getSkinName();
|
||||
if ( !self::isVectorSkin( $skinName ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -474,6 +538,10 @@ class Hooks {
|
|||
// list.
|
||||
if ( self::isSkinVersionLegacy() ) {
|
||||
$bodyAttrs['class'] .= ' skin-vector-legacy';
|
||||
} else {
|
||||
// The modern Vector skin must also carry skin-vector for compatibility with older
|
||||
// skins.
|
||||
$bodyAttrs['class'] .= ' skin-vector';
|
||||
}
|
||||
|
||||
// Determine the search widget treatment to send to the user
|
||||
|
@ -578,7 +646,8 @@ class Hooks {
|
|||
* @param OutputPage $out OutputPage instance calling the hook
|
||||
*/
|
||||
public static function onMakeGlobalVariablesScript( &$vars, OutputPage $out ) {
|
||||
if ( !$out->getSkin() instanceof SkinVector ) {
|
||||
$skin = $out->getSkin();
|
||||
if ( !self::isVectorSkin( $skin->getSkinName() ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ use Vector\SkinVersionLookup;
|
|||
|
||||
return [
|
||||
Constants::SERVICE_CONFIG => static function ( MediaWikiServices $services ) {
|
||||
return $services->getService( 'ConfigFactory' )->makeConfig( Constants::SKIN_NAME );
|
||||
return $services->getService( 'ConfigFactory' )->makeConfig( Constants::SKIN_NAME_LEGACY );
|
||||
},
|
||||
Constants::SERVICE_FEATURE_MANAGER => static function ( MediaWikiServices $services ) {
|
||||
$featureManager = new FeatureManager();
|
||||
|
|
|
@ -28,11 +28,39 @@ use Vector\Hooks;
|
|||
use Vector\VectorServices;
|
||||
|
||||
/**
|
||||
* Skin subclass for Vector
|
||||
* Skin subclass for Vector that may be the new or old version of Vector.
|
||||
*
|
||||
* @ingroup Skins
|
||||
* Skins extending SkinVector are not supported
|
||||
*
|
||||
* @package Vector
|
||||
* @internal
|
||||
*
|
||||
* # Migration Plan (please remove stages when done)
|
||||
*
|
||||
* Stage 1:
|
||||
* In future when we are ready to transition to two separate skins in this order:
|
||||
* - Use $wgSkipSkins to hide vector-2022.
|
||||
* - Remove skippable field from the `vector-2022` skin version. This will defer the code to the
|
||||
* configuration option wgSkipSkins
|
||||
* - Set $wgVectorSkinMigrationMode = true and unset the Vector entry in wgSkipSkins
|
||||
* - for one wiki, to trial run. This will expose Vector in preferences. The new Vector will show
|
||||
* as Vector (2022) to begin with and the skin version preference will be hidden.
|
||||
* - Check VectorPrefDiffInstrumentation instrumentation is still working.
|
||||
*
|
||||
* Stage 2:
|
||||
* - Set $wgVectorSkinMigrationMode = true for all wikis and update skin preference labels
|
||||
* (See Iebe60b560069c8cfcdeed3f5986b8be35501dcbc). This will hide the skin version
|
||||
* preference, and update the skin preference instead.
|
||||
* - We will set $wgDefaultSkin = 'vector-2022'; for desktop improvements wikis.
|
||||
* - Run script that updates prefs table, migrating any rows where skin=vector AND
|
||||
* skinversion = 2 to skin=vector22, skinversion=2
|
||||
*
|
||||
* Stage 3:
|
||||
* - Move all modern code into SkinVector22.
|
||||
* - Move legacy skin code from SkinVector to SkinVectorLegacy.
|
||||
* - Update skin.json `vector` key to point to SkinVectorLegacy.
|
||||
* - SkinVector left as alias if necessary.
|
||||
*/
|
||||
class SkinVector extends SkinMustache {
|
||||
/** @var null|array for caching purposes */
|
||||
|
@ -153,7 +181,11 @@ class SkinVector extends SkinMustache {
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isLegacy(): bool {
|
||||
protected function isLegacy(): bool {
|
||||
$options = $this->getOptions();
|
||||
if ( $options['name'] === Constants::SKIN_NAME_MODERN ) {
|
||||
return false;
|
||||
}
|
||||
$isLatestSkinFeatureEnabled = MediaWikiServices::getInstance()
|
||||
->getService( Constants::SERVICE_FEATURE_MANAGER )
|
||||
->isFeatureEnabled( Constants::FEATURE_LATEST_SKIN );
|
||||
|
@ -422,8 +454,11 @@ class SkinVector extends SkinMustache {
|
|||
public function getDefaultModules() {
|
||||
// FIXME: Do not repeat this pattern. Will be addressed in T291098.
|
||||
if ( $this->isLegacy() ) {
|
||||
$this->options['scripts'] = [ 'skins.vector.legacy.js' ];
|
||||
$this->options['styles'] = [ 'skins.vector.styles.legacy' ];
|
||||
$this->options['scripts'] = SkinVectorLegacy::getScriptsOption();
|
||||
$this->options['styles'] = SkinVectorLegacy::getStylesOption();
|
||||
} else {
|
||||
$this->options['scripts'] = SkinVector22::getScriptsOption();
|
||||
$this->options['styles'] = SkinVector22::getStylesOption();
|
||||
}
|
||||
return parent::getDefaultModules();
|
||||
}
|
||||
|
@ -436,7 +471,7 @@ class SkinVector extends SkinMustache {
|
|||
*/
|
||||
public function generateHTML() {
|
||||
if ( $this->isLegacy() ) {
|
||||
$this->options['template'] = 'skin-legacy';
|
||||
$this->options['template'] = SkinVectorLegacy::getTemplateOption();
|
||||
if ( $this->isTableOfContentsVisibleInSidebar() ) {
|
||||
throw new RuntimeException(
|
||||
'The table of contents flag cannot safely be applied without ' .
|
||||
|
|
54
includes/SkinVector22.php
Normal file
54
includes/SkinVector22.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* @ingroup Skins
|
||||
* @package Vector
|
||||
* @internal
|
||||
*/
|
||||
class SkinVector22 extends SkinVector {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct( $options = [] ) {
|
||||
$options += [
|
||||
'template' => self::getTemplateOption(),
|
||||
'scripts' => self::getScriptsOption(),
|
||||
'styles' => self::getStylesOption(),
|
||||
];
|
||||
parent::__construct( $options );
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary static function while we deprecate SkinVector class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTemplateOption() {
|
||||
return 'skin';
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary static function while we deprecate SkinVector class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getScriptsOption() {
|
||||
return [
|
||||
'skins.vector.js',
|
||||
'skins.vector.es6',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary static function while we deprecate SkinVector class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getStylesOption() {
|
||||
return [
|
||||
'mediawiki.ui.button',
|
||||
'skins.vector.styles',
|
||||
'skins.vector.icons',
|
||||
'mediawiki.ui.icon',
|
||||
];
|
||||
}
|
||||
}
|
51
includes/SkinVectorLegacy.php
Normal file
51
includes/SkinVectorLegacy.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @ingroup Skins
|
||||
* @package Vector
|
||||
* @internal
|
||||
*/
|
||||
class SkinVectorLegacy extends SkinVector {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct( $options = [] ) {
|
||||
$options += [
|
||||
'template' => self::getTemplateOption(),
|
||||
'scripts' => self::getScriptsOption(),
|
||||
'styles' => self::getStylesOption(),
|
||||
];
|
||||
parent::__construct( $options );
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary static function while we deprecate SkinVector class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTemplateOption() {
|
||||
return 'skin-legacy';
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary static function while we deprecate SkinVector class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getScriptsOption() {
|
||||
return [
|
||||
'skins.vector.legacy.js',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary static function while we deprecate SkinVector class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getStylesOption() {
|
||||
return [
|
||||
'skins.vector.styles.legacy',
|
||||
];
|
||||
}
|
||||
}
|
|
@ -107,6 +107,9 @@ final class SkinVersionLookup {
|
|||
* @throws \ConfigException
|
||||
*/
|
||||
public function getVersion(): string {
|
||||
// If skin key is not vector, then version should be considered legacy.
|
||||
|
||||
// If skin is "Vector" invoke additional skin versioning detection.
|
||||
// Obtain the skin version from the 1) `useskinversion` URL query parameter override, 2) the
|
||||
// user preference, 3) the configured default for logged in users, 4) or the site default.
|
||||
//
|
||||
|
@ -114,19 +117,40 @@ final class SkinVersionLookup {
|
|||
// sessions are unavailable at that time so it's not possible to determine whether the
|
||||
// preference is for a logged in user or an anonymous user. Since new users are known to have
|
||||
// had their user preferences initialized in `Hooks::onLocalUserCreated()`, that means all
|
||||
// subsequent requests to `UserOptionsLookup->getOption()` that do not have a preference set
|
||||
//are either existing accounts or anonymous users. Login state makes the distinction.
|
||||
// subsequent requests to `User->getOption()` that do not have a preference set are either
|
||||
// existing accounts or anonymous users. Login state makes the distinction.
|
||||
$skin = $this->userOptionsLookup->getOption(
|
||||
$this->user,
|
||||
Constants::PREF_KEY_SKIN
|
||||
);
|
||||
|
||||
if ( $skin === Constants::SKIN_NAME_MODERN ) {
|
||||
return Constants::SKIN_VERSION_LATEST;
|
||||
}
|
||||
|
||||
$skinVersionPref = $this->userOptionsLookup->getOption(
|
||||
$this->user,
|
||||
Constants::PREF_KEY_SKIN_VERSION,
|
||||
$this->config->get(
|
||||
$this->user->isRegistered()
|
||||
? Constants::CONFIG_KEY_DEFAULT_SKIN_VERSION_FOR_EXISTING_ACCOUNTS
|
||||
: Constants::CONFIG_KEY_DEFAULT_SKIN_VERSION
|
||||
)
|
||||
);
|
||||
|
||||
// If we are in migration mode, we must check the skin version preference.
|
||||
if ( $this->config->get( 'VectorSkinMigrationMode' ) ) {
|
||||
if (
|
||||
$skin === Constants::SKIN_NAME_LEGACY &&
|
||||
$skinVersionPref === Constants::SKIN_VERSION_LATEST
|
||||
) {
|
||||
return Constants::SKIN_VERSION_LATEST;
|
||||
}
|
||||
return Constants::SKIN_VERSION_LEGACY;
|
||||
}
|
||||
return (string)$this->request->getVal(
|
||||
Constants::QUERY_PARAM_SKIN_VERSION,
|
||||
$this->userOptionsLookup->getOption(
|
||||
$this->user,
|
||||
Constants::PREF_KEY_SKIN_VERSION,
|
||||
$this->config->get(
|
||||
$this->user->isRegistered()
|
||||
? Constants::CONFIG_KEY_DEFAULT_SKIN_VERSION_FOR_EXISTING_ACCOUNTS
|
||||
: Constants::CONFIG_KEY_DEFAULT_SKIN_VERSION
|
||||
)
|
||||
)
|
||||
$skinVersionPref
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
73
skin.json
73
skin.json
|
@ -24,24 +24,53 @@
|
|||
"MediaWiki": ">= 1.38.0"
|
||||
},
|
||||
"ValidSkinNames": {
|
||||
"vector-2022": {
|
||||
"class": "SkinVector22",
|
||||
"skippable": true,
|
||||
"args": [
|
||||
{
|
||||
"name": "vector-2022",
|
||||
"templateDirectory": "includes/templates",
|
||||
"responsive": true,
|
||||
"link": {
|
||||
"text-wrapper": {
|
||||
"tag": "span"
|
||||
}
|
||||
},
|
||||
"messages": [
|
||||
"tooltip-p-logo",
|
||||
"vector-opt-out-tooltip",
|
||||
"vector-opt-out",
|
||||
"vector-action-toggle-sidebar",
|
||||
"vector-main-menu-tooltip",
|
||||
"vector-menu-checkbox-expanded",
|
||||
"vector-menu-checkbox-collapsed",
|
||||
"vector-jumptosearch",
|
||||
"vector-jumptocontent",
|
||||
"search",
|
||||
"searchbutton",
|
||||
"searcharticle",
|
||||
"searchsuggest-search",
|
||||
"sitesubtitle",
|
||||
"sitetitle",
|
||||
"tagline"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"vector": {
|
||||
"class": "SkinVector",
|
||||
"@args": "See SkinVector::__construct for more detail.",
|
||||
"args": [
|
||||
{
|
||||
"name": "vector",
|
||||
"scripts": [
|
||||
"skins.vector.es6",
|
||||
"skins.vector.js"
|
||||
],
|
||||
"templateDirectory": "includes/templates",
|
||||
"responsive": true,
|
||||
"styles": [
|
||||
"mediawiki.ui.button",
|
||||
"skins.vector.styles",
|
||||
"skins.vector.icons",
|
||||
"mediawiki.ui.icon"
|
||||
],
|
||||
"link": {
|
||||
"text-wrapper": {
|
||||
"tag": "span"
|
||||
}
|
||||
},
|
||||
"messages": [
|
||||
"tooltip-p-logo",
|
||||
"vector-opt-out-tooltip",
|
||||
|
@ -61,12 +90,7 @@
|
|||
"sitesubtitle",
|
||||
"sitetitle",
|
||||
"tagline"
|
||||
],
|
||||
"link": {
|
||||
"text-wrapper": {
|
||||
"tag": "span"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -80,7 +104,9 @@
|
|||
]
|
||||
},
|
||||
"AutoloadClasses": {
|
||||
"SkinVector": "includes/SkinVector.php"
|
||||
"SkinVector": "includes/SkinVector.php",
|
||||
"SkinVectorLegacy": "includes/SkinVectorLegacy.php",
|
||||
"SkinVector22": "includes/SkinVector22.php"
|
||||
},
|
||||
"AutoloadNamespaces": {
|
||||
"Vector\\": "includes/"
|
||||
|
@ -278,6 +304,15 @@
|
|||
"remoteSkinPath": "Vector"
|
||||
},
|
||||
"ResourceModuleSkinStyles": {
|
||||
"vector-2022": {
|
||||
"+ext.echo.styles.alert": "skinStyles/ext.echo.styles.alert.less",
|
||||
"+mediawiki.action.view.redirectPage": "skinStyles/mediawiki.action.view.redirectPage.less",
|
||||
"+mediawiki.notification": "skinStyles/mediawiki.notification.less",
|
||||
"+oojs-ui-core.styles": "skinStyles/ooui.less",
|
||||
"mediawiki.special": "skinStyles/mediawiki.special.less",
|
||||
"+ext.relatedArticles.readMore": "skinStyles/ext.relatedArticles.readMore.less",
|
||||
"+ext.uls.compactlinks": "skinStyles/ext.uls.compactlinks.less"
|
||||
},
|
||||
"vector": {
|
||||
"+ext.echo.styles.alert": "skinStyles/ext.echo.styles.alert.less",
|
||||
"jquery.tipsy": "skinStyles/jquery.tipsy.less",
|
||||
|
@ -355,6 +390,10 @@
|
|||
"VectorUseWvuiSearch": {
|
||||
"value": true
|
||||
},
|
||||
"VectorSkinMigrationMode": {
|
||||
"value": false,
|
||||
"description": "@internal. For usage to fulfil [[phab:T291098]]"
|
||||
},
|
||||
"VectorSearchTreatmentABTest": {
|
||||
"value": false,
|
||||
"description": "@var boolean Enables or disables the search treatment A/B test. See https://phabricator.wikimedia.org/T261647 and associated tasks for additional detail."
|
||||
|
|
|
@ -72,7 +72,7 @@ class HTMLLegacySkinVersionFieldTest extends \MediaWikiIntegrationTestCase {
|
|||
'label-message' => 'prefs-vector-enable-vector-1-label',
|
||||
'help-message' => 'prefs-vector-enable-vector-1-help',
|
||||
'default' => true,
|
||||
'hide-if' => [ '!==', 'wpskin', Constants::SKIN_NAME ],
|
||||
'hide-if' => [ '!==', 'wpskin', Constants::SKIN_NAME_LEGACY ],
|
||||
];
|
||||
$skinVersionField = new HTMLLegacySkinVersionField( $params );
|
||||
$checkField = new \HTMLCheckField( $params );
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
|
||||
use MediaWiki\User\UserOptionsLookup;
|
||||
use Vector\Constants;
|
||||
use Vector\SkinVersionLookup;
|
||||
|
||||
/**
|
||||
|
@ -44,11 +45,14 @@ class SkinVersionLookupTest extends \MediaWikiIntegrationTestCase {
|
|||
->willReturn( false );
|
||||
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorDefaultSkinVersion' => '2',
|
||||
'VectorDefaultSkinVersionForExistingAccounts' => '1'
|
||||
] );
|
||||
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, '2', 'beta' );
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, 'beta', [
|
||||
'skin' => Constants::SKIN_NAME_LEGACY,
|
||||
] );
|
||||
|
||||
$skinVersionLookup = new SkinVersionLookup( $request, $user, $config, $userOptionsLookup );
|
||||
|
||||
|
@ -81,11 +85,14 @@ class SkinVersionLookupTest extends \MediaWikiIntegrationTestCase {
|
|||
->willReturn( false );
|
||||
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorDefaultSkinVersion' => '2',
|
||||
'VectorDefaultSkinVersionForExistingAccounts' => '1'
|
||||
] );
|
||||
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, '2', 'beta' );
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, 'beta', [
|
||||
'skin' => Constants::SKIN_NAME_LEGACY,
|
||||
] );
|
||||
|
||||
$skinVersionLookup = new SkinVersionLookup( $request, $user, $config, $userOptionsLookup );
|
||||
|
||||
|
@ -118,11 +125,14 @@ class SkinVersionLookupTest extends \MediaWikiIntegrationTestCase {
|
|||
->willReturn( true );
|
||||
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorDefaultSkinVersion' => '2',
|
||||
'VectorDefaultSkinVersionForExistingAccounts' => '1'
|
||||
] );
|
||||
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, '1', '1' );
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, '1', [
|
||||
'skin' => Constants::SKIN_NAME_LEGACY,
|
||||
] );
|
||||
|
||||
$skinVersionLookup = new SkinVersionLookup( $request, $user, $config, $userOptionsLookup );
|
||||
|
||||
|
@ -138,6 +148,38 @@ class SkinVersionLookupTest extends \MediaWikiIntegrationTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getVersion
|
||||
*/
|
||||
public function testSkin22() {
|
||||
$request = $this->getMockBuilder( \WebRequest::class )->getMock();
|
||||
$request
|
||||
->method( 'getVal' )
|
||||
->willReturn( '1' );
|
||||
$user = $this->createMock( \User::class );
|
||||
$user
|
||||
->method( 'isRegistered' )
|
||||
->willReturn( true );
|
||||
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorDefaultSkinVersion' => '1',
|
||||
'VectorDefaultSkinVersionForExistingAccounts' => '1'
|
||||
] );
|
||||
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, '1', [
|
||||
'skin' => Constants::SKIN_NAME_MODERN
|
||||
] );
|
||||
|
||||
$skinVersionLookup = new SkinVersionLookup( $request, $user, $config, $userOptionsLookup );
|
||||
|
||||
$this->assertSame(
|
||||
'2',
|
||||
$skinVersionLookup->getVersion(),
|
||||
'Using the modern skin always returns 2. Ignores skinversion query string.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getVersion
|
||||
* @covers ::isLegacy
|
||||
|
@ -155,11 +197,14 @@ class SkinVersionLookupTest extends \MediaWikiIntegrationTestCase {
|
|||
->willReturn( false );
|
||||
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorDefaultSkinVersion' => '2',
|
||||
'VectorDefaultSkinVersionForExistingAccounts' => '1'
|
||||
] );
|
||||
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, '2', '2' );
|
||||
$userOptionsLookup = $this->getUserOptionsLookupMock( $user, '2', [
|
||||
'skin' => Constants::SKIN_NAME_LEGACY,
|
||||
] );
|
||||
|
||||
$skinVersionLookup = new SkinVersionLookup( $request, $user, $config, $userOptionsLookup );
|
||||
|
||||
|
@ -177,15 +222,16 @@ class SkinVersionLookupTest extends \MediaWikiIntegrationTestCase {
|
|||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param mixed|null $defaultOverride
|
||||
* @param mixed|null $returnVal
|
||||
* @param array $returnVal
|
||||
* @param array $lookup values
|
||||
* @return UserOptionsLookup
|
||||
*/
|
||||
private function getUserOptionsLookupMock( $user, $defaultOverride, $returnVal ) {
|
||||
private function getUserOptionsLookupMock( $user, $returnVal, $lookup = [] ) {
|
||||
$mock = $this->createMock( UserOptionsLookup::class );
|
||||
$mock->method( 'getOption' )
|
||||
->with( $user, $this->anything(), $defaultOverride )
|
||||
->willReturn( $returnVal );
|
||||
->willReturnCallback( static function ( $user, $key ) use ( $returnVal, $lookup ) {
|
||||
return $lookup[ $key ] ?? $returnVal;
|
||||
} );
|
||||
return $mock;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use Vector\HTMLForm\Fields\HTMLLegacySkinVersionField;
|
|||
* @coversDefaultClass \Vector\Hooks
|
||||
*/
|
||||
class VectorHooksTest extends MediaWikiIntegrationTestCase {
|
||||
private const HIDE_IF = [ '!==', 'wpskin', Constants::SKIN_NAME_LEGACY ];
|
||||
|
||||
private const SKIN_PREFS_SECTION = 'rendering/skin/skin-prefs';
|
||||
|
||||
|
@ -282,6 +283,7 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase {
|
|||
*/
|
||||
public function testOnGetPreferencesShowPreferencesDisabled() {
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorShowSkinPreferences' => false,
|
||||
] );
|
||||
$this->setService( 'Vector.Config', $config );
|
||||
|
@ -324,7 +326,7 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase {
|
|||
'help-message' => 'prefs-vector-enable-vector-1-help',
|
||||
'section' => self::SKIN_PREFS_SECTION,
|
||||
'default' => $isLegacy,
|
||||
'hide-if' => [ '!==', 'wpskin', Constants::SKIN_NAME ]
|
||||
'hide-if' => self::HIDE_IF,
|
||||
],
|
||||
'VectorSidebarVisible' => [
|
||||
'type' => 'api',
|
||||
|
@ -389,7 +391,7 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase {
|
|||
'help-message' => 'prefs-vector-enable-vector-1-help',
|
||||
'section' => self::SKIN_PREFS_SECTION,
|
||||
'default' => $isLegacy,
|
||||
'hide-if' => [ '!==', 'wpskin', Constants::SKIN_NAME ]
|
||||
'hide-if' => self::HIDE_IF,
|
||||
],
|
||||
'VectorSidebarVisible' => [
|
||||
'type' => 'api',
|
||||
|
@ -447,12 +449,17 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase {
|
|||
$formData = [
|
||||
'VectorSkinVersion' => Constants::SKIN_VERSION_LATEST,
|
||||
];
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorShowSkinPreferences' => false,
|
||||
] );
|
||||
$form = $this->createMock( HTMLForm::class );
|
||||
$user = $this->createMock( User::class );
|
||||
$userOptionsManager = $this->createMock( UserOptionsManager::class );
|
||||
$userOptionsManager->expects( $this->once() )
|
||||
->method( 'setOption' )
|
||||
->with( $user, 'VectorSkinVersion', 'old' );
|
||||
$this->setService( 'Vector.Config', $config );
|
||||
$this->setService( 'UserOptionsManager', $userOptionsManager );
|
||||
$result = true;
|
||||
$oldPreferences = [
|
||||
|
@ -467,6 +474,7 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase {
|
|||
*/
|
||||
public function testOnLocalUserCreatedLegacy() {
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorDefaultSkinVersionForNewAccounts' => Constants::SKIN_VERSION_LEGACY,
|
||||
] );
|
||||
$this->setService( 'Vector.Config', $config );
|
||||
|
@ -486,6 +494,7 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase {
|
|||
*/
|
||||
public function testOnLocalUserCreatedLatest() {
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorDefaultSkinVersionForNewAccounts' => Constants::SKIN_VERSION_LATEST,
|
||||
] );
|
||||
$this->setService( 'Vector.Config', $config );
|
||||
|
|
|
@ -45,7 +45,10 @@ class LatestSkinVersionRequirementTest extends \MediaWikiUnitTestCase {
|
|||
* @covers ::isMet
|
||||
*/
|
||||
public function testIsMet( $version, $expected, $msg ) {
|
||||
$config = new HashConfig( [ 'VectorDefaultSkinVersionForExistingAccounts' => $version ] );
|
||||
$config = new HashConfig( [
|
||||
'VectorSkinMigrationMode' => false,
|
||||
'VectorDefaultSkinVersionForExistingAccounts' => $version
|
||||
] );
|
||||
|
||||
$user = $this->createMock( User::class );
|
||||
$user->method( 'isRegistered' )->willReturn( true );
|
||||
|
|
Loading…
Reference in a new issue