|
16 | 16 | use LaunchDarkly\Subsystems\FeatureRequester; |
17 | 17 | use Psr\Log\LoggerInterface; |
18 | 18 |
|
19 | | -/** |
20 | | - * @ignore |
21 | | - * @internal |
22 | | - */ |
23 | | -class EvaluatorState |
24 | | -{ |
25 | | - public ?array $prerequisiteStack = null; |
26 | | - public ?array $segmentStack = null; |
27 | | - |
28 | | - public function __construct(public FeatureFlag $originalFlag) |
29 | | - { |
30 | | - } |
31 | | -} |
32 | | - |
33 | 19 | /** |
34 | 20 | * Encapsulates the feature flag evaluation logic. The Evaluator has no direct access to the |
35 | 21 | * rest of the SDK environment; if it needs to retrieve flags or segments that are referenced |
@@ -62,15 +48,15 @@ public function __construct(FeatureRequester $featureRequester, ?LoggerInterface |
62 | 48 | */ |
63 | 49 | public function evaluate(FeatureFlag $flag, LDContext $context, ?callable $prereqEvalSink): EvalResult |
64 | 50 | { |
65 | | - $stateStack = null; |
66 | 51 | $state = new EvaluatorState($flag); |
67 | 52 | try { |
68 | | - return $this->evaluateInternal($flag, $context, $prereqEvalSink, $state); |
| 53 | + return $this->evaluateInternal($flag, $context, $prereqEvalSink, $state) |
| 54 | + ->withState($state); |
69 | 55 | } catch (EvaluationException $e) { |
70 | | - return new EvalResult(new EvaluationDetail(null, null, EvaluationReason::error($e->getErrorKind()))); |
| 56 | + return new EvalResult(new EvaluationDetail(null, null, EvaluationReason::error($e->getErrorKind())), false, $state); |
71 | 57 | } catch (\Throwable $e) { |
72 | 58 | Util::logExceptionAtErrorLevel($this->_logger, $e, 'Unexpected error when evaluating flag ' . $flag->getKey()); |
73 | | - return new EvalResult(new EvaluationDetail(null, null, EvaluationReason::error(EvaluationReason::EXCEPTION_ERROR))); |
| 59 | + return new EvalResult(new EvaluationDetail(null, null, EvaluationReason::error(EvaluationReason::EXCEPTION_ERROR)), false, $state); |
74 | 60 | } |
75 | 61 | } |
76 | 62 |
|
@@ -144,14 +130,25 @@ private function checkPrerequisites( |
144 | 130 | EvaluationReason::MALFORMED_FLAG_ERROR |
145 | 131 | ); |
146 | 132 | } |
| 133 | + |
| 134 | + if ($state->depth == 0) { |
| 135 | + if ($state->prerequisites === null) { |
| 136 | + $state->prerequisites = []; |
| 137 | + } |
| 138 | + $state->prerequisites[] = $prereqKey; |
| 139 | + } |
| 140 | + |
| 141 | + |
147 | 142 | $prereqOk = true; |
148 | 143 | $prereqFeatureFlag = $this->_featureRequester->getFeature($prereqKey); |
149 | 144 | if ($prereqFeatureFlag === null) { |
150 | 145 | $prereqOk = false; |
151 | 146 | } else { |
152 | 147 | // Note that if the prerequisite flag is off, we don't consider it a match no matter what its |
153 | 148 | // off variation was. But we still need to evaluate it in order to generate an event. |
| 149 | + $state->depth++; |
154 | 150 | $prereqEvalResult = $this->evaluateInternal($prereqFeatureFlag, $context, $prereqEvalSink, $state); |
| 151 | + $state->depth--; |
155 | 152 | $variation = $prereq->getVariation(); |
156 | 153 | if (!$prereqFeatureFlag->isOn() || $prereqEvalResult->getDetail()->getVariationIndex() !== $variation) { |
157 | 154 | $prereqOk = false; |
|
0 commit comments