Skip to content
Snippets Groups Projects
Commit f4514fa9 authored by Pierre Dureau's avatar Pierre Dureau Committed by christian.wiedemann
Browse files

Resolve #3420517 "2.0.0 alpha1 follwoing form"

parent 590b3dff
No related branches found
No related tags found
1 merge request!62Resolve #3420517 "2.0.0 alpha1 follwoing form"
Showing
with 532 additions and 96 deletions
......@@ -33,7 +33,7 @@ class ComponentBlock extends BlockBase {
*/
public function build() {
$configuration = $this->getConfiguration();
$build = $this->buildComponentData($configuration, $this->getPluginId());
$build = $this->buildComponentRenderable($configuration);
return $build;
}
......
......@@ -44,8 +44,7 @@ class ComponentLayout extends LayoutDefault implements PluginFormInterface {
public function build(array $regions) {
$build = parent::build($regions);
$configuration = $this->getConfiguration();
$data = $this->buildComponentData($configuration, $this->getPluginId());
$data = $this->buildComponentRenderable($configuration, $this->getPluginId());
$build['#layout'] = $this;
$build['#slots'] = $regions;
$build['#props'] = $data['#props'] ?? [];
......
<?php
/**
* @file
* Adds views configuration changes after AJAX interactions.
*/
......@@ -31,8 +31,8 @@ use Drupal\Core\Form\FormStateInterface;
* Usage example:
*
* @code
* $form['component_form_builder'] = [
* '#type' => 'component_form_builder',
* $form['component_form'] = [
* '#type' => 'component_form',
*
* '#default_value' => [
* 'component_id' => 'my_module:my_component',
......@@ -43,9 +43,9 @@ use Drupal\Core\Form\FormStateInterface;
* ];
* @endcode
*
* @FormElement("component_form_builder")
* @FormElement("component_form")
*/
class ComponentFormBuilder extends ComponentFormBuilderBase {
class ComponentForm extends ComponentFormBase {
/**
* {@inheritdoc}
......@@ -75,8 +75,8 @@ class ComponentFormBuilder extends ComponentFormBuilderBase {
if ($input) {
$value = [
'component_id' => $input['component_id'] ?? NULL,
'props' => $input['component_form_builder']['props'] ?? [],
'slots' => $input['component_form_builder']['slots'] ?? [],
'props' => $input['component_form']['props'] ?? [],
'slots' => $input['component_form']['slots'] ?? [],
];
$element['#default_value'] = $value;
return $value;
......@@ -110,7 +110,7 @@ class ComponentFormBuilder extends ComponentFormBuilderBase {
$component_id
));
}
$element["component_form_builder"] = self::buildComponentForm(
$element["component_form"] = self::buildComponentForm(
$element,
$wrapper_id,
$component_id,
......@@ -168,26 +168,26 @@ class ComponentFormBuilder extends ComponentFormBuilderBase {
'#type' => 'container',
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
'props' => [
'#title' => 'Props',
'#type' => 'component_form_props_builder',
'#component_id' => $component_id,
'#source_context' => $element['#source_context'],
'#ajax_url' => $element['#ajax_url'],
'#access' => $element['#render_props'] ?? TRUE,
'#default_value' => ['props' => $element['#default_value']['props']]
],
'slots' => [
'#title' => 'Slots',
'#type' => 'component_form_slots_builder',
'#type' => 'component_slots_form',
'#component_id' => $component_id,
'#source_context' => $element['#source_context'],
'#ajax_url' => $element['#ajax_url'],
'#access' => $element['#render_slots'] ?? TRUE,
'#default_value' => [
'slots' => $element['#default_value']['slots']
]
]
'slots' => $element['#default_value']['slots'],
],
],
'props' => [
'#title' => 'Props',
'#type' => 'component_props_form',
'#component_id' => $component_id,
'#source_context' => $element['#source_context'],
'#ajax_url' => $element['#ajax_url'],
'#access' => $element['#render_props'] ?? TRUE,
'#default_value' => ['props' => $element['#default_value']['props']],
],
];
}
......@@ -267,7 +267,7 @@ class ComponentFormBuilder extends ComponentFormBuilderBase {
$parents = $form_state->getTriggeringElement()['#array_parents'];
$sub_form = NestedArray::getValue($form, array_slice($parents, 0, -1));
$form_state->setRebuild();
return $sub_form['component_form_builder'];
return $sub_form['component_form'];
}
/**
......
......@@ -11,9 +11,9 @@ use Drupal\sdc\Plugin\Component;
use Drupal\ui_patterns\SourcePluginManager;
/**
* Provides a Component form builder element.
* Base class for components forms.
*/
abstract class ComponentFormBuilderBase extends FormElement {
abstract class ComponentFormBase extends FormElement {
/**
* Expand each ajax element with ajax urls.
......@@ -60,7 +60,6 @@ abstract class ComponentFormBuilderBase extends FormElement {
* Returns the source plugin manager.
*/
protected static function sourcePluginManager(): SourcePluginManager {
/** @var \Drupal\ui_patterns\SourcePluginManager $source_plugin_manager */
return \Drupal::service(
'plugin.manager.ui_patterns_source'
);
......@@ -116,7 +115,7 @@ abstract class ComponentFormBuilderBase extends FormElement {
* The parents to locate the form builder.
*/
protected static function getComponentFormStateParents(array $parents): array {
$needle = array_search('component_form_builder', $parents);
$needle = array_search('component_form', $parents);
return array_slice($parents, 0, $needle);
}
......
......@@ -5,6 +5,7 @@ namespace Drupal\ui_patterns\Element;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\ui_patterns\SourceInterface;
use Drupal\ui_patterns\SourcePluginManager;
/**
......@@ -24,16 +25,16 @@ use Drupal\ui_patterns\SourcePluginManager;
*
* @code
* $form['slots'] = [
* '#type' => 'component_form_props_builder',
* '#type' => 'component_props_form',
* '#default_value' => [
* 'props' => [],
* ],
* ];
* @endcode
*
* @FormElement("component_form_props_builder")
* @FormElement("component_props_form")
*/
class ComponentFormPropsBuilder extends ComponentFormBuilderBase {
class ComponentPropsForm extends ComponentFormBase {
/**
* {@inheritdoc}
......@@ -41,7 +42,6 @@ class ComponentFormPropsBuilder extends ComponentFormBuilderBase {
public function getInfo() {
$class = get_class($this);
return [
// The component id.
'#input' => TRUE,
'#multiple' => FALSE,
'#default_value' => NULL,
......@@ -51,91 +51,23 @@ class ComponentFormPropsBuilder extends ComponentFormBuilderBase {
'#theme_wrappers' => ['container'],
];
}
/**
* Build Props Forms.
* Build props forms.
*/
public static function buildForm(
array &$element,
FormStateInterface $form_state,
): array {
$component = self::getComponent($element);
$contexts = self::getComponentSourceContexts($element);
$props = $component->metadata->schema['properties'];
if (empty($props)) {
return $element;
}
$source_plugin_manager = self::sourcePluginManager();
$configuration = $element['#default_value']['props'] ?? [];
foreach ($props as $prop_id => $prop) {
$prop_type = $prop['ui_patterns']['type_definition'];
$source_ids = array_keys($source_plugin_manager->getDefinitionsForPropType($prop_type->getPluginId(), $contexts));
$source_ids = array_combine($source_ids, $source_ids);
if (count($source_ids) === 0) {
continue;
}
$sources = $source_plugin_manager->createInstances($source_ids, SourcePluginManager::buildPluginConfiguration($prop_id, $prop, $configuration[$prop_id] ?? []));
/** @var \Drupal\ui_patterns\SourcePluginBase $selected_source */
$selected_source = NULL;
if (isset($configuration[$prop_id]['source_id']) && $sources[$configuration[$prop_id]['source_id']]) {
$selected_source = $sources[$configuration[$prop_id]['source_id']];
}
else {
$source_id = $source_plugin_manager->getPropTypeDefault($prop_type->getPluginId(), $contexts);
if ($source_id) {
$selected_source = $source_plugin_manager->createInstance($source_id, SourcePluginManager::buildPluginConfiguration($prop_id, $prop, $configuration[$prop_id] ?? []));
}
}
if ($selected_source) {
$element[$prop_id]['value'] = $selected_source->settingsForm(
$element,
$form_state
);
$element[$prop_id]['source_id'] = [
'#type' => 'hidden',
'#value' => $selected_source->getPluginId(),
];
$wrapper_id = 'ui-patterns-prop-item-' . $prop_id;
$element[$prop_id]['#prefix'] = '<div id="' . $wrapper_id . '" class="ui-patterns-wrapper-absolute">';
$element[$prop_id]['#suffix'] = '</div>';
$dropdown_actions = [];
foreach ($sources as $source) {
$source_id = $source->getPluginId();
if ($source_id !== $selected_source->getPluginId()) {
$button = [
'#type' => 'submit',
'#name' => $prop_id . '_' . strtr($source_id, '-', '_') . '_change',
'#value' => $source_id,
'#submit' => [self::class . '::changePropSubmitAjax'],
'#ui_patterns' => [
'parents' => 6,
],
'#source_id' => $source_id,
'#prop_id' => $prop_id,
'#ajax' => [
'callback' => [
self::class,
'changePropItemAjax',
],
'wrapper' => $wrapper_id,
'effect' => 'fade',
],
];
$dropdown_actions[$source_id] = self::expandComponentButton($button, $form_state);
}
}
$element[$prop_id]['source_id'] = [
'#type' => 'hidden',
'#value' => $selected_source->getPluginId(),
];
if (count($dropdown_actions) !== 0) {
$element[$prop_id]['dropdown_actions'] = [
'#type' => 'ui_patterns_actions',
'dropdown_actions' => $dropdown_actions,
];
}
}
$element[$prop_id] = self::buildPropForm($form_state, $prop_id, $prop, $configuration[$prop_id] ?? [], $contexts);
}
if (count(Element::children($element)) === 0) {
hide($element);
......@@ -143,6 +75,86 @@ class ComponentFormPropsBuilder extends ComponentFormBuilderBase {
return $element;
}
/**
* Build single prop form.
*/
protected static function buildPropForm(FormStateInterface $form_state, string $prop_id, array $definition, array $configuration, array $contexts): array {
$element = [];
$source_plugin_manager = self::sourcePluginManager();
$prop_type = $definition['ui_patterns']['type_definition'];
$source_ids = array_keys($source_plugin_manager->getDefinitionsForPropType($prop_type->getPluginId(), $contexts));
$source_ids = array_combine($source_ids, $source_ids);
if (count($source_ids) === 0) {
return [];
}
$sources = $source_plugin_manager->createInstances($source_ids, SourcePluginManager::buildPluginConfiguration($prop_id, $definition, $configuration));
/** @var \Drupal\ui_patterns\SourcePluginBase $selected_source */
$selected_source = NULL;
if (isset($configuration['source_id']) && $sources[$configuration['source_id']]) {
$selected_source = $sources[$configuration['source_id']];
}
else {
$source_id = $source_plugin_manager->getPropTypeDefault($prop_type->getPluginId(), $contexts);
if ($source_id) {
$selected_source = $source_plugin_manager->createInstance($source_id, SourcePluginManager::buildPluginConfiguration($prop_id, $definition, $configuration));
}
}
if ($selected_source) {
$element['value'] = $selected_source->settingsForm(
$element,
$form_state
);
$element['source_id'] = [
'#type' => 'hidden',
'#value' => $selected_source->getPluginId(),
];
$wrapper_id = 'ui-patterns-prop-item-' . $prop_id;
$element['#prefix'] = '<div id="' . $wrapper_id . '" class="ui-patterns-wrapper-absolute">';
$element['#suffix'] = '</div>';
$element['dropdown_actions'] = self::buildSourceSelector($form_state, $prop_id, $wrapper_id, $sources, $selected_source);
}
return $element;
}
/**
* Build sources selector widget.
*/
protected static function buildSourceSelector(FormStateInterface $form_state, string $prop_id, string $wrapper_id, array $sources, SourceInterface $selected_source): array {
$actions = [];
foreach ($sources as $source) {
$source_id = $source->getPluginId();
if ($source_id !== $selected_source->getPluginId()) {
$button = [
'#type' => 'submit',
'#name' => $prop_id . '_' . strtr($source_id, '-', '_') . '_change',
'#value' => $source_id,
'#submit' => [self::class . '::changePropSubmitAjax'],
'#ui_patterns' => [
'parents' => 6,
],
'#source_id' => $source_id,
'#prop_id' => $prop_id,
'#ajax' => [
'callback' => [
self::class,
'changePropItemAjax',
],
'wrapper' => $wrapper_id,
'effect' => 'fade',
],
];
$actions[$source_id] = self::expandComponentButton($button, $form_state);
}
}
if (count($actions) === 0) {
return [];
}
return [
'#type' => 'ui_patterns_actions',
'dropdown_actions' => $actions,
];
}
/**
* Ajax submit handler: Change props type submit handler.
*/
......@@ -155,7 +167,7 @@ class ComponentFormPropsBuilder extends ComponentFormBuilderBase {
$source_id = $trigger_element['#source_id'];
$component_form_parents = self::getComponentFormStateParents($trigger_element['#parents']);
$configuration = $form_state->getValue($component_form_parents);
$configuration['component_form_builder']['props'][$prop_id]['source_id'] = $source_id;
$configuration['component_form']['props'][$prop_id]['source_id'] = $source_id;
$form_state->setValue($component_form_parents, $configuration);
$form_state->setRebuild();
}
......
......@@ -25,16 +25,16 @@ use Drupal\ui_patterns\SourcePluginManager;
*
* @code
* $form['slots'] = [
* '#type' => 'component_form_slots_builder',
* '#type' => 'component_slots_form',
* '#default_value' => [
* 'slots' => [],
* ],
* ];
* @endcode
*
* @FormElement("component_form_slots_builder")
* @FormElement("component_slots_form")
*/
class ComponentFormSlotsBuilder extends ComponentFormBuilderBase {
class ComponentSlotsForm extends ComponentFormBase {
/**
* {@inheritdoc}
......@@ -42,7 +42,6 @@ class ComponentFormSlotsBuilder extends ComponentFormBuilderBase {
public function getInfo() {
$class = get_class($this);
return [
// The component id.
'#input' => TRUE,
'#multiple' => FALSE,
'#default_value' => NULL,
......@@ -56,10 +55,7 @@ class ComponentFormSlotsBuilder extends ComponentFormBuilderBase {
/**
* Processes slotes form element.
*/
public static function buildForm(
array &$element,
FormStateInterface $form_state,
): array {
public static function buildForm(array &$element, FormStateInterface $form_state): array {
/** @var \Drupal\ui_patterns\SourcePluginManager $sources_manager */
$sources_manager = \Drupal::service("plugin.manager.ui_patterns_source");
......@@ -67,7 +63,7 @@ class ComponentFormSlotsBuilder extends ComponentFormBuilderBase {
$source_ids = array_combine($source_ids, $source_ids);
$valid_source_plugins = $sources_manager->createInstances(
$source_ids,
SourcePluginManager::buildPluginConfiguration('slot', [], [] ),
SourcePluginManager::buildPluginConfiguration('slot', [], []),
);
$options = [];
foreach ($valid_source_plugins as $valid_source_plugin) {
......@@ -82,102 +78,139 @@ class ComponentFormSlotsBuilder extends ComponentFormBuilderBase {
}
$configuration = $element['#default_value']['slots'] ?? [];
foreach ($component->metadata->slots as $slot_id => $slot) {
$wrapper_id = 'ui-patterns-slot-' . $slot_id;
$element[$slot_id]['#slot_id'] = $slot_id;
$element[$slot_id]['sources'] = [
'#theme' => 'field_multiple_value_form',
'#title' => $slot['title'],
'#cardinality_multiple' => TRUE,
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
];
if (isset($configuration[$slot_id]['sources'])) {
foreach ($configuration[$slot_id]['sources'] as $delta => $source_configuration) {
if (!isset($source_configuration['source_id'])) {
continue;
}
$source = $sources_manager->createInstance(
$source_configuration['source_id'],
SourcePluginManager::buildPluginConfiguration($slot_id, $slot, $source_configuration)
);
$element[$slot_id]['sources'][$delta]['value'] = $source->settingsForm(
[],
$form_state
);
$element[$slot_id]['sources'][$delta]['source_id'] = [
'#type' => 'hidden',
'#value' => $source->getPluginId()
];
$element[$slot_id]['sources'][$delta]['_weight'] = [
'#type' => 'weight',
'#title' => t(
'Weight for row @number',
['@number' => $delta + 1]
),
'#title_display' => 'invisible',
'#delta' => count($element[$slot_id]['sources'][$delta]),
'#default_value' => $source_configuration['_weight'] ?? $delta,
'#weight' => 100,
];
$delete_action = [
'#type' => 'submit',
'#name' => strtr($slot_id, '-', '_') . $delta . '_remove',
'#value' => t('Delete'),
'#submit' => [self::class . '::removeSlotItemSubmitAjax'],
'#access' => TRUE,
'#delta' => $delta,
'#ui_patterns' => [
'parents' => 5,
],
'#slot_id' => $slot_id,
'#ajax' => [
'callback' => [self::class, 'removeSlotItemAjax'],
'wrapper' => $wrapper_id,
'effect' => 'fade',
],
];
$element[$slot_id]['sources'][$delta]['_remove'] = [
'#type' => 'ui_patterns_actions',
'#ui_patterns_header' => TRUE,
'dropdown_actions' => [
self::expandComponentButton(
$delete_action,
$form_state
),
],
];
}
}
$action_buttons = [];
foreach ($options as $source_id => $source_label) {
$action_buttons[$source_id] = self::expandComponentButton([
'#type' => 'submit',
'#name' => strtr($slot_id, '-', '_') . $source_id . '_add_more',
'#value' => t('Add %source', ['%source' => $source_label]),
'#submit' => [
self::class . '::addSlotItemSubmitAjax',
],
'#access' => TRUE,
'#ui_patterns' => TRUE,
'#slot_id' => $slot_id,
'#source_id' => $source_id,
'#ajax' => [
'callback' => [
self::class,
'addSlotItemAjax',
],
'wrapper' => $wrapper_id,
'effect' => 'fade',
],
], $form_state);
$element[$slot_id] = self::buildSlotForm($form_state, $slot_id, $slot, $configuration[$slot_id] ?? [], $options);
}
return $element;
}
/**
* Build single slot form.
*/
protected static function buildSlotForm(FormStateInterface $form_state, string $slot_id, array $definition, array $configuration, array $options): array {
$element = [];
$wrapper_id = 'ui-patterns-slot-' . $slot_id;
$element['#slot_id'] = $slot_id;
$element['sources'] = self::buildSourcesForm($form_state, $slot_id, $definition, $configuration, $wrapper_id);
$element['add_more_button'] = self::buildSourceSelector($form_state, $slot_id, $wrapper_id, $options);
return $element;
}
/**
* Build single slot's sources form.
*/
protected static function buildSourcesForm(FormStateInterface $form_state, string $slot_id, array $definition, array $configuration, string $wrapper_id): array {
$element = [
'#theme' => 'field_multiple_value_form',
'#title' => $definition['title'],
'#cardinality_multiple' => TRUE,
'#prefix' => '<div id="' . $wrapper_id . '">',
'#suffix' => '</div>',
];
if (!isset($configuration['sources'])) {
return $element;
}
foreach ($configuration['sources'] as $delta => $source_configuration) {
if (!isset($source_configuration['source_id'])) {
continue;
}
$element[$slot_id]['add_more_button'] = self::buildComponentDropbutton(
$action_buttons
);
$element[$delta] = self::buildSourceForm($form_state, $slot_id, $definition, $source_configuration, $delta, $wrapper_id);
}
return $element;
}
/**
* Build single source form.
*/
protected static function buildSourceForm(FormStateInterface $form_state, string $slot_id, array $definition, array $configuration, int $delta, string $wrapper_id): array {
$element = [];
$sources_manager = \Drupal::service("plugin.manager.ui_patterns_source");
$source = $sources_manager->createInstance(
$configuration['source_id'],
SourcePluginManager::buildPluginConfiguration($slot_id, $definition, $configuration)
);
$element['value'] = $source->settingsForm([], $form_state);
$element['source_id'] = [
'#type' => 'hidden',
'#value' => $source->getPluginId(),
];
$element['_weight'] = [
'#type' => 'weight',
'#title' => t(
'Weight for row @number',
['@number' => $delta + 1]
),
'#title_display' => 'invisible',
'#delta' => count($element),
'#default_value' => $configuration['_weight'] ?? $delta,
'#weight' => 100,
];
$element['_remove'] = self::buildRemoveSourceButton($form_state, $slot_id, $wrapper_id, $delta);
return $element;
}
/**
* Build widget to remove source.
*/
protected static function buildRemoveSourceButton(FormStateInterface $form_state, string $slot_id, string $wrapper_id, int $delta): array {
$delete_action = [
'#type' => 'submit',
'#name' => strtr($slot_id, '-', '_') . $delta . '_remove',
'#value' => t('Delete'),
'#submit' => [self::class . '::removeSlotItemSubmitAjax'],
'#access' => TRUE,
'#delta' => $delta,
'#ui_patterns' => [
'parents' => 5,
],
'#slot_id' => $slot_id,
'#ajax' => [
'callback' => [self::class, 'removeSlotItemAjax'],
'wrapper' => $wrapper_id,
'effect' => 'fade',
],
];
return [
'#type' => 'ui_patterns_actions',
'#ui_patterns_header' => TRUE,
'dropdown_actions' => [
self::expandComponentButton(
$delete_action,
$form_state
),
],
];
}
/**
* Build source selector.
*/
protected static function buildSourceSelector(FormStateInterface $form_state, string $slot_id, string $wrapper_id, array $options): array {
$action_buttons = [];
foreach ($options as $source_id => $source_label) {
$action_buttons[$source_id] = self::expandComponentButton([
'#type' => 'submit',
'#name' => strtr($slot_id, '-', '_') . $source_id . '_add_more',
'#value' => t('Add %source', ['%source' => $source_label]),
'#submit' => [
self::class . '::addSlotItemSubmitAjax',
],
'#access' => TRUE,
'#ui_patterns' => TRUE,
'#slot_id' => $slot_id,
'#source_id' => $source_id,
'#ajax' => [
'callback' => [
self::class,
'addSlotItemAjax',
],
'wrapper' => $wrapper_id,
'effect' => 'fade',
],
], $form_state);
}
return self::buildComponentDropbutton($action_buttons);
}
/**
* Ajax submit handler: Add slot item.
*/
......@@ -190,7 +223,7 @@ class ComponentFormSlotsBuilder extends ComponentFormBuilderBase {
$source_id = $trigger_element['#source_id'];
$component_form_parents = self::getComponentFormStateParents($trigger_element['#parents']);
$configuration = $form_state->getValue($component_form_parents);
$configuration['component_form_builder']['slots'][$slot_id]['sources'][]['source_id'] = $source_id;
$configuration['component_form']['slots'][$slot_id]['sources'][]['source_id'] = $source_id;
$form_state->setValue($component_form_parents, $configuration);
$form_state->setRebuild();
}
......@@ -216,7 +249,7 @@ class ComponentFormSlotsBuilder extends ComponentFormBuilderBase {
$slot_id = $trigger_element['#slot_id'];
$component_form_parents = self::getComponentFormStateParents($trigger_element['#parents']);
$configuration = $form_state->getValue($component_form_parents);
unset($configuration['component_form_builder']['slots'][$slot_id]['sources'][$delta]);
unset($configuration['component_form']['slots'][$slot_id]['sources'][$delta]);
$form_state->setValue($component_form_parents, $configuration);
$form_state->setRebuild();
}
......
......@@ -80,7 +80,7 @@ class ComponentElementBuilder {
[
'prop_id' => $prop_id,
'prop_definition' => $definition,
'form_value' => $configuration['value'] ?? [],
'settings' => $configuration,
]
);
if (!$source) {
......@@ -140,8 +140,8 @@ class ComponentElementBuilder {
/**
* Add source data to the slot.
*/
protected function addSlotSource(array $build, string $slot_id, array $definition, array $source_configuration, array $contexts): array {
$source_id = $source_configuration['id'];
protected function addSlotSource(array $build, string $slot_id, array $definition, array $configuration, array $contexts): array {
$source_id = $configuration['source_id'];
if (!$this->sourcesManager->isApplicable($source_id, $contexts)) {
return $build;
}
......@@ -150,7 +150,7 @@ class ComponentElementBuilder {
[
'prop_id' => $slot_id,
'prop_definition' => $definition,
'form_value' => $source_configuration['value'] ?? [],
'settings' => $configuration,
]
);
$build = $source->alterComponent($build);
......
......@@ -86,12 +86,10 @@ trait ComponentFormBuilderTrait {
bool $render_slots = TRUE,
bool $render_props = TRUE
): array {
$form_state = $form_state instanceof SubformState ? $form_state->getCompleteFormState(
) : $form_state;
$form_state = $form_state instanceof SubformState ? $form_state->getCompleteFormState() : $form_state;
return [
'ui_patterns' => [
'#type' => 'component_form_builder',
'#type' => 'component_form',
'#component_id' => $initial_component_id,
'#ajax_url' => $this->getAjaxUrl($form_state),
'#source_context' => $this->getComponentSourceContexts(),
......@@ -103,10 +101,22 @@ trait ComponentFormBuilderTrait {
}
/**
* Build component data.
* Build component renderable (a SDC render element).
*/
public function buildComponentData() {
return [];
protected function buildComponentRenderable(array $configuration, string $initial_component_id = NULL): array {
$configuration = $configuration['ui_patterns'] ?? [];
$component_id = $configuration['component_id'] ?? $initial_component_id;
if ($component_id === NULL) {
return [];
}
if (!str_contains($component_id, ':')) {
return [];
}
// @todo injection
$component = \Drupal::service('plugin.manager.sdc')->find($component_id);
$builder = \Drupal::service('ui_patterns.component_element_builder');
$contexts = $this->getComponentSourceContexts();
return $builder->build($component, $configuration, $contexts);
}
}
......@@ -6,7 +6,6 @@ namespace Drupal\ui_patterns\Plugin\UiPatterns\Source;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Template\Attribute;
use Drupal\ui_patterns\SourcePluginBase;
/**
......@@ -31,25 +30,23 @@ class AttributesWidget extends SourcePluginBase {
// possible anymore because SDC will not validate it against the prop
// type schema.
$value = parent::getData();
if (is_array($value)) {
return $value;
if (!is_string($value)) {
return [];
}
return [];
return $this->convertStringToAttributesMapping($value);
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state): array {
// In UI Patterns 2.x, attributes are associative arrays, not strings.
// We use textfield (like UI Patterns Settings do), but we don't store it
// as a string in config.
// Attributes are associative arrays, but this source plugin is storing
// them as string in config.
// It would be better to use something else than a textfield one day.
$value = new Attribute($this->getSetting('value'));
$form = [
'#type' => 'textfield',
'#title' => $this->propDefinition['title'],
'#default_value' => (string) $value,
'#default_value' => $this->getSetting('value'),
];
// Allow anything in attributes values, which are between simple and double
// quotes. Forbide some characters in attributes names.
......@@ -62,11 +59,9 @@ class AttributesWidget extends SourcePluginBase {
}
/**
* {@inheritdoc}
* Convert a string to an attribute mapping.
*/
final public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::submitConfigurationForm($form, $form_state);
$value = $this->getSetting('value');
protected function convertStringToAttributesMapping(string $value): array {
$parse_html = '<div ' . $value . '></div>';
$attributes = [];
foreach (Html::load($parse_html)->getElementsByTagName('div') as $div) {
......@@ -74,7 +69,7 @@ class AttributesWidget extends SourcePluginBase {
$attributes[$attr->nodeName] = $attr->nodeValue;
}
}
$this->configuration['form_value'] = $attributes;
return $attributes;
}
}
......@@ -25,7 +25,7 @@ class ChecboxesWidget extends SourcePluginBase {
* {@inheritdoc}
*/
public function getData(): mixed {
return array_filter($this->getSetting('value'));
return array_filter($this->getSetting('value') ?? []);
}
/**
......
......@@ -21,29 +21,29 @@ use Drupal\ui_patterns\SourcePluginBase;
*/
class ListTextareaWidget extends SourcePluginBase {
/**
* {@inheritdoc}
*/
public function getData(): mixed {
$long_text = $this->getSetting('value');
return preg_split("/\r\n|\n|\r/", $long_text);
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state): array {
$items = $this->getSetting('value');
$long_text = implode("\r", $items);
if (is_array($items)) {
$items = implode("\r", $items);
}
$form = [
'#type' => 'textarea',
'#title' => $this->propDefinition['title'],
'#default_value' => $long_text,
'#default_value' => $items,
"#description" => $this->t("One item by line"),
];
return $form;
}
/**
* {@inheritdoc}
*/
final public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::submitConfigurationForm($form, $form_state);
$long_text = $this->getSetting('value');
$items = preg_split("/\r\n|\n|\r/", $long_text);
$this->configuration['form_value'] = $items;
}
}
......@@ -73,7 +73,6 @@ interface SourceInterface extends ConfigurableInterface, PluginInspectionInterfa
*/
public function getData(): mixed;
/**
* Returns a form to configure settings for the source plugins.
*
......
......@@ -6,6 +6,7 @@ namespace Drupal\ui_patterns;
use Drupal\Component\Plugin\PluginBase;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
use Drupal\Core\Plugin\ContextAwarePluginAssignmentTrait;
......@@ -90,6 +91,12 @@ abstract class SourcePluginBase extends PluginBase implements
$this->setDefinedContextValues();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state): array {
return [];
}
/**
* {@inheritdoc}
......
......@@ -69,9 +69,9 @@ class SourcePluginManager extends DefaultPluginManager implements ContextAwarePl
}
/**
* Builds default plugin configuration array.
* Build plugin configuration.
*/
public static function buildPluginConfiguration(string $prop_id, array $prop_definition, array $settings = []):array {
public static function buildPluginConfiguration(string $prop_id, array $prop_definition, array $settings = []): array {
return [
'prop_id' => $prop_id,
'prop_definition' => $prop_definition,
......
......@@ -43,24 +43,3 @@ function template_preprocess_ui_patterns_actions(&$variables) {
$variables['dropdown_actions'] = $element['dropdown_actions'];
}
}
/**
* Implements hook_preprocess_HOOK() for field_multiple_value_form().
*/
function ui_patterns_preprocess_field_multiple_value_form(&$variables) {
// @todo Move header buttons to own column.
/*
if (!empty($variables['table']['#header']) && isset($variables['table']['#rows'][0])) {
// Find paragraph_actions and move to header.
// @see template_preprocess_field_multiple_value_form()
if (is_array($variables['table']['#rows'][0]['data'][1]) && !empty($variables['table']['#rows'][0]['data'][1]['data']['_remove']['#ui_patterns_header'])) {
$variables['table']['#header'][0]['data'] = [
'title' => $variables['table']['#header'][0]['data'],
'button' => $variables['table']['#rows'][0]['data'][1]['_remove']['data'],
];
unset($variables['table']['#rows'][0]);
}
}
*/
}
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