1<?php
2
3
4namespace ComboStrap\Meta\Api;
5
6
7use ComboStrap\DataType;
8use ComboStrap\ExceptionBadArgument;
9use ComboStrap\ExceptionBadSyntax;
10use ComboStrap\ExceptionCompile;
11use ComboStrap\ExceptionNotFound;
12use ComboStrap\ExceptionRuntime;
13use ComboStrap\ExceptionRuntimeInternal;
14use ComboStrap\Iso8601Date;
15use ComboStrap\LogUtility;
16use DateTime;
17
18abstract class MetadataDateTime extends Metadata
19{
20
21    /**
22     * @var DateTime|null
23     * may be null as this is a stored value
24     * but throw a not found exception when the value is null
25     */
26    protected ?DateTime $dateTimeValue = null;
27
28
29    /**
30     * Helper function for date metadata
31     * @return string|array (may be an array for dokuwiki ie {@link CreationDate::toStoreValue()} for instance
32     */
33    public function toStoreValue()
34    {
35
36        $this->buildCheck();
37        try {
38            $value = $this->getValue();
39        } catch (ExceptionNotFound $e) {
40            return null;
41        }
42        try {
43            return $this->toPersistentDateTimeUtility($value);
44        } catch (ExceptionBadArgument $e) {
45            throw ExceptionRuntimeInternal::withMessageAndError("The date time should have been checked on set. This error should not happen", $e);
46        }
47
48    }
49
50    /**
51     * @param DateTime|null $value
52     * @return $this
53     */
54    public function setValue($value): Metadata
55    {
56        if ($value === null) {
57            $this->dateTimeValue = null;
58            return $this;
59        }
60        if (!($value instanceof DateTime)) {
61            throw new ExceptionRuntime("The value is not a date time. Value: " . var_export($value, true));
62        }
63        $this->dateTimeValue = $value;
64        return $this;
65    }
66
67    /**
68     * @throws ExceptionCompile
69     */
70    public function setFromStoreValue($value): Metadata
71    {
72        return $this->setValue($this->fromPersistentDateTimeUtility($value));
73    }
74
75
76    public function toStoreDefaultValue(): ?string
77    {
78
79        try {
80            $defaultValue = $this->getDefaultValue();
81        } catch (ExceptionNotFound $e) {
82            return null;
83        }
84        try {
85            return $this->toPersistentDateTimeUtility($defaultValue);
86        } catch (ExceptionBadArgument $e) {
87            $message = "The date time ($this) has a default value ($defaultValue) that is not valid. Error: {$e->getMessage()}";
88            LogUtility::internalError($message);
89            return null;
90        }
91
92    }
93
94    public static function getDataType(): string
95    {
96        return DataType::DATETIME_TYPE_VALUE;
97    }
98
99
100    public function buildFromReadStore(): MetadataDateTime
101    {
102        $value = $this->getReadStore()->get($this);
103        try {
104            $this->dateTimeValue = $this->fromPersistentDateTimeUtility($value);
105        } catch (ExceptionCompile $e) {
106            LogUtility::msg($e->getMessage(), $this->getCanonical());
107        }
108        return $this;
109    }
110
111    /**
112     * @throws ExceptionBadSyntax - if the string is not a date string
113     * @throws ExceptionBadArgument - if this is not a string
114     */
115    protected function fromPersistentDateTimeUtility($value)
116    {
117        if ($value === null || $value === "") {
118            return null;
119        }
120        if (!is_string($value)) {
121            throw new ExceptionBadArgument("This is not a string value");
122        }
123        return Iso8601Date::createFromString($value)->getDateTime();
124    }
125
126    /**
127     * @throws ExceptionNotFound
128     */
129    public function getValue(): DateTime
130    {
131        $this->buildCheck();
132        if ($this->dateTimeValue === null) {
133            throw new ExceptionNotFound("The resource does not have this date time ($this)");
134        }
135        return $this->dateTimeValue;
136    }
137
138
139    /**
140     * @throws ExceptionBadArgument - if the value is not valid
141     */
142    private function toPersistentDateTimeUtility($value): string
143    {
144        if ($value === null) {
145            throw new ExceptionBadArgument("The passed value is null");
146        }
147        if (!($value instanceof DateTime)) {
148            throw new ExceptionBadArgument("This is not a date time");
149        }
150        return Iso8601Date::createFromDateTime($value)->toString();
151    }
152
153    public static function getCanonical(): string
154    {
155        return "date";
156    }
157
158    public function valueIsNotNull(): bool
159    {
160        return $this->dateTimeValue !== null;
161    }
162
163    public function setFromStoreValueWithoutException($value): Metadata
164    {
165        try {
166            $this->dateTimeValue = $this->fromPersistentDateTimeUtility($value);
167        } catch (ExceptionCompile $e) {
168            LogUtility::msg($e->getMessage(), LogUtility::LVL_MSG_ERROR, $e->getCanonical());
169        }
170        return $this;
171    }
172
173
174}
175