1<?php
2
3declare(strict_types=1);
4
5/*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18namespace TYPO3\CMS\Form\Mvc\Validation;
19
20use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
21use TYPO3\CMS\Form\Mvc\Validation\Exception\InvalidValidationOptionsException;
22
23/**
24 * Validator for date ranges
25 *
26 * Scope: frontend
27 */
28class DateRangeValidator extends AbstractValidator
29{
30    /**
31     * @var array
32     */
33    protected $supportedOptions = [
34        'minimum' => ['', 'The minimum date formatted as Y-m-d', 'string'],
35        'maximum' => ['', 'The maximum date formatted as Y-m-d', 'string'],
36        'format' => ['Y-m-d', 'The format of the minimum and maximum option', 'string'],
37    ];
38
39    /**
40     * @param \DateTime $value The value that should be validated
41     */
42    public function isValid($value)
43    {
44        $this->validateOptions();
45
46        if (!($value instanceof \DateTime)) {
47            $this->addError(
48                $this->translateErrorMessage(
49                    'validation.error.1521293685',
50                    'form',
51                    [gettype($value)]
52                ) ?? '',
53                1521293685
54            );
55
56            return;
57        }
58
59        $minimum = $this->options['minimum'];
60        $maximum = $this->options['maximum'];
61        $format = $this->options['format'];
62        $value->modify('midnight');
63
64        if (
65            $minimum instanceof \DateTime
66            && $value < $minimum
67        ) {
68            $this->addError(
69                $this->translateErrorMessage(
70                    'validation.error.1521293686',
71                    'form',
72                    [$minimum->format($format)]
73                ) ?? '',
74                1521293686,
75                [$minimum->format($format)]
76            );
77        }
78
79        if (
80            $maximum instanceof \DateTime
81            && $value > $maximum
82        ) {
83            $this->addError(
84                $this->translateErrorMessage(
85                    'validation.error.1521293687',
86                    'form',
87                    [$maximum->format($format)]
88                ) ?? '',
89                1521293687,
90                [$maximum->format($format)]
91            );
92        }
93    }
94
95    /**
96     * Checks if this validator is correctly configured
97     *
98     * @throws InvalidValidationOptionsException if the configured validation options are incorrect
99     */
100    protected function validateOptions()
101    {
102        if (!empty($this->options['minimum'])) {
103            $minimum = \DateTime::createFromFormat($this->options['format'], $this->options['minimum']);
104            if (!($minimum instanceof \DateTime)) {
105                $message = sprintf('The option "minimum" (%s) could not be converted to \DateTime from format "%s".', $this->options['minimum'], $this->options['format']);
106                throw new InvalidValidationOptionsException($message, 1521293813);
107            }
108
109            $minimum->modify('midnight');
110            $this->options['minimum'] = $minimum;
111        }
112
113        if (!empty($this->options['maximum'])) {
114            $maximum = \DateTime::createFromFormat($this->options['format'], $this->options['maximum']);
115            if (!($maximum instanceof \DateTime)) {
116                $message = sprintf('The option "maximum" (%s) could not be converted to \DateTime from format "%s".', $this->options['maximum'], $this->options['format']);
117                throw new InvalidValidationOptionsException($message, 1521293814);
118            }
119
120            $maximum->modify('midnight');
121            $this->options['maximum'] = $maximum;
122        }
123    }
124}
125