mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Compare commits
2 Commits
a380d7f758
...
226e278719
Author | SHA1 | Date | |
---|---|---|---|
|
226e278719 | ||
|
0d824ccaab |
@ -23,7 +23,7 @@ class DateFieldValidator extends FieldValidator
|
||||
// Not using symfony/validator because it was allowing d-m-Y format strings
|
||||
$date = date_parse_from_format($this->getFormat(), $this->value ?? '');
|
||||
if ($date === false || $date['error_count'] > 0 || $date['warning_count'] > 0) {
|
||||
$result->addFieldError($this->name, $this->getMessage(), value: $this->value);
|
||||
$result->addFieldError($this->name, $this->getMessage());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
@ -8,7 +8,5 @@ interface FieldValidationInterface extends ValidationInterface
|
||||
{
|
||||
public function getName(): string;
|
||||
|
||||
public function getValue(): mixed;
|
||||
|
||||
public function getValueForValidation(): mixed;
|
||||
}
|
||||
|
@ -35,10 +35,6 @@ trait FieldValidatorsTrait
|
||||
public function validate(): ValidationResult
|
||||
{
|
||||
$result = ValidationResult::create();
|
||||
// Skip validation if the field value is null
|
||||
if ($this->getValue() === null) {
|
||||
return $result;
|
||||
}
|
||||
$fieldValidators = $this->getFieldValidators();
|
||||
foreach ($fieldValidators as $fieldValidator) {
|
||||
$validationResult = $fieldValidator->validate();
|
||||
|
@ -43,7 +43,6 @@ class StringFieldValidator extends FieldValidator
|
||||
$result->addFieldError($this->name, $message, value: $this->value);
|
||||
return $result;
|
||||
}
|
||||
// TODO this seems non-sensical - should enforce minLength??
|
||||
// Blank strings are valid, even if there's a minLength requirement
|
||||
if ($this->value === '') {
|
||||
return $result;
|
||||
|
@ -1257,10 +1257,6 @@ class FormField extends RequestHandler
|
||||
{
|
||||
$isValid = true;
|
||||
$result = ValidationResult::create();
|
||||
if ($this->getValue() === null) {
|
||||
// Skip field validation if the value is null
|
||||
return $this->extendValidationResult($isValid, $validator);
|
||||
}
|
||||
$fieldValidators = $this->getFieldValidators();
|
||||
foreach ($fieldValidators as $fieldValidator) {
|
||||
$validationResult = $fieldValidator->validate();
|
||||
|
@ -57,6 +57,11 @@ class DBDate extends DBField
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function nullValue(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse timestamp or iso8601-ish date into standard iso8601 format
|
||||
*
|
||||
|
@ -60,7 +60,7 @@ class DBDatetime extends DBDate implements TemplateGlobalProvider
|
||||
/**
|
||||
* Flag idicating if this field is considered immutable
|
||||
* when this is enabled setting the value of this field will return a new field instance
|
||||
* instead updatin the old one
|
||||
* instead updating the old one
|
||||
*/
|
||||
protected bool $immutable = false;
|
||||
|
||||
|
@ -176,6 +176,11 @@ class DBEnum extends DBString
|
||||
return $this->enum;
|
||||
}
|
||||
|
||||
public function nullValue(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of enum values, including obsolete values still present in the database
|
||||
*
|
||||
|
@ -90,6 +90,11 @@ abstract class DBString extends DBField
|
||||
return $value || (is_string($value) && strlen($value ?? ''));
|
||||
}
|
||||
|
||||
public function nullValue(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function prepValueForDB(mixed $value): array|string|null
|
||||
{
|
||||
// Cast non-empty value
|
||||
|
@ -44,13 +44,16 @@ class DBTime extends DBField
|
||||
|
||||
/**
|
||||
* Parse timestamp or iso8601-ish date into standard iso8601 format
|
||||
*
|
||||
* @return string|null|false Formatted time, null if empty but valid, or false if invalid
|
||||
*/
|
||||
protected function parseTime(mixed $value): mixed
|
||||
protected function parseTime(mixed $value): string|null|false
|
||||
{
|
||||
// Return empty dates as-is, they will get caught by validator later
|
||||
// Skip empty values
|
||||
if (empty($value) && !is_numeric($value)) {
|
||||
return $value;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Determine value to parse
|
||||
if (is_array($value)) {
|
||||
$source = $value; // parse array
|
||||
@ -60,16 +63,14 @@ class DBTime extends DBField
|
||||
// Convert using strtotime
|
||||
$source = strtotime($value ?? '');
|
||||
}
|
||||
if ($value === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Format as iso8601
|
||||
$formatter = $this->getFormatter();
|
||||
$formatter->setPattern($this->getISOFormat());
|
||||
$formatted = $formatter->format($source);
|
||||
// If it failed to format, return the original value so that it can
|
||||
// be caught by the validator
|
||||
if ($formatted === false) {
|
||||
return $value;
|
||||
}
|
||||
return $formatted;
|
||||
return $formatter->format($source);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,6 +66,11 @@ class DBYear extends DBField
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function nullValue(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getMinYear(): int
|
||||
{
|
||||
return DBYear::MIN_YEAR;
|
||||
|
@ -444,8 +444,8 @@ class Member extends DataObject
|
||||
if (!$this->PasswordExpiry) {
|
||||
return false;
|
||||
}
|
||||
$expired = strtotime(date('Y-m-d')) >= strtotime($this->PasswordExpiry ?? '');
|
||||
return $expired;
|
||||
|
||||
return strtotime(date('Y-m-d')) >= strtotime($this->PasswordExpiry ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,7 +39,6 @@ use SilverStripe\Security\PermissionCheckboxSetField_Readonly;
|
||||
use SilverStripe\Forms\SearchableMultiDropdownField;
|
||||
use SilverStripe\Forms\SearchableDropdownField;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use SilverStripe\ORM\FieldType\DBInt;
|
||||
|
||||
class FormFieldTest extends SapphireTest
|
||||
{
|
||||
|
@ -181,21 +181,9 @@ class DBDateTest extends SapphireTest
|
||||
);
|
||||
}
|
||||
|
||||
public static function provideSetValue()
|
||||
public static function provideSetNullAndZeroValues()
|
||||
{
|
||||
return [
|
||||
'date' => [
|
||||
'value' => '1998-04-05',
|
||||
'expected' => '1998-04-05'
|
||||
],
|
||||
'int' => [
|
||||
'value' => 978797878,
|
||||
'expected' => '2001-01-06'
|
||||
],
|
||||
'int-string' => [
|
||||
'value' => '978797878',
|
||||
'expected' => '2001-01-06'
|
||||
],
|
||||
'blank-string' => [
|
||||
'value' => '',
|
||||
'expected' => ''
|
||||
@ -220,9 +208,9 @@ class DBDateTest extends SapphireTest
|
||||
'value' => 0,
|
||||
'expected' => '1970-01-01'
|
||||
],
|
||||
'zero-date' => [
|
||||
'value' => '0000-00-00',
|
||||
'expected' => '0000-00-00'
|
||||
'zero-datetime' => [
|
||||
'value' => '0000-00-00 00:00:00',
|
||||
'expected' => '0000-00-00 00:00:00'
|
||||
],
|
||||
'zero-date-slashes' => [
|
||||
'value' => '00/00/0000',
|
||||
@ -239,12 +227,11 @@ class DBDateTest extends SapphireTest
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('provideSetValue')]
|
||||
public function testSetValue(mixed $value, mixed $expected)
|
||||
#[DataProvider('provideSetNullAndZeroValues')]
|
||||
public function testSetNullAndZeroValues(mixed $value, mixed $expected)
|
||||
{
|
||||
$field = new DBDate('MyField');
|
||||
$field->setValue($value);
|
||||
$this->assertSame($expected, $field->getValue());
|
||||
$date = DBField::create_field('Date', $value);
|
||||
$this->assertSame($expected, $date->getValue());
|
||||
}
|
||||
|
||||
public function testDayOfMonth()
|
||||
|
@ -330,50 +330,4 @@ class DBDatetimeTest extends SapphireTest
|
||||
$after = (new DBDateTime())->setValue($timeAfter);
|
||||
$this->assertSame($expected, DBDatetime::getTimeBetween($before, $after));
|
||||
}
|
||||
|
||||
public static function provideSetValue(): array
|
||||
{
|
||||
return [
|
||||
'int' => [
|
||||
'value' => 800001234,
|
||||
'expected' => '1995-05-09 06:33:54',
|
||||
],
|
||||
'string-int' => [
|
||||
'value' => '800001234',
|
||||
'expected' => '1995-05-09 06:33:54',
|
||||
],
|
||||
'zero' => [
|
||||
'value' => 0,
|
||||
'expected' => '1970-01-01 00:00:00',
|
||||
],
|
||||
'zeroed' => [
|
||||
'value' => '0000-00-00 00:00:00',
|
||||
'expected' => '0000-00-00 00:00:00',
|
||||
],
|
||||
'non-date-string' => [
|
||||
'value' => 'fish',
|
||||
'expected' => 'fish',
|
||||
],
|
||||
'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 DBDatetime('MyField');
|
||||
$field->setValue($value);
|
||||
$this->assertSame($expected, $field->getValue());
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use Exception;
|
||||
use SilverStripe\Assets\Image;
|
||||
use SilverStripe\ORM\FieldType\DBBigInt;
|
||||
use SilverStripe\ORM\FieldType\DBBoolean;
|
||||
use SilverStripe\ORM\FieldType\DBCurrency;
|
||||
@ -55,6 +56,7 @@ use SilverStripe\ORM\FieldType\DBPolymorphicRelationAwareForeignKey;
|
||||
use SilverStripe\ORM\FieldType\DBIp;
|
||||
use SilverStripe\ORM\FieldType\DBEmail;
|
||||
use SilverStripe\Core\Validation\FieldValidation\DatetimeFieldValidator;
|
||||
use SilverStripe\Assets\Storage\DBFile;
|
||||
use SilverStripe\ORM\FieldType\DBClassNameVarchar;
|
||||
|
||||
/**
|
||||
@ -520,6 +522,7 @@ class DBFieldTest extends SapphireTest
|
||||
CompositeFieldValidator::class,
|
||||
],
|
||||
DBMultiEnum::class => [
|
||||
StringFieldValidator::class,
|
||||
MultiEnumFieldValidator::class,
|
||||
],
|
||||
DBPercentage::class => [
|
||||
@ -575,22 +578,4 @@ class DBFieldTest extends SapphireTest
|
||||
// that haven't been tested
|
||||
$this->assertSame(29, $count);
|
||||
}
|
||||
|
||||
public function testSkipValidateIfNull()
|
||||
{
|
||||
$field = new DBInt('MyField');
|
||||
$field->setValue(null);
|
||||
// assert value isn't getting changed on setValue();
|
||||
$this->assertNull($field->getValue());
|
||||
// assert that field validators were not called
|
||||
$this->assertTrue($field->validate()->isValid());
|
||||
// assert that IntFieldValidator was applied to the field
|
||||
$method = new ReflectionMethod(DBInt::class, 'getFieldValidators');
|
||||
$method->setAccessible(true);
|
||||
$actual = array_map('get_class', $method->invoke($field));
|
||||
$this->assertSame([IntFieldValidator::class], $actual);
|
||||
// assert that IntFieldValidator considers null as invalid
|
||||
$validator = new IntFieldValidator('Test', null);
|
||||
$this->assertFalse($validator->validate()->isValid());
|
||||
}
|
||||
}
|
||||
|
@ -17,78 +17,33 @@ class DBTimeTest extends SapphireTest
|
||||
i18n::set_locale('en_NZ');
|
||||
}
|
||||
|
||||
public static function provideSetValue()
|
||||
public static function dataTestParse()
|
||||
{
|
||||
return [
|
||||
'time-11pm' => [
|
||||
'value' => '11:01 pm',
|
||||
'expected' => '23:01:00'
|
||||
],
|
||||
'time-11am' => [
|
||||
'value' => '11:01 am',
|
||||
'expected' => '11:01:00'
|
||||
],
|
||||
'time-12am' => [
|
||||
'value' => '12:01 am',
|
||||
'expected' => '00:01:00'
|
||||
],
|
||||
'time-12pm' => [
|
||||
'value' => '12:01 pm',
|
||||
'expected' => '12:01:00'
|
||||
],
|
||||
'time-11pm-seconds' => [
|
||||
'value' => '11:01.01 pm',
|
||||
'expected' => '23:01:01'
|
||||
],
|
||||
'time-12-seconds' => [
|
||||
'value' => '12:01.01',
|
||||
'expected' => '12:01:01'
|
||||
],
|
||||
'wrong-format-works' => [
|
||||
'value' => '12.34.56',
|
||||
'expected' => '12:34:56',
|
||||
],
|
||||
'int' => [
|
||||
'value' => 6789,
|
||||
'expected' => '01:53:09'
|
||||
],
|
||||
'int-string' => [
|
||||
'value' => '6789',
|
||||
'expected' => '01:53:09'
|
||||
],
|
||||
'zero-string' => [
|
||||
'value' => '0',
|
||||
'expected' => '00:00:00'
|
||||
],
|
||||
'zero-int' => [
|
||||
'value' => 0,
|
||||
'expected' => '00:00:00'
|
||||
],
|
||||
'blank-string' => [
|
||||
'value' => '',
|
||||
'expected' => ''
|
||||
],
|
||||
'null' => [
|
||||
'value' => null,
|
||||
'expected' => null
|
||||
],
|
||||
'false' => [
|
||||
'value' => false,
|
||||
'expected' => false
|
||||
],
|
||||
'empty-array' => [
|
||||
'value' => [],
|
||||
'expected' => []
|
||||
],
|
||||
// Test am-pm conversion
|
||||
['11:01 pm', '23:01:00'],
|
||||
['11:01 am', '11:01:00'],
|
||||
['12:01 pm', '12:01:00'],
|
||||
['12:01 am', '00:01:00'],
|
||||
// Test seconds
|
||||
['11:01.01 pm', '23:01:01'],
|
||||
['12:01.01', '12:01:01'],
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('provideSetValue')]
|
||||
public function testSetValue(mixed $value, mixed $expected)
|
||||
/**
|
||||
* @param string $input
|
||||
* @param string $expected
|
||||
*/
|
||||
#[DataProvider('dataTestParse')]
|
||||
public function testParse($input, $expected)
|
||||
{
|
||||
$field = new DBTime('MyField');
|
||||
$field->setValue($value);
|
||||
$this->assertSame($expected, $field->getValue());
|
||||
$time = DBField::create_field('Time', $input);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$time->getValue(),
|
||||
"Date parsed from {$input} should be {$expected}"
|
||||
);
|
||||
}
|
||||
|
||||
public function testNice()
|
||||
|
@ -30,9 +30,9 @@ class DecimalTest extends SapphireTest
|
||||
public function testDefaultValue()
|
||||
{
|
||||
$this->assertSame(
|
||||
0.0,
|
||||
0,
|
||||
$this->testDataObject->MyDecimal1,
|
||||
'Database default for Decimal type is 0.0'
|
||||
'Database default for Decimal type is 0'
|
||||
);
|
||||
}
|
||||
|
||||
@ -53,9 +53,9 @@ class DecimalTest extends SapphireTest
|
||||
|
||||
public function testSpecifiedDefaultValueInDefaultsArray()
|
||||
{
|
||||
$this->assertSame(
|
||||
$this->assertEquals(
|
||||
$this->testDataObject->MyDecimal4,
|
||||
4.0,
|
||||
4,
|
||||
'Default value for Decimal type is set to 4'
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user