Passed
Pull Request — master (#646)
by
unknown
02:35
created

DateTimeHandler   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 35
c 1
b 0
f 1
dl 0
loc 82
rs 10
wmc 14

2 Methods

Rating   Name   Duplication   Size   Complexity  
B toDateTime() 0 25 7
B validate() 0 34 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Rule;
6
7
use DateTimeInterface;
8
use Yiisoft\Validator\Result;
9
use Yiisoft\Validator\ValidationContext;
10
use Yiisoft\Validator\RuleHandlerInterface;
11
use Yiisoft\Validator\Exception\UnexpectedRuleException;
12
13
use function is_string;
14
15
/**
16
 * Validates that the value is a valid date.
17
 */
18
final class DateTimeHandler implements RuleHandlerInterface
19
{
20
    private string $format = DateTimeInterface::W3C;
21
22
    /**
23
     * Validates a value against a DateTime rule.
24
     *
25
     * @param mixed $value The value to validate.
26
     * @param object $rule The DateTime rule.
27
     * @param ValidationContext $context The validation context.
28
     * @return Result The validation result.
29
     * @throws UnexpectedRuleException If the rule is not an instance of DateTime.
30
     */
31
    public function validate(mixed $value, object $rule, ValidationContext $context): Result
32
    {
33
        if (!$rule instanceof DateTime) {
34
            throw new UnexpectedRuleException(DateTime::class, $rule);
35
        }
36
        $result = new Result();
37
        $datetime = $this->toDateTime($value, $rule);
38
39
        $debugType = get_debug_type($value);
40
41
        if ($datetime === null) {
42
            $result->addError($rule->getMessage(), [
43
                'attribute' => $context->getTranslatedAttribute(),
44
                'value' => $debugType,
45
            ]);
46
        }
47
48
        if ($rule->getMin() && $datetime < $rule->getMin()) {
49
            return $result->addError($rule->getLessThanMinMessage(), [
50
                'attribute' => $context->getTranslatedAttribute(),
51
                'value' => $debugType,
52
                'min' => $rule->getMin()->format($this->format),
53
            ]);
54
        }
55
56
        if ($rule->getMax() && $datetime > $rule->getMax()) {
57
            return $result->addError($rule->getGreaterThanMaxMessage(), [
58
                'attribute' => $context->getTranslatedAttribute(),
59
                'value' => $debugType,
60
                'max' => $rule->getMax()->format($this->format),
61
            ]);
62
        }
63
64
        return $result;
65
    }
66
67
68
    /**
69
     * Converts a value to a DateTime object based on a given rule.
70
     *
71
     * @param mixed $value The value to convert.
72
     * @param DateTime $rule The DateTime rule to use for conversion.
73
     * @return DateTimeInterface|null The converted DateTime object, or null if the conversion fails.
74
     */
75
    private function toDateTime(mixed $value, DateTime $rule): ?DateTimeInterface
76
    {
77
        if ($value instanceof DateTimeInterface) {
78
            return $value;
79
        }
80
        if (filter_var($value, FILTER_VALIDATE_INT) !== false) {
81
            $this->format = 'U';
82
            if ($value = \DateTime::createFromFormat($this->format, (string) $value)) {
83
                return $value;
84
            }
85
            return null;
86
        }
87
88
        if (!is_string($value)) {
89
            return null;
90
        }
91
        // Try to convert the value to a DateTime object using each format in the rule's formats array.
92
        foreach ($rule->getFormats() as $format) {
93
            if ($formatted = \DateTime::createFromFormat($format, $value)) {
94
                $this->format = $format;
95
                return $formatted;
96
            }
97
        }
98
99
        return null;
100
    }
101
}
102