Skip to content

Commit 1370cdf

Browse files
author
Kenneth Ocastro
committed
Add failedConditions attribute for failed event
1 parent 9759947 commit 1370cdf

File tree

3 files changed

+64
-51
lines changed

3 files changed

+64
-51
lines changed

src/Engine.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public function evaluate(): array
6161
}
6262

6363
$result = [];
64+
$failedConditions = [];
6465

6566
// Evaluate the target rule
6667
if ($this->targetRule->evaluate($this->facts, $this->allRules)) {
@@ -69,9 +70,14 @@ public function evaluate(): array
6970
['interpretation' => $this->targetRule->interpretRules()]
7071
);
7172
} else {
73+
$failedConditions = $this->targetRule->getFailedConditions();
74+
7275
$result[] = array_merge(
7376
$this->targetRule->triggerFailureEvent($this->facts),
74-
['interpretation' => $this->targetRule->interpretRules()]
77+
[
78+
'interpretation' => $this->targetRule->interpretRules(),
79+
'failedConditions' => $failedConditions
80+
]
7581
);
7682
}
7783

src/Rule.php

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class Rule
1010
private array $event;
1111
private array $failureEvent;
1212
private ?string $name;
13+
private array $failedConditions = [];
1314

1415
public function __construct(array $options)
1516
{
@@ -33,6 +34,8 @@ public function getName(): ?string
3334

3435
public function evaluate(Facts $facts, array $allRules): bool
3536
{
37+
$this->failedConditions = []; // Reset failed conditions before evaluation
38+
3639
if (isset($this->conditions['all'])) {
3740
return $this->evaluateAll($this->conditions['all'], $facts, $allRules);
3841
} elseif (isset($this->conditions['any'])) {
@@ -52,25 +55,30 @@ private function evaluateAll(array $conditions, Facts $facts, array $allRules):
5255
if (isset($allRules[$dependencyRuleName])) {
5356
$dependencyRule = $allRules[$dependencyRuleName];
5457
if (!$dependencyRule->evaluate($facts, $allRules)) {
58+
$this->failedConditions[] = $condition;
5559
return false;
5660
}
5761
} else {
5862
throw new Exception("Dependent rule '$dependencyRuleName' not found");
5963
}
6064
} elseif (isset($condition['all'])) {
6165
if (!$this->evaluateAll($condition['all'], $facts, $allRules)) {
66+
$this->failedConditions[] = $condition;
6267
return false;
6368
}
6469
} elseif (isset($condition['any'])) {
6570
if (!$this->evaluateAny($condition['any'], $facts, $allRules)) {
71+
$this->failedConditions[] = $condition;
6672
return false;
6773
}
6874
} elseif (isset($condition['not'])) {
6975
if ($this->evaluateCondition($condition['not'], $facts, $allRules)) {
76+
$this->failedConditions[] = $condition;
7077
return false; // Negate the condition
7178
}
7279
} else {
7380
if (!$this->evaluateCondition($condition, $facts, $allRules)) {
81+
$this->failedConditions[] = $condition;
7482
return false;
7583
}
7684
}
@@ -87,31 +95,46 @@ private function evaluateAny(array $conditions, Facts $facts, array $allRules):
8795
$dependencyRule = $allRules[$dependencyRuleName];
8896
if ($dependencyRule->evaluate($facts, $allRules)) {
8997
return true;
98+
} else {
99+
$this->failedConditions[] = $condition;
90100
}
91101
} else {
92102
throw new Exception("Dependent rule '$dependencyRuleName' not found");
93103
}
94104
} elseif (isset($condition['all'])) {
95105
if ($this->evaluateAll($condition['all'], $facts, $allRules)) {
96106
return true;
107+
} else {
108+
$this->failedConditions[] = $condition;
97109
}
98110
} elseif (isset($condition['any'])) {
99111
if ($this->evaluateAny($condition['any'], $facts, $allRules)) {
100112
return true;
113+
} else {
114+
$this->failedConditions[] = $condition;
101115
}
102116
} elseif (isset($condition['not'])) {
103117
if (!$this->evaluateCondition($condition['not'], $facts, $allRules)) {
104118
return true; // Negate the condition
119+
} else {
120+
$this->failedConditions[] = $condition;
105121
}
106122
} else {
107123
if ($this->evaluateCondition($condition, $facts, $allRules)) {
108124
return true;
125+
} else {
126+
$this->failedConditions[] = $condition;
109127
}
110128
}
111129
}
112130
return false;
113131
}
114132

133+
public function getFailedConditions(): array
134+
{
135+
return $this->failedConditions;
136+
}
137+
115138
private function evaluateCondition(array $condition, Facts $facts, array $allRules): bool
116139
{
117140
$factName = $condition['fact'] ?? null;
@@ -125,26 +148,17 @@ private function evaluateCondition(array $condition, Facts $facts, array $allRul
125148

126149
$factData = $facts->get($factName, $path);
127150

128-
switch ($operator) {
129-
case 'equal':
130-
return $factData === $value;
131-
case 'lessThanInclusive':
132-
return $factData <= $value;
133-
case 'greaterThanInclusive':
134-
return $factData >= $value;
135-
case 'lessThan':
136-
return $factData < $value;
137-
case 'greaterThan':
138-
return $factData > $value;
139-
case 'in':
140-
return in_array($factData, $value, true);
141-
case 'notIn':
142-
return !in_array($factData, $value, true);
143-
case 'contains':
144-
return is_array($factData) && in_array($value, $factData);
145-
default:
146-
throw new Exception("Unknown operator: $operator");
147-
}
151+
return match ($operator) {
152+
'equal' => $factData === $value,
153+
'lessThanInclusive' => $factData <= $value,
154+
'greaterThanInclusive' => $factData >= $value,
155+
'lessThan' => $factData < $value,
156+
'greaterThan' => $factData > $value,
157+
'in' => in_array($factData, $value, true),
158+
'notIn' => !in_array($factData, $value, true),
159+
'contains' => is_array($factData) && in_array($value, $factData),
160+
default => throw new Exception("Unknown operator: $operator"),
161+
};
148162
}
149163

150164
public function triggerEvent(Facts $facts): array
@@ -205,34 +219,18 @@ private function interpretCondition(array $condition): string
205219
}
206220

207221
// Mapping operator to a readable format
208-
switch ($operator) {
209-
case 'equal':
210-
$operatorText = 'is equal to';
211-
break;
212-
case 'greaterThanInclusive':
213-
$operatorText = 'is >=';
214-
break;
215-
case 'lessThanInclusive':
216-
$operatorText = 'is <=';
217-
break;
218-
case 'lessThan':
219-
$operatorText = 'is less than';
220-
break;
221-
case 'greaterThan':
222-
$operatorText = 'is greater than';
223-
break;
224-
case 'in':
225-
$operatorText = 'is in';
226-
break;
227-
case 'notIn':
228-
$operatorText = 'is not in';
229-
break;
230-
case 'contains':
231-
$operatorText = 'contains';
232-
break;
233-
default:
234-
throw new Exception("Unknown operator: $operator");
235-
}
222+
$operatorText = match ($operator) {
223+
'equal' => 'is equal to',
224+
'greaterThanInclusive' => 'is >=',
225+
'lessThanInclusive' => 'is <=',
226+
'lessThan' => 'is less than',
227+
'greaterThan' => 'is greater than',
228+
'in' => 'is in',
229+
'notIn' => 'is not in',
230+
'contains' => 'contains',
231+
default => throw new Exception("Unknown operator: $operator"),
232+
};
233+
236234
return "$factDisplay $operatorText $value";
237235
}
238236
}

tests/EngineTest.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ public function testPlayerIsFouledOut()
3030
$engine->setTargetRule('rule.player.isFouledOut');
3131

3232
$result = $engine->evaluate();
33-
3433
$expectedResult = [
3534
[
3635
'type' => 'fouledOut',
@@ -98,7 +97,17 @@ public function testProfileIsCompleted()
9897
]
9998
]
10099
],
101-
'interpretation' => '(NOT (username is equal to NULL) AND NOT (birthdayYear is equal to NULL) AND NOT (profilePic is equal to NULL) AND NOT (primaryLocation is equal to NULL))'
100+
'interpretation' => '(NOT (username is equal to NULL) AND NOT (birthdayYear is equal to NULL) AND NOT (profilePic is equal to NULL) AND NOT (primaryLocation is equal to NULL))',
101+
'failedConditions' => [
102+
[
103+
'not' => [
104+
'fact' => 'profile',
105+
'path' => '$.attributes.username',
106+
'value' => NULL,
107+
'operator' => 'equal'
108+
]
109+
]
110+
]
102111
]
103112
];
104113

0 commit comments

Comments
 (0)