Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit cce236e

Browse files
authored
Merge pull request #17 from programmatordev/YAPV-39-use-strcmp-for-strings-in-comparison-rules
Use strcmp for strings in comparison rules
2 parents aeaa911 + 650c92c commit cce236e

12 files changed

+39
-81
lines changed

src/Rule/AbstractComparisonRule.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,26 @@ abstract class AbstractComparisonRule extends AbstractRule
1111

1212
public function assert(mixed $value, string $name): void
1313
{
14-
$constraint = $this->convertToComparable($this->constraint);
15-
$value = $this->convertToComparable($value);
16-
17-
if (!$this->isComparable($constraint, $value)) {
14+
if (!$this->isComparable($value, $this->constraint)) {
1815
throw new UnexpectedComparableException(
19-
get_debug_type($constraint),
20-
get_debug_type($value)
16+
get_debug_type($value),
17+
get_debug_type($this->constraint)
2118
);
2219
}
2320

24-
if (!$this->comparison($constraint, $value)) {
21+
if (!$this->comparison($value, $this->constraint)) {
2522
throw new ($this->getException())(
2623
message: $this->options['message'],
2724
parameters: [
2825
'value' => $value,
2926
'name' => $name,
30-
'constraint' => $constraint
27+
'constraint' => $this->constraint
3128
]
3229
);
3330
}
3431
}
3532

36-
protected abstract function comparison(mixed $constraint, mixed $value): bool;
33+
protected abstract function comparison(mixed $value1, mixed $value2): bool;
3734

3835
protected abstract function getException(): string;
3936
}

src/Rule/GreaterThan.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ public function __construct(
2323
$this->options = $resolver->resolve($options);
2424
}
2525

26-
protected function comparison(mixed $constraint, mixed $value): bool
26+
protected function comparison(mixed $value1, mixed $value2): bool
2727
{
28-
return $value > $constraint;
28+
if (\is_string($value1) && \is_string($value2)) {
29+
return strcmp($value1, $value2) > 0;
30+
}
31+
32+
return $value1 > $value2;
2933
}
3034

3135
protected function getException(): string

src/Rule/GreaterThanOrEqual.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ public function __construct(
2323
$this->options = $resolver->resolve($options);
2424
}
2525

26-
protected function comparison(mixed $constraint, mixed $value): bool
26+
protected function comparison(mixed $value1, mixed $value2): bool
2727
{
28-
return $value >= $constraint;
28+
if (\is_string($value1) && \is_string($value2)) {
29+
return strcmp($value1, $value2) >= 0;
30+
}
31+
32+
return $value1 >= $value2;
2933
}
3034

3135
protected function getException(): string

src/Rule/LessThan.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ public function __construct(
2323
$this->options = $resolver->resolve($options);
2424
}
2525

26-
protected function comparison(mixed $constraint, mixed $value): bool
26+
protected function comparison(mixed $value1, mixed $value2): bool
2727
{
28-
return $value < $constraint;
28+
if (\is_string($value1) && \is_string($value2)) {
29+
return strcmp($value1, $value2) < 0;
30+
}
31+
32+
return $value1 < $value2;
2933
}
3034

3135
protected function getException(): string

src/Rule/LessThanOrEqual.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ public function __construct(
2323
$this->options = $resolver->resolve($options);
2424
}
2525

26-
protected function comparison(mixed $constraint, mixed $value): bool
26+
protected function comparison(mixed $value1, mixed $value2): bool
2727
{
28-
return $value <= $constraint;
28+
if (\is_string($value1) && \is_string($value2)) {
29+
return strcmp($value1, $value2) <= 0;
30+
}
31+
32+
return $value1 <= $value2;
2933
}
3034

3135
protected function getException(): string

src/Rule/Range.php

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,38 +32,34 @@ public function __construct(
3232

3333
public function assert(mixed $value, string $name): void
3434
{
35-
$minConstraint = $this->convertToComparable($this->minConstraint);
36-
$maxConstraint = $this->convertToComparable($this->maxConstraint);
37-
$value = $this->convertToComparable($value);
38-
39-
if (!$this->isComparable($minConstraint, $maxConstraint)) {
35+
if (!$this->isComparable($this->minConstraint, $this->maxConstraint)) {
4036
throw new UnexpectedComparableException(
41-
get_debug_type($minConstraint),
42-
get_debug_type($maxConstraint)
37+
get_debug_type($this->minConstraint),
38+
get_debug_type($this->maxConstraint)
4339
);
4440
}
4541

4642
if (
47-
!Validator::greaterThan($minConstraint)
48-
->validate($maxConstraint)
43+
!Validator::greaterThan($this->minConstraint)
44+
->validate($this->maxConstraint)
4945
) {
5046
throw new UnexpectedValueException(
5147
'Max constraint value must be greater than min constraint value.'
5248
);
5349
}
5450

5551
if (
56-
!Validator::greaterThanOrEqual($minConstraint)
57-
->lessThanOrEqual($maxConstraint)
52+
!Validator::greaterThanOrEqual($this->minConstraint)
53+
->lessThanOrEqual($this->maxConstraint)
5854
->validate($value)
5955
) {
6056
throw new RangeException(
6157
message: $this->options['message'],
6258
parameters: [
6359
'value' => $value,
6460
'name' => $name,
65-
'minConstraint' => $minConstraint,
66-
'maxConstraint' => $maxConstraint
61+
'minConstraint' => $this->minConstraint,
62+
'maxConstraint' => $this->maxConstraint
6763
]
6864
);
6965
}

src/Rule/Util/ComparableTrait.php

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,4 @@ private function isComparable(mixed $value1, mixed $value2): bool
2020

2121
return false;
2222
}
23-
24-
private function convertToComparable(mixed $value): mixed
25-
{
26-
// Try to guess if it is a valid datetime format,
27-
// like "yesterday" or "1985-07-19"
28-
// https://www.php.net/manual/en/datetime.formats.php
29-
if (\is_string($value) && \mb_strlen($value) > 1) {
30-
try {
31-
return new \DateTimeImmutable($value);
32-
}
33-
catch (\Exception) {
34-
return $value;
35-
}
36-
}
37-
38-
return $value;
39-
}
4023
}

tests/GreaterThanOrEqualTest.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public static function provideRuleUnexpectedValueData(): \Generator
2323
yield 'datetime constraint with int value' => [new GreaterThanOrEqual(new \DateTime()), 10, $message];
2424
yield 'datetime constraint with float value' => [new GreaterThanOrEqual(new \DateTime()), 1.0, $message];
2525
yield 'datetime constraint with string value' => [new GreaterThanOrEqual(new \DateTime()), 'a', $message];
26-
yield 'datetime string constraint with string value' => [new GreaterThanOrEqual('now'), 'a', $message];
2726
yield 'int constraint with string value' => [new GreaterThanOrEqual(10), 'a', $message];
2827
yield 'float constraint with string value' => [new GreaterThanOrEqual(1.0), 'a', $message];
2928
yield 'array constraint' => [new GreaterThanOrEqual([10]), 10, $message];
@@ -36,20 +35,16 @@ public static function provideRuleFailureConditionData(): \Generator
3635
$message = '/The "(.*)" value should be greater than or equal to "(.*)", "(.*)" given./';
3736

3837
yield 'datetime' => [new GreaterThanOrEqual(new \DateTime('today')), new \DateTime('yesterday'), $exception, $message];
39-
yield 'datetime string' => [new GreaterThanOrEqual('today'), 'yesterday', $exception, $message];
4038
yield 'int' => [new GreaterThanOrEqual(10), 1, $exception, $message];
4139
yield 'float' => [new GreaterThanOrEqual(10.0), 1.0, $exception, $message];
4240
yield 'int with float' => [new GreaterThanOrEqual(10), 1.0, $exception, $message];
4341
yield 'string' => [new GreaterThanOrEqual('z'), 'a', $exception, $message];
44-
yield 'empty string' => [new GreaterThanOrEqual('a'), '', $exception, $message];
4542
}
4643

4744
public static function provideRuleSuccessConditionData(): \Generator
4845
{
4946
yield 'datetime' => [new GreaterThanOrEqual(new \DateTime('today')), new \DateTime('tomorrow')];
5047
yield 'same datetime' => [new GreaterThanOrEqual(new \DateTime('today')), new \DateTime('today')];
51-
yield 'datetime string' => [new GreaterThanOrEqual('today'), 'tomorrow'];
52-
yield 'same datetime string' => [new GreaterThanOrEqual('today'), 'today'];
5348
yield 'int' => [new GreaterThanOrEqual(10), 20];
5449
yield 'same int' => [new GreaterThanOrEqual(10), 10];
5550
yield 'float' => [new GreaterThanOrEqual(10.0), 20.0];
@@ -58,8 +53,6 @@ public static function provideRuleSuccessConditionData(): \Generator
5853
yield 'same int with float' => [new GreaterThanOrEqual(10), 10.0];
5954
yield 'string' => [new GreaterThanOrEqual('a'), 'z'];
6055
yield 'same string' => [new GreaterThanOrEqual('a'), 'a'];
61-
yield 'empty string' => [new GreaterThanOrEqual(''), 'a'];
62-
yield 'same empty string' => [new GreaterThanOrEqual(''), ''];
6356
}
6457

6558
public static function provideRuleMessageOptionData(): \Generator

tests/GreaterThanTest.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public static function provideRuleUnexpectedValueData(): \Generator
2323
yield 'datetime constraint with int value' => [new GreaterThan(new \DateTime()), 10, $message];
2424
yield 'datetime constraint with float value' => [new GreaterThan(new \DateTime()), 1.0, $message];
2525
yield 'datetime constraint with string value' => [new GreaterThan(new \DateTime()), 'a', $message];
26-
yield 'datetime string constraint with string value' => [new GreaterThan('now'), 'a', $message];
2726
yield 'int constraint with string value' => [new GreaterThan(10), 'a', $message];
2827
yield 'float constraint with string value' => [new GreaterThan(1.0), 'a', $message];
2928
yield 'array constraint' => [new GreaterThan([10]), 10, $message];
@@ -37,8 +36,6 @@ public static function provideRuleFailureConditionData(): \Generator
3736

3837
yield 'datetime' => [new GreaterThan(new \DateTime('today')), new \DateTime('yesterday'), $exception, $message];
3938
yield 'same datetime' => [new GreaterThan(new \DateTime('today')), new \DateTime('today'), $exception, $message];
40-
yield 'datetime string' => [new GreaterThan('today'), 'yesterday', $exception, $message];
41-
yield 'same datetime string' => [new GreaterThan('today'), 'today', $exception, $message];
4239
yield 'int' => [new GreaterThan(10), 1, $exception, $message];
4340
yield 'same int' => [new GreaterThan(10), 10, $exception, $message];
4441
yield 'float' => [new GreaterThan(10.0), 1.0, $exception, $message];
@@ -47,19 +44,15 @@ public static function provideRuleFailureConditionData(): \Generator
4744
yield 'same int with float' => [new GreaterThan(10), 10.0, $exception, $message];
4845
yield 'string' => [new GreaterThan('z'), 'a', $exception, $message];
4946
yield 'same string' => [new GreaterThan('a'), 'a', $exception, $message];
50-
yield 'empty string' => [new GreaterThan('a'), '', $exception, $message];
51-
yield 'same empty string' => [new GreaterThan(''), '', $exception, $message];
5247
}
5348

5449
public static function provideRuleSuccessConditionData(): \Generator
5550
{
5651
yield 'datetime' => [new GreaterThan(new \DateTime('today')), new \DateTime('tomorrow')];
57-
yield 'datetime string' => [new GreaterThan('today'), 'tomorrow'];
5852
yield 'int' => [new GreaterThan(10), 20];
5953
yield 'float' => [new GreaterThan(10.0), 20.0];
6054
yield 'int with float' => [new GreaterThan(10), 20.0];
6155
yield 'string' => [new GreaterThan('a'), 'z'];
62-
yield 'empty string' => [new GreaterThan(''), 'a'];
6356
}
6457

6558
public static function provideRuleMessageOptionData(): \Generator

tests/LessThanOrEqualTest.php

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public static function provideRuleUnexpectedValueData(): \Generator
2323
yield 'datetime constraint with int value' => [new LessThanOrEqual(new \DateTime()), 10, $message];
2424
yield 'datetime constraint with float value' => [new LessThanOrEqual(new \DateTime()), 1.0, $message];
2525
yield 'datetime constraint with string value' => [new LessThanOrEqual(new \DateTime()), 'a', $message];
26-
yield 'datetime string constraint with string value' => [new LessThanOrEqual('now'), 'a', $message];
2726
yield 'int constraint with string value' => [new LessThanOrEqual(10), 'a', $message];
2827
yield 'float constraint with string value' => [new LessThanOrEqual(1.0), 'a', $message];
2928
yield 'array constraint' => [new LessThanOrEqual([10]), 10, $message];
@@ -36,20 +35,16 @@ public static function provideRuleFailureConditionData(): \Generator
3635
$message = '/The "(.*)" value should be less than or equal to "(.*)", "(.*)" given./';
3736

3837
yield 'datetime' => [new LessThanOrEqual(new \DateTime('today')), new \DateTime('tomorrow'), $exception, $message];
39-
yield 'datetime string' => [new LessThanOrEqual('today'), 'tomorrow', $exception, $message];
4038
yield 'int' => [new LessThanOrEqual(10), 20, $exception, $message];
4139
yield 'float' => [new LessThanOrEqual(10.0), 20.0, $exception, $message];
4240
yield 'int with float' => [new LessThanOrEqual(10), 20.0, $exception, $message];
4341
yield 'string' => [new LessThanOrEqual('a'), 'z', $exception, $message];
44-
yield 'empty string' => [new LessThanOrEqual(''), 'a', $exception, $message];
4542
}
4643

4744
public static function provideRuleSuccessConditionData(): \Generator
4845
{
4946
yield 'datetime' => [new LessThanOrEqual(new \DateTime('today')), new \DateTime('yesterday')];
5047
yield 'same datetime' => [new LessThanOrEqual(new \DateTime('today')), new \DateTime('today')];
51-
yield 'datetime string' => [new LessThanOrEqual('today'), 'yesterday'];
52-
yield 'same datetime string' => [new LessThanOrEqual('today'), 'today'];
5348
yield 'int' => [new LessThanOrEqual(10), 1];
5449
yield 'same int' => [new LessThanOrEqual(10), 10];
5550
yield 'float' => [new LessThanOrEqual(10.0), 1.0];
@@ -58,8 +53,6 @@ public static function provideRuleSuccessConditionData(): \Generator
5853
yield 'same int with float' => [new LessThanOrEqual(10), 10.0];
5954
yield 'string' => [new LessThanOrEqual('z'), 'a'];
6055
yield 'same string' => [new LessThanOrEqual('a'), 'a'];
61-
yield 'empty string' => [new LessThanOrEqual('a'), ''];
62-
yield 'same empty string' => [new LessThanOrEqual(''), ''];
6356
}
6457

6558
public static function provideRuleMessageOptionData(): \Generator

0 commit comments

Comments
 (0)