Version 1
[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' => 'fieldset',
40       '#field_title' => $this->fieldDefinition->getLabel(),
41       '#after_build' => [
42         [get_class($this), 'removeTranslatabilityClue'],
43       ],
44     ] + $element;
45     $item = $items->get($delta);
46     if ($item->target_id && !$item->entity) {
47       $element['warning']['#markup'] = $this->t('Unable to load the referenced entity.');
48       return $element;
49     }
50     $entity = $item->entity;
51     $op = $entity ? 'edit' : 'add';
52     $langcode = $items->getEntity()->language()->getId();
53     $parents = array_merge($element['#field_parents'], [
54       $items->getName(),
55       $delta,
56       'inline_entity_form'
57     ]);
58     $bundle = !empty($this->getFieldSetting('handler_settings')['target_bundles']) ? reset($this->getFieldSetting('handler_settings')['target_bundles']) : NULL;
59     $element['inline_entity_form'] = $this->getInlineEntityForm($op, $bundle, $langcode, $delta, $parents, $entity);
60
61     if ($op == 'edit') {
62       /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
63       if (!$entity->access('update')) {
64         // The user isn't allowed to edit the entity, but still needs to see
65         // it, to be able to reorder values.
66         $element['entity_label'] = [
67           '#type' => 'markup',
68           '#markup' => $entity->label(),
69         ];
70         // Hide the inline form. getInlineEntityForm() still needed to be
71         // called because otherwise the field re-ordering doesn't work.
72         $element['inline_entity_form']['#access'] = FALSE;
73       }
74     }
75     return $element;
76   }
77
78   /**
79    * {@inheritdoc}
80    */
81   protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
82     $element = parent::formMultipleElements($items, $form, $form_state);
83
84     // If we're using ulimited cardinality we don't display one empty item. Form
85     // validation will kick in if left empty which esentially means people won't
86     // be able to submit w/o creating another entity.
87     if (!$form_state->isSubmitted() && $element['#cardinality'] == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED && $element['#max_delta'] > 0) {
88       $max = $element['#max_delta'];
89       unset($element[$max]);
90       $element['#max_delta'] = $max - 1;
91       $items->removeItem($max);
92       // Decrement the items count.
93       $field_name = $element['#field_name'];
94       $parents = $element[0]['#field_parents'];
95       $field_state = static::getWidgetState($parents, $field_name, $form_state);
96       $field_state['items_count']--;
97       static::setWidgetState($parents, $field_name, $form_state, $field_state);
98     }
99
100     // Remove add options if the user cannot add new entities.
101     if (!$this->canAddNew()) {
102       if (isset($element['add_more'])) {
103         unset($element['add_more']);
104       }
105       foreach (Element::children($element) as $delta) {
106         if (isset($element[$delta]['inline_entity_form'])) {
107           if ($element[$delta]['inline_entity_form']['#op'] == 'add') {
108             unset($element[$delta]);
109           }
110         }
111       }
112     }
113
114     return $element;
115   }
116
117   /**
118    * {@inheritdoc}
119    */
120   public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
121     if ($this->isDefaultValueWidget($form_state)) {
122       $items->filterEmptyItems();
123       return;
124     }
125
126     $field_name = $this->fieldDefinition->getName();
127     $parents = array_merge($form['#parents'], [$field_name]);
128     $submitted_values = $form_state->getValue($parents);
129     $values = [];
130     foreach ($items as $delta => $value) {
131       $element = NestedArray::getValue($form, [$field_name, 'widget', $delta]);
132       /** @var \Drupal\Core\Entity\EntityInterface $entity */
133       $entity = $element['inline_entity_form']['#entity'];
134       $weight = isset($submitted_values[$delta]['_weight']) ? $submitted_values[$delta]['_weight'] : 0;
135       $values[$weight] = ['entity' => $entity];
136     }
137
138     // Sort items base on weights.
139     ksort($values);
140     $values = array_values($values);
141
142     // Let the widget massage the submitted values.
143     $values = $this->massageFormValues($values, $form, $form_state);
144
145     // Assign the values and remove the empty ones.
146     $items->setValue($values);
147     $items->filterEmptyItems();
148
149     // Populate the IEF form state with $items so that WidgetSubmit can
150     // perform the necessary saves.
151     $ief_id = sha1(implode('-', $parents));
152     $widget_state = [
153       'instance' => $this->fieldDefinition,
154       'delete' => [],
155       'entities' => [],
156     ];
157     foreach ($items as $delta => $value) {
158       TranslationHelper::updateEntityLangcode($value->entity, $form_state);
159       $widget_state['entities'][$delta] = [
160         'entity' => $value->entity,
161         'needs_save' => TRUE,
162       ];
163     }
164     $form_state->set(['inline_entity_form', $ief_id], $widget_state);
165
166     // Put delta mapping in $form_state, so that flagErrors() can use it.
167     $field_name = $this->fieldDefinition->getName();
168     $field_state = WidgetBase::getWidgetState($form['#parents'], $field_name, $form_state);
169     foreach ($items as $delta => $item) {
170       $field_state['original_deltas'][$delta] = isset($item->_original_delta) ? $item->_original_delta : $delta;
171       unset($item->_original_delta, $item->weight);
172     }
173     WidgetBase::setWidgetState($form['#parents'], $field_name, $form_state, $field_state);
174   }
175
176   /**
177    * {@inheritdoc}
178    */
179   public static function isApplicable(FieldDefinitionInterface $field_definition) {
180     $handler_settings = $field_definition->getSettings()['handler_settings'];
181     $target_entity_type_id = $field_definition->getFieldStorageDefinition()->getSetting('target_type');
182     $target_entity_type = \Drupal::entityTypeManager()->getDefinition($target_entity_type_id);
183     // The target entity type doesn't use bundles, no need to validate them.
184     if (!$target_entity_type->getKey('bundle')) {
185       return TRUE;
186     }
187
188     if (empty($handler_settings['target_bundles'])) {
189       return FALSE;
190     }
191
192     if (count($handler_settings['target_bundles']) != 1) {
193       return FALSE;
194     }
195
196     return TRUE;
197   }
198
199 }