Skip to content

Commit d194fc3

Browse files
committed
Fiquela conditions support compare values between row fields
1 parent cd3deaf commit d194fc3

File tree

6 files changed

+96
-32
lines changed

6 files changed

+96
-32
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## [2.0.6]
4+
5+
- Fiquela conditions support compare values between row fields
6+
37
## [2.0.5]
48

59
- Fixed evaluating `LIKE` operator

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
![Packagist Dependency Version](https://img.shields.io/packagist/dependency-v/1biot/fiquela/php)
88
![Packagist License](https://img.shields.io/packagist/l/1biot/fiquela)
99

10-
![Static Badge](https://img.shields.io/badge/PHPUnit-tests%3A_180-lightgreen)
11-
![Static Badge](https://img.shields.io/badge/PHPUnit-asserts%3A_605-lightgreen)
10+
![Static Badge](https://img.shields.io/badge/PHPUnit-tests%3A_182-lightgreen)
11+
![Static Badge](https://img.shields.io/badge/PHPUnit-asserts%3A_610-lightgreen)
1212
![Static Badge](https://img.shields.io/badge/PHPStan_6-OK-lightgreen)
1313
![Static Badge](https://img.shields.io/badge/PHPStan_7|8-16_errors-orange)
1414

src/Conditions/SimpleCondition.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,24 @@
44

55
use FQL\Enum;
66
use FQL\Exception\UnexpectedValueException;
7+
use FQL\Interface;
78
use FQL\Traits\Helpers;
89

10+
/**
11+
* @phpstan-import-type ConditionValue from Interface\Query
12+
*/
913
class SimpleCondition extends Condition
1014
{
1115
use Helpers\NestedArrayAccessor;
1216

17+
/**
18+
* @param ConditionValue $value
19+
*/
1320
public function __construct(
1421
Enum\LogicalOperator $logicalOperator,
1522
public readonly string $field,
1623
public readonly Enum\Operator $operator,
17-
public readonly mixed $value
24+
public readonly null|array|float|int|string|Enum\Type $value
1825
) {
1926
parent::__construct($logicalOperator);
2027
}
@@ -29,9 +36,16 @@ public function evaluate(array $item, bool $nestingValues): bool
2936
: $item[$this->field]
3037
?? throw new UnexpectedValueException(sprintf('Field %s not found in item', $this->field));
3138

39+
$compareValue = $this->value;
40+
if (is_scalar($this->value)) {
41+
$compareValue = $nestingValues
42+
? ($this->accessNestedValue($item, (string) $this->value, false) ?? $this->value)
43+
: ($item[$this->value] ?? $this->value);
44+
}
45+
3246
return $this->operator->evaluate(
3347
$value,
34-
$this->value
48+
$compareValue
3549
);
3650
}
3751

src/Interface/Query.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
use FQL\Enum\LogicalOperator;
77
use FQL\Enum\Operator;
88
use FQL\Enum\Sort;
9+
use FQL\Enum\Type;
910
use FQL\Exception;
1011
use FQL\Results;
1112
use FQL\Results\ResultsProvider;
1213

1314
/**
1415
* @phpstan-type InArrayList string[]|int[]|float[]|array<int|string>
15-
* @phpstan-type ConditionValue null|int|float|string|InArrayList
16+
* @phpstan-type ConditionValue null|int|float|string|InArrayList|Type
1617
* @phpstan-type Condition array{
1718
* type: LogicalOperator,
1819
* key: string,
@@ -483,19 +484,19 @@ public function on(string $leftKey, Operator $operator, string $rightKey): Query
483484
* Add a conditional clause to the query.
484485
* @param ConditionValue $value The value to compare against.
485486
*/
486-
public function where(string $field, Operator $operator, null|array|float|int|string $value): Query;
487+
public function where(string $field, Operator $operator, null|array|float|int|string|Type $value): Query;
487488

488489
/** @param ConditionValue $value The value to compare against. */
489-
public function having(string $field, Operator $operator, null|array|float|int|string $value): Query;
490+
public function having(string $field, Operator $operator, null|array|float|int|string|Type $value): Query;
490491

491492
/** @param ConditionValue $value */
492-
public function and(string $field, Operator $operator, null|int|float|string|array $value): Query;
493+
public function and(string $field, Operator $operator, null|int|float|string|array|Type $value): Query;
493494

494495
/** @param ConditionValue $value */
495-
public function or(string $field, Operator $operator, null|int|float|string|array $value): Query;
496+
public function or(string $field, Operator $operator, null|int|float|string|array|Type $value): Query;
496497

497498
/** @param ConditionValue $value */
498-
public function xor(string $field, Operator $operator, null|int|float|string|array $value): Query;
499+
public function xor(string $field, Operator $operator, null|int|float|string|array|Type $value): Query;
499500

500501
/** Add a conditional group clause in WHERE context to the query */
501502
public function whereGroup(): Query;

src/Traits/Conditions.php

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,88 +8,111 @@
88
use FQL\Conditions\SimpleCondition;
99
use FQL\Enum;
1010
use FQL\Exception;
11-
use FQL\Interface\Query;
11+
use FQL\Interface;
1212

13+
/**
14+
* @phpstan-import-type ConditionValue from Interface\Query
15+
*/
1316
trait Conditions
1417
{
1518
private BaseConditionGroup $whereConditions;
1619
private BaseConditionGroup $havingConditions;
1720
private GroupCondition $currentGroup;
1821

19-
private function initialize(): Query
22+
private function initialize(): Interface\Query
2023
{
21-
// Výchozí skupiny pro WHERE a HAVING
24+
// Default groups for WHERE and HAVING
2225
$this->whereConditions = new BaseConditionGroup(Condition::WHERE);
2326
$this->havingConditions = new BaseConditionGroup(Condition::HAVING);
2427

25-
// Nastavení výchozí aktuální skupiny na WHERE
28+
// Setting the default current group to WHERE
2629
$this->currentGroup = $this->whereConditions;
2730
return $this;
2831
}
2932

3033
/**
3134
* Switch context to WHERE and optionally add condition
35+
* @param ConditionValue $value
3236
*/
33-
public function where(string $key, Enum\Operator $operator, null|array|float|int|string $value): Query
34-
{
37+
public function where(
38+
string $key,
39+
Enum\Operator $operator,
40+
null|array|float|int|string|Enum\Type $value
41+
): Interface\Query {
3542
$this->addCondition(Enum\LogicalOperator::AND, $key, $operator, $value);
3643
return $this;
3744
}
3845

3946
/**
4047
* Switch context to HAVING and optionally add condition
48+
* @param ConditionValue $value
4149
*/
42-
public function having(string $key, Enum\Operator $operator, null|array|float|int|string $value): Query
43-
{
50+
public function having(
51+
string $key,
52+
Enum\Operator $operator,
53+
null|array|float|int|string|Enum\Type $value
54+
): Interface\Query {
4455
$this->currentGroup = $this->havingConditions;
4556
$this->addCondition(Enum\LogicalOperator::AND, $key, $operator, $value);
4657
return $this;
4758
}
4859

4960
/**
5061
* Add AND condition to current context
62+
* @param ConditionValue $value
5163
*/
52-
public function and(string $key, Enum\Operator $operator, mixed $value): Query
53-
{
64+
public function and(
65+
string $key,
66+
Enum\Operator $operator,
67+
null|array|float|int|string|Enum\Type $value
68+
): Interface\Query {
5469
$this->addCondition(Enum\LogicalOperator::AND, $key, $operator, $value);
5570
return $this;
5671
}
5772

5873
/**
5974
* Add OR condition to current context
75+
* @param ConditionValue $value
6076
*/
61-
public function or(string $key, Enum\Operator $operator, mixed $value): Query
62-
{
77+
public function or(
78+
string $key,
79+
Enum\Operator $operator,
80+
null|array|float|int|string|Enum\Type $value
81+
): Interface\Query {
6382
$this->addCondition(Enum\LogicalOperator::OR, $key, $operator, $value);
6483
return $this;
6584
}
6685

6786
/**
6887
* Add XOR condition to current context
88+
* @param ConditionValue $value
6989
*/
70-
public function xor(string $key, Enum\Operator $operator, mixed $value): Query
71-
{
90+
public function xor(
91+
string $key,
92+
Enum\Operator $operator,
93+
null|array|float|int|string|Enum\Type $value
94+
): Interface\Query {
7295
$this->addCondition(Enum\LogicalOperator::XOR, $key, $operator, $value);
7396
return $this;
7497
}
7598

76-
public function whereGroup(): Query
99+
public function whereGroup(): Interface\Query
77100
{
78101
return $this->andGroup();
79102
}
80103

81-
public function havingGroup(): Query
104+
public function havingGroup(): Interface\Query
82105
{
83106
$this->currentGroup = $this->havingConditions;
84107
return $this->andGroup();
85108
}
86109

87-
public function orGroup(): Query
110+
public function orGroup(): Interface\Query
88111
{
89112
return $this->beginGroup(Enum\LogicalOperator::OR);
90113
}
91114

92-
public function andGroup(): Query
115+
public function andGroup(): Interface\Query
93116
{
94117
return $this->beginGroup(Enum\LogicalOperator::AND);
95118
}
@@ -108,7 +131,7 @@ public function beginGroup(Enum\LogicalOperator $logicalOperator): self
108131
/**
109132
* Ends the current group of conditions in the current context.
110133
*/
111-
public function endGroup(): Query
134+
public function endGroup(): Interface\Query
112135
{
113136
if ($this->currentGroup instanceof BaseConditionGroup) {
114137
throw new Exception\UnexpectedValueException('No group to end');
@@ -120,9 +143,14 @@ public function endGroup(): Query
120143

121144
/**
122145
* Add condition to the actual group context
146+
* @param ConditionValue $value
123147
*/
124-
private function addCondition(Enum\LogicalOperator $type, string $key, Enum\Operator $operator, mixed $value): void
125-
{
148+
private function addCondition(
149+
Enum\LogicalOperator $type,
150+
string $key,
151+
Enum\Operator $operator,
152+
null|array|float|int|string|Enum\Type $value
153+
): void {
126154
$this->currentGroup->addCondition($type, new SimpleCondition($type, $key, $operator, $value));
127155
}
128156

tests/Conditions/ConditionTest.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function testNonExistentKeyThrowsException(): void
109109
$condition->evaluate([], false);
110110
}
111111

112-
public function testAccessNestedValue(): void
112+
public function testAccessNestedLeftValue(): void
113113
{
114114
$condition = new SimpleCondition(LogicalOperator::AND, 'user.age', Operator::GREATER_THAN, 18);
115115

@@ -119,4 +119,21 @@ public function testAccessNestedValue(): void
119119
$data = ['user' => ['age' => 17]];
120120
$this->assertFalse($condition->evaluate($data, true));
121121
}
122+
123+
public function testAccessNestedRightValue(): void
124+
{
125+
$condition = new SimpleCondition(LogicalOperator::AND, 'user.age', Operator::EQUAL, 'user.status');
126+
127+
$data = ['user' => ['age' => 20, 'status' => 20]];
128+
$this->assertTrue($condition->evaluate($data, true));
129+
130+
$data = ['user' => ['age' => 20, 'status' => 30]];
131+
$this->assertFalse($condition->evaluate($data, true));
132+
133+
$data = ['user.age' => 20, 'user.status' => 30];
134+
$this->assertFalse($condition->evaluate($data, false));
135+
136+
$data = ['user.age' => 10, 'user.status' => 10];
137+
$this->assertTrue($condition->evaluate($data, false));
138+
}
122139
}

0 commit comments

Comments
 (0)