Passed
Push — master ( 0a4514...70449d )
by Vincent
04:28
created

DateTimeElement::tryCast()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 11
ccs 6
cts 6
cp 1
rs 10
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
namespace Bdf\Form\Leaf\Date;
4
5
use Bdf\Form\Choice\ChoiceInterface;
6
use Bdf\Form\Leaf\LeafElement;
7
use Bdf\Form\Transformer\TransformerInterface;
8
use Bdf\Form\Validator\ValueValidatorInterface;
9
use DateTime;
10
use DateTimeInterface;
11
use DateTimeZone;
12
use InvalidArgumentException;
13
use TypeError;
14
15
/**
16
 * Handle DateTime form element
17
 * The element use a formatted string as http value, and can return any implementation of DateTimeInterface
18
 *
19
 * @method DateTimeInterface value()
20
 * @extends LeafElement<DateTimeInterface>
21
 */
22
final class DateTimeElement extends LeafElement
23
{
24
    /**
25
     * @var class-string<DateTimeInterface>
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<DateTimeInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<DateTimeInterface>.
Loading history...
26
     */
27
    private $className;
28
29
    /**
30
     * @var string
31
     */
32
    private $format;
33
34
    /**
35
     * @var DateTimeZone|null
36
     */
37
    private $timezone;
38
39
    /**
40
     * Reset the fields value which are not provided by the format
41
     *
42
     * @var bool
43
     */
44
    private $resetNotProvidedFields;
45
46
    /**
47
     * DateTimeType constructor.
48
     *
49
     * @param ValueValidatorInterface|null $validator
50
     * @param TransformerInterface|null $transformer
51
     * @param ChoiceInterface|null $choices
52
     * @param class-string<DateTimeInterface> $className The date time class name to use
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<DateTimeInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<DateTimeInterface>.
Loading history...
53
     * @param string $format The time format string
54
     * @param DateTimeZone|null $timezone Timezone to use. Use null to not define a timezone
55
     * @param bool $resetNotProvidedFields Does the fields which are not provided by the format will be reset ? (and set to UNIX time)
56
     */
57 66
    public function __construct(?ValueValidatorInterface $validator = null, ?TransformerInterface $transformer = null, ?ChoiceInterface $choices = null, string $className = DateTime::class, string $format = DateTime::ATOM, ?DateTimeZone $timezone = null, bool $resetNotProvidedFields = true)
58
    {
59 66
        parent::__construct($validator, $transformer, $choices);
60
61 66
        $this->className = $className;
62 66
        $this->format = $format;
63 66
        $this->timezone = $timezone;
64 66
        $this->resetNotProvidedFields = $resetNotProvidedFields;
65 66
    }
66
67
    /**
68
     * Get the timezone of the element
69
     *
70
     * @return DateTimeZone|null The timezone, or null if not defined
71
     */
72 3
    public function timezone(): ?DateTimeZone
73
    {
74 3
        return $this->timezone;
75
    }
76
77
    /**
78
     * Get the handled date time class name
79
     *
80
     * @return class-string<DateTimeInterface>
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<DateTimeInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<DateTimeInterface>.
Loading history...
81
     */
82 2
    public function dateTimeClassName(): string
83
    {
84 2
        return $this->className;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90 36
    protected function toPhp($httpValue): ?DateTimeInterface
91
    {
92 36
        if ($httpValue === null) {
93 3
            return null;
94
        }
95
96
        switch (true) {
97 33
            case $httpValue instanceof $this->className:
98 1
                $dateTime = $httpValue; // Clone ?
99 1
                break;
100
101 32
            case $httpValue instanceof DateTimeInterface:
102 1
                $httpValue = $httpValue->format($this->format);
103
                // No break
104
105
            default:
106 32
                if (!method_exists($this->className, 'createFromFormat')) {
107 1
                    throw new \LogicException('Invalid DateTime class name "'.$this->className.'" : method createFromFormat() is not found.');
108
                }
109
110 31
                $format = $this->format;
111
112 31
                if ($this->resetNotProvidedFields && !str_contains($format, '|')) {
113 30
                    $format .= '|';
114
                }
115
116 31
                $dateTime = ($this->className)::createFromFormat($format, $httpValue, $this->timezone);
117
        }
118
119 32
        if ($dateTime === false) {
120 2
            throw new InvalidArgumentException('Invalid date format');
121
        }
122
123 30
        if ($this->timezone !== null) {
124 2
            $dateTime->setTimezone($this->timezone);
125
        }
126
127 30
        return $dateTime;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133 13
    protected function toHttp($phpValue)
134
    {
135 13
        if (is_string($phpValue)) {
136 3
            return $phpValue;
137
        }
138
139 10
        if (!$phpValue instanceof DateTimeInterface) {
140 2
            return null;
141
        }
142
143 8
        return $phpValue->format($this->format);
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149 27
    protected function tryCast($value): ?DateTimeInterface
150
    {
151 27
        if ($value === null) {
152 3
            return null;
153
        }
154
155 26
        if (!$value instanceof $this->className) {
156 10
            throw new TypeError('The import()\'ed value of a '.static::class.' must be an instance of '.$this->className.' or null');
157
        }
158
159 16
        return $value;
160
    }
161
}
162