diff --git a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewsSourceBase.php b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewsSourceBase.php index 70bc1661b2c1b9d44f73d7092ea55b93d2a0663c..2f14109c0f2a3ad3ec5d636487d7dd54c2e72df5 100644 --- a/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewsSourceBase.php +++ b/modules/ui_patterns_views/src/Plugin/UiPatterns/Source/ViewsSourceBase.php @@ -174,9 +174,10 @@ abstract class ViewsSourceBase extends SourcePluginBase { */ public function settingsForm(array $form, FormStateInterface $form_state): array { $form = parent::settingsForm($form, $form_state); + $propTitle = $this->propDefinition['title'] ?? ''; $form['label_map'] = [ "#type" => "label", - "#title" => $this->propDefinition['title'] . ": " . $this->label(), + "#title" => empty($propTitle) ? $this->label() : $propTitle . ": " . $this->label(), ]; return $form; } diff --git a/src/Element/ComponentElementBuilder.php b/src/Element/ComponentElementBuilder.php index e2948b34e57d6a2739782c9dd7d8389d1eca881f..23a3a1e85f39d2299cb42e195ad45510e4a487c6 100644 --- a/src/Element/ComponentElementBuilder.php +++ b/src/Element/ComponentElementBuilder.php @@ -152,7 +152,7 @@ class ComponentElementBuilder implements TrustedCallbackInterface { // We don't want to break the render process, so we just ignore the prop. $error_message = t("Context error for '@prop_id' in component '@component_id': @message", [ '@prop_id' => $prop_or_slot_id, - '@component_id' => $build['#component'], + '@component_id' => $build['#component'] ?? '', '@message' => $e->getMessage(), ]); $this->logger->error($error_message); diff --git a/src/Element/ComponentForm.php b/src/Element/ComponentForm.php index eb440834cd1d9f94e9910c8b52fbcea4787cdafd..87724d47c262a9528ee1ea8114f021bac97ef8cc 100644 --- a/src/Element/ComponentForm.php +++ b/src/Element/ComponentForm.php @@ -62,6 +62,7 @@ class ComponentForm extends ComponentFormBase { '#component_id' => NULL, '#input' => TRUE, '#multiple' => FALSE, + '#component_required' => TRUE, '#default_value' => NULL, '#source_contexts' => [], '#tag_filter' => [], @@ -150,13 +151,20 @@ class ComponentForm extends ComponentFormBase { $contextComponentDefinition = ContextDefinition::create('string'); $element['#source_contexts']['component_id'] = new Context($contextComponentDefinition, $component_id); } - if ($initial_component_id === NULL) { + if (empty($initial_component_id)) { $component_selector_form = array_merge(self::buildComponentSelectorForm( $wrapper_id, - $component_id + $component_id, + $element['#component_required'] ?? TRUE, ), ["#ajax_url" => $element["#ajax_url"] ?? NULL]); $element["component_id"] = self::expandAjax($component_selector_form); } + else { + $element["component_id"] = [ + '#type' => 'hidden', + '#value' => $component_id, + ]; + } self::buildComponentForm( $element, $wrapper_id, @@ -207,6 +215,7 @@ class ComponentForm extends ComponentFormBase { private static function buildComponentSelectorForm( ?string $wrapper_id, ?string $selected_component_id, + bool $required = TRUE, ): array { /* @phpstan-ignore method.notFound */ $definitions = \Drupal::service("plugin.manager.sdc")->getGroupedDefinitions(); @@ -229,7 +238,7 @@ class ComponentForm extends ComponentFormBase { '#executes_submit_callback' => FALSE, '#empty_value' => '', '#empty_option' => t('- None -'), - '#required' => TRUE, + '#required' => $required, ]; } diff --git a/src/Element/ComponentFormBase.php b/src/Element/ComponentFormBase.php index ef59f72aa027d70e55c5ba2d29238725c1ddd62f..1aa8c9b0c007afeb1525e70fc9f74f8f5af1b61f 100644 --- a/src/Element/ComponentFormBase.php +++ b/src/Element/ComponentFormBase.php @@ -154,13 +154,13 @@ abstract class ComponentFormBase extends FormElementBase implements TrustedCallb */ protected static function getSources(string $prop_or_slot_id, array $definition, array $element): array { $configuration = $element['#default_value'] ?? []; - $source_contexts = $element['#source_contexts']; - $form_array_parents = $element['#array_parents']; - $tag_filter = $element['#tag_filter']; - /** @var \Drupal\ui_patterns\PropTypeInterface $prop_type */ - $prop_type = empty($definition) ? NULL : $definition['ui_patterns']['type_definition']; + $source_contexts = $element['#source_contexts'] ?? []; + $form_array_parents = $element['#array_parents'] ?? []; + $tag_filter = $element['#tag_filter'] ?? []; /** @var \Drupal\ui_patterns\SourcePluginManager $source_plugin_manager */ $source_plugin_manager = \Drupal::service("plugin.manager.ui_patterns_source"); + /** @var \Drupal\ui_patterns\PropTypeInterface $prop_type */ + $prop_type = empty($definition) ? $source_plugin_manager->getSlotPropType() : $definition['ui_patterns']['type_definition']; $prop_plugin_definition = $prop_type->getPluginDefinition(); $default_source_id = (is_array($prop_plugin_definition) && isset($prop_plugin_definition["default_source"])) ? $prop_plugin_definition["default_source"] : NULL; $sources = $source_plugin_manager->getDefinitionsForPropType($prop_type->getPluginId(), $source_contexts, $tag_filter); diff --git a/src/Element/ComponentSlotForm.php b/src/Element/ComponentSlotForm.php index fcc47856c83b9ca8f264e0f3b8b5b2f75ad41d05..5fa120be39dd86dbd4e8c1563f9b52f8eb180f49 100644 --- a/src/Element/ComponentSlotForm.php +++ b/src/Element/ComponentSlotForm.php @@ -69,6 +69,7 @@ class ComponentSlotForm extends ComponentFormBase { '#source_contexts' => [], '#tag_filter' => [], '#display_remove' => TRUE, + '#display_weight' => TRUE, '#component_id' => NULL, '#slot_id' => NULL, '#cardinality_multiple' => TRUE, @@ -231,26 +232,52 @@ class ComponentSlotForm extends ComponentFormBase { if (!isset($configuration['sources'])) { return $form; } + $slot_id = $element['#slot_id'] ?? ''; + $n_sources = count($configuration['sources']); foreach ($configuration['sources'] as $delta => $source_configuration) { - $form[$delta] = static::buildSourceForm($element, $form_state, $definition, $source_configuration, $delta, $wrapper_id); + $form[$delta] = static::buildSourceForm( + array_merge($element, [ + "#default_value" => $source_configuration, + "#array_parents" => array_merge($element["#array_parents"], [$delta]), + ]), $form_state, $definition, $source_configuration); + if ($element['#display_remove'] ?? TRUE) { + $form[$delta]['_remove'] = static::buildRemoveSourceButton($element, $slot_id, $wrapper_id, $delta); + } + if ($element['#display_weight'] ?? TRUE) { + $form[$delta]['_weight'] = static::buildSlotWeight($source_configuration, $delta, $n_sources); + } } return $form; } + /** + * Add slot weight. + */ + protected static function buildSlotWeight(array $configuration, int $delta, int $weight_delta): array { + return [ + '#type' => 'weight', + '#title' => t( + 'Weight for row @number', + ['@number' => $delta + 1] + ), + '#title_display' => 'invisible', + '#delta' => $weight_delta, + '#default_value' => $configuration['_weight'] ?? $delta, + '#weight' => 100, + ]; + } + /** * Build single source form. */ - protected static function buildSourceForm(array $element, FormStateInterface $form_state, array $definition, array $configuration, int $delta, string $parent_wrapper_id): array { + public static function buildSourceForm(array $element, FormStateInterface $form_state, array $definition, array $configuration): array { $slot_id = $element['#slot_id'] ?? ""; - $sources = static::getSources($slot_id, $definition, array_merge( - $element, - [ - "#default_value" => $configuration, - "#array_parents" => array_merge($element["#array_parents"], [$delta]), - ] - )); + if (!isset($element['#default_value'])) { + $element['#default_value'] = $configuration; + } + $sources = static::getSources($slot_id, $definition, $element); $selected_source = static::getSelectedSource($configuration, $sources); - $wrapper_id = static::getElementId($element, 'ui-patterns-slot-item-' . $slot_id . '-' . $delta); + $wrapper_id = static::getElementId($element, 'ui-patterns-slot-item-' . $slot_id); $source_selector = static::buildSourceSelector($sources, $selected_source, $wrapper_id); $form = [ 'source_id' => $source_selector, @@ -261,22 +288,7 @@ class ComponentSlotForm extends ComponentFormBase { ], ], ]; - $form = static::addRequired($form, $slot_id); - $form['_weight'] = [ - '#type' => 'weight', - '#title' => t( - 'Weight for row @number', - ['@number' => $delta + 1] - ), - '#title_display' => 'invisible', - '#delta' => count($form), - '#default_value' => $configuration['_weight'] ?? $delta, - '#weight' => 100, - ]; - if ($element['#display_remove'] === TRUE) { - $form['_remove'] = static::buildRemoveSourceButton($element, $slot_id, $parent_wrapper_id, $delta); - } - return $form; + return empty($slot_id) ? $form : static::addRequired($form, $slot_id); } /** diff --git a/src/Plugin/UiPatterns/Source/DerivableContextSourceBase.php b/src/Plugin/UiPatterns/Source/DerivableContextSourceBase.php index 07e67511ee333132095044a0bbec5bd304e042e7..1a49db7d92e10a45a78974a20b8150c66d6a7c6d 100644 --- a/src/Plugin/UiPatterns/Source/DerivableContextSourceBase.php +++ b/src/Plugin/UiPatterns/Source/DerivableContextSourceBase.php @@ -404,7 +404,7 @@ abstract class DerivableContextSourceBase extends SourcePluginBase { /** @var \Drupal\ui_patterns\SourceInterface $plugin */ $plugin = $this->sourcePluginManager->createInstance( $plugin_id, - SourcePluginBase::buildConfiguration($plugin_id, $this->propDefinition, ["source" => $configuration], $contexts, $form_array_parents) + SourcePluginBase::buildConfiguration($this->propId, $this->propDefinition, ["source" => $configuration], $contexts, $form_array_parents) ); // If ($contexts && $plugin instanceof ContextAwarePluginInterface) { // $this->contextHandler->applyContextMapping($plugin, $contexts); diff --git a/src/Plugin/UiPatterns/Source/FieldSourceBase.php b/src/Plugin/UiPatterns/Source/FieldSourceBase.php index db81e04d3dc88b663a2182303be03ad88d3a4a20..8926e21a3aa7fb81ca03075e514845d1ee1b9f36 100644 --- a/src/Plugin/UiPatterns/Source/FieldSourceBase.php +++ b/src/Plugin/UiPatterns/Source/FieldSourceBase.php @@ -54,7 +54,7 @@ abstract class FieldSourceBase extends SourcePluginBase implements SourceInterfa $form = parent::settingsForm($form, $form_state); $form['label_map'] = [ "#type" => "label", - "#title" => $this->propDefinition['title'] . ": " . $this->label(), + "#title" => $this->propDefinition['title'] ?? '' . ": " . $this->label(), ]; return $form; } diff --git a/src/SourcePluginManager.php b/src/SourcePluginManager.php index de07ef0df79b3550aed78da1dcc152deb91ebc29..70b7809f2ca15339df1ad1026431bff8e73065a1 100644 --- a/src/SourcePluginManager.php +++ b/src/SourcePluginManager.php @@ -359,7 +359,7 @@ class SourcePluginManager extends DefaultPluginManager implements ContextAwarePl public function getSource(string $prop_or_slot_id, array $definition, array $configuration, array $source_contexts = [], array $form_array_parents = []) : ?SourceInterface { if (empty($definition)) { // We consider a slot if no definition is provided. - $definition = ['ui_patterns' => ['type_definition' => $this->propTypeManager->createInstance('slot')]]; + $definition = ['ui_patterns' => ['type_definition' => $this->getSlotPropType()]]; } $source_id = $configuration['source_id'] ?? NULL; if (!$source_id && isset($definition['ui_patterns']['type_definition'])) { @@ -376,4 +376,16 @@ class SourcePluginManager extends DefaultPluginManager implements ContextAwarePl return $source; } + /** + * Get the slot prop type. + * + * @return \Drupal\ui_patterns\PropTypeInterface + * The slot prop type. + */ + public function getSlotPropType() : PropTypeInterface { + /** @var \Drupal\ui_patterns\PropTypeInterface $slot_prop_type */ + $slot_prop_type = $this->propTypeManager->createInstance('slot'); + return $slot_prop_type; + } + }