Split up NumberConstraint and DateTimeConstraint for better type enforcement

This commit is contained in:
Jan Böhmer 2024-06-22 18:53:26 +02:00
parent 07afff8db5
commit 8f631cae63
2 changed files with 103 additions and 20 deletions

View file

@ -22,9 +22,92 @@ declare(strict_types=1);
*/
namespace App\DataTables\Filters\Constraints;
use Doctrine\ORM\QueryBuilder;
use RuntimeException;
/**
* An alias of NumberConstraint to use to filter on a DateTime
* Similar to NumberConstraint but for DateTime values
*/
class DateTimeConstraint extends NumberConstraint
class DateTimeConstraint extends AbstractConstraint
{
protected const ALLOWED_OPERATOR_VALUES = ['=', '!=', '<', '>', '<=', '>=', 'BETWEEN'];
public function __construct(
string $property,
string $identifier = null,
/**
* The value1 used for comparison (this is the main one used for all mono-value comparisons)
*/
protected \DateTimeInterface|null $value1 = null,
protected ?string $operator = null,
/**
* The second value used when operator is RANGE; this is the upper bound of the range
*/
protected \DateTimeInterface|null $value2 = null)
{
parent::__construct($property, $identifier);
}
public function getValue1(): ?\DateTimeInterface
{
return $this->value1;
}
public function setValue1(\DateTimeInterface|null $value1): void
{
$this->value1 = $value1;
}
public function getValue2(): ?\DateTimeInterface
{
return $this->value2;
}
public function setValue2(?\DateTimeInterface $value2): void
{
$this->value2 = $value2;
}
public function getOperator(): string|null
{
return $this->operator;
}
/**
* @param string $operator
*/
public function setOperator(?string $operator): void
{
$this->operator = $operator;
}
public function isEnabled(): bool
{
return $this->value1 !== null
&& ($this->operator !== null && $this->operator !== '');
}
public function apply(QueryBuilder $queryBuilder): void
{
//If no value is provided then we do not apply a filter
if (!$this->isEnabled()) {
return;
}
//Ensure we have an valid operator
if(!in_array($this->operator, self::ALLOWED_OPERATOR_VALUES, true)) {
throw new \RuntimeException('Invalid operator '. $this->operator . ' provided. Valid operators are '. implode(', ', self::ALLOWED_OPERATOR_VALUES));
}
if ($this->operator !== 'BETWEEN') {
$this->addSimpleAndConstraint($queryBuilder, $this->property, $this->identifier, $this->operator, $this->value1);
} else {
if ($this->value2 === null) {
throw new RuntimeException("Cannot use operator BETWEEN without value2!");
}
$this->addSimpleAndConstraint($queryBuilder, $this->property, $this->identifier . '1', '>=', $this->value1);
$this->addSimpleAndConstraint($queryBuilder, $this->property, $this->identifier . '2', '<=', $this->value2);
}
}
}

View file

@ -29,12 +29,28 @@ class NumberConstraint extends AbstractConstraint
{
protected const ALLOWED_OPERATOR_VALUES = ['=', '!=', '<', '>', '<=', '>=', 'BETWEEN'];
public function getValue1(): float|int|null|\DateTimeInterface
public function __construct(
string $property,
string $identifier = null,
/**
* The value1 used for comparison (this is the main one used for all mono-value comparisons)
*/
protected float|int|null $value1 = null,
protected ?string $operator = null,
/**
* The second value used when operator is RANGE; this is the upper bound of the range
*/
protected float|int|null $value2 = null)
{
parent::__construct($property, $identifier);
}
public function getValue1(): float|int|null
{
return $this->value1;
}
public function setValue1(float|int|\DateTimeInterface|null $value1): void
public function setValue1(float|int|null $value1): void
{
$this->value1 = $value1;
}
@ -63,22 +79,6 @@ class NumberConstraint extends AbstractConstraint
}
public function __construct(
string $property,
string $identifier = null,
/**
* The value1 used for comparison (this is the main one used for all mono-value comparisons)
*/
protected float|int|\DateTimeInterface|null $value1 = null,
protected ?string $operator = null,
/**
* The second value used when operator is RANGE; this is the upper bound of the range
*/
protected float|int|\DateTimeInterface|null $value2 = null)
{
parent::__construct($property, $identifier);
}
public function isEnabled(): bool
{
return $this->value1 !== null