Commit 9ce9eba3 authored by bojanz's avatar bojanz
Browse files

Issue #2974105 by bojanz: Update the Address element and AddressFormatConstraint for FieldOverrides

parent d79ce69b
......@@ -5,6 +5,8 @@ namespace Drupal\address\Element;
use CommerceGuys\Addressing\AddressFormat\AddressField;
use CommerceGuys\Addressing\AddressFormat\AddressFormat;
use CommerceGuys\Addressing\AddressFormat\AddressFormatHelper;
use CommerceGuys\Addressing\AddressFormat\FieldOverride;
use CommerceGuys\Addressing\AddressFormat\FieldOverrides;
use CommerceGuys\Addressing\Locale;
use Drupal\address\FieldHelper;
use Drupal\address\LabelHelper;
......@@ -18,6 +20,9 @@ use Drupal\Core\Render\Element\FormElement;
/**
* Provides an address form element.
*
* Use #field_overrides to override the country-specific address format,
* forcing specific fields to be hidden, optional, or required.
*
* Usage example:
* @code
* $form['address'] = [
......@@ -33,6 +38,11 @@ use Drupal\Core\Render\Element\FormElement;
* 'country_code' => 'US',
* 'langcode' => 'en',
* ],
* '@field_overrides' => [
* AddressField::ORGANIZATION => FieldOverride::REQUIRED,
* AddressField::ADDRESS_LINE2 => FieldOverride::HIDDEN,
* AddressField::POSTAL_CODE => FieldOverride::OPTIONAL,
* ],
* '#available_countries' => ['DE', 'FR'],
* ];
* @endcode
......@@ -49,7 +59,9 @@ class Address extends FormElement {
return [
// List of country codes. If empty, all countries will be available.
'#available_countries' => [],
// List of AddressField constants. If empty, all fields will be used.
// FieldOverride constants keyed by AddressField constants.
'#field_overrides' => [],
// Deprecated. Use #field_overrides instead.
'#used_fields' => [],
'#input' => TRUE,
......@@ -136,9 +148,21 @@ class Address extends FormElement {
* Thrown when #used_fields is malformed.
*/
public static function processAddress(array &$element, FormStateInterface $form_state, array &$complete_form) {
if (isset($element['#used_fields']) && !is_array($element['#used_fields'])) {
throw new \InvalidArgumentException('The #used_fields property must be an array.');
// Convert #used_fields into #field_overrides.
if (!empty($element['#used_fields']) && is_array($element['#used_fields'])) {
$unused_fields = array_diff(AddressField::getAll(), $element['#used_fields']);
$element['#field_overrides'] = [];
foreach ($unused_fields as $field) {
$element['#field_overrides'][$field] = FieldOverride::HIDDEN;
}
unset($element['#used_fields']);
}
// Validate and parse #field_overrides.
if (!is_array($element['#field_overrides'])) {
throw new \InvalidArgumentException('The #field_overrides property must be an array.');
}
$element['#parsed_field_overrides'] = new FieldOverrides($element['#field_overrides']);
$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.
......@@ -197,9 +221,10 @@ class Address extends FormElement {
AddressField::ADDITIONAL_NAME => 25,
AddressField::FAMILY_NAME => 25,
];
$field_overrides = $element['#parsed_field_overrides'];
/** @var \CommerceGuys\Addressing\AddressFormat\AddressFormat $address_format */
$address_format = \Drupal::service('address.address_format_repository')->get($value['country_code']);
$required_fields = $address_format->getRequiredFields();
$required_fields = AddressFormatHelper::getRequiredFields($address_format, $field_overrides);
$labels = LabelHelper::getFieldLabels($address_format);
$locale = \Drupal::languageManager()->getConfigOverrideLanguage()->getId();
if (Locale::matchCandidates($address_format->getLocale(), $locale)) {
......@@ -208,7 +233,7 @@ class Address extends FormElement {
else {
$format_string = $address_format->getFormat();
}
$grouped_fields = AddressFormatHelper::getGroupedFields($format_string);
$grouped_fields = AddressFormatHelper::getGroupedFields($format_string, $field_overrides);
foreach ($grouped_fields as $line_index => $line_fields) {
if (count($line_fields) > 1) {
// Used by the #pre_render callback to group fields inline.
......@@ -244,15 +269,6 @@ class Address extends FormElement {
if (isset($element['address_line2'])) {
$element['address_line2']['#title_display'] = 'invisible';
}
// Hide unused fields.
if (!empty($element['#used_fields'])) {
$used_fields = $element['#used_fields'];
$unused_fields = array_diff(AddressField::getAll(), $used_fields);
foreach ($unused_fields as $field) {
$property = FieldHelper::getPropertyName($field);
$element[$property]['#access'] = FALSE;
}
}
// Add predefined options to the created subdivision elements.
$element = static::processSubdivisionElements($element, $value, $address_format);
......
......@@ -2,8 +2,7 @@
namespace Drupal\address\Plugin\Validation\Constraint;
use CommerceGuys\Addressing\AddressFormat\AddressField;
use Symfony\Component\Validator\Constraint;
use CommerceGuys\Addressing\Validator\Constraints\AddressFormatConstraint as ExternalAddressFormatConstraint;
/**
* Address format constraint.
......@@ -14,30 +13,10 @@ use Symfony\Component\Validator\Constraint;
* type = { "address" }
* )
*/
class AddressFormatConstraint extends Constraint {
class AddressFormatConstraint extends ExternalAddressFormatConstraint {
public $fields;
public $blankMessage = '@name field must be blank.';
public $notBlankMessage = '@name field is required.';
public $invalidMessage = '@name field is not in the right format.';
/**
* {@inheritdoc}
*/
public function __construct($options = NULL) {
parent::__construct($options);
// Validate all fields by default.
if (empty($this->fields)) {
$this->fields = array_values(AddressField::getAll());
}
}
/**
* {@inheritdoc}
*/
public function getTargets() {
return self::CLASS_CONSTRAINT;
}
}
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