Skip to content
Snippets Groups Projects
Commit 8c66937b authored by Mikael Meulle's avatar Mikael Meulle
Browse files

Merge branch '3517343-infinite-loop-with' into '2.0.x'

Resolve #3517343 "Infinite loop with"

See merge request !364
parents b2216dcb 12bbf267
No related branches found
No related tags found
No related merge requests found
Pipeline #465946 failed
......@@ -187,12 +187,19 @@ abstract class ComponentFormBase extends FormElementBase implements TrustedCallb
/**
* Get source plugin form.
*/
protected static function getSourcePluginForm(FormStateInterface $form_state, SourceInterface $source, string $wrapper_id): array {
protected static function getSourcePluginForm(FormStateInterface $form_state, ?SourceInterface $source, string $wrapper_id): array {
if (!$source) {
return [
"#type" => 'container',
"#attributes" => [
'id' => $wrapper_id,
],
];
}
$form = $source->settingsForm([], $form_state);
$form["#type"] = 'container';
$form['#attributes'] = [
'id' => $wrapper_id,
];
// @phpstan-ignore-next-line
$form['#prefix'] = "<div id='" . $wrapper_id . "'>" . ($form['#prefix'] ?? '');
$form['#suffix'] = ($form['#suffix'] ?? '' ) . "</div>";
// Weird, but :switchSourceForm() AJAX handler doesn't work without that.
foreach (Element::children($form) as $child) {
if (isset($form[$child]['#description']) && !isset($form[$child]['#description_display'])) {
......@@ -214,13 +221,17 @@ abstract class ComponentFormBase extends FormElementBase implements TrustedCallb
/**
* Get selected source plugin.
*/
protected static function getSelectedSource(array $configuration, array $sources): ?SourceInterface {
protected static function getSelectedSource(array $configuration, array $sources, bool $auto_select = FALSE): ?SourceInterface {
$source_id = $configuration['source_id'] ?? NULL;
foreach ($sources as $source) {
if ($source->getPluginId() === $source_id) {
return $source;
}
}
if (($auto_select && count($sources) > 0) || (count($sources) == 1)) {
// Default source is in first position.
return current($sources);
}
return NULL;
}
......@@ -244,6 +255,28 @@ abstract class ComponentFormBase extends FormElementBase implements TrustedCallb
return $element;
}
/**
* Add title and description to the source element.
*
* @param array $element
* The element.
*
* @return array
* The element with title and description.
*/
protected static function addTitleAndDescription(array $element): array {
if (isset($element["source"]["value"])) {
$element["source"]["value"]["#title_display"] = 'before';
if (empty($element["source"]["value"]["#title"])) {
$element["source"]["value"]["#title"] = $element["#title"];
}
if (empty($element["source"]["value"]["#description"])) {
$element["source"]["value"]["#description"] = $element['#description'] ?? NULL;
}
}
return $element;
}
/**
* Alter the element after the form is built.
*
......@@ -303,7 +336,7 @@ abstract class ComponentFormBase extends FormElementBase implements TrustedCallb
if (empty($sources)) {
return [];
}
if (count($sources) == 1) {
if ($selected_source && (count($sources) == 1)) {
return [
'#type' => 'hidden',
'#value' => array_keys($sources)[0],
......@@ -318,6 +351,7 @@ abstract class ComponentFormBase extends FormElementBase implements TrustedCallb
'#attributes' => [
'class' => ["uip-source-selector"],
],
'#empty_option' => t('- Select -'),
// '#prop_id' => $selected_source?->getPropId(),
// '#prop_definition' => $selected_source?->getPropDefinition(),
'#ajax' => [
......
......@@ -54,6 +54,7 @@ class ComponentPropForm extends ComponentFormBase {
// Wrapped (into details/summary) or not.
'#wrap' => FALSE,
'#render_sources' => TRUE,
'#auto_select' => TRUE,
'#process' => [
[$class, 'buildForm'],
[$class, 'processPropOrSlot'],
......@@ -76,32 +77,30 @@ class ComponentPropForm extends ComponentFormBase {
*/
public static function buildForm(array &$element, FormStateInterface $form_state): array {
$element['#tree'] = TRUE;
$prop_id = $element['#prop_id'];
$component = static::getComponent($element);
if (!$component) {
if (!$component || !isset($element['#prop_id'])) {
return [];
}
$prop_id = $element['#prop_id'];
$definition = $component->metadata->schema['properties'][$prop_id];
$configuration = $element['#default_value'] ?? [];
$sources = static::getSources($prop_id, $definition, $element);
$selected_source = static::getSelectedSource($configuration, $sources);
if (!$selected_source) {
// Default source is in first position.
$selected_source = current($sources);
}
if (!$selected_source) {
return [];
}
$wrapper_id = static::getElementId($element, 'ui-patterns-prop-item-' . $prop_id);
// -----
$sources = static::getSources($prop_id, $definition, $element);
$selected_source = static::getSelectedSource($configuration, $sources, $element['#auto_select'] ?? TRUE);
$source_selector = static::buildSourceSelector($sources, $selected_source, $wrapper_id);
$source_form = static::getSourcePluginForm($form_state, $selected_source, $wrapper_id);
$source_form = $selected_source ? static::getSourcePluginForm($form_state, $selected_source, $wrapper_id) : [
'#type' => 'container',
'#attributes' => [
'id' => $wrapper_id,
],
];
$element += [
'source_id' => $source_selector,
'source' => array_merge($source_form, ['#prop_id' => $prop_id]),
];
if (!($element['#render_sources'] ?? TRUE)) {
if (!($element['#render_sources'] ?? TRUE) && $selected_source) {
$element['source_id'] = [
'#type' => 'hidden',
'#value' => $selected_source->getPluginId(),
......@@ -109,14 +108,8 @@ class ComponentPropForm extends ComponentFormBase {
}
$element = static::addRequired($element, $prop_id);
// This allows "widgets" to have a title when #wrap is unset.
if (!($element['#wrap'] ?? TRUE) && isset($element["source"]["value"])) {
$element["source"]["value"]["#title_display"] = 'before';
if (empty($element["source"]["value"]["#title"])) {
$element["source"]["value"]["#title"] = $element["#title"];
}
if (empty($element["source"]["value"]["#description"])) {
$element["source"]["value"]["#description"] = $element['#description'] ?? NULL;
}
if (!($element['#wrap'] ?? TRUE)) {
$element = static::addTitleAndDescription($element);
}
return $element;
}
......
......@@ -72,6 +72,7 @@ class ComponentSlotForm extends ComponentFormBase {
'#display_weight' => TRUE,
'#component_id' => NULL,
'#slot_id' => NULL,
'#auto_select' => TRUE,
'#cardinality_multiple' => TRUE,
'#process' => [
[$class, 'buildForm'],
......@@ -278,9 +279,9 @@ class ComponentSlotForm extends ComponentFormBase {
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);
$sources = static::getSources($slot_id, $definition, $element);
$selected_source = static::getSelectedSource($configuration, $sources, $element['#auto_select'] ?? TRUE);
$source_selector = static::buildSourceSelector($sources, $selected_source, $wrapper_id);
$form = [
'source_id' => $source_selector,
......@@ -291,7 +292,14 @@ class ComponentSlotForm extends ComponentFormBase {
],
],
];
return empty($slot_id) ? $form : static::addRequired($form, $slot_id);
if (empty($slot_id)) {
return $form;
}
$form = static::addRequired($form, $slot_id);
if (!($element['#wrap'] ?? TRUE)) {
$form = static::addTitleAndDescription($form);
}
return $form;
}
/**
......
......@@ -244,7 +244,7 @@ abstract class DerivableContextSourceBase extends SourcePluginBase {
'#tree' => TRUE,
];
if (!$derivable_context || !array_key_exists($derivable_context, $derivableContexts)) {
$form["source"] = $source_container;
$form[$derivable_context ?? ''] = $source_container;
return $form;
}
$source = $this->getSetting($derivable_context) ?? [];
......@@ -254,7 +254,6 @@ 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 */
......@@ -271,15 +270,16 @@ abstract class DerivableContextSourceBase extends SourcePluginBase {
}
$derivable_context_form["value"] = [
'#type' => $is_slot ? 'component_slot_form' : 'component_prop_form',
'#default_value' => $source,
'#component_id' => $component_id,
'#title' => '',
'#source_contexts' => $derived_context,
'#cardinality_multiple' => FALSE,
'#auto_select' => FALSE,
'#display_remove' => FALSE,
"#wrap" => FALSE,
'#' . ($is_slot ? 'slot_id' : 'prop_id') => $this->getPropId(),
'#tree' => TRUE,
'#default_value' => $source,
'#source_contexts' => $derived_context,
'#tag_filter' => $this->getSourcesTagFilter(),
];
return $form;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment