D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
psa
/
admin
/
plib
/
modules
/
monitoring
/
vendor
/
laminas
/
laminas-validator
/
src
/
Filename :
DateComparison.php
back
Copy
<?php declare (strict_types=1); namespace PleskMonitoring\Laminas\Validator; use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; use PleskMonitoring\Laminas\Validator\Exception\InvalidArgumentException; use function assert; use function get_debug_type; use function is_string; use function preg_match; /** * @psalm-type OptionsArgument = array{ * min?: string|DateTimeInterface|null, * max?: string|DateTimeInterface|null, * inclusiveMin?: bool, * inclusiveMax?: bool, * inputFormat?: string|null, * } */ final class DateComparison extends AbstractValidator { public const ERROR_INVALID_TYPE = 'invalidType'; public const ERROR_INVALID_DATE = 'invalidDate'; public const ERROR_NOT_GREATER_INCLUSIVE = 'notGreaterInclusive'; public const ERROR_NOT_GREATER = 'notGreater'; public const ERROR_NOT_LESS_INCLUSIVE = 'notLessInclusive'; public const ERROR_NOT_LESS = 'notLess'; /** @var array<string, string> */ protected array $messageTemplates = [self::ERROR_INVALID_TYPE => 'Expected a string or a date time instance but received "%type"', self::ERROR_INVALID_DATE => 'Invalid date provided', self::ERROR_NOT_GREATER_INCLUSIVE => 'A date equal to or after %min% is required', self::ERROR_NOT_GREATER => 'A date after %min% is required', self::ERROR_NOT_LESS_INCLUSIVE => 'A date equal to or before %max% is required', self::ERROR_NOT_LESS => 'A date before %max% is required']; /** @var array<string, string> */ protected array $messageVariables = ['type' => 'type', 'min' => 'minString', 'max' => 'maxString']; private readonly ?DateTimeInterface $min; private readonly ?DateTimeInterface $max; private readonly bool $inclusiveMin; private readonly bool $inclusiveMax; private readonly ?string $inputFormat; /** Input type used in message variables */ protected ?string $type = null; protected ?string $minString = null; protected ?string $maxString = null; /** @param OptionsArgument $options */ public function __construct(array $options = []) { parent::__construct($options); $this->min = $this->dateInstanceBound($options['min'] ?? null); $this->max = $this->dateInstanceBound($options['max'] ?? null); $this->inclusiveMin = $options['inclusiveMin'] ?? \true; $this->inclusiveMax = $options['inclusiveMax'] ?? \true; $this->inputFormat = $options['inputFormat'] ?? null; if ($this->min === null && $this->max === null) { throw new InvalidArgumentException('At least one date boundary must be supplied'); } $outputFormat = $this->inputFormat ?? 'jS F Y H:i:s'; if ($this->min !== null) { $this->minString = $this->min->format($outputFormat); } if ($this->max !== null) { $this->maxString = $this->max->format($outputFormat); } } public function isValid(mixed $value) : bool { $this->type = get_debug_type($value); $this->value = $value; if (!is_string($value) && !$value instanceof DateTimeInterface) { $this->error(self::ERROR_INVALID_TYPE); return \false; } $date = $this->valueToDate($value); if ($date === null) { $this->error(self::ERROR_INVALID_DATE); return \false; } if ($this->min !== null && $this->inclusiveMin && $date < $this->min) { $this->error(self::ERROR_NOT_GREATER_INCLUSIVE); return \false; } if ($this->min !== null && !$this->inclusiveMin && $date <= $this->min) { $this->error(self::ERROR_NOT_GREATER); return \false; } if ($this->max !== null && $this->inclusiveMax && $date > $this->max) { $this->error(self::ERROR_NOT_LESS_INCLUSIVE); return \false; } if ($this->max !== null && !$this->inclusiveMax && $date >= $this->max) { $this->error(self::ERROR_NOT_LESS); return \false; } return \true; } private function valueToDate(string|DateTimeInterface $input) : DateTimeInterface|null { if ($input instanceof DateTimeInterface) { return $this->w3cDateFromString($input->format('Y-m-d\\TH:i:s')); } if ($this->inputFormat !== null) { $date = DateTimeImmutable::createFromFormat($this->inputFormat, $input, new DateTimeZone('UTC')); if ($date instanceof DateTimeImmutable) { return $date; } } $date = $this->isoDateFromString($input); if ($date !== null) { return $date; } $date = $this->w3cDateFromString($input); if ($date !== null) { return $date; } return null; } private function dateInstanceBound(string|DateTimeInterface|null $dateTime) : DateTimeInterface|null { if ($dateTime instanceof DateTimeInterface) { return $this->w3cDateFromString($dateTime->format('Y-m-d\\TH:i:s')); } if ($dateTime === null) { return null; } $date = $this->isoDateFromString($dateTime); if ($date !== null) { return $date; } $date = $this->w3cDateFromString($dateTime); if ($date !== null) { return $date; } throw new InvalidArgumentException('Min/max date bounds must be either DateTime instances, or a string in one of the formats: ' . '"Y-m-d" for a date or "Y-m-d\\TH:i:s" for date time'); } private function isoDateFromString(string $input) : DateTimeImmutable|null { if (!preg_match('/^\\d{4}-[0-1]\\d-[0-3]\\d$/', $input)) { return null; } $date = DateTimeImmutable::createFromFormat('!Y-m-d', $input, new DateTimeZone('UTC')); assert($date !== \false); return $date; } private function w3cDateFromString(string $input) : DateTimeImmutable|null { if (!preg_match('/^\\d{4}-[0-1]\\d-[0-3]\\dT\\d{1,2}:[0-5]\\d:[0-5]\\d$/', $input)) { return null; } $date = DateTimeImmutable::createFromFormat('Y-m-d\\TH:i:s', $input, new DateTimeZone('UTC')); assert($date !== \false); return $date; } }