Compare commits

..

2 Commits

Author SHA1 Message Date
Steve Boyd
26166512d0
Merge a213fe2a08 into f83f56eba1 2024-10-11 11:25:00 +13:00
Steve Boyd
a213fe2a08 NEW Validate DBFields 2024-10-11 10:40:42 +13:00
21 changed files with 141 additions and 429 deletions

View File

@ -9,12 +9,12 @@ use SilverStripe\Core\Validation\FieldValidation\FieldValidator;
* Validates value is boolean stored as an integer i.e. 1 or 0 * Validates value is boolean stored as an integer i.e. 1 or 0
* true and false are not valid values * true and false are not valid values
*/ */
class BooleanFieldValidator extends FieldValidator class BooleanIntFieldValidator extends FieldValidator
{ {
protected function validateValue(): ValidationResult protected function validateValue(): ValidationResult
{ {
$result = ValidationResult::create(); $result = ValidationResult::create();
if ($this->value !== true && $this->value !== false) { if ($this->value !== 1 && $this->value !== 0) {
$message = _t(__CLASS__ . '.INVALID', 'Invalid value'); $message = _t(__CLASS__ . '.INVALID', 'Invalid value');
$result->addFieldError($this->name, $message, value: $this->value); $result->addFieldError($this->name, $message, value: $this->value);
} }

View File

@ -18,10 +18,6 @@ class EnumFieldValidator extends FieldValidator
protected function validateValue(): ValidationResult protected function validateValue(): ValidationResult
{ {
$result = ValidationResult::create(); $result = ValidationResult::create();
// Allow empty strings
if ($this->value === '') {
return $result;
}
if (!in_array($this->value, $this->allowedValues, true)) { if (!in_array($this->value, $this->allowedValues, true)) {
$message = _t(__CLASS__ . '.NOTALLOWED', 'Not an allowed value'); $message = _t(__CLASS__ . '.NOTALLOWED', 'Not an allowed value');
$result->addFieldError($this->name, $message, value: $this->value); $result->addFieldError($this->name, $message, value: $this->value);

View File

@ -1,42 +0,0 @@
<?php
namespace SilverStripe\Core\Validation\FieldValidation;
use SilverStripe\Core\Validation\ValidationResult;
use SilverStripe\Core\Validation\FieldValidation\NumericFieldValidator;
/**
* Validates that a field is an integer year between two dates, or 0 for a null value.
*/
class YearFieldValidator extends IntFieldValidator
{
private ?int $minValue;
public function __construct(
string $name,
mixed $value,
?int $minValue = null,
?int $maxValue = null
) {
$this->minValue = $minValue;
parent::__construct($name, $value, 0, $maxValue);
}
protected function validateValue(): ValidationResult
{
$result = parent::validateValue();
if ($this->value === 0) {
return $result;
}
if ($this->minValue && $this->value < $this->minValue) {
// Uses the same translation key as NumericFieldValidator
$message = _t(
NumericFieldValidator::class . '.TOOSMALL',
'Value cannot be less than {minValue}',
['minValue' => $this->minValue]
);
$result->addFieldError($this->name, $message, value: $this->value);
}
return $result;
}
}

View File

@ -2,14 +2,17 @@
namespace SilverStripe\Forms; namespace SilverStripe\Forms;
use SilverStripe\Core\Validation\ConstraintValidator; use SilverStripe\Core\Validation\FieldValidation\EmailFieldValidator;
use Symfony\Component\Validator\Constraints\Email as EmailConstraint;
/** /**
* Text input field with validation for correct email format according to the relevant RFC. * Text input field with validation for correct email format according to the relevant RFC.
*/ */
class EmailField extends TextField class EmailField extends TextField
{ {
private static array $field_validators = [
EmailFieldValidator::class,
];
protected $inputType = 'email'; protected $inputType = 'email';
public function Type() public function Type()
@ -17,27 +20,6 @@ class EmailField extends TextField
return 'email text'; return 'email text';
} }
/**
* Validates for RFC compliant email addresses.
*
* @param Validator $validator
*/
public function validate($validator)
{
$this->value = trim($this->value ?? '');
$message = _t('SilverStripe\\Forms\\EmailField.VALIDATION', 'Please enter an email address');
$result = ConstraintValidator::validate(
$this->value,
new EmailConstraint(message: $message, mode: EmailConstraint::VALIDATION_MODE_STRICT),
$this->getName()
);
$validator->getResult()->combineAnd($result);
$isValid = $result->isValid();
return $this->extendValidationResult($isValid, $validator);
}
public function getSchemaValidation() public function getSchemaValidation()
{ {
$rules = parent::getSchemaValidation(); $rules = parent::getSchemaValidation();

View File

@ -2,6 +2,8 @@
namespace SilverStripe\Forms; namespace SilverStripe\Forms;
use SilverStripe\Core\Validation\FieldValidation\StringFieldValidator;
/** /**
* Text input field. * Text input field.
*/ */
@ -14,6 +16,10 @@ class TextField extends FormField implements TippableFieldInterface
protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TEXT; protected $schemaDataType = FormField::SCHEMA_DATA_TYPE_TEXT;
private static array $field_validators = [
StringFieldValidator::class => [null, 'getMaxLength'],
];
/** /**
* @var Tip|null A tip to render beside the input * @var Tip|null A tip to render beside the input
*/ */
@ -43,6 +49,14 @@ class TextField extends FormField implements TippableFieldInterface
parent::__construct($name, $title, $value); parent::__construct($name, $title, $value);
} }
public function setValue($value, $data = null)
{
parent::setValue($value, $data = null);
if (is_null($this->value)) {
$this->value = '';
}
}
/** /**
* @param int $maxLength * @param int $maxLength
* @return $this * @return $this

View File

@ -2,7 +2,7 @@
namespace SilverStripe\ORM\FieldType; namespace SilverStripe\ORM\FieldType;
use SilverStripe\Core\Validation\FieldValidation\BooleanFieldValidator; use SilverStripe\Core\Validation\FieldValidation\BooleanIntFieldValidator;
use SilverStripe\Forms\CheckboxField; use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FormField; use SilverStripe\Forms\FormField;
@ -11,17 +11,17 @@ use SilverStripe\Model\ModelData;
/** /**
* Represents a boolean field * Represents a boolean field
* Values are stored in the database as tinyint i.e. 1 or 0 * Values are stored as a tinyint i.e. 1 or 0 and NOT as true or false
*/ */
class DBBoolean extends DBField class DBBoolean extends DBField
{ {
private static array $field_validators = [ private static array $field_validators = [
BooleanFieldValidator::class, BooleanIntFieldValidator::class,
]; ];
public function __construct(?string $name = null, bool $defaultVal = false) public function __construct(?string $name = null, bool|int $defaultVal = 0)
{ {
$this->setDefaultValue($defaultVal); $this->setDefaultValue($defaultVal ? 1 : 0);
parent::__construct($name); parent::__construct($name);
} }
@ -43,7 +43,7 @@ class DBBoolean extends DBField
public function setValue(mixed $value, null|array|ModelData $record = null, bool $markChanged = true): static public function setValue(mixed $value, null|array|ModelData $record = null, bool $markChanged = true): static
{ {
parent::setValue($value); parent::setValue($value);
$this->value = $this->convertBooleanLikeValue($value); $this->value = $this->convertBooleanLikeValueToTinyInt($value);
return $this; return $this;
} }
@ -64,7 +64,7 @@ class DBBoolean extends DBField
if ($this->value instanceof DBField) { if ($this->value instanceof DBField) {
$this->value->saveInto($dataObject); $this->value->saveInto($dataObject);
} else { } else {
$dataObject->__set($fieldName, $this->value ? true : false); $dataObject->__set($fieldName, $this->value ? 1 : 0);
} }
} else { } else {
$class = static::class; $class = static::class;
@ -82,8 +82,8 @@ class DBBoolean extends DBField
$anyText = _t(__CLASS__ . '.ANY', 'Any'); $anyText = _t(__CLASS__ . '.ANY', 'Any');
$source = [ $source = [
'' => $anyText, '' => $anyText,
'1' => _t(__CLASS__ . '.YESANSWER', 'Yes'), 1 => _t(__CLASS__ . '.YESANSWER', 'Yes'),
'0' => _t(__CLASS__ . '.NOANSWER', 'No') 0 => _t(__CLASS__ . '.NOANSWER', 'No')
]; ];
return DropdownField::create($this->name, $title, $source) return DropdownField::create($this->name, $title, $source)
@ -97,35 +97,33 @@ class DBBoolean extends DBField
public function prepValueForDB(mixed $value): array|int|null public function prepValueForDB(mixed $value): array|int|null
{ {
$bool = $this->convertBooleanLikeValue($value); $ret = $this->convertBooleanLikeValueToTinyInt($value);
// Ensure a tiny int is returned no matter what e.g. value is an // Ensure a tiny int is returned no matter what e.g. value is an
return $bool ? 1 : 0; return $ret ? 1 : 0;
} }
/** private function convertBooleanLikeValueToTinyInt(mixed $value): mixed
* Convert boolean-like values to boolean
* Does not convert non-boolean-like values e.g. array - will be handled by the FieldValidator
*/
private function convertBooleanLikeValue(mixed $value): mixed
{ {
if (is_bool($value)) {
return $value ? 1 : 0;
}
if (empty($value)) {
return 0;
}
if (is_string($value)) { if (is_string($value)) {
switch (strtolower($value)) { switch (strtolower($value ?? '')) {
case 'false': case 'false':
case 'f': case 'f':
case '0': case '0':
return false; return 0;
case 'true': case 'true':
case 't': case 't':
case '1': case '1':
return true; return 1;
} }
} }
if ($value === 0) { // Note that something like "lorem" will NOT be converted to 1
return false; // instead it will throw a ValidationException in BooleanIntFieldValidator
}
if ($value === 1) {
return true;
}
return $value; return $value;
} }
} }

View File

@ -63,7 +63,7 @@ class DBDate extends DBField
* @param mixed $value * @param mixed $value
* @return mixed Formatted date, or the original value if it couldn't be parsed * @return mixed Formatted date, or the original value if it couldn't be parsed
*/ */
protected function parseDate(mixed $value): mixed protected function parseDate(mixed $value): string|null|false
{ {
// Determine value to parse // Determine value to parse
if (is_array($value)) { if (is_array($value)) {
@ -73,16 +73,11 @@ class DBDate extends DBField
} else { } else {
// Convert US date -> iso, fix y2k, etc // Convert US date -> iso, fix y2k, etc
$fixedValue = $this->fixInputDate($value); $fixedValue = $this->fixInputDate($value);
if ($fixedValue === '') {
// Dates with an invalid format will be caught by validator later
return $value;
}
// convert string to timestamp // convert string to timestamp
$source = strtotime($fixedValue ?? ''); $source = strtotime($fixedValue ?? '');
} }
if (!$source && $source !== 0 and $source !== '0') { if (!$source) {
// Unable to parse date, keep as is so that the validator can catch it later // Unable to parse date, keep as is so that the validator can catch it later
// Note that 0 and '0' are valid dates for Jan 1 1970
return $value; return $value;
} }
// Format as iso8601 // Format as iso8601
@ -556,12 +551,16 @@ class DBDate extends DBField
/** /**
* Fix non-iso dates * Fix non-iso dates
*
* @param string $value
* @return string
*/ */
protected function fixInputDate(string $value): string protected function fixInputDate($value)
{ {
[$year, $month, $day, $time] = $this->explodeDateString($value); [$year, $month, $day, $time] = $this->explodeDateString($value);
if (!checkdate((int) $month, (int) $day, (int) $year)) { if (!checkdate((int) $month, (int) $day, (int) $year)) {
return ''; // Keep invalid dates as they are so that the validator can catch them later
return $value;
} }
// Convert to Y-m-d // Convert to Y-m-d
return sprintf('%d-%02d-%02d%s', $year, $month, $day, $time); return sprintf('%d-%02d-%02d%s', $year, $month, $day, $time);

View File

@ -82,16 +82,6 @@ class DBDecimal extends DBField
DB::require_field($this->tableName, $this->name, $values); DB::require_field($this->tableName, $this->name, $values);
} }
public function setValue(mixed $value, null|array|ModelData $record = null, bool $markChanged = true): static
{
parent::setValue($value, $record, $markChanged);
// Cast ints and numeric strings to floats
if (is_int($this->value) || (is_string($this->value) && is_numeric($this->value))) {
$this->value = (float) $value;
}
return $this;
}
public function saveInto(ModelData $model): void public function saveInto(ModelData $model): void
{ {
$fieldName = $this->name; $fieldName = $this->name;

View File

@ -176,11 +176,6 @@ class DBEnum extends DBString
return $this->enum; return $this->enum;
} }
public function nullValue(): string
{
return '';
}
/** /**
* Get the list of enum values, including obsolete values still present in the database * Get the list of enum values, including obsolete values still present in the database
* *
@ -253,4 +248,13 @@ class DBEnum extends DBString
$this->setDefaultValue($default); $this->setDefaultValue($default);
return $this; return $this;
} }
public function setValue(mixed $value, null|array|ModelData $record = null, bool $markChanged = true): static
{
parent::setValue($value, $record, $markChanged);
if (empty($this->value)) {
$this->value = $this->getDefault();
}
return $this;
}
} }

View File

@ -3,7 +3,6 @@
namespace SilverStripe\ORM\FieldType; namespace SilverStripe\ORM\FieldType;
use SilverStripe\Model\ModelData; use SilverStripe\Model\ModelData;
use SilverStripe\Core\Validation\FieldValidation\DecimalFieldValidator;
/** /**
* Represents a decimal field from 0-1 containing a percentage value. * Represents a decimal field from 0-1 containing a percentage value.
@ -18,10 +17,6 @@ use SilverStripe\Core\Validation\FieldValidation\DecimalFieldValidator;
*/ */
class DBPercentage extends DBDecimal class DBPercentage extends DBDecimal
{ {
private static array $field_validators = [
DecimalFieldValidator::class => ['getWholeSize', 'getDecimalSize', 'getMinValue', 'getMaxValue'],
];
/** /**
* Create a new Decimal field. * Create a new Decimal field.
*/ */
@ -34,16 +29,6 @@ class DBPercentage extends DBDecimal
parent::__construct($name, $precision + 1, $precision); parent::__construct($name, $precision + 1, $precision);
} }
public function getMinValue(): float
{
return 0.0;
}
public function getMaxValue(): float
{
return 1.0;
}
/** /**
* Returns the number, expressed as a percentage. For example, “36.30% * Returns the number, expressed as a percentage. For example, “36.30%
*/ */

View File

@ -90,9 +90,14 @@ abstract class DBString extends DBField
return $value || (is_string($value) && strlen($value ?? '')); return $value || (is_string($value) && strlen($value ?? ''));
} }
public function nullValue(): string public function setValue(mixed $value, null|array|ModelData $record = null, bool $markChanged = true): static
{ {
return ''; if (is_null($value)) {
$this->value = '';
} else {
$this->value = $value;
}
return $this;
} }
public function prepValueForDB(mixed $value): array|string|null public function prepValueForDB(mixed $value): array|string|null

View File

@ -6,7 +6,7 @@ use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FormField; use SilverStripe\Forms\FormField;
use SilverStripe\ORM\DB; use SilverStripe\ORM\DB;
use SilverStripe\Model\ModelData; use SilverStripe\Model\ModelData;
use SilverStripe\Core\Validation\FieldValidation\YearFieldValidator; use SilverStripe\Core\Validation\FieldValidation\IntFieldValidator;
/** /**
* Represents a single year field * Represents a single year field
@ -15,11 +15,11 @@ class DBYear extends DBField
{ {
// MySQL year datatype supports years between 1901 and 2155 // MySQL year datatype supports years between 1901 and 2155
// https://dev.mysql.com/doc/refman/8.0/en/year.html // https://dev.mysql.com/doc/refman/8.0/en/year.html
public const MIN_YEAR = 1901; private const MIN_YEAR = 1901;
public const MAX_YEAR = 2155; private const MAX_YEAR = 2155;
private static $field_validators = [ private static $field_validators = [
YearFieldValidator::class => ['getMinYear', 'getMaxYear'], IntFieldValidator::class => ['getMinYear', 'getMaxYear'],
]; ];
public function requireField(): void public function requireField(): void

View File

@ -4,9 +4,9 @@ namespace SilverStripe\Core\Tests\Validation\FieldValidation;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProvider;
use SilverStripe\Core\Validation\FieldValidation\BooleanFieldValidator; use SilverStripe\Core\Validation\FieldValidation\BooleanIntFieldValidator;
class BooleanFieldValidatorTest extends SapphireTest class BooleanIntFieldValidatorTest extends SapphireTest
{ {
public static function provideValidate(): array public static function provideValidate(): array
{ {
@ -65,7 +65,7 @@ class BooleanFieldValidatorTest extends SapphireTest
#[DataProvider('provideValidate')] #[DataProvider('provideValidate')]
public function testValidate(mixed $value, bool $expected): void public function testValidate(mixed $value, bool $expected): void
{ {
$validator = new BooleanFieldValidator('MyField', $value); $validator = new BooleanIntFieldValidator('MyField', $value);
$result = $validator->validate(); $result = $validator->validate();
$this->assertSame($expected, $result->isValid()); $this->assertSame($expected, $result->isValid());
} }

View File

@ -1,43 +0,0 @@
<?php
namespace SilverStripe\Core\Tests\Validation\FieldValidation;
use SilverStripe\Dev\SapphireTest;
use PHPUnit\Framework\Attributes\DataProvider;
use SilverStripe\Core\Validation\FieldValidation\YearFieldValidator;
use SilverStripe\ORM\FieldType\DBYear;
class YearFieldValidatorTest extends SapphireTest
{
public static function provideValidate(): array
{
// YearFieldValidator extends IntFieldValidator so only testing a subset
// of possible values here
return [
'valid-int' => [
'value' => 2021,
'expected' => true,
],
'valid-zero' => [
'value' => 0,
'expected' => true,
],
'invalid-out-of-range-low' => [
'value' => 1850,
'expected' => false,
],
'invalid-out-of-range-high' => [
'value' => 3000,
'expected' => false,
],
];
}
#[DataProvider('provideValidate')]
public function testValidate(mixed $value, bool $expected): void
{
$validator = new YearFieldValidator('MyField', $value, DBYear::MIN_YEAR, DBYear::MAX_YEAR);
$result = $validator->validate();
$this->assertSame($expected, $result->isValid());
}
}

View File

@ -1,98 +0,0 @@
<?php
namespace SilverStripe\ORM\Tests;
use SilverStripe\Dev\SapphireTest;
use PHPUnit\Framework\Attributes\DataProvider;
use SilverStripe\ORM\FieldType\DBBoolean;
class DBBooleanTest extends SapphireTest
{
public function testDefaultValue(): void
{
$field = new DBBoolean('MyField');
$this->assertSame(false, $field->getValue());
}
public static function provideSetValue(): array
{
return [
'true' => [
'value' => true,
'expected' => true,
],
'false' => [
'value' => false,
'expected' => false,
],
'1-int' => [
'value' => 1,
'expected' => true,
],
'1-string' => [
'value' => '1',
'expected' => true,
],
'0-int' => [
'value' => 0,
'expected' => false,
],
'0-string' => [
'value' => '0',
'expected' => false,
],
't' => [
'value' => 't',
'expected' => true,
],
'f' => [
'value' => 'f',
'expected' => false,
],
'T' => [
'value' => 'T',
'expected' => true,
],
'F' => [
'value' => 'F',
'expected' => false,
],
'true-string' => [
'value' => 'true',
'expected' => true,
],
'false-string' => [
'value' => 'false',
'expected' => false,
],
'2-int' => [
'value' => 2,
'expected' => 2,
],
'0.0' => [
'value' => 0.0,
'expected' => 0.0,
],
'1.0' => [
'value' => 1.0,
'expected' => 1.0,
],
'null' => [
'value' => null,
'expected' => null,
],
'array' => [
'value' => [],
'expected' => [],
],
];
}
#[DataProvider('provideSetValue')]
public function testSetValue(mixed $value, mixed $expected): void
{
$field = new DBBoolean('MyField');
$field->setValue($value);
$this->assertSame($expected, $field->getValue());
}
}

View File

@ -10,7 +10,6 @@ use SilverStripe\ORM\FieldType\DBDate;
use SilverStripe\ORM\FieldType\DBDatetime; use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBField;
use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProvider;
use SilverStripe\Core\Validation\ValidationException;
class DBDateTest extends SapphireTest class DBDateTest extends SapphireTest
{ {
@ -92,6 +91,20 @@ class DBDateTest extends SapphireTest
); );
} }
public function testMDYConversion()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("Invalid date: '3/16/2003'. Use y-MM-dd to prevent this error.");
DBField::create_field('Date', '3/16/2003');
}
public function testY2kCorrection()
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("Invalid date: '03-03-04'. Use y-MM-dd to prevent this error.");
DBField::create_field('Date', '03-03-04');
}
public function testInvertedYearCorrection() public function testInvertedYearCorrection()
{ {
// iso8601 expects year first, but support year last // iso8601 expects year first, but support year last
@ -181,57 +194,31 @@ class DBDateTest extends SapphireTest
); );
} }
public static function provideSetNullAndZeroValues() public function testSetNullAndZeroValues()
{ {
return [ $date = DBField::create_field('Date', '');
'blank-string' => [ $this->assertNull($date->getValue(), 'Empty string evaluates to NULL');
'value' => '',
'expected' => ''
],
'null' => [
'value' => null,
'expected' => null
],
'false' => [
'value' => false,
'expected' => false
],
'empty-array' => [
'value' => [],
'expected' => []
],
'zero-string' => [
'value' => '0',
'expected' => '1970-01-01'
],
'zero-int' => [
'value' => 0,
'expected' => '1970-01-01'
],
'zero-datetime' => [
'value' => '0000-00-00 00:00:00',
'expected' => '0000-00-00 00:00:00'
],
'zero-date-slashes' => [
'value' => '00/00/0000',
'expected' => '00/00/0000'
],
'wrong-format-a' => [
'value' => '3/16/2003',
'expected' => '3/16/2003',
],
'wrong-format-b' => [
'value' => '03-03-04',
'expected' => '2003-03-04',
],
];
}
#[DataProvider('provideSetNullAndZeroValues')] $date = DBField::create_field('Date', null);
public function testSetNullAndZeroValues(mixed $value, mixed $expected) $this->assertNull($date->getValue(), 'NULL is set as NULL');
{
$date = DBField::create_field('Date', $value); $date = DBField::create_field('Date', false);
$this->assertSame($expected, $date->getValue()); $this->assertNull($date->getValue(), 'Boolean FALSE evaluates to NULL');
$date = DBField::create_field('Date', []);
$this->assertNull($date->getValue(), 'Empty array evaluates to NULL');
$date = DBField::create_field('Date', '0');
$this->assertEquals('1970-01-01', $date->getValue(), 'Zero is UNIX epoch date');
$date = DBField::create_field('Date', 0);
$this->assertEquals('1970-01-01', $date->getValue(), 'Zero is UNIX epoch date');
$date = DBField::create_field('Date', '0000-00-00 00:00:00');
$this->assertNull($date->getValue(), '0000-00-00 00:00:00 is set as NULL');
$date = DBField::create_field('Date', '00/00/0000');
$this->assertNull($date->getValue(), '00/00/0000 is set as NULL');
} }
public function testDayOfMonth() public function testDayOfMonth()

View File

@ -1,87 +0,0 @@
<?php
namespace SilverStripe\ORM\Tests;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\FieldType\DBInt;
use PHPUnit\Framework\Attributes\DataProvider;
use SilverStripe\ORM\FieldType\DBDecimal;
class DBDecimalTest extends SapphireTest
{
public function testDefaultValue(): void
{
$field = new DBDecimal('MyField');
$this->assertSame(0.0, $field->getValue());
}
public static function provideSetValue(): array
{
return [
'float' => [
'value' => 9.123,
'expected' => 9.123,
],
'negative-float' => [
'value' => -9.123,
'expected' => -9.123,
],
'string-float' => [
'value' => '9.123',
'expected' => 9.123,
],
'string-negative-float' => [
'value' => '-9.123',
'expected' => -9.123,
],
'zero' => [
'value' => 0,
'expected' => 0.0,
],
'int' => [
'value' => 3,
'expected' => 3.0,
],
'negative-int' => [
'value' => -3,
'expected' => -3.0,
],
'string-int' => [
'value' => '3',
'expected' => 3.0,
],
'negative-string-int' => [
'value' => '-3',
'expected' => -3.0,
],
'string' => [
'value' => 'fish',
'expected' => 'fish',
],
'array' => [
'value' => [],
'expected' => [],
],
'null' => [
'value' => null,
'expected' => null,
],
'true' => [
'value' => true,
'expected' => true,
],
'false' => [
'value' => false,
'expected' => false,
],
];
}
#[DataProvider('provideSetValue')]
public function testSetValue(mixed $value, mixed $expected): void
{
$field = new DBDecimal('MyField');
$field->setValue($value);
$this->assertSame($expected, $field->getValue());
}
}

View File

@ -118,7 +118,7 @@ class DBEnumTest extends SapphireTest
$obj2 = new FieldType\DBEnumTestObject(); $obj2 = new FieldType\DBEnumTestObject();
$obj2->Colour = 'Purple'; $obj2->Colour = 'Purple';
$obj2->write(skipValidation: true); $obj2->write();
$this->assertEquals( $this->assertEquals(
['Purple', 'Red'], ['Purple', 'Red'],

View File

@ -33,7 +33,7 @@ use SilverStripe\ORM\FieldType\DBYear;
use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProvider;
use SilverStripe\Core\ClassInfo; use SilverStripe\Core\ClassInfo;
use ReflectionClass; use ReflectionClass;
use SilverStripe\Core\Validation\FieldValidation\BooleanFieldValidator; use SilverStripe\Core\Validation\FieldValidation\BooleanIntFieldValidator;
use SilverStripe\Dev\TestOnly; use SilverStripe\Dev\TestOnly;
use SilverStripe\Core\Validation\FieldValidation\BigIntFieldValidator; use SilverStripe\Core\Validation\FieldValidation\BigIntFieldValidator;
use SilverStripe\ORM\FieldType\DBClassName; use SilverStripe\ORM\FieldType\DBClassName;
@ -458,7 +458,7 @@ class DBFieldTest extends SapphireTest
BigIntFieldValidator::class, BigIntFieldValidator::class,
], ],
DBBoolean::class => [ DBBoolean::class => [
BooleanFieldValidator::class, BooleanIntFieldValidator::class,
], ],
DBClassName::class => [ DBClassName::class => [
StringFieldValidator::class, StringFieldValidator::class,

View File

@ -33,10 +33,6 @@ class DBIntTest extends SapphireTest
'value' => '-3', 'value' => '-3',
'expected' => -3, 'expected' => -3,
], ],
'float' => [
'value' => 3.5,
'expected' => 3.5,
],
'string' => [ 'string' => [
'value' => 'fish', 'value' => 'fish',
'expected' => 'fish', 'expected' => 'fish',

View File

@ -69,4 +69,30 @@ class DBStringTest extends SapphireTest
$this->assertFalse(DBField::create_field(MyStringField::class, 0)->exists()); $this->assertFalse(DBField::create_field(MyStringField::class, 0)->exists());
$this->assertFalse(DBField::create_field(MyStringField::class, 0.0)->exists()); $this->assertFalse(DBField::create_field(MyStringField::class, 0.0)->exists());
} }
public static function provideSetValue(): array
{
return [
'string' => [
'value' => 'fish',
'expected' => 'fish',
],
'blank-string' => [
'value' => '',
'expected' => '',
],
'null' => [
'value' => null,
'expected' => '',
],
];
}
#[DataProvider('provideSetValue')]
public function testSetValue(mixed $value, string $expected): void
{
$obj = new MyStringField('TestField');
$obj->setValue($value);
$this->assertSame($expected, $obj->getValue());
}
} }