Commit 251c1460 authored by bojanz's avatar bojanz
Browse files

Issue #2908575 by bojanz: Crash when there's only one available country + another one

parent 35fdda5b
......@@ -74,19 +74,15 @@ class Address extends FormElement {
}
/**
* {@inheritdoc}
* Ensures all keys are set on the provided value.
*
* @param array $value
* The value.
*
* @return array
* The modified value.
*/
public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
if (is_array($input)) {
$value = $input;
}
else {
if (!is_array($element['#default_value'])) {
$element['#default_value'] = [];
}
$value = $element['#default_value'];
}
// Initialize default keys.
public static function applyDefaults(array $value) {
$properties = [
'given_name', 'additional_name', 'family_name', 'organization',
'address_line1', 'address_line2', 'postal_code', 'sorting_code',
......@@ -102,6 +98,24 @@ class Address extends FormElement {
return $value;
}
/**
* {@inheritdoc}
*/
public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
// Ensure both the default value and the input have all keys set.
// Preselect the default country to ensure it's present in the value.
if (is_array($input)) {
$input = self::applyDefaults($input);
}
$element['#default_value'] = (array) $element['#default_value'];
$element['#default_value'] = self::applyDefaults($element['#default_value']);
if (empty($element['#default_value']['country_code']) && $element['#required']) {
$element['#default_value']['country_code'] = Country::getDefaultCountry($element['#available_countries']);
}
return is_array($input) ? $input : $element['#default_value'];
}
/**
* Processes the address form element.
*
......@@ -124,11 +138,8 @@ class Address extends FormElement {
}
$id_prefix = implode('-', $element['#parents']);
$wrapper_id = Html::getUniqueId($id_prefix . '-ajax-wrapper');
// The #value has the new values on #ajax, the #default_value otherwise.
$value = $element['#value'];
if (empty($value['country_code']) && $element['#required']) {
// Preselect the default country so that the other elements can be shown.
$value['country_code'] = Country::getDefaultCountry($element['#available_countries']);
}
$element = [
'#tree' => TRUE,
......@@ -145,7 +156,7 @@ class Address extends FormElement {
'#type' => 'address_country',
'#title' => t('Country'),
'#available_countries' => $element['#available_countries'],
'#default_value' => $value['country_code'],
'#default_value' => $element['#default_value']['country_code'],
'#required' => $element['#required'],
'#limit_validation_errors' => [],
'#ajax' => [
......
......@@ -60,19 +60,15 @@ class Zone extends FormElement {
}
/**
* {@inheritdoc}
* Ensures all keys are set on the provided value.
*
* @param array $value
* The value.
*
* @return array
* The modified value.
*/
public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
if (is_array($input)) {
$value = $input;
}
else {
if (!is_array($element['#default_value'])) {
$element['#default_value'] = [];
}
$value = $element['#default_value'];
}
// Initialize default keys.
public static function applyDefaults(array $value) {
foreach (['label', 'territories'] as $property) {
if (!isset($value[$property])) {
$value[$property] = NULL;
......@@ -82,6 +78,21 @@ class Zone extends FormElement {
return $value;
}
/**
* {@inheritdoc}
*/
public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
// Ensure both the default value and the input have all keys set.
// Preselect the default country to ensure it's present in the value.
if (is_array($input)) {
$input = self::applyDefaults($input);
}
$element['#default_value'] = (array) $element['#default_value'];
$element['#default_value'] = self::applyDefaults($element['#default_value']);
return is_array($input) ? $input : $element['#default_value'];
}
/**
* Processes the zone form element.
*
......
......@@ -213,7 +213,7 @@ class AddressDefaultWidgetTest extends JavascriptTestBase {
$this->assertNotEmpty($node, 'Created article ' . $edit['title[0][value]']);
// Now remove 'US' from the list of available countries.
$countries = ['FR', 'BR', 'JP'];
$countries = ['FR'];
$edit = [];
$edit['settings[available_countries][]'] = array_map(function ($country) {
return $country;
......@@ -232,6 +232,13 @@ class AddressDefaultWidgetTest extends JavascriptTestBase {
$this->assertOptionSelected($field_name . '[0][address][administrative_area]', $address['administrative_area']);
$this->assertSession()->fieldValueEquals($field_name . '[0][address][postal_code]', $address['postal_code']);
$this->assertOptionSelected($field_name . '[0][address][country_code]', $country_code);
// Confirm that it is possible to switch the country to France, and back.
$this->getSession()->getPage()->fillField($field_name . '[0][address][country_code]', 'FR');
$this->waitForAjaxToFinish();
$this->assertSession()->fieldNotExists($field_name . '[0][address][administrative_area]');
$this->getSession()->getPage()->fillField($field_name . '[0][address][country_code]', 'US');
$this->waitForAjaxToFinish();
$this->assertSession()->fieldExists($field_name . '[0][address][administrative_area]');
// Test the widget with only one available country.
// Since the field is required, the country selector should be hidden.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment