Skip to content
Snippets Groups Projects
Commit b2fc6e1a authored by dpi's avatar dpi
Browse files

Issue #3030603 by dpi, vidorado, kevinc_, acbramley, drenton, codebymikey:...

Issue #3030603 by dpi, vidorado, kevinc_, acbramley, drenton, codebymikey: Allow partially-invalid field value defaults
parent aeaa9da8
No related branches found
Tags 8.x-2.10
No related merge requests found
......@@ -7,7 +7,10 @@ field.value.date_recur:
label: 'A time zone identifier used for default start and/or end dates.'
default_time_zone:
type: string
label: 'A time zone identifier used as default value for time zone. If empty, current user time zone should be used.'
label: 'A time zone identifier used as default value for time zone.'
default_time_zone_source:
type: string
label: 'Determine where to get the time zone: the sibling `default_time_zone` with `fixed`, or the current user time zone with `current_user`.'
default_rrule:
type: string
label: 'Default RRULE'
......
......@@ -14,6 +14,7 @@ use Drupal\Core\Entity\Sql\SqlEntityStorageInterface;
use Drupal\Core\Utility\UpdateException;
use Drupal\date_recur\Entity\DateRecurInterpreter;
use Drupal\date_recur\Plugin\Field\FieldWidget\DateRecurBasicWidget;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
/**
......@@ -325,3 +326,40 @@ function date_recur_update_8206(&$sandbox): void {
}
}
}
/**
* Updates default time zone configuration.
*/
function date_recur_update_8207(&$sandbox): void {
/** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager */
$entityFieldManager = \Drupal::service('entity_field.manager');
$entityFieldMap = $entityFieldManager->getFieldMapByFieldType('date_recur');
// Iterate over all date_recur fields for all entity types.
/** @var \Drupal\Core\Field\FieldConfigInterface[] $drFields */
$drFields = [];
foreach ($entityFieldMap as $entityTypeId => $fields) {
foreach ($fields as $fieldName => ['bundles' => $bundles]) {
foreach ($bundles as $bundle) {
$field = FieldConfig::loadByName($entityTypeId, $bundle, $fieldName);
if ($field) {
array_push($drFields, $field);
}
}
}
}
foreach ($drFields as $fieldConfig) {
$defaultValue = $fieldConfig->getDefaultValueLiteral();
// Skip if the whole value is empty.
if (empty($defaultValue)) {
continue;
}
$defaultValue[0]['default_time_zone_source'] = !empty($defaultValue[0]['default_time_zone'])
? 'fixed'
: 'current_user';
$fieldConfig->setDefaultValue($defaultValue);
$fieldConfig->save();
}
}
......@@ -28,6 +28,16 @@ class DateRecurFieldItemList extends DateRangeFieldItemList {
*/
protected ?EventDispatcherInterface $eventDispatcher = NULL;
/**
* Value for 'default_time_zone_source' to get time zone from a fixed string.
*/
public const DEFAULT_TIME_ZONE_SOURCE_FIXED = 'fixed';
/**
* Value for 'default_time_zone_source' to get current users time zone.
*/
public const DEFAULT_TIME_ZONE_SOURCE_CURRENT_USER = 'current_user';
/**
* {@inheritdoc}
*/
......@@ -94,13 +104,20 @@ class DateRecurFieldItemList extends DateRangeFieldItemList {
],
];
$defaultTimeZoneSource = $defaultValue[0]['default_time_zone_source'] ?? NULL;
$defaultTimeZone = $defaultTimeZoneSource === 'current_user'
? 'current_user'
: $defaultValue[0]['default_time_zone'] ?? '';
$element['default_time_zone'] = [
'#type' => 'select',
'#title' => $this->t('Time zone'),
'#description' => $this->t('Default time zone.'),
'#options' => $this->getTimeZoneOptions(),
'#default_value' => $defaultValue[0]['default_time_zone'] ?? '',
'#empty_option' => $this->t('- Current user time zone -'),
'#options' => [
'current_user' => $this->t('- Current user time zone -'),
] + $this->getTimeZoneOptions(),
'#default_value' => $defaultTimeZone,
'#empty_option' => $this->t('- None -'),
];
$element['default_rrule'] = [
......@@ -156,7 +173,13 @@ class DateRecurFieldItemList extends DateRangeFieldItemList {
// @codingStandardsIgnoreLine
$defaultTimeZone = $form_state->getValue(['default_value_input', 'default_time_zone']);
if ($defaultTimeZone) {
$values[0]['default_time_zone'] = $defaultTimeZone;
if ($defaultTimeZone === 'current_user') {
$values[0]['default_time_zone_source'] = 'current_user';
}
else {
$values[0]['default_time_zone_source'] = 'fixed';
$values[0]['default_time_zone'] = $defaultTimeZone;
}
}
return $values;
......@@ -204,17 +227,18 @@ class DateRecurFieldItemList extends DateRangeFieldItemList {
$defaultValue[0]['rrule'] = $rrule;
}
$defaultTimeZone = $default_value[0]['default_time_zone'] ?? NULL;
if (!empty($defaultTimeZone)) {
$defaultValue[0]['timezone'] = $defaultTimeZone;
$timeZoneSource = $default_value[0]['default_time_zone_source'] ?? NULL;
if ($timeZoneSource === static::DEFAULT_TIME_ZONE_SOURCE_FIXED) {
$defaultValue[0]['timezone'] = $default_value[0]['default_time_zone'];
}
else {
elseif ($timeZoneSource === static::DEFAULT_TIME_ZONE_SOURCE_CURRENT_USER) {
$timeZone = \date_default_timezone_get();
!empty($timeZone) ?: throw new \Exception('Something went wrong. User has no time zone.');
$defaultValue[0]['timezone'] = $timeZone;
}
unset($defaultValue[0]['default_time_zone']);
unset($defaultValue[0]['default_time_zone_source']);
unset($defaultValue[0]['default_rrule']);
return $defaultValue;
}
......
......@@ -19,6 +19,7 @@ use Drupal\date_recur\DateRecurRruleMap;
use Drupal\date_recur\Exception\DateRecurHelperArgumentException;
use Drupal\date_recur\Plugin\Field\DateRecurDateTimeComputed;
use Drupal\date_recur\Plugin\Field\DateRecurOccurrencesComputed;
use Drupal\date_recur\Plugin\Validation\Constraint\DateRecurTimeZoneConstraint;
use Drupal\datetime_range\Plugin\Field\FieldType\DateRangeItem;
/**
......@@ -102,7 +103,7 @@ class DateRecurItem extends DateRangeItem {
$properties['timezone'] = DataDefinition::create('string')
->setLabel((string) new TranslatableMarkup('Timezone'))
->setRequired(TRUE)
->addConstraint('DateRecurTimeZone');
->addConstraint(DateRecurTimeZoneConstraint::PLUGIN_ID);
$properties['infinite'] = DataDefinition::create('boolean')
->setLabel((string) new TranslatableMarkup('Whether the RRule is an infinite rule. Derived value from RRULE.'))
......@@ -459,10 +460,8 @@ class DateRecurItem extends DateRangeItem {
$start_value = $this->get('value')->getValue();
$end_value = $this->get('end_value')->getValue();
return (
// Use OR operator instead of AND from parent. See
// https://www.drupal.org/project/drupal/issues/3025812
($start_value === NULL || $start_value === '') ||
($end_value === NULL || $end_value === '') ||
($start_value === NULL || $start_value === '') &&
($end_value === NULL || $end_value === '') &&
empty($this->get('timezone')->getValue())
);
}
......
......@@ -73,6 +73,9 @@ class DateRecurBasicWidget extends DateRangeDefaultWidget {
// @codingStandardsIgnoreLine
$element['value']['#value_callback'] = $element['end_value']['#value_callback'] = [$this, 'dateValueCallback'];
// Replace \Datetime::validateDatetime validator with our own.
$element['value']['#element_validate'] = $element['end_value']['#element_validate'] = [[$this, 'validateDatetime']];
// Saved values (should) always have a time zone.
$timeZone = $items[$delta]->timezone ?? NULL;
......@@ -113,13 +116,14 @@ class DateRecurBasicWidget extends DateRangeDefaultWidget {
* @return array
* The value to assign to the element.
*/
public function dateValueCallback(array $element, $input, FormStateInterface $form_state): array {
public function dateValueCallback(array &$element, $input, FormStateInterface $form_state): array {
if ($input !== FALSE) {
$timeZonePath = array_slice($element['#parents'], 0, -1);
$timeZonePath[] = 'timezone';
// Warning: The time zone is not yet validated, make sure it is valid
// before using.
/** @var string|null $submittedTimeZone */
$submittedTimeZone = NestedArray::getValue($form_state->getUserInput(), $timeZonePath);
if (!isset($submittedTimeZone)) {
// If no time zone was submitted, such as when the 'timezone' field is
......@@ -138,9 +142,16 @@ class DateRecurBasicWidget extends DateRangeDefaultWidget {
// Need to kill inputs otherwise
// \Drupal\Core\Datetime\Element\Datetime::validateDatetime thinks there
// is valid input.
// Indicate to validator the value could not be built since time zone
// was invalid combined with a provided non-empty start or end date.
// This key/value is internal and may be modified at any time.
$element['#date_recur_basic_widget__invalid_timezone'] = TRUE;
return [
'date' => '',
'time' => '',
// Restore the inputs' previous values.
'date' => $input['date'],
'time' => $input['time'],
// Marking object as NULL indicates this field is invalid, see
// \Drupal\Core\Datetime\Element\Datetime::processDatetime.
'object' => NULL,
];
}
......@@ -153,6 +164,36 @@ class DateRecurBasicWidget extends DateRangeDefaultWidget {
return Datetime::valueCallback($element, $input, $form_state);
}
/**
* Validates start and end date field.
*
* If a time zone was not provided then its not necessary to validate start
* and end date values if they are non-empty.
*
* @param array $element
* An associative array containing the properties and children of the
* generic form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param array $complete_form
* The complete form structure.
*/
public function validateDatetime(array &$element, FormStateInterface $form_state, array &$complete_form): void {
$input_exists = FALSE;
$input = NestedArray::getValue($form_state->getValues(), $element['#parents'], $input_exists);
if ($input_exists) {
if ((!empty($input['date']) || !empty($input['time'])) && isset($element['#date_recur_basic_widget__invalid_timezone'])) {
$timeZoneFieldPath = array_slice($element['#array_parents'], 0, -1);
$timeZoneFieldPath[] = 'timezone';
$timeZoneField = NestedArray::getValue($form_state->getCompleteForm(), $timeZoneFieldPath);
$form_state->setError($timeZoneField, $this->t('Missing time zone for date.'));
return;
}
}
Datetime::validateDatetime($element, $form_state, $complete_form);
}
/**
* Validates RRULE and first occurrence dates.
*
......
......@@ -10,13 +10,18 @@ use Symfony\Component\Validator\Constraint;
* Checks the time zone is a recognized zone.
*
* @Constraint(
* id = "DateRecurTimeZone",
* id = \Drupal\date_recur\Plugin\Validation\Constraint\DateRecurTimeZoneConstraint::PLUGIN_ID,
* label = @Translation("Valid Time Zone", context = "Validation"),
* type = "string"
* )
*/
class DateRecurTimeZoneConstraint extends Constraint {
/**
* The plugin ID.
*/
public const PLUGIN_ID = 'DateRecurTimeZone';
/**
* Violation message for an invalid time zone.
*
......
......@@ -4,6 +4,7 @@ namespace Drupal\Tests\date_recur\Functional;
use Drupal\Core\Field\Entity\BaseFieldOverride;
use Drupal\Core\Url;
use Drupal\date_recur\Plugin\Field\FieldType\DateRecurFieldItemList;
use Drupal\date_recur\Plugin\Field\FieldType\DateRecurItem;
use Drupal\date_recur_entity_test\Entity\DrEntityTest;
use Drupal\field\Entity\FieldConfig;
......@@ -150,94 +151,268 @@ class DateRecurBasicWidgetTest extends BrowserTestBase {
}
/**
* Tests inherited validation.
* Tests form field submission.
*
* Tests validation that comes automatically from date range. Specifically,
* assert end date comes on or after start date.
* Tests simple form success and failure without testing the saved entity.
*
* @param array $edit
* Form field values.
* @param bool $isSuccess
* Whether submitting the form results in success.
* @param string|null $errorMessage
* The the form submission results in failure, assert the error message.
*
* @dataProvider providerFields
*/
public function testInheritedValidation() {
$edit = [
'dr[0][value][date]' => '2008-06-17',
'dr[0][value][time]' => '03:00:00',
'dr[0][end_value][date]' => '2008-06-15',
'dr[0][end_value][time]' => '03:00:00',
'dr[0][timezone]' => 'America/Chicago',
'dr[0][rrule]' => 'FREQ=DAILY',
];
public function testFields(array $edit, bool $isSuccess, ?string $errorMessage = NULL) {
$this->drupalGet(Url::fromRoute('entity.dr_entity_test.add_form'));
$this->submitForm($edit, 'Save');
$this->assertSession()->pageTextContains('end date cannot be before the start date');
if ($isSuccess) {
$this->assertSession()->pageTextContains('dr_entity_test 1 has been created.');
}
else {
$this->assertSession()->pageTextNotContains('dr_entity_test 1 has been created.');
$this->assertSession()->pageTextContains($errorMessage);
}
}
/**
* Tests start date must be set if end date is set.
* Data provider for testFields.
*
* @return array
* Data for testing.
*/
public function testStartDateSetIfEndPosted() {
$edit = [
'dr[0][value][date]' => '',
'dr[0][value][time]' => '',
'dr[0][end_value][date]' => '2008-06-17',
'dr[0][end_value][time]' => '12:00:04',
'dr[0][timezone]' => 'America/Chicago',
'dr[0][rrule]' => 'FREQ=DAILY',
public function providerFields(): array {
$scenarios = [];
$scenarios['Test no failures if nothing is filled.'] = [
[
'dr[0][value][date]' => '',
'dr[0][value][time]' => '',
'dr[0][end_value][date]' => '',
'dr[0][end_value][time]' => '',
'dr[0][timezone]' => '',
'dr[0][rrule]' => '',
],
TRUE,
];
$this->drupalGet(Url::fromRoute('entity.dr_entity_test.add_form'));
$this->submitForm($edit, 'Save');
$this->assertSession()->pageTextContains('Start date must be set if end date is set.');
$scenarios['Test failure when only start date field filled.'] = [
[
'dr[0][value][date]' => '2008-06-17',
'dr[0][value][time]' => '',
'dr[0][end_value][date]' => '',
'dr[0][end_value][time]' => '',
'dr[0][timezone]' => '',
'dr[0][rrule]' => '',
],
FALSE,
'Missing time zone for date.',
];
$scenarios['Test failure when only start time field filled.'] = [
[
'dr[0][value][date]' => '',
'dr[0][value][time]' => '10:00:00',
'dr[0][end_value][date]' => '',
'dr[0][end_value][time]' => '',
'dr[0][timezone]' => '',
'dr[0][rrule]' => '',
],
FALSE,
'Missing time zone for date.',
];
$scenarios['Test failure when start date and time field filled.'] = [
[
'dr[0][value][date]' => '2008-06-17',
'dr[0][value][time]' => '10:00:00',
'dr[0][end_value][date]' => '',
'dr[0][end_value][time]' => '',
'dr[0][timezone]' => '',
'dr[0][rrule]' => '',
],
FALSE,
'Missing time zone for date.',
];
$scenarios['Test failure when end date filled.'] = [
[
'dr[0][value][date]' => '',
'dr[0][value][time]' => '',
'dr[0][end_value][date]' => '2008-06-17',
'dr[0][end_value][time]' => '',
'dr[0][timezone]' => '',
'dr[0][rrule]' => '',
],
FALSE,
'Missing time zone for date.',
];
$scenarios['Test failure when end time filled.'] = [
[
'dr[0][value][date]' => '',
'dr[0][value][time]' => '',
'dr[0][end_value][date]' => '',
'dr[0][end_value][time]' => '10:00:00',
'dr[0][timezone]' => '',
'dr[0][rrule]' => '',
],
FALSE,
'Missing time zone for date.',
];
$scenarios['Test success when start date and time and time zone field filled.'] = [
[
'dr[0][value][date]' => '2008-06-17',
'dr[0][value][time]' => '10:00:00',
'dr[0][end_value][date]' => '',
'dr[0][end_value][time]' => '',
'dr[0][timezone]' => 'Australia/Sydney',
'dr[0][rrule]' => '',
],
TRUE,
];
$scenarios['Test failure when end date and time and time zone field filled.'] = [
[
'dr[0][value][date]' => '',
'dr[0][value][time]' => '',
'dr[0][end_value][date]' => '2008-06-17',
'dr[0][end_value][time]' => '10:00:00',
'dr[0][timezone]' => 'Australia/Sydney',
'dr[0][rrule]' => '',
],
FALSE,
'Start date must be set if end date is set.',
];
$scenarios['Tests failure on invalid rule.'] = [
[
'dr[0][value][date]' => '2008-06-17',
'dr[0][value][time]' => '12:00:00',
'dr[0][end_value][date]' => '2008-06-17',
'dr[0][end_value][time]' => '12:00:00',
'dr[0][timezone]' => 'America/Chicago',
'dr[0][rrule]' => $this->randomMachineName(),
],
FALSE,
'Repeat rule is formatted incorrectly.',
];
// Tests validation that comes automatically from date range. Specifically,
// assert end date comes on or after start date.
$scenarios['Tests inherited validation: end before start'] = [
[
'dr[0][value][date]' => '2008-06-17',
'dr[0][value][time]' => '03:00:00',
'dr[0][end_value][date]' => '2008-06-15',
'dr[0][end_value][time]' => '03:00:00',
'dr[0][timezone]' => 'America/Chicago',
'dr[0][rrule]' => 'FREQ=DAILY',
],
FALSE,
'end date cannot be before the start date',
];
return $scenarios;
}
/**
* Tests default values appear in widget.
*
* @dataProvider providerDefaultValues
*/
public function testDefaultValues() {
public function testDefaultValues(array $baseFieldValue, array $assertFieldValues) {
/** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager */
$entityFieldManager = \Drupal::service('entity_field.manager');
$baseFields = $entityFieldManager->getBaseFieldDefinitions('dr_entity_test');
$baseFieldOverride = BaseFieldOverride::createFromBaseFieldDefinition($baseFields['dr'], 'dr_entity_test');
// Default values need to evaluate FALSE per DateRecurItem::isEmpty
// otherwise the values will be cleared out before display.
$baseFieldOverride->setDefaultValue([
[
'default_date_type' => 'relative',
'default_date' => '12th April 2013 3pm',
'default_end_date_type' => 'relative',
'default_end_date' => '12th April 2013 4pm',
'default_date_time_zone' => 'Europe/Oslo',
'default_time_zone' => 'Indian/Christmas',
'default_rrule' => 'FREQ=WEEKLY;COUNT=995',
],
]);
$baseFieldOverride->setDefaultValue($baseFieldValue);
$baseFieldOverride->save();
$url = Url::fromRoute('entity.dr_entity_test.add_form');
$this->drupalGet($url);
// 3pm/4pm Oslo (UTC+2) -> 8pm/9pm Christmas (UTC+7).
$this->assertSession()->fieldValueEquals('dr[0][value][date]', '2013-04-12');
$this->assertSession()->fieldValueEquals('dr[0][value][time]', '20:00:00');
$this->assertSession()->fieldValueEquals('dr[0][end_value][date]', '2013-04-12');
$this->assertSession()->fieldValueEquals('dr[0][end_value][time]', '21:00:00');
$this->assertSession()->fieldValueEquals('dr[0][timezone]', 'Indian/Christmas');
$this->assertSession()->fieldValueEquals('dr[0][rrule]', 'FREQ=WEEKLY;COUNT=995');
foreach ($assertFieldValues as [$fieldName, $fieldValue]) {
$this->assertSession()->fieldValueEquals($fieldName, $fieldValue);
}
}
/**
* Tests invalid rule.
* Data provider for testFields.
*
* @return array
* Data for testing.
*/
public function testInvalidRule() {
$edit = [
'dr[0][value][date]' => '2008-06-17',
'dr[0][value][time]' => '12:00:00',
'dr[0][end_value][date]' => '2008-06-17',
'dr[0][end_value][time]' => '12:00:00',
'dr[0][timezone]' => 'America/Chicago',
'dr[0][rrule]' => $this->randomMachineName(),
public function providerDefaultValues(): array {
$scenarios = [];
$scenarios['all values'] = [
// 3pm/4pm Oslo (UTC+2) -> 8pm/9pm Christmas (UTC+7).
[
[
'default_date_type' => 'relative',
'default_date' => '12th April 2013 3pm',
'default_end_date_type' => 'relative',
'default_end_date' => '12th April 2013 4pm',
'default_date_time_zone' => 'Europe/Oslo',
'default_time_zone' => 'Indian/Christmas',
'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
'default_rrule' => 'FREQ=WEEKLY;COUNT=995',
],
],
[
['dr[0][value][date]', '2013-04-12'],
['dr[0][value][time]', '20:00:00'],
['dr[0][end_value][date]', '2013-04-12'],
['dr[0][end_value][time]', '21:00:00'],
['dr[0][timezone]', 'Indian/Christmas'],
['dr[0][rrule]', 'FREQ=WEEKLY;COUNT=995'],
],
];
$this->drupalGet(Url::fromRoute('entity.dr_entity_test.add_form'));
$this->submitForm($edit, 'Save');
$this->assertSession()->pageTextContains('Repeat rule is formatted incorrectly.');
$scenarios['only time zone'] = [
[
[
'default_time_zone' => 'Indian/Christmas',
'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
],
],
[
['dr[0][value][date]', ''],
['dr[0][value][time]', ''],
['dr[0][end_value][date]', ''],
['dr[0][end_value][time]', ''],
['dr[0][timezone]', 'Indian/Christmas'],
['dr[0][rrule]', ''],
],
];
$scenarios['only start'] = [
[
[
'default_date_type' => 'relative',
'default_date' => '12th April 2013 3pm',
'default_date_time_zone' => 'Europe/Oslo',
'default_time_zone' => 'Indian/Christmas',
'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
],
],
[
['dr[0][value][date]', '2013-04-12'],
['dr[0][value][time]', '20:00:00'],
['dr[0][end_value][date]', ''],
['dr[0][end_value][time]', ''],
['dr[0][timezone]', 'Indian/Christmas'],
['dr[0][rrule]', ''],
],
];
return $scenarios;
}
/**
......@@ -290,11 +465,23 @@ class DateRecurBasicWidgetTest extends BrowserTestBase {
}
/**
* Tests if field is set to required, only start date is required.
* Tests if time zone is programmatically hidden, default value is used.
*
* End date must never be required, value is copied over from start date.
* Field default time zone will be populated behind the scenes..
*/
public function testHiddenTimeZoneField() {
/** @var \Drupal\Core\Entity\EntityFieldManagerInterface $entityFieldManager */
$entityFieldManager = \Drupal::service('entity_field.manager');
$baseFields = $entityFieldManager->getBaseFieldDefinitions('dr_entity_test');
$baseFieldOverride = BaseFieldOverride::createFromBaseFieldDefinition($baseFields['dr'], 'dr_entity_test');
$baseFieldOverride->setDefaultValue([
[
'default_time_zone' => 'Asia/Singapore',
'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
],
]);
$baseFieldOverride->save();
\Drupal::state()->set('DATE_RECUR_BASIC_WIDGET_TEST_HIDDEN_TIMEZONE_FIELD_HOOK_FORM_ALTER', TRUE);
$this->drupalGet(Url::fromRoute('entity.dr_entity_test.add_form'));
......@@ -305,7 +492,7 @@ class DateRecurBasicWidgetTest extends BrowserTestBase {
$this->assertSession()->fieldExists('dr[0][rrule]');
$edit = [
// No time zone here.
// No time zone here, but the time zone is set from field defaults.
'dr[0][value][date]' => '2008-06-17',
'dr[0][value][time]' => '12:00:00',
'dr[0][end_value][date]' => '2008-06-17',
......@@ -317,6 +504,15 @@ class DateRecurBasicWidgetTest extends BrowserTestBase {
// The form would previously would not submit, an error was displayed.
$this->assertSession()->pageTextContains('dr_entity_test 1 has been created.');
$entity = $this->getLastSavedDrEntityTest();
$this->assertEquals([
'value' => '2008-06-17T04:00:00',
'end_value' => '2008-06-17T04:00:00',
'rrule' => 'FREQ=DAILY;COUNT=10',
'timezone' => 'Asia/Singapore',
'infinite' => FALSE,
], $entity->dr[0]->toArray());
}
/**
......
......@@ -3,6 +3,7 @@
namespace Drupal\Tests\date_recur\Kernel;
use Drupal\Core\Field\Entity\BaseFieldOverride;
use Drupal\date_recur\Plugin\Field\FieldType\DateRecurFieldItemList;
use Drupal\date_recur_entity_test\Entity\DrEntityTest;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
......@@ -76,6 +77,7 @@ class DateRecurFieldItemDefaultValuesTest extends KernelTestBase {
'default_end_date' => '12th April 2013 4pm',
'default_date_time_zone' => 'Europe/Oslo',
'default_time_zone' => 'Indian/Christmas',
'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_FIXED,
'default_rrule' => 'FREQ=DAILY;COUNT=100',
],
]);
......@@ -104,6 +106,7 @@ class DateRecurFieldItemDefaultValuesTest extends KernelTestBase {
'default_end_date' => '12th April 2013 4pm',
'default_date_time_zone' => 'Europe/Oslo',
'default_time_zone' => '',
'default_time_zone_source' => DateRecurFieldItemList::DEFAULT_TIME_ZONE_SOURCE_CURRENT_USER,
],
]);
$this->baseFieldOverride->save();
......
......@@ -2,6 +2,7 @@
namespace Drupal\Tests\date_recur\Kernel;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\date_recur\Exception\DateRecurHelperArgumentException;
use Drupal\date_recur\Plugin\Field\FieldType\DateRecurItem;
use Drupal\date_recur_entity_test\Entity\DrEntityTest;
......@@ -264,7 +265,9 @@ class DateRecurFieldItemTest extends KernelTestBase {
}
/**
* Tests value is emptied if time zone is empty.
* Tests error if time zone is empty when saving programmatically.
*
* Either use validate() before save and fix errors or set correct time zone.
*/
public function testNoTimeZone() {
$entity = DrEntityTest::create();
......@@ -276,13 +279,15 @@ class DateRecurFieldItemTest extends KernelTestBase {
],
];
// After saving, empty/invalid values are emptied.
$this->expectException(EntityStorageException::class);
$this->expectExceptionMessage("Integrity constraint violation: 1048 Column 'dr_timezone' cannot be null");
$entity->save();
$this->assertEquals(0, $entity->dr->count());
}
/**
* Tests value is emptied if start is empty.
* Tests error if start is empty when saving programmatically.
*
* Either use validate() before or use correct value.
*/
public function testMissingStart() {
$entity = DrEntityTest::create();
......@@ -293,13 +298,15 @@ class DateRecurFieldItemTest extends KernelTestBase {
],
];
// After saving, empty/invalid values are emptied.
$this->expectException(EntityStorageException::class);
$this->expectExceptionMessage("Integrity constraint violation: 1048 Column 'dr_value' cannot be null");
$entity->save();
$this->assertEquals(0, $entity->dr->count());
}
/**
* Tests value is emptied if end is empty.
* Tests error if end is empty when saving programmatically.
*
* Either use validate() before or use correct value.
*/
public function testMissingEnd() {
$entity = DrEntityTest::create();
......@@ -310,9 +317,9 @@ class DateRecurFieldItemTest extends KernelTestBase {
],
];
// After saving, empty/invalid values are emptied.
$this->expectException(EntityStorageException::class);
$this->expectExceptionMessage("Integrity constraint violation: 1048 Column 'dr_end_value' cannot be null");
$entity->save();
$this->assertEquals(0, $entity->dr->count());
}
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment