mediawiki-skins-Vector/includes/FeatureManagement/Requirements/OverridableConfigRequirement.php
jdlrobson ef59d7b973 Disable table of contents in article body
This will currently remove table of contents in article body
for legacy and modern skin.

To prevent us deploying this in current form, a check is
added in generateHTML

This requires an adjustment of OverridableConfigRequirement to
support requirements which do not vary on whether the user is
logged in or not.

Bug: T297610
Change-Id: I847a284229e498b3aa04c16ea3f84c360e735052
2021-12-16 16:11:05 -07:00

208 lines
5.3 KiB
PHP

<?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
*/
namespace Vector\FeatureManagement\Requirements;
use CentralIdLookup;
use Config;
use User;
use Vector\FeatureManagement\Requirement;
use WebRequest;
/**
* The `OverridableConfigRequirement` allows us to define requirements that can override
* configuration like querystring parameters, e.g.
*
* ```lang=php
* $featureManager->registerRequirement(
* new OverridableConfigRequirement(
* $config,
* $user,
* $request,
* $centralIdLookup,
* 'configName',
* 'requirementName',
* 'overrideName',
* 'configTestName',
* )
* );
* ```
*
* registers a requirement that will evaluate to true only when `mediawiki/includes/Setup.php` has
* finished executing (after all service wiring has executed). I.e., every call to
* `Requirement->isMet()` re-interrogates the request, user authentication status,
* and config object for the current state and returns it. Contrast to:
*
* ```lang=php
* $featureManager->registerRequirement(
* 'Foo',
* $config->get( 'Sitename' )
* );
* ```
*
* wherein state is evaluated only once at registration time and permanently cached.
*
* NOTE: This API hasn't settled. It may change at any time without warning. Please don't bind to
* it unless you absolutely need to
*
* @package Vector\FeatureManagement\Requirements
*/
final class OverridableConfigRequirement implements Requirement {
/**
* @var Config
*/
private $config;
/**
* @var User
*/
private $user;
/**
* @var WebRequest
*/
private $request;
/**
* @var CentralIdLookup|null
*/
private $centralIdLookup;
/**
* @var string
*/
private $configName;
/**
* @var string
*/
private $requirementName;
/**
* @var string
*/
private $overrideName;
/**
* @var string|null
*/
private $configTestName;
/**
* This constructor accepts all dependencies needed to determine whether
* the overridable config is enabled for the current user and request.
*
* @param Config $config
* @param User $user
* @param WebRequest $request
* @param CentralIdLookup|null $centralIdLookup
* @param string $configName Any `Config` key. This name is used to query `$config` state.
* @param string $requirementName The name of the requirement presented to FeatureManager.
* @param string $overrideName The name of the override presented to FeatureManager, i.e. query parameter.
* @param string|null $configTestName The name of the AB test config presented to FeatureManager if applicable.
*/
public function __construct(
Config $config,
User $user,
WebRequest $request,
?CentralIdLookup $centralIdLookup,
string $configName,
string $requirementName,
string $overrideName,
?string $configTestName
) {
$this->config = $config;
$this->user = $user;
$this->request = $request;
$this->centralIdLookup = $centralIdLookup;
$this->configName = $configName;
$this->requirementName = $requirementName;
$this->overrideName = $overrideName;
$this->configTestName = $configTestName;
}
/**
* @inheritDoc
*/
public function getName(): string {
return $this->requirementName;
}
/**
* Check query parameter to override config or not.
* Then check for AB test value.
* Fallback to config value.
*
* @inheritDoc
*/
public function isMet(): bool {
// Check query parameter.
if ( $this->request->getCheck( $this->overrideName ) ) {
return $this->request->getBool( $this->overrideName );
}
// Check if there's config for AB testing.
if (
!empty( $this->configTestName ) &&
(bool)$this->config->get( $this->configTestName ) &&
$this->user->isRegistered()
) {
$id = null;
if ( $this->centralIdLookup ) {
$id = $this->centralIdLookup->centralIdFromLocalUser( $this->user );
}
// $id will be 0 if the central ID lookup failed.
if ( !$id ) {
$id = $this->user->getId();
}
return $id % 2 === 0;
}
// If AB test is not enabled, fallback to checking config state.
$thisConfig = $this->config->get( $this->configName );
// Backwards compatibility with config variables that have been set in production.
if ( is_bool( $thisConfig ) ) {
$thisConfig = [
'logged_in' => $thisConfig,
'logged_out' => $thisConfig,
];
} elseif ( array_key_exists( 'default', $thisConfig ) ) {
$thisConfig = [
'default' => $thisConfig['default'],
];
} else {
$thisConfig = [
'logged_in' => $thisConfig['logged_in'] ?? false,
'logged_out' => $thisConfig['logged_out'] ?? false,
];
}
// Fallback to config.
return array_key_exists( 'default', $thisConfig ) ?
$thisConfig[ 'default' ] :
$thisConfig[ $this->user->isRegistered() ? 'logged_in' : 'logged_out' ];
}
}