Skip to content

Commit deadcde

Browse files
oakbanimikeproeng37
authored andcommitted
API - getEnabledFeatures (#81)
1 parent b33d751 commit deadcde

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

src/Optimizely/Optimizely.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,32 @@ public function isFeatureEnabled($featureFlagKey, $userId, $attributes = null)
501501
return true;
502502
}
503503

504+
/**
505+
* Get keys of all feature flags which are enabled for the user
506+
* @param string User ID
507+
* @param array Associative array of user attributes
508+
* @return array List of feature flag keys
509+
*/
510+
public function getEnabledFeatures($userId, $attributes = null)
511+
{
512+
$enabledFeatureKeys = [];
513+
514+
if (!$this->_isValid) {
515+
$this->_logger->log(Logger::ERROR, "Datafile has invalid format. Failing '".__FUNCTION__."'.");
516+
return $enabledFeatureKeys;
517+
}
518+
519+
$featureFlags = $this->_config->getFeatureFlags();
520+
foreach ($featureFlags as $feature){
521+
$featureKey = $feature->getKey();
522+
if ($this->isFeatureEnabled($featureKey, $userId, $attributes) === true) {
523+
$enabledFeatureKeys[] = $featureKey;
524+
}
525+
}
526+
527+
return $enabledFeatureKeys;
528+
}
529+
504530
/**
505531
* Get the string value of the specified variable in the feature flag.
506532
* @param string Feature flag key

src/Optimizely/ProjectConfig.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,14 @@ public function getRevision()
272272
return $this->_revision;
273273
}
274274

275+
/**
276+
* @return array List of feature flags parsed from the datafile
277+
*/
278+
public function getFeatureFlags()
279+
{
280+
return $this->_featureFlags;
281+
}
282+
275283
/**
276284
* @param $groupId string ID of the group.
277285
*

tests/OptimizelyTest.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,6 +2159,95 @@ public function testIsFeatureEnabledGivenFeatureFlagIsEnabledAndUserIsNotBeingEx
21592159
);
21602160
}
21612161

2162+
public function testGetEnabledFeaturesGivenInvalidDataFile()
2163+
{
2164+
$optlyObject = new Optimizely('Random datafile');
2165+
2166+
$this->expectOutputRegex("/Datafile has invalid format. Failing 'getEnabledFeatures'./");
2167+
2168+
$this->assertEmpty($optlyObject->getEnabledFeatures("user_id", []));
2169+
}
2170+
2171+
public function testGetEnabledFeaturesGivenNoFeatureIsEnabledForUser()
2172+
{
2173+
$optimizelyMock = $this->getMockBuilder(Optimizely::class)
2174+
->setConstructorArgs(array($this->datafile))
2175+
->setMethods(array('isFeatureEnabled'))
2176+
->getMock();
2177+
2178+
// Mock isFeatureEnabled to return false for all calls
2179+
$optimizelyMock->expects($this->exactly(8))
2180+
->method('isFeatureEnabled')
2181+
->will($this->returnValue(false));
2182+
2183+
$this->assertEmpty($optimizelyMock->getEnabledFeatures("user_id", []));
2184+
}
2185+
2186+
public function testGetEnabledFeaturesGivenFeaturesAreEnabledForUser()
2187+
{
2188+
$optimizelyMock = $this->getMockBuilder(Optimizely::class)
2189+
->setConstructorArgs(array($this->datafile))
2190+
->setMethods(array('isFeatureEnabled'))
2191+
->getMock();
2192+
2193+
$map = [
2194+
['boolean_feature','user_id', [], true],
2195+
['double_single_variable_feature','user_id', [], false],
2196+
['integer_single_variable_feature','user_id', [], false],
2197+
['boolean_single_variable_feature','user_id', [], true],
2198+
['string_single_variable_feature','user_id', [], false],
2199+
['multi_variate_feature','user_id', [], false],
2200+
['mutex_group_feature','user_id', [], false],
2201+
['empty_feature','user_id', [], true],
2202+
];
2203+
2204+
// Mock isFeatureEnabled to return specific values
2205+
$optimizelyMock->expects($this->exactly(8))
2206+
->method('isFeatureEnabled')
2207+
->will($this->returnValueMap($map));
2208+
2209+
$this->assertEquals(
2210+
['boolean_feature', 'boolean_single_variable_feature', 'empty_feature'],
2211+
$optimizelyMock->getEnabledFeatures("user_id", [])
2212+
);
2213+
}
2214+
2215+
public function testGetEnabledFeaturesWithUserAttributes()
2216+
{
2217+
$optimizelyMock = $this->getMockBuilder(Optimizely::class)
2218+
->setConstructorArgs(array($this->datafile))
2219+
->setMethods(array('isFeatureEnabled'))
2220+
->getMock();
2221+
2222+
$userAttributes = [
2223+
'device_type' => 'iPhone',
2224+
'company' => 'Optimizely',
2225+
'location' => 'San Francisco'
2226+
];
2227+
2228+
$map = [
2229+
['boolean_feature','user_id', $userAttributes, false],
2230+
['double_single_variable_feature','user_id', $userAttributes, false],
2231+
['integer_single_variable_feature','user_id', $userAttributes, false],
2232+
['boolean_single_variable_feature','user_id', $userAttributes, false],
2233+
['string_single_variable_feature','user_id', $userAttributes, false],
2234+
['multi_variate_feature','user_id', $userAttributes, false],
2235+
['mutex_group_feature','user_id', $userAttributes, false],
2236+
['empty_feature','user_id', $userAttributes, true],
2237+
];
2238+
2239+
// Assert that isFeatureEnabled is called with the same attributes and mock to return value map
2240+
$optimizelyMock->expects($this->exactly(8))
2241+
->method('isFeatureEnabled')
2242+
->with()
2243+
->will($this->returnValueMap($map));
2244+
2245+
$this->assertEquals(
2246+
['empty_feature'],
2247+
$optimizelyMock->getEnabledFeatures("user_id", $userAttributes)
2248+
);
2249+
}
2250+
21622251
public function testGetFeatureVariableValueForTypeGivenInvalidArguments()
21632252
{
21642253
// should return null and log a message when feature flag key is empty

0 commit comments

Comments
 (0)