address-8.x-1.x-dev/src/Plugin/Field/FieldWidget/AddressDefaultWidget.php
src/Plugin/Field/FieldWidget/AddressDefaultWidget.php
<?php
namespace Drupal\address\Plugin\Field\FieldWidget;
use CommerceGuys\Addressing\Country\CountryRepositoryInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Render\Element;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Validator\ConstraintViolationInterface;
/**
* Plugin implementation of the 'address_default' widget.
*
* @FieldWidget(
* id = "address_default",
* label = @Translation("Address"),
* field_types = {
* "address"
* },
* )
*/
class AddressDefaultWidget extends WidgetBase implements ContainerFactoryPluginInterface {
/**
* The country repository.
*
* @var \CommerceGuys\Addressing\Country\CountryRepositoryInterface
*/
protected $countryRepository;
/**
* The event dispatcher.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Constructs a AddressDefaultWidget object.
*
* @param string $plugin_id
* The plugin_id for the widget.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The definition of the field to which the widget is associated.
* @param array $settings
* The widget settings.
* @param array $third_party_settings
* Any third party settings.
* @param \CommerceGuys\Addressing\Country\CountryRepositoryInterface $country_repository
* The country repository.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* The event dispatcher.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, CountryRepositoryInterface $country_repository, EventDispatcherInterface $event_dispatcher, ConfigFactoryInterface $config_factory) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->countryRepository = $country_repository;
$this->eventDispatcher = $event_dispatcher;
$this->configFactory = $config_factory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
// @see \Drupal\Core\Field\WidgetPluginManager::createInstance().
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['third_party_settings'],
$container->get('address.country_repository'),
$container->get('event_dispatcher'),
$container->get('config.factory')
);
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'wrapper_type' => 'fieldset',
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
return [
'wrapper_type' => [
'#type' => 'radios',
'#title' => $this->t('Wrapper type'),
'#options' => $this->wrapperTypeOptions(),
'#default_value' => $this->getSetting('wrapper_type'),
],
];
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = parent::settingsSummary();
$summary[] = $this->t('Wrapper type: @wrapper_type', [
'@wrapper_type' => $this->wrapperTypeOptions()[$this->getSetting('wrapper_type')],
]);
return $summary;
}
/**
* Gets the options for the "Wrapper type" setting.
*
* @return string[]
* The available options.
*/
protected function wrapperTypeOptions(): array {
return [
'container' => $this->t('Container (invisible)'),
'details' => $this->t('Details (collapsible)'),
'fieldset' => $this->t('Fieldset (non-collapsible)'),
];
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$item = $items[$delta];
$value = $item->toArray();
// Calling initializeLangcode() every time, and not just when the field
// is empty, ensures that the langcode can be changed on subsequent
// edits (because the entity or interface language changed, for example).
$value['langcode'] = $item->initializeLangcode();
// If cardinality is multiple then there is no need to set address field
// as required since $element handles this already.
$required = FALSE;
if ($this->fieldDefinition->getFieldStorageDefinition()->getCardinality() == 1) {
$required = $this->fieldDefinition->isRequired();
}
$element += [
'#type' => $this->getSetting('wrapper_type'),
'#open' => TRUE,
];
$element['address'] = [
'#type' => 'address',
'#default_value' => $value,
'#required' => $required,
'#available_countries' => $item->getAvailableCountries(),
'#field_overrides' => $item->getFieldOverrides(),
];
// Make sure no properties are required on the default value widget.
if ($this->isDefaultValueWidget($form_state)) {
$element['address']['#after_build'][] = [
get_class($this),
'makeFieldsOptional',
];
}
return $element;
}
/**
* {@inheritdoc}
*/
public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
$property_path_array = explode('.', $violation->getPropertyPath());
$error_element = NestedArray::getValue($element['address'], [$property_path_array[1]]);
return is_array($error_element) ? $error_element : FALSE;
}
/**
* {@inheritdoc}
*/
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
$new_values = [];
foreach ($values as $delta => $value) {
$new_values[$delta] = $value['address'];
}
return $new_values;
}
/**
* Form API callback: Makes all address field properties optional.
*/
public static function makeFieldsOptional(array $element, FormStateInterface $form_state) {
foreach (Element::getVisibleChildren($element) as $key) {
if (!empty($element[$key]['#required'])) {
$element[$key]['#required'] = FALSE;
}
}
return $element;
}
}
