diff --git a/includes/Constants.php b/includes/Constants.php index b8a37a6..c4cafb9 100644 --- a/includes/Constants.php +++ b/includes/Constants.php @@ -79,6 +79,11 @@ final class Constants { */ public const CONFIG_SEARCH_IN_HEADER = 'VectorIsSearchInHeader'; + /** + * @var string + */ + public const CONFIG_SEARCH_IN_HEADER_AB = 'VectorIsSearchInHeaderABTest'; + /** * @var string */ diff --git a/includes/FeatureManagement/Requirements/SearchInHeaderRequirement.php b/includes/FeatureManagement/Requirements/SearchInHeaderRequirement.php index 71cfb7c..fa2260c 100644 --- a/includes/FeatureManagement/Requirements/SearchInHeaderRequirement.php +++ b/includes/FeatureManagement/Requirements/SearchInHeaderRequirement.php @@ -31,6 +31,9 @@ use Vector\FeatureManagement\Requirement; * the tabs (as in the old design). * The search in header is enabled if: * - the associated feature flag has been enabled + * - the feature flag for the A/B test is enabled, + * and the user is logged and bucketed, + * in which case 50% of logged in users will see the search in the header * * @unstable * @@ -43,14 +46,21 @@ final class SearchInHeaderRequirement implements Requirement { */ private $config; + /** + * @var \User + */ + private $user; + /** * This constructor accepts all dependencies needed to determine * whether search in header is enabled for current user and config. * * @param \Config $config + * @param \User $user */ - public function __construct( Config $config ) { + public function __construct( \Config $config, \User $user ) { $this->config = $config; + $this->user = $user; } /** @@ -60,11 +70,27 @@ final class SearchInHeaderRequirement implements Requirement { return Constants::REQUIREMENT_SEARCH_IN_HEADER; } + /** + * If A/B test is enabled check whether the user is logged in and bucketed + * @return bool + */ + private function isBucketed() { + $isABTestEnabled = (bool)$this->config->get( Constants::CONFIG_SEARCH_IN_HEADER_AB ); + + if ( $isABTestEnabled ) { + return $this->user->getId() % 2 === 0; + } else { + // if A/B test is disabled then resort to using CONFIG_SEARCH_IN_HEADER + return (bool)$this->config->get( Constants::CONFIG_SEARCH_IN_HEADER ); + } + } + /** * @inheritDoc * @throws \ConfigException */ public function isMet() : bool { - return (bool)$this->config->get( Constants::CONFIG_SEARCH_IN_HEADER ); + return $this->user->isRegistered() ? + $this->isBucketed() : (bool)$this->config->get( Constants::CONFIG_SEARCH_IN_HEADER ); } } diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 3fcc0ad..2c63182 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -71,7 +71,8 @@ return [ // ======================================== $featureManager->registerRequirement( new SearchInHeaderRequirement( - $services->getMainConfig() + $services->getMainConfig(), + $context->getUser() ) ); diff --git a/skin.json b/skin.json index 7e32ca6..70db03a 100644 --- a/skin.json +++ b/skin.json @@ -189,6 +189,9 @@ "VectorIsSearchInHeader": { "value": false }, + "VectorIsSearchInHeaderABTest": { + "value": false + }, "VectorDefaultSidebarVisibleForAuthorisedUser": { "value": true }, diff --git a/tests/phpunit/integration/FeatureManagement/Requirements/SearchInHeaderRequirementTest.php b/tests/phpunit/integration/FeatureManagement/Requirements/SearchInHeaderRequirementTest.php new file mode 100644 index 0000000..a4f5576 --- /dev/null +++ b/tests/phpunit/integration/FeatureManagement/Requirements/SearchInHeaderRequirementTest.php @@ -0,0 +1,127 @@ + $searchInHeaderConfigValue, + Constants::CONFIG_SEARCH_IN_HEADER_AB => $abValue, + ] ); + $user = $this->getTestUser()->getUser(); + $user->setId( $userId ); + + $requirement = new SearchInHeaderRequirement( + $config, $user + ); + + $this->assertSame( $requirement->isMet(), $expected, $msg ); + } +}