diff --git a/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeFormatConstraint.php b/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeFormatConstraint.php index 5ad78de..ecfe31c 100644 --- a/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeFormatConstraint.php +++ b/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeFormatConstraint.php @@ -19,41 +19,41 @@ class DateRangeFormatConstraint extends Constraint { * * @var string */ - public $badStartType = "The daterange start value must be a string."; + public $badStartType = "The date range start value must be a string."; /** * Message for when the end value isn't a string. * * @var string */ - public $badEndType = "The daterange end value must be a string."; + public $badEndType = "The date range end value must be a string."; /** * Message for when the start value isn't in the proper format. * * @var string */ - public $badStartFormat = "The daterange start value '@value' is invalid for the format '@format'"; + public $badStartFormat = "The date range start value '@value' is invalid for the format '@format'"; /** * Message for when the end value isn't in the proper format. * * @var string */ - public $badEndFormat = "The daterange end value '@end_value' is invalid for the format '@format'"; + public $badEndFormat = "The date range end value '@end_value' is invalid for the format '@format'"; /** * Message for when the start value did not parse properly. * * @var string */ - public $badStartValue = "The daterange start value '@value' did not parse properly for the format '@format'"; + public $badStartValue = "The date range start value '@value' did not parse properly for the format '@format'"; /** * Message for when the end value did not parse properly. * * @var string */ - public $badEndValue = "The daterange end value '@end_value' did not parse properly for the format '@format'"; + public $badEndValue = "The date range end value '@end_value' did not parse properly for the format '@format'"; } diff --git a/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeFormatConstraintValidator.php b/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeFormatConstraintValidator.php index 752a7d6..6f68280 100644 --- a/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeFormatConstraintValidator.php +++ b/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeFormatConstraintValidator.php @@ -34,9 +34,6 @@ public function validate($item, Constraint $constraint) { if ($stop) return; - // @todo Reorder this w/ $stop... - return; - $datetime_type = $item->getFieldDefinition()->getSetting('datetime_type'); $format = $datetime_type === DateRangeItem::DATETIME_TYPE_DATE ? DateTimeItemInterface::DATE_STORAGE_FORMAT : DateTimeItemInterface::DATETIME_STORAGE_FORMAT; @@ -49,20 +46,14 @@ public function validate($item, Constraint $constraint) { '@value' => $value, '@format' => $format, ]); - return; + $stop = TRUE; } catch (\UnexpectedValueException $e) { $this->context->addViolation($constraint->badStartValue, [ '@value' => $value, '@format' => $format, ]); - return; - } - if ($start_date === NULL || $start_date->hasErrors()) { - $this->context->addViolation($constraint->badStartFormat, [ - '@value' => $value, - '@format' => $format, - ]); + $stop = TRUE; } $end_date = NULL; @@ -74,15 +65,25 @@ public function validate($item, Constraint $constraint) { '@end_value' => $end_value, '@format' => $format, ]); - return; + $stop = TRUE; } catch (\UnexpectedValueException $e) { $this->context->addViolation($constraint->badEndValue, [ '@end_value' => $end_value, '@format' => $format, ]); - return; + $stop = TRUE; } + + if ($stop) return; + + if ($start_date === NULL || $start_date->hasErrors()) { + $this->context->addViolation($constraint->badStartFormat, [ + '@value' => $value, + '@format' => $format, + ]); + } + if ($end_date === NULL || $end_date->hasErrors()) { $this->context->addViolation($constraint->badEndFormat, [ '@end_value' => $end_value, diff --git a/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeStartEndConstraint.php b/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeStartEndConstraint.php index fb46363..bebdc27 100644 --- a/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeStartEndConstraint.php +++ b/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeStartEndConstraint.php @@ -19,6 +19,6 @@ class DateRangeStartEndConstraint extends Constraint { * * @var string */ - public $badStartEnd = "The daterange end value '@end_value' must equal to or after the start value '@value'"; + public $badStartEnd = "The date range end value '@end_value' must equal to or after the start value '@value'"; } diff --git a/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeStartEndConstraintValidator.php b/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeStartEndConstraintValidator.php index 5a76393..a1d2ea9 100644 --- a/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeStartEndConstraintValidator.php +++ b/core/modules/datetime_range/src/Plugin/Validation/Constraint/DateRangeStartEndConstraintValidator.php @@ -2,6 +2,7 @@ namespace Drupal\datetime_range\Plugin\Validation\Constraint; +use Drupal\Core\Datetime\DrupalDateTime; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -16,14 +17,24 @@ class DateRangeStartEndConstraintValidator extends ConstraintValidator { public function validate($item, Constraint $constraint) { /* @var $item \Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem */ if (isset($item)) { - $value = $item->getValue()['value']; - $end_value = $item->getValue()['end_value']; + $values = $item->getValue(); + $value = $values['value']; + $end_value = $values['end_value']; - if ($end_value < $value) { - $this->context->addViolation($constraint->badStartEnd, [ - '@value' => $value, - '@end_value' => $end_value, - ]); + // Only run this validation when the item has proper start and end date + // objects, which means the values were parsed properly. + if (isset($values['start_date']) && $values['start_date'] instanceof DrupalDateTime && isset($values['end_date']) && $values['end_date'] instanceof DrupalDateTime) { + /** @var \Drupal\Core\Datetime\DrupalDateTime $start_date */ + $start_date = $values['start_date']; + /** @var \Drupal\Core\Datetime\DrupalDateTime $start_date */ + $end_date = $values['end_date']; + + if ($start_date->format('c') < $end_date->format('c')) { + $this->context->addViolation($constraint->badStartEnd, [ + '@value' => $value, + '@end_value' => $end_value, + ]); + } } } } diff --git a/core/modules/datetime_range/tests/src/Functional/EntityResource/EntityTest/EntityTestDatetimeTest.php b/core/modules/datetime_range/tests/src/Functional/EntityResource/EntityTest/EntityTestDaterangeTest.php similarity index 62% rename from core/modules/datetime_range/tests/src/Functional/EntityResource/EntityTest/EntityTestDatetimeTest.php rename to core/modules/datetime_range/tests/src/Functional/EntityResource/EntityTest/EntityTestDaterangeTest.php index e05895b..49baf9c 100644 --- a/core/modules/datetime_range/tests/src/Functional/EntityResource/EntityTest/EntityTestDatetimeTest.php +++ b/core/modules/datetime_range/tests/src/Functional/EntityResource/EntityTest/EntityTestDaterangeTest.php @@ -17,7 +17,7 @@ * * @group datetime */ -class EntityTestDatetimeTest extends EntityTestResourceTestBase { +class EntityTestDaterangeTest extends EntityTestResourceTestBase { use AnonResourceTestTrait; @@ -36,13 +36,18 @@ class EntityTestDatetimeTest extends EntityTestResourceTestBase { protected static $endDateString = '2017-03-02T20:02:00'; /** - * Datetime test field name. + * Daterange test field name. * * @var string */ protected static $fieldName = 'field_daterange'; /** + * Daterange field type. + */ + protected static $datetimeType = DateRangeItem::DATETIME_TYPE_DATETIME; + + /** * {@inheritdoc} */ public static $modules = ['datetime', 'datetime_range', 'entity_test']; @@ -58,7 +63,7 @@ public function setUp() { 'field_name' => static::$fieldName, 'type' => 'daterange', 'entity_type' => static::$entityTypeId, - 'settings' => ['datetime_type' => DateRangeItem::DATETIME_TYPE_DATETIME], + 'settings' => ['datetime_type' => static::$datetimeType], ]) ->save(); @@ -66,7 +71,6 @@ public function setUp() { 'field_name' => static::$fieldName, 'entity_type' => static::$entityTypeId, 'bundle' => $this->entity->bundle(), -// 'settings' => ['default_value' => static::$startDateString], ]) ->save(); @@ -137,46 +141,54 @@ protected function assertNormalizationEdgeCases($method, Url $url, array $reques // DX: 422 when date type is incorrect. - // Errors? $value = ['2017', '03', '01', '21', '53', '00']; $end_value = static::$endDateString; - $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The daterange start value must be a string.\n{$fieldName}.0: The daterange end value must be a string.\n{$fieldName}.0.value: This value should be of the correct primitive type.\n{$fieldName}.0.end_value: This value should be of the correct primitive type.\n"; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range start value must be a string.\n{$fieldName}.0.value: This value should be of the correct primitive type.\n"; $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); - // Works! $value = static::$startDateString; $end_value = ['2017', '03', '02', '21', '53', '00']; - $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The daterange end value must be a string.\n{$fieldName}.0.end_value: This value should be of the correct primitive type.\n"; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range end value must be a string.\n{$fieldName}.0.end_value: This value should be of the correct primitive type.\n"; $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); - // Works?? $value = ['2017', '03', '01', '21', '53', '00']; $end_value = ['2017', '03', '02', '21', '53', '00']; - $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The daterange start value must be a string.\n{$fieldName}.0: The daterange end value must be a string.\n{$fieldName}.0.value: This value should be of the correct primitive type.\n{$fieldName}.0.end_value: This value should be of the correct primitive type.\n"; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range start value must be a string.\n{$fieldName}.0: The date range end value must be a string.\n{$fieldName}.0.value: This value should be of the correct primitive type.\n{$fieldName}.0.end_value: This value should be of the correct primitive type.\n"; $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); - // @todo Adjust the stuff below... - return; - // DX: 422 when date format is incorrect. - $normalization = $this->getNormalizedPostEntity(); + $value = '2017-03-01'; - $normalization[static::$fieldName][0]['value'] = $value; + $end_value = static::$endDateString; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range start value '{$value}' is invalid for the format '{$fieldFormat}'\n"; + $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); + + $value = static::$startDateString; + $end_value = '2017-03-02'; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range end value '{$end_value}' is invalid for the format '{$fieldFormat}'\n"; + $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - $response = $this->request($method, $url, $request_options); - $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The daterange start value '{$value}' is invalid for the format '{$fieldFormat}'\n"; - $this->assertResourceErrorResponse(422, $message, $response); + $value = '2017-03-01'; + $end_value = '2017-03-02'; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range start value '{$value}' is invalid for the format '{$fieldFormat}'\n{$fieldName}.0: The date range end value '{$end_value}' is invalid for the format '{$fieldFormat}'\n"; + $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); // DX: 422 when date format is incorrect. - $normalization = $this->getNormalizedPostEntity(); + $value = '2017-13-55T20:02:00'; - $normalization[static::$fieldName][0]['value'] = $value; + $end_value = static::$endDateString; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range start value '{$value}' did not parse properly for the format '{$fieldFormat}'\n{$fieldName}.0.value: This value should be of the correct primitive type.\n"; + $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); - $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format); - $response = $this->request($method, $url, $request_options); - $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The daterange start value '{$value}' did not parse properly for the format '{$fieldFormat}'\n{$fieldName}.0.value: This value should be of the correct primitive type.\n"; - $this->assertResourceErrorResponse(422, $message, $response); + $value = static::$startDateString; + $end_value = '2017-13-56T20:02:00'; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range end value '{$end_value}' did not parse properly for the format '{$fieldFormat}'\n{$fieldName}.0.end_value: This value should be of the correct primitive type.\n"; + $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); + + $value = '2017-13-55T20:02:00'; + $end_value = '2017-13-56T20:02:00'; + $message = "Unprocessable Entity: validation failed.\n{$fieldName}.0: The date range start value '{$value}' did not parse properly for the format '{$fieldFormat}'\n{$fieldName}.0: The date range end value '{$end_value}' did not parse properly for the format '{$fieldFormat}'\n{$fieldName}.0.value: This value should be of the correct primitive type.\n{$fieldName}.0.end_value: This value should be of the correct primitive type.\n"; + $this->doEdgeCaseCall($method, $url, $request_options, $value, $end_value, $message); } } @@ -190,11 +202,11 @@ protected function assertNormalizationEdgeCases($method, Url $url, array $reques * @param array $request_options * Request options to apply. * @var mixed $value - * Foo. + * The test start date value. * @var mixed $end_value - * Foo. + * The test end date value. * @var string $message - * Foo. + * The expected error message. */ protected function doEdgeCaseCall($method, Url $url, array $request_options, $value, $end_value, $message) { $normalization = $this->getNormalizedPostEntity();