mediawiki-skins-Vector/includes/FeatureManagement/Requirements/DynamicConfigRequirement.php

112 lines
3.2 KiB
PHP
Raw Normal View History

featureManager: Add DynamicConfigRequirement requirement We expect the vast majority of requirements and features to be defined in services as possible. However, there are some "complex" requirements that require additional application/HTTP request state. Unfortunately, service wiring is done before some of that state is available. I65702426 attempted to work around this by requiring clients of the Feature Manager to pass that additional state on every interaction with the system. Those complex requirements would then select the parts of the state that they required when it was required. However implementations of \IContextSource are God objects and their use should be limited. Whilst reviewing I65702426, Stephen Niedzielski mentioned that the application state being available is a requirement. This remarkably simple solution: - Keeps the Requirement interface and FeatureManager API free of God objects; - Is true to the nature of the Feature Manager - it makes clear and centralizes the various checks for application state being available across the codebase; and - Inject a Requirement implementations' dependencies at construction time It just so happens that the $wgFullyInitialised variable flags whether the application state is available... Changes: - Add the the FeatureManager\Requirements\DynamicConfigRequirement class and tests. The DynamicConfigRequirement lazily evaluates a single configuration value whenever ::isMet is invoked - Register an DynamicConfigRequirement instance, configured to evaluate $wgFullyInitialised while constructing the Vector.FeatureManager service Bug: T244481 Change-Id: I7a2cdc2dfdf20d78e4548f07cf53994563b234b3
2020-03-13 17:22:59 +00:00
<?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\FeatureManagement\Requirements;
use Vector\FeatureManagement\Requirement;
/**
* Some application state changes throughout the lifetime of the application, e.g. `wgSitename` or
featureManager: Add DynamicConfigRequirement requirement We expect the vast majority of requirements and features to be defined in services as possible. However, there are some "complex" requirements that require additional application/HTTP request state. Unfortunately, service wiring is done before some of that state is available. I65702426 attempted to work around this by requiring clients of the Feature Manager to pass that additional state on every interaction with the system. Those complex requirements would then select the parts of the state that they required when it was required. However implementations of \IContextSource are God objects and their use should be limited. Whilst reviewing I65702426, Stephen Niedzielski mentioned that the application state being available is a requirement. This remarkably simple solution: - Keeps the Requirement interface and FeatureManager API free of God objects; - Is true to the nature of the Feature Manager - it makes clear and centralizes the various checks for application state being available across the codebase; and - Inject a Requirement implementations' dependencies at construction time It just so happens that the $wgFullyInitialised variable flags whether the application state is available... Changes: - Add the the FeatureManager\Requirements\DynamicConfigRequirement class and tests. The DynamicConfigRequirement lazily evaluates a single configuration value whenever ::isMet is invoked - Register an DynamicConfigRequirement instance, configured to evaluate $wgFullyInitialised while constructing the Vector.FeatureManager service Bug: T244481 Change-Id: I7a2cdc2dfdf20d78e4548f07cf53994563b234b3
2020-03-13 17:22:59 +00:00
* `wgFullyInitialised`, which signals whether the application boot process has finished and
* critical resources like database connections are available.
*
* The `DynamicStateRequirement` allows us to define requirements that lazily evaluate the
* application state statically, e.g.
*
* ```lang=php
* $featureManager->registerComplexRequirement(
* new DynamicConfigRequirement(
* $config,
* 'Sitename',
featureManager: Add DynamicConfigRequirement requirement We expect the vast majority of requirements and features to be defined in services as possible. However, there are some "complex" requirements that require additional application/HTTP request state. Unfortunately, service wiring is done before some of that state is available. I65702426 attempted to work around this by requiring clients of the Feature Manager to pass that additional state on every interaction with the system. Those complex requirements would then select the parts of the state that they required when it was required. However implementations of \IContextSource are God objects and their use should be limited. Whilst reviewing I65702426, Stephen Niedzielski mentioned that the application state being available is a requirement. This remarkably simple solution: - Keeps the Requirement interface and FeatureManager API free of God objects; - Is true to the nature of the Feature Manager - it makes clear and centralizes the various checks for application state being available across the codebase; and - Inject a Requirement implementations' dependencies at construction time It just so happens that the $wgFullyInitialised variable flags whether the application state is available... Changes: - Add the the FeatureManager\Requirements\DynamicConfigRequirement class and tests. The DynamicConfigRequirement lazily evaluates a single configuration value whenever ::isMet is invoked - Register an DynamicConfigRequirement instance, configured to evaluate $wgFullyInitialised while constructing the Vector.FeatureManager service Bug: T244481 Change-Id: I7a2cdc2dfdf20d78e4548f07cf53994563b234b3
2020-03-13 17:22:59 +00:00
* 'Foo'
* )
* );
* ```
*
* 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()` reinterrogates the 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.
featureManager: Add DynamicConfigRequirement requirement We expect the vast majority of requirements and features to be defined in services as possible. However, there are some "complex" requirements that require additional application/HTTP request state. Unfortunately, service wiring is done before some of that state is available. I65702426 attempted to work around this by requiring clients of the Feature Manager to pass that additional state on every interaction with the system. Those complex requirements would then select the parts of the state that they required when it was required. However implementations of \IContextSource are God objects and their use should be limited. Whilst reviewing I65702426, Stephen Niedzielski mentioned that the application state being available is a requirement. This remarkably simple solution: - Keeps the Requirement interface and FeatureManager API free of God objects; - Is true to the nature of the Feature Manager - it makes clear and centralizes the various checks for application state being available across the codebase; and - Inject a Requirement implementations' dependencies at construction time It just so happens that the $wgFullyInitialised variable flags whether the application state is available... Changes: - Add the the FeatureManager\Requirements\DynamicConfigRequirement class and tests. The DynamicConfigRequirement lazily evaluates a single configuration value whenever ::isMet is invoked - Register an DynamicConfigRequirement instance, configured to evaluate $wgFullyInitialised while constructing the Vector.FeatureManager service Bug: T244481 Change-Id: I7a2cdc2dfdf20d78e4548f07cf53994563b234b3
2020-03-13 17:22:59 +00:00
*
* 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
*
* @unstable
*
* @package Vector\FeatureManagement\Requirements
featureManager: Add DynamicConfigRequirement requirement We expect the vast majority of requirements and features to be defined in services as possible. However, there are some "complex" requirements that require additional application/HTTP request state. Unfortunately, service wiring is done before some of that state is available. I65702426 attempted to work around this by requiring clients of the Feature Manager to pass that additional state on every interaction with the system. Those complex requirements would then select the parts of the state that they required when it was required. However implementations of \IContextSource are God objects and their use should be limited. Whilst reviewing I65702426, Stephen Niedzielski mentioned that the application state being available is a requirement. This remarkably simple solution: - Keeps the Requirement interface and FeatureManager API free of God objects; - Is true to the nature of the Feature Manager - it makes clear and centralizes the various checks for application state being available across the codebase; and - Inject a Requirement implementations' dependencies at construction time It just so happens that the $wgFullyInitialised variable flags whether the application state is available... Changes: - Add the the FeatureManager\Requirements\DynamicConfigRequirement class and tests. The DynamicConfigRequirement lazily evaluates a single configuration value whenever ::isMet is invoked - Register an DynamicConfigRequirement instance, configured to evaluate $wgFullyInitialised while constructing the Vector.FeatureManager service Bug: T244481 Change-Id: I7a2cdc2dfdf20d78e4548f07cf53994563b234b3
2020-03-13 17:22:59 +00:00
* @internal
*/
final class DynamicConfigRequirement implements Requirement {
/**
* @var \Config
*/
private $config;
/**
* @var string
*/
private $configName;
/**
* @var string
*/
private $requirementName;
/**
* @param \Config $config
* @param string $configName Any `Config` key. This name is used to query `$config` state. E.g.,
* `'DBname'`. See https://www.mediawiki.org/wiki/Manual:Configuration_settings
* @param string $requirementName The name of the requirement presented to FeatureManager.
* This name _usually_ matches the `$configName` parameter for simplicity but allows for
* abstraction as needed. See `Requirement->getName()`.
featureManager: Add DynamicConfigRequirement requirement We expect the vast majority of requirements and features to be defined in services as possible. However, there are some "complex" requirements that require additional application/HTTP request state. Unfortunately, service wiring is done before some of that state is available. I65702426 attempted to work around this by requiring clients of the Feature Manager to pass that additional state on every interaction with the system. Those complex requirements would then select the parts of the state that they required when it was required. However implementations of \IContextSource are God objects and their use should be limited. Whilst reviewing I65702426, Stephen Niedzielski mentioned that the application state being available is a requirement. This remarkably simple solution: - Keeps the Requirement interface and FeatureManager API free of God objects; - Is true to the nature of the Feature Manager - it makes clear and centralizes the various checks for application state being available across the codebase; and - Inject a Requirement implementations' dependencies at construction time It just so happens that the $wgFullyInitialised variable flags whether the application state is available... Changes: - Add the the FeatureManager\Requirements\DynamicConfigRequirement class and tests. The DynamicConfigRequirement lazily evaluates a single configuration value whenever ::isMet is invoked - Register an DynamicConfigRequirement instance, configured to evaluate $wgFullyInitialised while constructing the Vector.FeatureManager service Bug: T244481 Change-Id: I7a2cdc2dfdf20d78e4548f07cf53994563b234b3
2020-03-13 17:22:59 +00:00
*/
public function __construct( \Config $config, string $configName, string $requirementName ) {
$this->config = $config;
$this->configName = $configName;
$this->requirementName = $requirementName;
}
/**
* @inheritDoc
*/
public function getName() : string {
return $this->requirementName;
}
/**
* @inheritDoc
*/
public function isMet() : bool {
return (bool)$this->config->get( $this->configName );
}
}