Commit d87e47cf authored by dww's avatar dww Committed by bojanz

Issue #2514126 by dww, pfrenssen, bojanz, gcb, jespermb, harings_rob,...

Issue #2514126 by dww, pfrenssen, bojanz, gcb, jespermb, harings_rob, jazzdrive3, ryanissamson, heddn, realityloop: Add field settings for global overrides of required/optional behavior
parent 2247fd40
......@@ -102,14 +102,24 @@ field.field_settings.address:
label: 'Available countries'
sequence:
- type: string
langcode_override:
type: string
label: 'Language override'
field_overrides:
type: sequence
label: 'Field overrides'
sequence:
type: mapping
mapping:
override:
type: string
label: 'Override'
# Deprecated, replaced by field_overrides.
fields:
type: sequence
label: 'Used fields'
sequence:
- type: string
langcode_override:
type: string
label: 'Language override'
field.field_settings.address_country:
type: mapping
......
......@@ -3,6 +3,8 @@
namespace Drupal\address\Plugin\Field\FieldType;
use CommerceGuys\Addressing\AddressFormat\AddressField;
use CommerceGuys\Addressing\AddressFormat\FieldOverride;
use CommerceGuys\Addressing\AddressFormat\FieldOverrides;
use Drupal\address\AddressInterface;
use Drupal\address\LabelHelper;
use Drupal\Core\Field\FieldItemBase;
......@@ -136,8 +138,10 @@ class AddressItem extends FieldItemBase implements AddressInterface {
*/
public static function defaultFieldSettings() {
return self::defaultCountrySettings() + [
'fields' => array_values(AddressField::getAll()),
'langcode_override' => '',
'field_overrides' => [],
// Replaced by field_overrides.
'fields' => [],
];
}
......@@ -155,14 +159,6 @@ class AddressItem extends FieldItemBase implements AddressInterface {
}
$element = $this->countrySettingsForm($form, $form_state);
$element['fields'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Used fields'),
'#description' => $this->t('Note: an address used for postal purposes needs all of the above fields.'),
'#default_value' => $this->getSetting('fields'),
'#options' => LabelHelper::getGenericFieldLabels(),
'#required' => TRUE,
];
$element['langcode_override'] = [
'#type' => 'select',
'#title' => $this->t('Language override'),
......@@ -173,9 +169,83 @@ class AddressItem extends FieldItemBase implements AddressInterface {
'#access' => \Drupal::languageManager()->isMultilingual(),
];
$element['field_overrides_title'] = [
'#type' => 'item',
'#title' => $this->t('Field overrides'),
'#description' => $this->t('Use field overrides to override the country-specific address format, forcing specific fields to always be hidden, optional, or required.'),
];
$element['field_overrides'] = [
'#type' => 'table',
'#header' => [
$this->t('Field'),
$this->t('Override'),
],
'#element_validate' => [[get_class($this), 'fieldOverridesValidate']],
];
$field_overrides = $this->getFieldOverrides();
foreach (LabelHelper::getGenericFieldLabels() as $field_name => $label) {
$override = isset($field_overrides[$field_name]) ? $field_overrides[$field_name] : '';
$element['field_overrides'][$field_name] = [
'field_label' => [
'#type' => 'markup',
'#markup' => $label,
],
'override' => [
'#type' => 'select',
'#options' => [
FieldOverride::HIDDEN => t('Hidden'),
FieldOverride::OPTIONAL => t('Optional'),
FieldOverride::REQUIRED => t('Required'),
],
'#default_value' => $override,
'#empty_option' => $this->t('- No override -'),
],
];
}
return $element;
}
/**
* Form element validation handler: Removes empty field overrides.
*
* @param array $element
* The field overrides form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state of the entire form.
*/
public static function fieldOverridesValidate(array $element, FormStateInterface $form_state) {
$overrides = $form_state->getValue($element['#parents']);
$overrides = array_filter($overrides, function ($data) {
return !empty($data['override']);
});
$form_state->setValue($element['#parents'], $overrides);
}
/**
* Gets the field overrides for the current field.
*
* @return array
* FieldOverride constants keyed by AddressField constants.
*/
public function getFieldOverrides() {
$field_overrides = [];
if ($fields = $this->getSetting('fields')) {
$unused_fields = array_diff(AddressField::getAll(), $fields);
foreach ($unused_fields as $field) {
$field_overrides[$field] = FieldOverride::HIDDEN;
}
}
else {
foreach ($this->getSetting('field_overrides') as $field => $data) {
$field_overrides[$field] = $data['override'];
}
}
return $field_overrides;
}
/**
* Initializes and returns the langcode property for the current field.
*
......@@ -226,7 +296,7 @@ class AddressItem extends FieldItemBase implements AddressInterface {
public function getConstraints() {
$constraints = parent::getConstraints();
$constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
$enabled_fields = array_filter($this->getSetting('fields'));
$field_overrides = new FieldOverrides($this->getFieldOverrides());
$constraints[] = $constraint_manager->create('ComplexData', [
'country_code' => [
'Country' => [
......@@ -234,7 +304,7 @@ class AddressItem extends FieldItemBase implements AddressInterface {
],
],
]);
$constraints[] = $constraint_manager->create('AddressFormat', ['fields' => $enabled_fields]);
$constraints[] = $constraint_manager->create('AddressFormat', ['fieldOverrides' => $field_overrides]);
return $constraints;
}
......
......@@ -202,7 +202,7 @@ class AddressDefaultWidget extends WidgetBase implements ContainerFactoryPluginI
'#default_value' => $value,
'#required' => $this->fieldDefinition->isRequired(),
'#available_countries' => $item->getAvailableCountries(),
'#used_fields' => $this->getFieldSetting('fields'),
'#field_overrides' => $item->getFieldOverrides(),
];
return $element;
......
......@@ -308,7 +308,7 @@ class AddressDefaultWidgetTest extends JavascriptTestBase {
}
/**
* Tests expected and disabled fields.
* Tests expected and overridden fields.
*/
public function testFields() {
$field_name = $this->field->getName();
......@@ -350,21 +350,24 @@ class AddressDefaultWidgetTest extends JavascriptTestBase {
$this->assertFieldValues($used_fields, $form_fields, 'Expected fields ' . implode(', ', $used_fields) . ' exists for country ' . $country . ", only found " . implode(', ', $form_fields));
}
// Disable the name and postal code fields.
$disabled_fields = ['givenName', 'familyName', 'postalCode'];
$edit = [];
foreach (array_keys($all_fields) as $field) {
$edit['settings[fields][' . $field . ']'] = !in_array($field, $disabled_fields);
}
// Test field overrides.
$edit = [
'settings[field_overrides][givenName][override]' => 'optional',
'settings[field_overrides][familyName][override]' => 'optional',
'settings[field_overrides][organization][override]' => 'required',
'settings[field_overrides][postalCode][override]' => 'hidden',
];
$this->drupalGet($this->fieldConfigUrl);
$this->submitForm($edit, t('Save settings'));
$this->assertSession()->statusCodeEquals(200);
// Confirm the absence of disabled fields.
$this->drupalGet($this->nodeAddUrl);
$this->assertEmpty((bool) $this->xpath('//input[@name="' . implode('" or @name="', $disabled_fields) . '"]'), 'Disabled fields ' . implode(', ', $disabled_fields) . ' are absent.');
$this->assertEmpty((bool) $this->xpath('//input[@name="field_address[0][address][given_name]" and contains(@required, "required")]'));
$this->assertEmpty((bool) $this->xpath('//input[@name="field_address[0][address][family_name]" and contains(@required, "required")]'));
$this->assertNotEmpty((bool) $this->xpath('//input[@name="field_address[0][address][organization]" and contains(@required, "required")]'));
$this->assertEmpty((bool) $this->xpath('//input[@name="field_address[0][address][postal_code]"]'));
// Confirm that creating an address without the disabled fields works.
// Test creating an address without the optional and hidden fields.
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName(8);
......
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