Skip to content

Commit

Permalink
API Provide minimum and maximum comparison values for numeric DBFields
Browse files Browse the repository at this point in the history
This will be used with handling WithinRangeFilter in searchable fields
so that if only one of the two ends of a range is filled in, the other
can be automatically populated.
  • Loading branch information
GuySartorelli committed Feb 13, 2025
1 parent 9d4e46d commit 842d328
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 44 deletions.
20 changes: 3 additions & 17 deletions src/Core/Validation/FieldValidation/BigIntFieldValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,14 @@

use RunTimeException;
use SilverStripe\Core\Validation\ValidationResult;
use SilverStripe\ORM\FieldType\DBBigInt;

/**
* A field validator for 64-bit integers
* Will throw a RunTimeException if used on a 32-bit system
*/
class BigIntFieldValidator extends IntFieldValidator
{
/**
* The minimum value for a signed 64-bit integer.
* Defined as string instead of int otherwise will end up as a float
* on 64-bit systems
*
* When this is cast to an int in IntFieldValidator::__construct()
* it will be properly cast to an int
*/
protected const MIN_INT = '-9223372036854775808';

/**
* The maximum value for a signed 64-bit integer.
*/
protected const MAX_INT = '9223372036854775807';

public function __construct(
string $name,
mixed $value,
Expand All @@ -51,10 +37,10 @@ protected function validateValue(): ValidationResult
// int values that are too large or too small will be cast to float
// on 64-bit systems and will fail the validation in IntFieldValidator
if (is_string($this->value)) {
if (!is_null($this->minValue) && bccomp($this->value, static::MIN_INT) === -1) {
if (!is_null($this->minValue) && bccomp($this->value, DBBigInt::getMinValue()) === -1) {
$result->addFieldError($this->name, $this->getTooSmallMessage());
}
if (!is_null($this->maxValue) && bccomp($this->value, static::MAX_INT) === 1) {
if (!is_null($this->maxValue) && bccomp($this->value, DBBigInt::getMaxValue()) === 1) {
$result->addFieldError($this->name, $this->getTooLargeMessage());
}
}
Expand Down
17 changes: 3 additions & 14 deletions src/Core/Validation/FieldValidation/IntFieldValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,24 @@
namespace SilverStripe\Core\Validation\FieldValidation;

use SilverStripe\Core\Validation\ValidationResult;
use SilverStripe\ORM\FieldType\DBInt;

/**
* Validates that a value is a 32-bit signed integer
*/
class IntFieldValidator extends NumericNonStringFieldValidator
{
/**
* The minimum value for a signed 32-bit integer.
* Defined as string instead of int because be cast to a float
* on 32-bit systems if defined as an int
*/
protected const MIN_INT = '-2147483648';

/**
* The maximum value for a signed 32-bit integer.
*/
protected const MAX_INT = '2147483647';

public function __construct(
string $name,
mixed $value,
?int $minValue = null,
?int $maxValue = null
) {
if (is_null($minValue)) {
$minValue = (int) static::MIN_INT;
$minValue = (int) DBInt::getMinValue();
}
if (is_null($maxValue)) {
$maxValue = (int) static::MAX_INT;
$maxValue = (int) DBInt::getMaxValue();
}
parent::__construct($name, $value, $minValue, $maxValue);
}
Expand Down
15 changes: 15 additions & 0 deletions src/ORM/FieldType/DBBigInt.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@
*/
class DBBigInt extends DBInt
{
/**
* The minimum value for a signed 64-bit integer.
* Defined as string instead of int otherwise will end up as a float
* on 64-bit systems
*
* When this is cast to an int in IntFieldValidator::__construct()
* it will be properly cast to an int
*/
protected const MIN_INT = '-9223372036854775808';

/**
* The maximum value for a signed 64-bit integer.
*/
protected const MAX_INT = '9223372036854775807';

private static array $field_validators = [
// Remove parent validator and add BigIntValidator instead
IntFieldValidator::class => null,
Expand Down
10 changes: 10 additions & 0 deletions src/ORM/FieldType/DBDate.php
Original file line number Diff line number Diff line change
Expand Up @@ -619,4 +619,14 @@ protected function explodeDateString($value)
$parts[] = $matches['time'];
return $parts;
}

public static function getMinValue(): string
{
return '0000-00-00';
}

public static function getMaxValue(): string
{
return '9999-12-31';
}
}
10 changes: 10 additions & 0 deletions src/ORM/FieldType/DBDatetime.php
Original file line number Diff line number Diff line change
Expand Up @@ -369,4 +369,14 @@ public function getISOFormat(): string
{
return DBDatetime::ISO_DATETIME;
}

public static function getMinValue(): string
{
return '0000-00-00 00:00:00';
}

public static function getMaxValue(): string
{
return '9999-12-31 23:59:59';
}
}
10 changes: 10 additions & 0 deletions src/ORM/FieldType/DBDecimal.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,14 @@ public function prepValueForDB(mixed $value): array|float|int|null

return (float) $value;
}

public static function getMinValue(): float
{
return PHP_FLOAT_MIN;
}

public static function getMaxValue(): float
{
return PHP_FLOAT_MAX;
}
}
16 changes: 16 additions & 0 deletions src/ORM/FieldType/DBField.php
Original file line number Diff line number Diff line change
Expand Up @@ -571,4 +571,20 @@ public function scalarValueOnly(): bool
{
return true;
}

/**
* @return mixed The minimum value for comparisons with this field - or null if that's not determinable.
*/
public static function getMinValue(): mixed
{
return null;
}

/**
* @return mixed The maximum value for comparisons with this field - or null if that's not determinable.
*/
public static function getMaxValue(): mixed
{
return null;
}
}
10 changes: 10 additions & 0 deletions src/ORM/FieldType/DBFloat.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,14 @@ public function prepValueForDB(mixed $value): array|float|int|null

return $value;
}

public static function getMinValue(): float
{
return PHP_FLOAT_MIN;
}

public static function getMaxValue(): float
{
return PHP_FLOAT_MAX;
}
}
8 changes: 1 addition & 7 deletions src/ORM/FieldType/DBForeignKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@

namespace SilverStripe\ORM\FieldType;

use SilverStripe\Assets\File;
use SilverStripe\Assets\Image;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Validation\FieldValidation\IntFieldValidator;
use SilverStripe\Forms\FileHandleField;
use SilverStripe\Forms\FormField;
use SilverStripe\Forms\SearchableDropdownField;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\DataObject;
use SilverStripe\Model\ModelData;

Expand Down Expand Up @@ -78,7 +72,7 @@ public function setValue(mixed $value, null|array|ModelData $record = null, bool
return parent::setValue($value, $record, $markChanged);
}

public function getMinValue(): int
public static function getMinValue(): int
{
return 0;
}
Expand Down
22 changes: 22 additions & 0 deletions src/ORM/FieldType/DBInt.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@
*/
class DBInt extends DBField
{
/**
* The minimum value for a signed 32-bit integer.
* Defined as string instead of int because be cast to a float
* on 32-bit systems if defined as an int
*/
protected const MIN_INT = '-2147483648';

/**
* The maximum value for a signed 32-bit integer.
*/
protected const MAX_INT = '2147483647';

private static array $field_validators = [
IntFieldValidator::class
];
Expand Down Expand Up @@ -89,4 +101,14 @@ public function prepValueForDB(mixed $value): array|int|null

return (int)$value;
}

public static function getMinValue(): string|int
{
return static::MIN_INT;
}

public static function getMaxValue(): string|int
{
return static::MAX_INT;
}
}
4 changes: 2 additions & 2 deletions src/ORM/FieldType/DBPercentage.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ public function __construct(?string $name = null, int $precision = 4)
parent::__construct($name, $precision + 1, $precision);
}

public function getMinValue(): float
public static function getMinValue(): float
{
return 0.0;
}

public function getMaxValue(): float
public static function getMaxValue(): float
{
return 1.0;
}
Expand Down
10 changes: 10 additions & 0 deletions src/ORM/FieldType/DBTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,14 @@ public function getTimestamp(): int
}
return 0;
}

public static function getMinValue(): string
{
return '00:00:00';
}

public static function getMaxValue(): string
{
return '23:59:59';
}
}
8 changes: 4 additions & 4 deletions src/ORM/FieldType/DBYear.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class DBYear extends DBField

private static $field_validators = [
YearFieldValidator::class => [
'minValue' => 'getMinYear',
'maxValue' => 'getMaxYear'
'minValue' => 'getMinValue',
'maxValue' => 'getMaxValue'
],
];

Expand Down Expand Up @@ -70,12 +70,12 @@ public function setValue(mixed $value, null|array|ModelData $record = null, bool
return $this;
}

public function getMinYear(): int
public static function getMinValue(): int
{
return DBYear::MIN_YEAR;
}

public function getMaxYear(): int
public static function getMaxValue(): int
{
return DBYear::MAX_YEAR;
}
Expand Down

0 comments on commit 842d328

Please sign in to comment.