AddressDefaultWidget.php 5.26 KB
Newer Older
bojanz's avatar
bojanz committed
1 2 3 4
<?php

namespace Drupal\address\Plugin\Field\FieldWidget;

5
use CommerceGuys\Addressing\Country\CountryRepositoryInterface;
6
use Drupal\Component\Utility\NestedArray;
7
use Drupal\Core\Config\ConfigFactoryInterface;
bojanz's avatar
bojanz committed
8 9 10
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
11 12
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
13
use Drupal\Core\Render\Element;
14
use Symfony\Component\DependencyInjection\ContainerInterface;
15
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
16
use Symfony\Component\Validator\ConstraintViolationInterface;
bojanz's avatar
bojanz committed
17 18

/**
19
 * Plugin implementation of the 'address_default' widget.
bojanz's avatar
bojanz committed
20 21 22 23 24 25 26 27 28
 *
 * @FieldWidget(
 *   id = "address_default",
 *   label = @Translation("Address"),
 *   field_types = {
 *     "address"
 *   },
 * )
 */
29 30 31 32 33
class AddressDefaultWidget extends WidgetBase implements ContainerFactoryPluginInterface {

  /**
   * The country repository.
   *
34
   * @var \CommerceGuys\Addressing\Country\CountryRepositoryInterface
35 36 37
   */
  protected $countryRepository;

38 39 40 41 42 43 44
  /**
   * The event dispatcher.
   *
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
   */
  protected $eventDispatcher;

45 46 47 48 49 50 51
  /**
   * The configuration factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

52 53 54
  /**
   * Constructs a AddressDefaultWidget object.
   *
55
   * @param string $plugin_id
56
   *   The plugin_id for the widget.
57
   * @param mixed $plugin_definition
58
   *   The plugin implementation definition.
59
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
60 61 62
   *   The definition of the field to which the widget is associated.
   * @param array $settings
   *   The widget settings.
63
   * @param array $third_party_settings
64
   *   Any third party settings.
65
   * @param \CommerceGuys\Addressing\Country\CountryRepositoryInterface $country_repository
66
   *   The country repository.
67
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
68
   *   The event dispatcher.
69
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
70
   *   The config factory.
71
   */
72
  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) {
73 74 75 76 77
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);

    $this->countryRepository = $country_repository;
    $this->eventDispatcher = $event_dispatcher;
    $this->configFactory = $config_factory;
78
  }
bojanz's avatar
bojanz committed
79 80 81 82

  /**
   * {@inheritdoc}
   */
83
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
84 85
    // @see \Drupal\Core\Field\WidgetPluginManager::createInstance().
    return new static(
86 87
      $plugin_id,
      $plugin_definition,
88 89 90 91
      $configuration['field_definition'],
      $configuration['settings'],
      $configuration['third_party_settings'],
      $container->get('address.country_repository'),
92
      $container->get('event_dispatcher'),
93
      $container->get('config.factory')
94 95 96 97 98 99
    );
  }

  /**
   * {@inheritdoc}
   */
100
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
101
    $item = $items[$delta];
102
    $value = $item->toArray();
103 104 105
    // 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).
106
    $value['langcode'] = $item->initializeLangcode();
107

108
    $element += [
bojanz's avatar
bojanz committed
109 110
      '#type' => 'details',
      '#open' => TRUE,
111
    ];
112 113 114 115 116
    $element['address'] = [
      '#type' => 'address',
      '#default_value' => $value,
      '#required' => $this->fieldDefinition->isRequired(),
      '#available_countries' => $item->getAvailableCountries(),
117
      '#field_overrides' => $item->getFieldOverrides(),
118
    ];
119 120 121 122
    // Make sure no properties are required on the default value widget.
    if ($this->isDefaultValueWidget($form_state)) {
      $element['address']['#after_build'][] = [get_class($this), 'makeFieldsOptional'];
    }
bojanz's avatar
bojanz committed
123

124 125 126
    return $element;
  }

127 128 129
  /**
   * {@inheritdoc}
   */
130
  public function errorElement(array $element, ConstraintViolationInterface $violation, array $form, FormStateInterface $form_state) {
131 132
    $error_element = NestedArray::getValue($element['address'], $violation->arrayPropertyPath);
    return is_array($error_element) ? $error_element : FALSE;
133 134 135
  }

  /**
136
   * {@inheritdoc}
137
   */
138 139 140 141
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    $new_values = [];
    foreach ($values as $delta => $value) {
      $new_values[$delta] = $value['address'];
142
    }
143
    return $new_values;
144 145
  }

146 147 148 149 150 151 152 153 154 155 156 157
  /**
   * 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;
  }

bojanz's avatar
bojanz committed
158
}