Updated all the contrib modules to their latest versions.
[yaffs-website] / web / modules / contrib / inline_entity_form / src / Plugin / Field / FieldWidget / InlineEntityFormSimple.php
1 <?php
2
3 namespace Drupal\inline_entity_form\Plugin\Field\FieldWidget;
4
5 use Drupal\Component\Utility\NestedArray;
6 use Drupal\Core\Field\FieldDefinitionInterface;
7 use Drupal\Core\Field\FieldItemListInterface;
8 use Drupal\Core\Field\FieldStorageDefinitionInterface;
9 use Drupal\Core\Field\WidgetBase;
10 use Drupal\Core\Form\FormStateInterface;
11 use Drupal\Core\Render\Element;
12 use Drupal\inline_entity_form\TranslationHelper;
13
14 /**
15  * Simple inline widget.
16  *
17  * @FieldWidget(
18  *   id = "inline_entity_form_simple",
19  *   label = @Translation("Inline entity form - Simple"),
20  *   field_types = {
21  *     "entity_reference"
22  *   },
23  *   multiple_values = false
24  * )
25  */
26 class InlineEntityFormSimple extends InlineEntityFormBase {
27
28   /**
29    * {@inheritdoc}
30    */
31   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
32     // Trick inline_entity_form_form_alter() into attaching the handlers,
33     // WidgetSubmit will be needed once extractFormValues fills the $form_state.
34     $parents = array_merge($element['#field_parents'], [$items->getName()]);
35     $ief_id = sha1(implode('-', $parents));
36     $form_state->set(['inline_entity_form', $ief_id], []);
37
38     $element = [
39       '#type' => $this->getSetting('collapsible') ? 'details' : 'fieldset',
40       '#field_title' => $this->fieldDefinition->getLabel(),
41       '#after_build' => [
42         [get_class($this), 'removeTranslatabilityClue'],
43       ],
44     ] + $element;
45     if ($element['#type'] == 'details') {
46       $element['#open'] = !$this->getSetting('collapsed');
47     }
48
49     $item = $items->get($delta);
50     if ($item->target_id && !$item->entity) {
51       $element['warning']['#markup'] = $this->t('Unable to load the referenced entity.');
52       return $element;
53     }
54     $entity = $item->entity;
55     $op = $entity ? 'edit' : 'add';
56     $langcode = $items->getEntity()->language()->getId();
57     $parents = array_merge($element['#field_parents'], [
58       $items->getName(),
59       $delta,
60       'inline_entity_form'
61     ]);
62     $bundle = $this->getBundle();
63     $element['inline_entity_form'] = $this->getInlineEntityForm($op, $bundle, $langcode, $delta, $parents, $entity);
64
65     if ($op == 'edit') {
66       /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
67       if (!$entity->access('update')) {
68         // The user isn't allowed to edit the entity, but still needs to see
69         // it, to be able to reorder values.
70         $element['entity_label'] = [
71           '#type' => 'markup',
72           '#markup' => $entity->label(),
73         ];
74         // Hide the inline form. getInlineEntityForm() still needed to be
75         // called because otherwise the field re-ordering doesn't work.
76         $element['inline_entity_form']['#access'] = FALSE;
77       }
78     }
79     return $element;
80   }
81
82   /**
83    * {@inheritdoc}
84    */
85   protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
86     $element = parent::formMultipleElements($items, $form, $form_state);
87
88     // If we're using ulimited cardinality we don't display one empty item. Form
89     // validation will kick in if left empty which esentially means people won't
90     // be able to submit w/o creating another entity.
91     if (!$form_state->isSubmitted() && $element['#cardinality'] == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && $element['#max_delta'] > 0) {
92       $max = $element['#max_delta'];
93       unset($element[$max]);
94       $element['#max_delta'] = $max - 1;
95       $items->removeItem($max);
96       // Decrement the items count.
97       $field_name = $element['#field_name'];
98       $parents = $element[0]['#field_parents'];
99       $field_state = static::getWidgetState($parents, $field_name, $form_state);
100       $field_state['items_count']--;
101       static::setWidgetState($parents, $field_name, $form_state, $field_state);
102     }
103
104     // Remove add options if the user cannot add new entities.
105     if (!$this->canAddNew()) {
106       if (isset($element['add_more'])) {
107         unset($element['add_more']);
108       }
109       foreach (Element::children($element) as $delta) {
110         if (isset($element[$delta]['inline_entity_form'])) {
111           if ($element[$delta]['inline_entity_form']['#op'] == 'add') {
112             unset($element[$delta]);
113           }
114         }
115       }
116     }
117
118     return $element;
119   }
120
121   /**
122    * {@inheritdoc}
123    */
124   public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
125     if ($this->isDefaultValueWidget($form_state)) {
126       $items->filterEmptyItems();
127       return;
128     }
129
130     $field_name = $this->fieldDefinition->getName();
131     $parents = array_merge($form['#parents'], [$field_name]);
132     $submitted_values = $form_state->getValue($parents);
133     $values = [];
134     foreach ($items as $delta => $value) {
135       $element = NestedArray::getValue($form, [$field_name, 'widget', $delta]);
136       /** @var \Drupal\Core\Entity\EntityInterface $entity */
137       $entity = $element['inline_entity_form']['#entity'];
138       $weight = isset($submitted_values[$delta]['_weight']) ? $submitted_values[$delta]['_weight'] : 0;
139       $values[$weight] = ['entity' => $entity];
140     }
141
142     // Sort items base on weights.
143     ksort($values);
144     $values = array_values($values);
145
146     // Let the widget massage the submitted values.
147     $values = $this->massageFormValues($values, $form, $form_state);
148
149     // Assign the values and remove the empty ones.
150     $items->setValue($values);
151     $items->filterEmptyItems();
152
153     // Populate the IEF form state with $items so that WidgetSubmit can
154     // perform the necessary saves.
155     $ief_id = sha1(implode('-', $parents));
156     $widget_state = [
157       'instance' => $this->fieldDefinition,
158       'delete' => [],
159       'entities' => [],
160     ];
161     foreach ($items as $delta => $value) {
162       TranslationHelper::updateEntityLangcode($value->entity, $form_state);
163       $widget_state['entities'][$delta] = [
164         'entity' => $value->entity,
165         'needs_save' => TRUE,
166       ];
167     }
168     $form_state->set(['inline_entity_form', $ief_id], $widget_state);
169
170     // Put delta mapping in $form_state, so that flagErrors() can use it.
171     $field_name = $this->fieldDefinition->getName();
172     $field_state = WidgetBase::getWidgetState($form['#parents'], $field_name, $form_state);
173     foreach ($items as $delta => $item) {
174       $field_state['original_deltas'][$delta] = isset($item->_original_delta) ? $item->_original_delta : $delta;
175       unset($item->_original_delta, $item->weight);
176     }
177     WidgetBase::setWidgetState($form['#parents'], $field_name, $form_state, $field_state);
178   }
179
180   /**
181    * {@inheritdoc}
182    */
183   public static function isApplicable(FieldDefinitionInterface $field_definition) {
184     $handler_settings = $field_definition->getSettings()['handler_settings'];
185     $target_entity_type_id = $field_definition->getFieldStorageDefinition()->getSetting('target_type');
186     $target_entity_type = \Drupal::entityTypeManager()->getDefinition($target_entity_type_id);
187     // The target entity type doesn't use bundles, no need to validate them.
188     if (!$target_entity_type->getKey('bundle')) {
189       return TRUE;
190     }
191
192     if (empty($handler_settings['target_bundles'])) {
193       return FALSE;
194     }
195
196     if (count($handler_settings['target_bundles']) != 1) {
197       return FALSE;
198     }
199
200     return TRUE;
201   }
202
203   /**
204    * Gets the bundle for the inline entity.
205    *
206    * @return string|null
207    *   The bundle, or NULL if not known.
208    */
209   protected function getBundle() {
210     if (!empty($this->getFieldSetting('handler_settings')['target_bundles'])) {
211       return reset($this->getFieldSetting('handler_settings')['target_bundles']);
212     }
213   }
214
215 }