Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dd1c027
WIP: First pass at using the new engine
emyller Oct 2, 2025
0c1f0ab
Merge branch 'feat/context-values' into feat/context-values-client
emyller Oct 3, 2025
340ab82
Let's talk, environment document
emyller Oct 4, 2025
00b8a2e
Fix the toolbox
emyller Oct 4, 2025
7747e52
Merge branch 'feat/context-values' into feat/context-values-client
emyller Oct 4, 2025
cc41007
Fix the talking
emyller Oct 6, 2025
5441f6f
Fix local evaluation setting
emyller Oct 7, 2025
b1937cb
Fix cloning contexts
emyller Oct 8, 2025
ec3bfa2
Make it easier to test private members
emyller Oct 8, 2025
feae1d3
Delete outdated code
emyller Oct 8, 2025
c63aa45
Make sure getEnvironmentFlags now works as expected
emyller Oct 8, 2025
10bdc8b
Merge branch 'feat/context-values' into feat/context-values-client
emyller Oct 8, 2025
3c6c3ce
Found the key
emyller Oct 9, 2025
d925f98
Connect all the dots
emyller Oct 9, 2025
2913611
Please run tests
emyller Oct 9, 2025
a52c914
Stop wasting cycles
emyller Oct 9, 2025
7a467ef
Revert API changes in the offline handler
emyller Oct 9, 2025
a7e74cb
Revert "Stop wasting cycles"
emyller Oct 9, 2025
c10189b
Prevent us from deleting code we don't understand
emyller Oct 9, 2025
b3351ab
Fix casting
emyller Oct 9, 2025
f5eaea7
Improve clarity
emyller Oct 10, 2025
779e732
Merge branch 'feat/context-values' into feat/context-values-client
emyller Oct 11, 2025
e7adeed
Map segment metadata from the environment context
emyller Oct 13, 2025
9b43cb8
Merge branch 'feat/context-values' into feat/context-values-client
emyller Oct 14, 2025
4145960
To each their responsibilities
emyller Oct 14, 2025
95591b8
Merge branch 'feat/context-values' into feat/context-values-client
emyller Oct 16, 2025
cf4fb6f
Respect historical variant priority (UUID-based)
emyller Oct 16, 2025
06bc628
Improve architecture with feature metadata
emyller Oct 16, 2025
a75e860
Fix virtual segments bleeding to the client
emyller Oct 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "tests/Engine/EngineTests/EngineTestData"]
path = tests/Engine/EngineTests/EngineTestData
url = git@github.com:Flagsmith/engine-test-data.git
tag = v2.4.0
tag = v2.5.0
5 changes: 4 additions & 1 deletion src/Engine/Engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public static function getEvaluationResult($context): EvaluationResult
$segmentResult = new SegmentResult();
$segmentResult->key = $segment->key;
$segmentResult->name = $segment->name;
$segmentResult->metadata = $segment->metadata ?? null;
$segmentResult->metadata = $segment->metadata;
$evaluatedSegments[] = $segmentResult;

foreach ($segment->overrides as $overrideFeature) {
Expand Down Expand Up @@ -152,6 +152,7 @@ private static function getFlagResultFromFeatureContext($feature, $splitKey)
$flag->enabled = $feature->enabled;
$flag->value = $variant->value;
$flag->reason = "SPLIT; weight={$variant->weight}";
$flag->metadata = $feature->metadata;
return $flag;
}
$startPercentage = $limit;
Expand All @@ -164,6 +165,7 @@ private static function getFlagResultFromFeatureContext($feature, $splitKey)
$flag->enabled = $feature->enabled;
$flag->value = $feature->value;
$flag->reason = 'DEFAULT';
$flag->metadata = $feature->metadata;
return $flag;
}

Expand All @@ -180,6 +182,7 @@ private static function getFlagResultFromSegmentContext($feature, $segment)
$flag->enabled = $feature->enabled;
$flag->value = $feature->value;
$flag->reason = "TARGETING_MATCH; segment={$segment->name}";
$flag->metadata = $feature->metadata;
return $flag;
}

Expand Down
10 changes: 5 additions & 5 deletions src/Engine/Features/FeatureStateModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class FeatureStateModel

public FeatureModel $feature;
public bool $enabled;
private $_value;
public mixed $feature_state_value;
public string $featurestate_uuid;
public MultivariateFeatureStateValueModelList $multivariate_feature_state_values;
public ?int $django_id = null;
Expand Down Expand Up @@ -157,7 +157,7 @@ public function getValue($identityId = null)
if ($identityId && count($this->multivariate_feature_state_values) > 0) {
return $this->getMultivariateValue($identityId);
}
return $this->_value;
return $this->feature_state_value;
}

/**
Expand Down Expand Up @@ -207,7 +207,7 @@ function (
$startPercentage = $limit;
}

return $this->_value;
return $this->feature_state_value;
}

/**
Expand All @@ -217,7 +217,7 @@ function (
*/
public function setValue($value)
{
$this->_value = $value;
$this->feature_state_value = $value;
}


Expand All @@ -232,7 +232,7 @@ protected function setValues($values)
unset($values->feature_state_value);
$this->setValuesSerializer($values);
if (!empty($featureStateValue)) {
$this->_value = $featureStateValue;
$this->feature_state_value = $featureStateValue;
}
}

Expand Down
24 changes: 18 additions & 6 deletions src/Engine/Utils/Types/Context/EvaluationContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static function fromJsonObject($jsonContext)
}

$context->segments = [];
foreach ($jsonContext->segments as $jsonSegment) {
foreach (($jsonContext->segments ?? []) as $jsonSegment) {
$segment = new SegmentContext();
$segment->key = $jsonSegment->key;
$segment->name = $jsonSegment->name;
Expand All @@ -51,6 +51,15 @@ public static function fromJsonObject($jsonContext)
return $context;
}

/**
* Deep clone the EvaluationContext
* @return EvaluationContext
*/
public function deepClone(): self
{
return EvaluationContext::fromJsonObject($this);
}

/**
* @param array<object> $jsonRules
* @return array<SegmentRule>
Expand All @@ -60,15 +69,17 @@ private static function _convertRules($jsonRules)
$rules = [];
foreach ($jsonRules as $jsonRule) {
$rule = new SegmentRule();
$rule->type = SegmentRuleType::from($jsonRule->type);
$rule->type = $jsonRule->type instanceof SegmentRuleType
? $jsonRule->type
: SegmentRuleType::from($jsonRule->type);

$rule->conditions = [];
foreach ($jsonRule->conditions ?? [] as $jsonCondition) {
$condition = new SegmentCondition();
$condition->property = $jsonCondition->property;
$condition->operator = SegmentConditionOperator::from(
$jsonCondition->operator,
);
$condition->operator = $jsonCondition->operator instanceof SegmentConditionOperator
? $jsonCondition->operator
: SegmentConditionOperator::from($jsonCondition->operator);
$condition->value = $jsonCondition->value;
$rule->conditions[] = $condition;
}
Expand All @@ -93,11 +104,12 @@ private static function _convertFeatures($jsonFeatures): array
foreach ($jsonFeatures as $jsonFeature) {
$feature = new FeatureContext();
$feature->key = $jsonFeature->key;
$feature->feature_key = $jsonFeature->feature_key;
$feature->feature_key = (string) $jsonFeature->feature_key;
$feature->name = $jsonFeature->name;
$feature->enabled = $jsonFeature->enabled;
$feature->value = $jsonFeature->value;
$feature->priority = $jsonFeature->priority ?? null;
$feature->metadata = (array) ($jsonFeature->metadata ?? []);
$feature->variants = [];
foreach ($jsonFeature->variants ?? [] as $jsonVariant) {
$variant = new FeatureValue();
Expand Down
3 changes: 3 additions & 0 deletions src/Engine/Utils/Types/Context/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ class FeatureContext

/** @var array<FeatureValue> */
public $variants;

/** @var ?array<string,mixed> */
public $metadata;
}
17 changes: 16 additions & 1 deletion src/Engine/Utils/Types/Result/FlagResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Flagsmith\Engine\Utils\Types\Result;

class FlagResult
class FlagResult implements \JsonSerializable
{
/** @var string */
public $feature_key;
Expand All @@ -18,4 +18,19 @@ class FlagResult

/** @var ?string */
public $reason;

/** @var ?array<string,mixed> */
public $metadata;

public function jsonSerialize(): array
{
$data = get_object_vars($this);

// 'metadata' is only added if there is any
if (empty($this->metadata)) {
unset($data['metadata']);
}

return $data;
}
}
9 changes: 3 additions & 6 deletions src/Engine/Utils/Types/Result/SegmentResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@ class SegmentResult implements \JsonSerializable

public function jsonSerialize(): array
{
$data = [
'key' => $this->key,
'name' => $this->name,
];
$data = get_object_vars($this);

// 'metadata' is only added if there is any
if (!empty($this->metadata)) {
$data['metadata'] = $this->metadata;
if (empty($this->metadata)) {
unset($data['metadata']);
}

return $data;
Expand Down
Loading