Skip to content

Commit 2f80b4c

Browse files
committed
add ability to filter for client-side flags only
1 parent c1ac079 commit 2f80b4c

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/LaunchDarkly/FeatureFlag.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ class FeatureFlag
3131
protected $_trackEvents = false;
3232
/** @var int | null */
3333
protected $_debugEventsUntilDate = null;
34+
/** @var bool */
35+
protected $_clientSide = false;
36+
3437
// Note, trackEvents and debugEventsUntilDate are not used in EventProcessor, because
3538
// the PHP client doesn't do summary events. However, we need to capture them in case
3639
// they want to pass the flag data to the front end with allFlagsState().
@@ -47,7 +50,8 @@ protected function __construct($key,
4750
array $variations,
4851
$deleted,
4952
$trackEvents,
50-
$debugEventsUntilDate)
53+
$debugEventsUntilDate,
54+
$clientSide)
5155
{
5256
$this->_key = $key;
5357
$this->_version = $version;
@@ -62,6 +66,7 @@ protected function __construct($key,
6266
$this->_deleted = $deleted;
6367
$this->_trackEvents = $trackEvents;
6468
$this->_debugEventsUntilDate = $debugEventsUntilDate;
69+
$this->_clientSide = $clientSide;
6570
}
6671

6772
public static function getDecoder()
@@ -80,7 +85,8 @@ public static function getDecoder()
8085
$v['variations'] ?: [],
8186
$v['deleted'],
8287
isset($v['trackEvents']) && $v['trackEvents'],
83-
isset($v['debugEventsUntilDate']) ? $v['debugEventsUntilDate'] : null
88+
isset($v['debugEventsUntilDate']) ? $v['debugEventsUntilDate'] : null,
89+
isset($v['clientSide']) && $v['clientSide']
8490
);
8591
};
8692
}
@@ -252,4 +258,12 @@ public function getDebugEventsUntilDate()
252258
{
253259
return $this->_debugEventsUntilDate;
254260
}
261+
262+
/**
263+
* @return boolean
264+
*/
265+
public function isClientSide()
266+
{
267+
return $this->_clientSide;
268+
}
255269
}

src/LaunchDarkly/LDClient.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,12 @@ public function allFlags($user)
282282
* The most common use case for this method is to bootstrap a set of client-side feature flags from a back-end service.
283283
* To convert the state object into a JSON data structure, call its toJson() method.
284284
* @param $user LDUser the end user requesting the feature flags
285+
* @param $options array optional properties affecting how the state is computed; set
286+
* <code>'clientSideOnly' => true</code> to specify that only flags marked for client-side use
287+
* should be included (by default, all flags are included)
285288
* @return FeatureFlagsState a FeatureFlagsState object (will never be null; see FeatureFlagsState.isValid())
286289
*/
287-
public function allFlagsState($user)
290+
public function allFlagsState($user, $options = array())
288291
{
289292
if (is_null($user) || is_null($user->getKey())) {
290293
$this->_logger->warn("allFlagsState called with null user or null/empty user key! Returning empty state");
@@ -304,7 +307,11 @@ public function allFlagsState($user)
304307
}
305308

306309
$state = new FeatureFlagsState(true);
310+
$clientOnly = isset($options['clientSideOnly']) && $options['clientSideOnly'];
307311
foreach ($flags as $key => $flag) {
312+
if ($clientOnly && !$flag->isClientSide()) {
313+
continue;
314+
}
308315
$result = $flag->evaluate($user, $this->_featureRequester);
309316
$state->addFlag($flag, $result);
310317
}

tests/LDClientTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,32 @@ public function testAllFlagsStateReturnsState()
164164
$this->assertEquals($expectedState, $state->jsonSerialize());
165165
}
166166

167+
public function testAllFlagsStateCanFilterForClientSideFlags()
168+
{
169+
$flag1Json = array('key' => 'server-side-1', 'on' => false, 'offVariation' => 0, 'variations' => array('a'), 'clientSide' => false);
170+
$flag1 = FeatureFlag::decode($flag1Json);
171+
$flag2Json = array('key' => 'server-side-2', 'on' => false, 'offVariation' => 0, 'variations' => array('b'), 'clientSide' => false);
172+
$flag2 = FeatureFlag::decode($flag2Json);
173+
$flag3Json = array('key' => 'client-side-1', 'on' => false, 'offVariation' => 0, 'variations' => array('value1'), 'clientSide' => true);
174+
$flag3 = FeatureFlag::decode($flag3Json);
175+
$flag4Json = array('key' => 'client-side-2', 'on' => false, 'offVariation' => 0, 'variations' => array('value2'), 'clientSide' => true);
176+
$flag4 = FeatureFlag::decode($flag4Json);
177+
MockFeatureRequester::$flags = array(
178+
$flag1->getKey() => $flag1, $flag2->getKey() => $flag2, $flag3->getKey() => $flag3, $flag4->getKey() => $flag4
179+
);
180+
$client = new LDClient("someKey", array(
181+
'feature_requester_class' => MockFeatureRequester::class,
182+
'events' => false
183+
));
184+
185+
$builder = new LDUserBuilder(3);
186+
$user = $builder->build();
187+
$state = $client->allFlagsState($user, array('clientSideOnly' => true));
188+
189+
$this->assertTrue($state->isValid());
190+
$this->assertEquals(array('client-side-1' => 'value1', 'client-side-2' => 'value2'), $state->toValuesMap());
191+
}
192+
167193
public function testOnlyValidFeatureRequester()
168194
{
169195
$this->setExpectedException(InvalidArgumentException::class);

0 commit comments

Comments
 (0)