Here’s my implementation. I found this code somewhere online (Cannot recall the source for credits).
<?php
namespace CalendarModule\Validator;
use Carbon\Carbon;
use Laminas\Validator\AbstractValidator;
/**
* Class BeforeDateValidator
* @package CalendarModule\Service
*/
class BeforeDateValidator extends AbstractValidator
{
/** @var string NOT_BEFORE */
public const NOT_BEFORE = 'not-before';
/** @var string NOT_A_VALID_DATE */
public const NOT_A_VALID_DATE = 'not-a-date';
/** @var array */
protected array $messageTemplates = [
self::NOT_BEFORE => "'%value%' should be before the end date.",
self::NOT_A_VALID_DATE => "'%value%' is not a valid date.",
];
/** @var mixed|string */
protected string $dateTimeFormat = 'Y-m-d\TH:i';
/** @var mixed|string */
protected string $secondDateFieldName = 'endDateTime';
/** @var bool|mixed */
protected bool $strictlyBefore = false;
/**
* BeforeDateValidator constructor.
* @param array|null $options
*/
public function __construct(array $options = null)
{
if (is_array($options)) {
if (array_key_exists('second_date_field', $options)) {
$this->secondDateFieldName = $options['second_date_field'];
}
if (array_key_exists('date_format', $options)) {
$this->dateTimeFormat = $options['date_format'];
}
if (array_key_exists('strict', $options)) {
$this->strictlyBefore = $options['strict'];
}
if (array_key_exists('messages', $options)) {
$this->messageTemplates = array_merge($this->messageTemplates, $options['messages']);
}
}
parent::__construct($options);
}
/**
* @param mixed $value
* @param null $context
* @return bool
*/
public function isValid($value, $context = null): bool
{
$isValid = true;
$date1 = Carbon::createFromFormat($this->dateTimeFormat, $value);
if (!$date1) {
$this->error(self::NOT_A_VALID_DATE, $value);
$isValid = false;
}
$secondDateFieldValue = trim($context[$this->secondDateFieldName]);
$date2 = Carbon::createFromFormat($this->dateTimeFormat, $secondDateFieldValue);
if (!$date2) {
$this->error(self::NOT_A_VALID_DATE, $secondDateFieldValue);
$isValid = false;
}
if ($this->strictlyBefore) {
if ($date1 >= $date2) {
$this->error(self::NOT_BEFORE, $value);
$isValid = false;
}
} elseif ($date1 > $date2) {
$this->error(self::NOT_BEFORE, $value);
$isValid = false;
}
return $isValid;
}
}
And here’s the code from EventFormInputFilter.php
.
/**
* Class EventFormInputFilter
* @package CalendarModule\InputFilter
*/
class EventFormInputFilter extends InputFilter
{
/** */
public function init()
{
parent::init();
$this->add(
[
"name" => "startDateTime",
"required" => false,
"filters" => [
["name" => Filter\StripTags::class],
["name" => Filter\StringTrim::class],
["name" => Filter\DateSelect::class],
],
"validators" => [
[
"name" => Validator\Date::class,
"options" => [
"format" => "Y-m-d\TH:i",
],
],
[
'name' => BeforeDateValidator::class,
'options' => [
'second_date_field' => 'endDateTime',
'date_format' => 'Y-m-d\TH:i',
'strict' => false,
'messages' => [
BeforeDateValidator::NOT_BEFORE => "Start Date Time should be before the End Date Time.",
BeforeDateValidator::NOT_A_VALID_DATE => "\"%value%\" is not a valid Date Time.",
],
],
],
],
]
)->add(
[
"name" => "endDateTime",
"required" => false,
"filters" => [
["name" => Filter\StripTags::class],
["name" => Filter\StringTrim::class],
["name" => Filter\DateSelect::class],
],
"validators" => [
[
"name" => Validator\Date::class,
"options" => [
"format" => "Y-m-d\TH:i",
],
],
],
]
);
}
}