Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 130 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
EntityViewDisplayFormTrait | |
0.00% |
0 / 130 |
|
0.00% |
0 / 8 |
812 | |
0.00% |
0 / 1 |
submitForm | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
20 | |||
entityViewDisplayForm | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
20 | |||
buildOverridesForm | |
0.00% |
0 / 51 |
|
0.00% |
0 / 1 |
6 | |||
getAlreadyMappedFields | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
30 | |||
getSourceFieldAsOptions | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
42 | |||
buildExtraFieldRow | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
buildFieldRow | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
copyFormValuesToEntity | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Drupal\display_builder_entity_view\Form; |
6 | |
7 | use Drupal\Core\Entity\Display\EntityViewDisplayInterface; |
8 | use Drupal\Core\Entity\EntityInterface; |
9 | use Drupal\Core\Field\FieldDefinitionInterface; |
10 | use Drupal\Core\Form\FormStateInterface; |
11 | use Drupal\Core\Url; |
12 | use Drupal\display_builder\ConfigFormBuilderInterface; |
13 | use Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface; |
14 | use Drupal\display_builder_entity_view\Entity\DisplayBuilderOverridableInterface; |
15 | |
16 | /** |
17 | * Common methods for entity view display form. |
18 | */ |
19 | trait EntityViewDisplayFormTrait { |
20 | |
21 | /** |
22 | * Form submission handler. |
23 | * |
24 | * @param array $form |
25 | * An associative array containing the structure of the form. |
26 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
27 | * The current state of the form. |
28 | */ |
29 | public function submitForm(array &$form, FormStateInterface $form_state): void { |
30 | parent::submitForm($form, $form_state); |
31 | |
32 | // @todo we should have always a fallback. |
33 | $display_builder_config = $form_state->getValue([ConfigFormBuilderInterface::PROFILE_PROPERTY]) ?? 'default'; |
34 | |
35 | // Empty means disabled. |
36 | if (empty($display_builder_config)) { |
37 | $this->entity->unsetThirdPartySetting('display_builder', ConfigFormBuilderInterface::PROFILE_PROPERTY); |
38 | } |
39 | else { |
40 | $this->entity->setThirdPartySetting('display_builder', ConfigFormBuilderInterface::PROFILE_PROPERTY, $display_builder_config); |
41 | } |
42 | |
43 | $display_builder_override = $form_state->getValue([ConfigFormBuilderInterface::OVERRIDE_FIELD_PROPERTY]) ?? ''; |
44 | |
45 | // Empty means disabled. |
46 | if (empty($display_builder_override)) { |
47 | $this->entity->unsetThirdPartySetting('display_builder', ConfigFormBuilderInterface::OVERRIDE_FIELD_PROPERTY); |
48 | } |
49 | else { |
50 | $this->entity->setThirdPartySetting('display_builder', ConfigFormBuilderInterface::OVERRIDE_FIELD_PROPERTY, $display_builder_override); |
51 | } |
52 | |
53 | $display_builder_override_profile = $form_state->getValue([ConfigFormBuilderInterface::OVERRIDE_PROFILE_PROPERTY]) ?? ''; |
54 | |
55 | // Empty means disabled. |
56 | if (empty($display_builder_override_profile)) { |
57 | $this->entity->unsetThirdPartySetting('display_builder', ConfigFormBuilderInterface::OVERRIDE_PROFILE_PROPERTY); |
58 | } |
59 | else { |
60 | $this->entity->setThirdPartySetting('display_builder', ConfigFormBuilderInterface::OVERRIDE_PROFILE_PROPERTY, $display_builder_override_profile); |
61 | } |
62 | |
63 | $this->entity->save(); |
64 | $this->localTaskManager->clearCachedDefinitions(); |
65 | $this->routeBuilder->rebuild(); |
66 | } |
67 | |
68 | /** |
69 | * Provides form elements to enable Display Builder. |
70 | * |
71 | * @param array $form |
72 | * The form structure. |
73 | * |
74 | * @return array |
75 | * The modified form. |
76 | */ |
77 | protected function entityViewDisplayForm(array $form): array { |
78 | $is_display_builder_enabled = $this->entity->isDisplayBuilderEnabled(); |
79 | |
80 | if ($is_display_builder_enabled) { |
81 | // Hide the table of fields. |
82 | $form['fields']['#access'] = FALSE; |
83 | $form['#fields'] = []; |
84 | $form['#extra'] = []; |
85 | } |
86 | |
87 | $form['manage_display_builder'] = [ |
88 | '#type' => 'link', |
89 | '#title' => $this->t('Display builder'), |
90 | '#weight' => -11, |
91 | '#attributes' => ['class' => ['button']], |
92 | '#url' => $this->entity->getBuilderUrl(), |
93 | '#access' => $is_display_builder_enabled, |
94 | ]; |
95 | |
96 | if (isset($form['modes'])) { |
97 | $form['modes']['#weight'] = 0; |
98 | } |
99 | |
100 | $form['display_builder_wrapper'] = [ |
101 | '#type' => 'details', |
102 | '#open' => TRUE, |
103 | '#title' => $this->t('Display builder'), |
104 | '#weight' => 1, |
105 | ]; |
106 | |
107 | $form['display_builder_wrapper'][ConfigFormBuilderInterface::PROFILE_PROPERTY] = $this->configFormBuilder->build($this->entity, FALSE); |
108 | |
109 | /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface $entity */ |
110 | $entity = $this->getEntity(); |
111 | |
112 | if ($entity instanceof DisplayBuilderOverridableInterface) { |
113 | $form['display_builder_wrapper'][ConfigFormBuilderInterface::PROFILE_PROPERTY]['override_form'] = $this->buildOverridesForm($entity); |
114 | } |
115 | |
116 | return $form; |
117 | } |
118 | |
119 | /** |
120 | * Build the form for entity display overrides per content. |
121 | * |
122 | * @param \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface $entity |
123 | * The entity. |
124 | * |
125 | * @return array |
126 | * The renderable form array. |
127 | */ |
128 | protected function buildOverridesForm(DisplayBuilderEntityDisplayInterface|DisplayBuilderOverridableInterface $entity): array { |
129 | $entity_type_id = $entity->getTargetEntityTypeId(); |
130 | $options = $this->getSourceFieldAsOptions(); |
131 | $target_entity_type_id = $this->entityTypeManager->getDefinition($entity_type_id)->getBundleEntityType(); |
132 | $description = [ |
133 | '#title' => $this->t('Add a UI Patterns Source field'), |
134 | '#type' => 'link', |
135 | '#attributes' => [ |
136 | 'data-dialog-type' => 'modal', |
137 | 'data-dialog-options' => \json_encode([ |
138 | 'title' => 'Add field: Source (UI Patterns)', |
139 | 'width' => '800', |
140 | ]), |
141 | 'class' => ['use-ajax'], |
142 | ], |
143 | '#url' => Url::fromRoute("field_ui.field_storage_config_add_sub_{$entity_type_id}", [ |
144 | $target_entity_type_id => $entity->getTargetBundle(), |
145 | 'display_as_group' => 'Group', |
146 | 'selected_field_type' => 'ui_patterns_source', |
147 | ]), |
148 | '#suffix' => '.', |
149 | ]; |
150 | |
151 | if (empty($options)) { |
152 | $description = [ |
153 | [ |
154 | '#plain_text' => $this->t('No eligible field found.') . ' ', |
155 | ], |
156 | $description, |
157 | ]; |
158 | } |
159 | /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderOverridableInterface $overridable */ |
160 | $overridable = $entity; |
161 | $form = []; |
162 | $form[ConfigFormBuilderInterface::OVERRIDE_FIELD_PROPERTY] = [ |
163 | '#type' => 'select', |
164 | '#title' => $this->t('Select a field to override this display per content'), |
165 | '#options' => $options, |
166 | '#empty_option' => $this->t('- Disabled -'), |
167 | '#default_value' => $overridable->getDisplayBuilderOverrideField(), |
168 | '#description' => $description, |
169 | ]; |
170 | |
171 | $form[ConfigFormBuilderInterface::OVERRIDE_PROFILE_PROPERTY] = [ |
172 | '#type' => 'select', |
173 | '#title' => $this->t('Override profile'), |
174 | '#description' => $this->t('The profile used for content overrides. It can be changed anytime.'), |
175 | '#options' => $this->configFormBuilder->getAllowedProfiles(), |
176 | '#default_value' => $overridable->getDisplayBuilderOverrideProfile()?->id(), |
177 | '#states' => [ |
178 | 'invisible' => [ |
179 | ':input[name="' . ConfigFormBuilderInterface::OVERRIDE_FIELD_PROPERTY . '"]' => ['filled' => FALSE], |
180 | ], |
181 | ], |
182 | ]; |
183 | |
184 | return $form; |
185 | } |
186 | |
187 | /** |
188 | * Returns an array of UI Patterns Source fields which are already mapped. |
189 | * |
190 | * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $current_display |
191 | * The current display. |
192 | * |
193 | * @return array |
194 | * An array of field names that are already mapped to the current display. |
195 | */ |
196 | protected function getAlreadyMappedFields(EntityViewDisplayInterface $current_display): array { |
197 | /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface[] $displays */ |
198 | $displays = $this->entityTypeManager->getStorage('entity_view_display')->loadByProperties([ |
199 | 'targetEntityType' => $current_display->getTargetEntityTypeId(), |
200 | 'bundle' => $current_display->getTargetBundle(), |
201 | ]); |
202 | $field_names = []; |
203 | |
204 | foreach ($displays as $display) { |
205 | if ($display instanceof DisplayBuilderOverridableInterface) { |
206 | if ($display->isDisplayBuilderOverridable() |
207 | && $current_display->id() !== $display->id()) { |
208 | $field_names[] = $display->getDisplayBuilderOverrideField(); |
209 | } |
210 | } |
211 | } |
212 | |
213 | return $field_names; |
214 | } |
215 | |
216 | /** |
217 | * Returns UI Patterns source fields as options. |
218 | * |
219 | * @return array |
220 | * An associative array of field names and labels. |
221 | */ |
222 | protected function getSourceFieldAsOptions(): array { |
223 | /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface $display */ |
224 | $display = $this->getEntity(); |
225 | $field_definitions = $this->entityFieldManager->getFieldDefinitions( |
226 | $display->getTargetEntityTypeId(), |
227 | $display->getTargetBundle(), |
228 | ); |
229 | $fields = []; |
230 | |
231 | if ($display instanceof DisplayBuilderOverridableInterface |
232 | && $display instanceof EntityViewDisplayInterface |
233 | ) { |
234 | $already_mapped = $this->getAlreadyMappedFields($display); |
235 | |
236 | foreach ($field_definitions as $field_name => $field_definition) { |
237 | if ($field_definition->getType() === 'ui_patterns_source' |
238 | && !\in_array($field_name, $already_mapped, TRUE) |
239 | ) { |
240 | $fields[$field_name] = $field_definition->getLabel(); |
241 | } |
242 | } |
243 | } |
244 | |
245 | return $fields; |
246 | } |
247 | |
248 | /** |
249 | * Builds the table row structure for a single extra field. |
250 | * |
251 | * @param string $field_id |
252 | * The field ID. |
253 | * @param array $extra_field |
254 | * The pseudo-field element. |
255 | * |
256 | * @return array |
257 | * A table row array. |
258 | */ |
259 | protected function buildExtraFieldRow($field_id, $extra_field): array { |
260 | if ($this->entity->isDisplayBuilderEnabled()) { |
261 | return []; |
262 | } |
263 | |
264 | return parent::buildExtraFieldRow($field_id, $extra_field); |
265 | } |
266 | |
267 | /** |
268 | * Builds the table row structure for a single field. |
269 | * |
270 | * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition |
271 | * The field definition. |
272 | * @param array $form |
273 | * An associative array containing the structure of the form. |
274 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
275 | * The current state of the form. |
276 | * |
277 | * @return array |
278 | * A table row array. |
279 | */ |
280 | protected function buildFieldRow(FieldDefinitionInterface $field_definition, array $form, FormStateInterface $form_state): array { |
281 | if ($this->entity->isDisplayBuilderEnabled()) { |
282 | return []; |
283 | } |
284 | |
285 | return parent::buildFieldRow($field_definition, $form, $form_state); |
286 | } |
287 | |
288 | /** |
289 | * Copies top-level form values to entity properties. |
290 | * |
291 | * This should not change existing entity properties that are not being edited |
292 | * by this form. |
293 | * |
294 | * @param \Drupal\Core\Entity\EntityInterface $entity |
295 | * The entity the current form should operate upon. |
296 | * @param array $form |
297 | * A nested array of form elements comprising the form. |
298 | * @param \Drupal\Core\Form\FormStateInterface $form_state |
299 | * The current state of the form. |
300 | * |
301 | * @see \Drupal\Core\Form\ConfigFormBase::copyFormValuesToConfig() |
302 | */ |
303 | protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state): void { |
304 | /** @var \Drupal\display_builder_entity_view\Entity\DisplayBuilderEntityDisplayInterface $entity */ |
305 | // Do not process field values if Display Builder is or will be enabled. |
306 | $set_enabled = (bool) $form_state->getValue(['display_builder', 'enabled'], FALSE); |
307 | $already_enabled = $entity->isDisplayBuilderEnabled(); |
308 | |
309 | if ($already_enabled || $set_enabled) { |
310 | $form['#fields'] = []; |
311 | $form['#extra'] = []; |
312 | } |
313 | |
314 | parent::copyFormValuesToEntity($entity, $form, $form_state); |
315 | } |
316 | |
317 | } |