Skip to content

Commit c0cbe89

Browse files
authored
feat: Identity overrides in local evaluation mode (#69)
* feat: Identity overrides in local evaluation mode
1 parent a0b1c22 commit c0cbe89

File tree

5 files changed

+76
-15
lines changed

5 files changed

+76
-15
lines changed

src/Engine/Environments/EnvironmentModel.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
use Flagsmith\Concerns\JsonSerializer;
77
use Flagsmith\Engine\Environments\Integrations\IntegrationModel;
88
use Flagsmith\Engine\Projects\ProjectModel;
9+
use Flagsmith\Engine\Identities\IdentityModel;
910
use Flagsmith\Engine\Utils\Collections\FeatureStateModelList;
11+
use Flagsmith\Engine\Utils\Collections\IdentityList;
1012

1113
#[\AllowDynamicProperties]
1214
class EnvironmentModel
@@ -16,17 +18,11 @@ class EnvironmentModel
1618
public int $id;
1719
public string $api_key;
1820
public FeatureStateModelList $feature_states;
19-
public IntegrationModel $segment_config;
20-
public IntegrationModel $heap_config;
21-
public IntegrationModel $mixpanel_config;
22-
public IntegrationModel $amplitude_config;
21+
public IdentityList $identity_overrides;
2322
public ProjectModel $project;
2423
private array $keys = [
24+
'identity_overrides' => 'Flagsmith\Engine\Utils\Collections\IdentityList',
2525
'feature_states' => 'Flagsmith\Engine\Utils\Collections\FeatureStateModelList',
26-
'segment_config' => 'Flagsmith\Engine\Environments\Integrations\IntegrationModel',
27-
'heap_config' => 'Flagsmith\Engine\Environments\Integrations\IntegrationModel',
28-
'mixpanel_config' => 'Flagsmith\Engine\Environments\Integrations\IntegrationModel',
29-
'amplitude_config' => 'Flagsmith\Engine\Environments\Integrations\IntegrationModel',
3026
'project' => 'Flagsmith\Engine\Projects\ProjectModel',
3127
];
3228

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Flagsmith\Engine\Utils\Collections;
4+
5+
class IdentityList extends \ArrayObject implements \JsonSerializable
6+
{
7+
use CollectionTrait;
8+
private string $list_type = 'Flagsmith\Engine\Identities\IdentityModel';
9+
/**
10+
* store identity models by identifiers.
11+
* @param mixed $key
12+
* @param IdentityModel $value
13+
* @return void
14+
*/
15+
public function offsetSet($offset, $value): void
16+
{
17+
parent::offsetSet($value->identifier, $value);
18+
}
19+
}

src/Flagsmith.php

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ public function getIdentitySegments(string $identifier, ?object $traits = null):
327327
}
328328

329329
$traits = $traits ?? (object)[];
330-
$identityModel = $this->buildIdentityModel($identifier, $traits);
330+
$identityModel = $this->getIdentityModel($identifier, $traits);
331331
$segmentModels = SegmentEvaluator::getIdentitySegments($this->environment, $identityModel);
332332

333333
return array_map(fn ($segment) => (new Segment())
@@ -384,7 +384,7 @@ private function getEnvironmentFlagsFromDocument(): Flags
384384
*/
385385
private function getIdentityFlagsFromDocument(string $identifier, object $traits): Flags
386386
{
387-
$identityModel = $this->buildIdentityModel($identifier, $traits);
387+
$identityModel = $this->getIdentityModel($identifier, $traits);
388388
$featureStates = Engine::getIdentityFeatureStates($this->environment, $identityModel);
389389

390390
return Flags::fromFeatureStateModels(
@@ -461,7 +461,7 @@ private function getIdentityFlagsFromApi(string $identifier, ?object $traits): F
461461
*
462462
* @throws FlagsmithClientError
463463
*/
464-
private function buildIdentityModel(string $identifier, ?object $traits): IdentityModel
464+
private function getIdentityModel(string $identifier, ?object $traits): IdentityModel
465465
{
466466
if (empty($this->environment)) {
467467
throw new FlagsmithClientError('Unable to build identity model when no local environment present.');
@@ -474,10 +474,16 @@ private function buildIdentityModel(string $identifier, ?object $traits): Identi
474474
->withTraitValue($value);
475475
}
476476

477-
return (new IdentityModel())
478-
->withIdentifier($identifier)
479-
->withEnvironmentApiKey($this->apiKey)
480-
->withIdentityTraits(new IdentityTraitList($traitModels));
477+
$identityModel = isset($this->environment->identity_overrides) ? $this->environment->identity_overrides[$identifier] ?? null : null;
478+
479+
if (is_null($identityModel)) {
480+
return (new IdentityModel())
481+
->withIdentifier($identifier)
482+
->withEnvironmentApiKey($this->apiKey)
483+
->withIdentityTraits(new IdentityTraitList($traitModels));
484+
}
485+
486+
return $identityModel->withIdentityTraits(new IdentityTraitList($traitModels));
481487
}
482488

483489
/**

tests/Data/environment.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,30 @@
5252
"segment_id": null,
5353
"enabled": true
5454
}
55+
],
56+
"identity_overrides": [
57+
{
58+
"identifier": "overridden-id",
59+
"identity_uuid": "0f21cde8-63c5-4e50-baca-87897fa6cd01",
60+
"created_date": "2019-08-27T14:53:45.698555Z",
61+
"updated_at": "2023-07-14 16:12:00.000000",
62+
"environment_api_key": "B62qaMZNwfiqT76p38ggrQ",
63+
"identity_features": [
64+
{
65+
"id": 1,
66+
"feature": {
67+
"id": 1,
68+
"name": "some_feature",
69+
"type": "STANDARD"
70+
},
71+
"featurestate_uuid": "1bddb9a5-7e59-42c6-9be9-625fa369749f",
72+
"feature_state_value": "some-overridden-value",
73+
"enabled": false,
74+
"environment": 1,
75+
"identity": null,
76+
"feature_segment": null
77+
}
78+
]
79+
}
5580
]
5681
}

tests/FlagsmithClientTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,19 @@ public function testGetIdentitySegmentsWithValidTrait()
279279
$this->assertEquals($segments[0]->getName(), 'Test segment');
280280
}
281281
}
282+
283+
public function testLocalEvaluationGetIdentityOverride()
284+
{
285+
foreach (ClientFixtures::localEvalFlagsmith() as $flagsmith) {
286+
$identifier = 'overridden-id';
287+
$featureName = 'some_feature';
288+
289+
$identityFlags = $flagsmith->getIdentityFlags($identifier);
290+
291+
$flag = $identityFlags->getFlag($featureName);
292+
293+
$this->assertEquals($flag->enabled, false);
294+
$this->assertEquals($flag->value, 'some-overridden-value');
295+
}
296+
}
282297
}

0 commit comments

Comments
 (0)