Interim commit.
[yaffs-website] / web / modules / contrib / entity_browser / modules / entity_form / entity_browser_entity_form.module
1 <?php
2
3 /**
4  * @file
5  * Hook implementations for entity_browser_entity_form.module.
6  *
7  * Provides integration with the Inline entity form module.
8  */
9
10 use Drupal\Core\Form\FormStateInterface;
11 use Drupal\Core\Field\FieldDefinitionInterface;
12 use Drupal\Core\Field\WidgetInterface;
13 use Drupal\Core\Url;
14 use Drupal\Component\Utility\NestedArray;
15 use Drupal\entity_browser\Element\EntityBrowserElement;
16 use Drupal\Core\Field\FieldStorageDefinitionInterface;
17
18 /**
19  * Implements hook_inline_entity_form_reference_form_alter().
20  */
21 function entity_browser_entity_form_inline_entity_form_reference_form_alter(&$reference_form, FormStateInterface &$form_state) {
22   /** @var \Drupal\field\FieldConfigInterface $instance */
23   $instance = $form_state->get([
24     'inline_entity_form',
25     $reference_form['#ief_id'],
26     'instance',
27   ]);
28
29   /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
30   $entity_form_id = $instance->getTargetEntityTypeId() . '.' . $instance->getTargetBundle() . '.default';
31   // TODO - 'default' might become configurable or something else in the future.
32   // See https://www.drupal.org/node/2510274
33   $form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load($entity_form_id);
34
35   $widget = $form_display->getRenderer($instance->getName());
36
37   $entity_browser_id = $widget->getThirdPartySetting('entity_browser_entity_form', 'entity_browser_id', '_none');
38   if ($entity_browser_id === '_none') {
39     return;
40   }
41
42   // Fetch the number of currently selected entities, if any.
43   $count_existing_selection = count($form_state->get([
44     'inline_entity_form',
45     $reference_form['#ief_id'],
46     'entities',
47   ]));
48
49   $cardinality = FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED;
50   if($instance->getFieldStorageDefinition()->get('cardinality') !== $cardinality) {
51     $cardinality = $instance->getFieldStorageDefinition()->get('cardinality') - $count_existing_selection;
52   }
53
54   unset($reference_form['entity_id']);
55   $reference_form['entity_browser'] = [
56     '#type' => 'entity_browser',
57     '#entity_browser' => $entity_browser_id,
58     '#cardinality' => $cardinality,
59   ];
60   $reference_form['#attached']['library'][] = 'entity_browser_entity_form/ief_autocomplete';
61   $reference_form['actions']['ief_reference_save']['#ajax']['event'] = 'entities-selected';
62
63   // Add custom validation and submit callbacks as we need to handle
64   // multi-value cases.
65   $reference_form['#element_validate'][0] = 'entity_browser_entity_form_reference_form_validate';
66   $reference_form['#ief_element_submit'][0] = 'entity_browser_entity_form_reference_form_submit';
67 }
68
69 /**
70  * Validates the form for adding existing entities.
71  *
72  * TODO see if we can get away without overriding entire IEF function.
73  *
74  * @param array $reference_form
75  *   The reference entity form.
76  * @param \Drupal\Core\Form\FormStateInterface $form_state
77  *   The form state of the parent form.
78  *
79  * @see inline_entity_form_reference_form_validate()
80  */
81 function entity_browser_entity_form_reference_form_validate(array &$reference_form, FormStateInterface $form_state) {
82   $form_values = NestedArray::getValue($form_state->getValues(), $reference_form['#parents']);
83   if (empty($form_values['entity_browser']['entity_ids'])) {
84     // The entity_id element is required, the value is empty only if
85     // the form was cancelled.
86     return;
87   }
88   $ief_id = $reference_form['#ief_id'];
89   $labels = $reference_form['#ief_labels'];
90   $attach_entities = EntityBrowserElement::processEntityIds($form_values['entity_browser']['entity_ids']);
91
92   // Check if the entity is already referenced by the field.
93   if (!empty($attach_entities)) {
94     foreach ($attach_entities as $attach_entity) {
95       foreach ($form_state->get(['inline_entity_form', $ief_id, 'entities']) as $key => $value) {
96         if ($value['entity'] == $attach_entity) {
97           $form_state->setError($reference_form, t('The selected @label has already been added.', ['@label' => $labels['singular']]));
98         }
99       }
100     }
101   }
102 }
103
104 /**
105  * Submits the form for adding existing entities.
106  *
107  * Adds the specified entity to the IEF form state.
108  *
109  * TODO see if we can get away without overriding entire IEF function.
110  *
111  * @param array $reference_form
112  *   The reference entity form.
113  * @param \Drupal\Core\Form\FormStateInterface $form_state
114  *   The form state of the parent form.
115  *
116  * @see inline_entity_form_reference_form_submit()
117  */
118 function entity_browser_entity_form_reference_form_submit($reference_form, FormStateInterface $form_state) {
119   $ief_id = $reference_form['#ief_id'];
120   $form_values = NestedArray::getValue($form_state->getValues(), $reference_form['#parents']);
121   $attach_entities = EntityBrowserElement::processEntityIds($form_values['entity_browser']['entity_ids']);
122   $entities =& $form_state->get(['inline_entity_form', $ief_id, 'entities']);
123
124   // Determine the correct weight of the new element.
125   $weight = 0;
126   if ($entities) {
127     $weight = max(array_keys($entities)) + 1;
128   }
129
130   foreach ($attach_entities as $attach_entity) {
131     $entities[] = array(
132       'entity' => $attach_entity,
133       'weight' => $weight,
134       'form' => NULL,
135       'needs_save' => FALSE,
136     );
137     $weight++;
138   }
139   $form_state->set(['inline_entity_form', $ief_id, 'entities'], $entities);
140
141   // In some rare cases entity_ids keeps values of selected entities which then
142   // causes problems in subsequent selections. Let's make sure it is empty and
143   // ready for next usage of entity browser.
144   $form_state->setValueForElement($reference_form['entity_browser']['entity_ids'], '');
145   $input = &$form_state->getUserInput();
146   NestedArray::unsetValue($input, array_merge($reference_form['#parents'], ['entity_browser', 'entity_ids']));
147 }
148
149 /**
150  * Implements hook_field_widget_third_party_settings_form().
151  */
152 function entity_browser_entity_form_field_widget_third_party_settings_form(WidgetInterface $plugin, FieldDefinitionInterface $field_definition, $form_mode, $form, FormStateInterface $form_state) {
153   if ($plugin->getPluginId() == 'inline_entity_form_complex') {
154     $entity_browsers = \Drupal::service('entity_type.manager')->getStorage('entity_browser')->loadMultiple();
155     if ($entity_browsers) {
156       $options = [];
157       foreach ($entity_browsers as $entity_browser) {
158         $options[$entity_browser->id()] = $entity_browser->label();
159       }
160       $element['entity_browser_id'] = [
161         '#type' => 'select',
162         '#title' => t('Entity browser'),
163         '#options' => $options,
164         '#empty_option' => t('- None -'),
165         '#empty_value' => '_none',
166         '#default_value' => $plugin->getThirdPartySetting('entity_browser_entity_form', 'entity_browser_id'),
167       ];
168     }
169     else {
170       $element['message'] = [
171         '#markup' => t('There are no entity browsers available. You can create one <a href="@url">here</a>.', ['@url' => Url::fromRoute('entity.entity_browser.collection')->toString()]),
172       ];
173     }
174     return $element;
175   }
176 }
177
178 /**
179  * Implements hook_field_widget_settings_summary_alter().
180  */
181 function entity_browser_entity_form_field_widget_settings_summary_alter(&$summary, $context) {
182   $plugin = $context['widget'];
183   if ($plugin->getPluginId() == 'inline_entity_form_complex' && $plugin->getThirdPartySetting('entity_browser_entity_form', 'entity_browser_id') && $plugin->getThirdPartySetting('entity_browser_entity_form', 'entity_browser_id') !== '_none') {
184     $entity_browser_id = $plugin->getThirdPartySetting('entity_browser_entity_form', 'entity_browser_id');
185     $entity_browser = \Drupal::service('entity_type.manager')->getStorage('entity_browser')->load($entity_browser_id);
186     if ($entity_browser) {
187       $summary[] = t('Entity browser: @entity_browser.', [
188         '@entity_browser' => $entity_browser->label(),
189       ]);
190     }
191     return $summary;
192   }
193 }