diff --git a/src/Element/ComponentElementBuilder.php b/src/Element/ComponentElementBuilder.php index 3471054d3cbafcb11cad2be26bf443552f782565..2b2902a23570c92702649f9530363dbe1b7a49a6 100644 --- a/src/Element/ComponentElementBuilder.php +++ b/src/Element/ComponentElementBuilder.php @@ -15,6 +15,7 @@ use Drupal\ui_patterns\SourceInterface; use Drupal\ui_patterns\SourcePluginBase; use Drupal\ui_patterns\SourcePluginManager; use Psr\Log\LoggerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; /** * Component render element builder. @@ -35,6 +36,7 @@ class ComponentElementBuilder implements TrustedCallbackInterface { protected SourcePluginManager $sourcesManager, protected PropTypePluginManager $propTypeManager, protected ComponentPluginManager $componentPluginManager, + protected ModuleHandlerInterface $moduleHandler, protected LoggerInterface $logger, ) { } @@ -89,7 +91,7 @@ class ComponentElementBuilder implements TrustedCallbackInterface { $build = $source->alterComponent($build); $prop_type = $definition['ui_patterns']['type_definition']; $data = $source->getValue($prop_type); - + $this->moduleHandler->alter('ui_patterns_source_value', $data, $source); if (empty($data) && $prop_type->getPluginId() !== 'attributes') { // For JSON Schema validator, empty value is not the same as missing // value, and we want to prevent some of the prop types rules to be @@ -183,7 +185,8 @@ class ComponentElementBuilder implements TrustedCallbackInterface { continue; } $build = $source->alterComponent($build); - $source_value = $source->getValue($slot_prop_type); + $source_value = $source->getValue($slot_prop_type) ?? []; + $this->moduleHandler->alter('ui_patterns_source_value', $source_value, $source); if (Element::isRenderArray($source_value)) { $build["#slots"][$slot_id][] = $this->isSingletonRenderArray($source_value) ? array_values($source_value)[0] : $source_value; } diff --git a/src/Element/ComponentForm.php b/src/Element/ComponentForm.php index b90623d7329edf342e12547564c8d7adc3e4189e..eb440834cd1d9f94e9910c8b52fbcea4787cdafd 100644 --- a/src/Element/ComponentForm.php +++ b/src/Element/ComponentForm.php @@ -287,7 +287,7 @@ class ComponentForm extends ComponentFormBase { '#ajax_url' => $element['#ajax_url'] ?? NULL, '#access' => $element['#render_props'] ?? TRUE, '#default_value' => [ - 'props' => $element['#default_value']['props'], + 'props' => $element['#default_value']['props'] ?? [], ], ]; } diff --git a/src/Element/ComponentSlotForm.php b/src/Element/ComponentSlotForm.php index e06e6e85524d517ae37583fb426dfc71b382abcf..fcc47856c83b9ca8f264e0f3b8b5b2f75ad41d05 100644 --- a/src/Element/ComponentSlotForm.php +++ b/src/Element/ComponentSlotForm.php @@ -149,10 +149,12 @@ class ComponentSlotForm extends ComponentFormBase { /** @var \Drupal\ui_patterns\PropTypePluginManager $prop_type_manager */ $prop_type_manager = \Drupal::service("plugin.manager.ui_patterns_prop_type"); $definition = [ - 'ui_patterns' => $prop_type_manager->createInstance('slot', []), + 'ui_patterns' => [ + "type_definition" => $prop_type_manager->createInstance('slot', []), + ], ]; } - $wrapper_id = static::getElementId($element, 'ui-patterns-slot-' . $slot_id); + $wrapper_id = static::getElementId($element, 'ui-patterns-slot-wrapper-' . $slot_id); $element['#tree'] = TRUE; $element['#table_title'] = $element['#title']; $element['#title_in_component'] = $element['#title']; @@ -162,7 +164,7 @@ class ComponentSlotForm extends ComponentFormBase { (!isset($element['#default_value']['sources']) || count($element['#default_value']['sources']) === 0)) { $element['add_more_button'] = static::buildAddSourceButton($element, $definition, $wrapper_id); } - $element['#prefix'] = '<div class="uip-slot" id="' . $wrapper_id . '">'; + $element['#prefix'] = '<div id="' . $wrapper_id . '">'; $element['#suffix'] = '</div>'; return $element; } @@ -398,10 +400,14 @@ class ComponentSlotForm extends ComponentFormBase { $form_state->setRebuild(TRUE); $returned = NestedArray::getValue($form, $parents); $response = new AjaxResponse(); + $returned["#prefix"] = ""; + $returned["#suffix"] = ""; $response->addCommand(new HtmlCommand('#' . $wrapper_id, $returned)); if (isset($triggering_element["#ui_patterns_slot_operation"]) && $triggering_element["#ui_patterns_slot_operation"] === "add") { $selector = "#" . $triggering_element["#id"]; - $response->addCommand(new InvokeCommand($selector, "val", [""])); + if (!isset($returned['#cardinality_multiple']) || $returned['#cardinality_multiple'] !== FALSE) { + $response->addCommand(new InvokeCommand($selector, "val", [""])); + } } return $response; } diff --git a/src/Plugin/UiPatterns/Source/DerivableContextSourceBase.php b/src/Plugin/UiPatterns/Source/DerivableContextSourceBase.php index 2ea0dbd8b7ec9f42f58b22ebdfa00c01fcd62964..07e67511ee333132095044a0bbec5bd304e042e7 100644 --- a/src/Plugin/UiPatterns/Source/DerivableContextSourceBase.php +++ b/src/Plugin/UiPatterns/Source/DerivableContextSourceBase.php @@ -240,7 +240,7 @@ abstract class DerivableContextSourceBase extends SourcePluginBase { ]; $source_container = [ '#type' => 'container', - '#attributes' => ["id" => $wrapper_id], + '#attributes' => ["id" => $wrapper_id, "class" => ["derivable-context-source-wrapper"]], '#tree' => TRUE, ]; if (!$derivable_context || !array_key_exists($derivable_context, $derivableContexts)) { @@ -254,12 +254,13 @@ abstract class DerivableContextSourceBase extends SourcePluginBase { $derived_contexts = $derivable_context_plugin->getDerivedContexts(); $form[$derivable_context] = $source_container; if (count($derived_contexts) === 0) { + $form["source"] = $source_container; return $form; } /** @var array<string, mixed> $derivable_context_form */ $derivable_context_form = &$form[$derivable_context]; $derived_context = reset($derived_contexts); - $component_id = $derived_context["component_id"]->getContextValue(); + $component_id = isset($derived_context["component_id"]) ? $derived_context["component_id"]->getContextValue() : NULL; $is_slot = $this->isSlot(); // When option is within a group. $group_label = $this->getDerivableContextsOptionGroupLabel($options_derivable_contexts, $derivable_context); @@ -297,6 +298,9 @@ abstract class DerivableContextSourceBase extends SourcePluginBase { */ private function getSelectedDerivableContext(FormStateInterface $form_state, array $options_derivable_contexts) : ?string { $derivable_context = (string) ($this->getSetting('derivable_context') ?? ''); + if (!$derivable_context) { + $derivable_context = $form_state->getValue('derivable_context') ?? NULL; + } // Validate the selected derivable context. if ($derivable_context && !isset($options_derivable_contexts[$derivable_context])) { // Reset value, or take the first one if only one is available. diff --git a/ui_patterns.api.php b/ui_patterns.api.php index bacffbaad5eab125a6c548325e2c9172cee522f9..17504cf6beef4679ba2176d7de6c537dde9f595b 100644 --- a/ui_patterns.api.php +++ b/ui_patterns.api.php @@ -16,3 +16,16 @@ function hook_component_info_alter(array &$definitions) { $definitions['COMPONENT_ID']['slots']['slot_name']["title"] = 'demo'; } + +/** + * Alter Hook for UI Patterns source values. + * + * @param mixed $value + * Value produced by the source. + * @param \Drupal\ui_patterns\SourceInterface $source + * The source object which has produced the value. + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ +function hook_ui_patterns_source_value_alter(mixed &$value, \Drupal\ui_patterns\SourceInterface $source) : void { +} diff --git a/ui_patterns.services.yml b/ui_patterns.services.yml index 2652c1f19d13fb6f523d433667887abad4496f30..ac131fbe71b9ee6e89c909bbbf4b87204a807612 100644 --- a/ui_patterns.services.yml +++ b/ui_patterns.services.yml @@ -46,6 +46,7 @@ services: - "@plugin.manager.ui_patterns_source" - "@plugin.manager.ui_patterns_prop_type" - "@plugin.manager.sdc" + - "@module_handler" - "@logger.channel.ui_patterns" ui_patterns.component_element_alter: class: Drupal\ui_patterns\Element\ComponentElementAlter