From b741fa04a1875145296573b209d518d9e509cd93 Mon Sep 17 00:00:00 2001 From: Florent Torregrosa <14238-florenttorregrosa@users.noreply.drupalcode.org> Date: Fri, 9 Jun 2023 17:06:03 +0200 Subject: [PATCH 01/17] Issue #3365913: Number: Support min and max --- src/Plugin/UiPatterns/SettingType/NumberSettingType.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Plugin/UiPatterns/SettingType/NumberSettingType.php b/src/Plugin/UiPatterns/SettingType/NumberSettingType.php index 99fd99c..8d30a27 100644 --- a/src/Plugin/UiPatterns/SettingType/NumberSettingType.php +++ b/src/Plugin/UiPatterns/SettingType/NumberSettingType.php @@ -24,6 +24,8 @@ class NumberSettingType extends PatternSettingTypeBase { '#title' => $def->getLabel(), '#description' => $def->getDescription(), '#default_value' => $this->getValue($value), + '#min' => $def['min'] ?? NULL, + '#max' => $def['max'] ?? NULL, ]; $this->handleInput($form[$def->getName()], $def, $form_type); return $form; -- GitLab From 65db0d6a7b8b9f6d5d310334e485b70fcbbf6d5c Mon Sep 17 00:00:00 2001 From: "Christian.wiedemann" <7688-Christian.wiedemann@users.noreply.drupalcode.org> Date: Mon, 17 Jul 2023 08:23:58 +0000 Subject: [PATCH 02/17] Issue #3373396: Field and Variant conditions --- src/Definition/PatternDefinitionSetting.php | 24 +++++++++++ src/Form/SettingsFormBuilder.php | 40 +++++++++++++++++++ src/Plugin/PatternSettingTypeBase.php | 2 +- .../SettingType/ValueSettingType.php | 34 ++++++++++++++++ .../templates/pattern-foo-settings.html.twig | 2 +- .../templates/settings.ui_patterns.yml | 20 +++++++++- 6 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 src/Plugin/UiPatterns/SettingType/ValueSettingType.php diff --git a/src/Definition/PatternDefinitionSetting.php b/src/Definition/PatternDefinitionSetting.php index d77932d..e66535c 100644 --- a/src/Definition/PatternDefinitionSetting.php +++ b/src/Definition/PatternDefinitionSetting.php @@ -53,6 +53,7 @@ class PatternDefinitionSetting implements \ArrayAccess { $this->definition['name'] = $name_key; $this->definition['group'] = $value['group'] ?? NULL; $this->definition['weight'] = $value['weight'] ?? NULL; + $this->definition['states'] = $value['states'] ?? []; $this->definition['type'] = $value['type'] ?? 'textfield'; $this->definition['label'] = $value['label'] ?? $name_key; $this->definition['required'] = $value['required'] ?? FALSE; @@ -350,6 +351,29 @@ class PatternDefinitionSetting implements \ArrayAccess { return $this; } + /** + * Get states property. + * + * @return string + * Property value. + */ + public function getStates() { + return $this->definition['states']; + } + + /** + * Set States property. + * + * @param string $type + * Property value. + * + * @return $this + */ + public function setStates($states) { + $this->definition['states'] = $states; + return $this; + } + /** * Get Type property. * diff --git a/src/Form/SettingsFormBuilder.php b/src/Form/SettingsFormBuilder.php index 38e48c8..0326b40 100644 --- a/src/Form/SettingsFormBuilder.php +++ b/src/Form/SettingsFormBuilder.php @@ -9,6 +9,7 @@ use Drupal\Core\Render\Element; use Drupal\Core\Render\Element\Form; use Drupal\ui_patterns\Definition\PatternDefinition; use Drupal\ui_patterns\UiPatterns; +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; use Drupal\ui_patterns_settings\UiPatternsSettings; use Drupal\ui_patterns_settings\UiPatternsSettingsManager; @@ -111,6 +112,7 @@ class SettingsFormBuilder { $form['settings'] += $settingType->buildConfigurationForm([], $setting_value, $token_value, 'layouts_display'); } SettingsFormBuilder::buildVariantsForm(".ui-patterns-variant-selector-" . $definition->id(), $form['settings'], $definition); + SettingsFormBuilder::buildStatesForm(".ui-patterns-variant-selector-" . $definition->id(), $form['settings'], $definition); } } @@ -178,6 +180,7 @@ class SettingsFormBuilder { $fieldset += $settingType->buildConfigurationForm([], $setting_value, $token_value, 'display'); } SettingsFormBuilder::buildVariantsForm('.ui-patterns-variant-selector-' . $pattern_id, $fieldset, $definition); + SettingsFormBuilder::buildStatesForm('.ui-patterns-variant-selector-' . $pattern_id, $fieldset, $definition); } } if (!empty($form['pattern_settings'])) { @@ -206,6 +209,43 @@ class SettingsFormBuilder { } } + /** + * Build settings form. + * + * @param string $select_selector + * The id of the variant select field. + * @param array $fieldset + * The fieldset. + * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition + * The pattern definition. + */ + private static function buildStatesForm($variant_selector, array &$fieldset, PatternDefinition $definition) { + $settings = UiPatternsSettings::getPatternDefinitionSettings($definition); + /** @var PatternDefinitionSetting $setting */ + foreach ($settings as $setting_name => $setting) { + $states = $setting->getStates(); + if (count($states) !== 0) { + foreach ($states as $visibilty => $conditions) { + foreach ($conditions as $state) { + if (isset($state['variant'])) { + $fieldset[$setting_name]['#states'][$visibilty][][$variant_selector]['value'] = $state['variant']; + if (isset($fieldset[$setting_name . '_token'])) { + $fieldset[$setting_name . '_token']['#states'][$visibilty][][$variant_selector]['value'] = $state['variant']; + } + } + if (isset($state['setting'])) { + $setting_select = '.js-ui-patterns-settings-' . $state['setting']; + $fieldset[$setting_name]['#states'][$visibilty][][$setting_select]['value'] = $state['value']; + if (isset($fieldset[$setting_name . '_token'])) { + $fieldset[$setting_name . '_token']['#states'][$visibilty][][$setting_select]['value'] = $state['value']; + } + } + } + } + } + } + } + /** * Hide all settings which are configured by the variant. * diff --git a/src/Plugin/PatternSettingTypeBase.php b/src/Plugin/PatternSettingTypeBase.php index fd024c2..85e96f8 100644 --- a/src/Plugin/PatternSettingTypeBase.php +++ b/src/Plugin/PatternSettingTypeBase.php @@ -326,7 +326,7 @@ abstract class PatternSettingTypeBase extends PluginBase implements PatternDefinitionSetting $def, $form_type ) { - $input['#attributes']['class'][] = 'js-ui-patterns-settings__input'; + $input['#attributes']['class'][] = 'js-ui-patterns-settings__input js-ui-patterns-settings-' . $def->getName(); $input['#wrapper_attributes']['class'][] = 'js-ui-patterns-settings__input-wrapper'; if ($def->getRequired()) { $input['#title'] .= ' *'; diff --git a/src/Plugin/UiPatterns/SettingType/ValueSettingType.php b/src/Plugin/UiPatterns/SettingType/ValueSettingType.php new file mode 100644 index 0000000..eb5ca41 --- /dev/null +++ b/src/Plugin/UiPatterns/SettingType/ValueSettingType.php @@ -0,0 +1,34 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; + +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; +use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; + +/** + * Value setting type. + * + * @UiPatternsSettingType( + * id = "value", + * label = @Translation("Value") + * ) + */ +class ValueSettingType extends PatternSettingTypeBase { + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm( + array $form, + $value, + $token_value, + $form_type + ) { + return []; + } + + public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { + return []; + } + +} diff --git a/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig b/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig index 1ed615f..cdb8747 100644 --- a/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig +++ b/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig @@ -14,5 +14,5 @@ <div class="group_sub">Group sub: {{ group_sub }}</div> <div class="media_style">Media Style: {{ media_style }}</div> <div class="select_config">select_config: {{ pattern_configuration('foo_settings', '', 'select_config')[select_config] }}</div> - + <div class="value">Value: {{ setting_value }}</div> </div> diff --git a/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml b/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml index f67ac4e..d121d6f 100644 --- a/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml +++ b/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml @@ -13,10 +13,15 @@ foo_settings: label: Blue settings: textfield: blue + setting_value: '%select_states' media_style: definition: image_style: 'large' settings: + setting_value: + type: value + label: Value Setting + default_value: text preview textfield: type: textfield label: Textfield @@ -72,9 +77,22 @@ foo_settings: options: key: value key2: value2 + select_states: + type: select + label: Select States + states: + visible: + - + variant: blue + - + setting: select_config + value: key2 + options: + key: value + key2: value2 select_config: type: select - label: Select + label: Select Config options: key: label: select_config 1 -- GitLab From 8897fe51f82700f25f2bcb2fbda9602f857bd122 Mon Sep 17 00:00:00 2001 From: Pierre <pierredureau@yahoo.fr> Date: Sat, 21 Oct 2023 11:11:43 +0200 Subject: [PATCH 03/17] Issue #3385452: Add machine_name setting type --- .../SettingType/MachineNameSettingType.php | 34 +++++++++++++++++++ .../templates/pattern-foo-settings.html.twig | 1 + .../templates/settings.ui_patterns.yml | 3 ++ .../UiPatternsSettingsRenderTest.php | 3 +- 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/Plugin/UiPatterns/SettingType/MachineNameSettingType.php diff --git a/src/Plugin/UiPatterns/SettingType/MachineNameSettingType.php b/src/Plugin/UiPatterns/SettingType/MachineNameSettingType.php new file mode 100644 index 0000000..916f0be --- /dev/null +++ b/src/Plugin/UiPatterns/SettingType/MachineNameSettingType.php @@ -0,0 +1,34 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingType; + +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; +use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; + +/** + * MachineName setting type. + * + * @UiPatternsSettingType( + * id = "machine_name", + * label = @Translation("Machine name") + * ) + */ +class MachineNameSettingType extends PatternSettingTypeBase { + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { + $form[$def->getName()] = [ + '#type' => 'textfield', + '#title' => $def->getLabel(), + '#description' => $def->getDescription(), + '#default_value' => $this->getValue($value), + '#pattern' => "[A-Za-z]+[\w\-]*", + ]; + + $this->handleInput($form[$def->getName()], $def, $form_type); + return $form; + } + +} diff --git a/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig b/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig index cdb8747..ad13d83 100644 --- a/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig +++ b/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig @@ -15,4 +15,5 @@ <div class="media_style">Media Style: {{ media_style }}</div> <div class="select_config">select_config: {{ pattern_configuration('foo_settings', '', 'select_config')[select_config] }}</div> <div class="value">Value: {{ setting_value }}</div> + <div class="machine_name">Machine name: {{ machine_name }}</div> </div> diff --git a/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml b/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml index d121d6f..a7a1d70 100644 --- a/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml +++ b/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml @@ -151,6 +151,9 @@ foo_settings: group: tab_2 options: option1: Option 1 + machine_name: + type: machine_name + label: Machine name configuration: config: config_value diff --git a/tests/src/Functional/UiPatternsSettingsRenderTest.php b/tests/src/Functional/UiPatternsSettingsRenderTest.php index aa7aaf8..02ba933 100644 --- a/tests/src/Functional/UiPatternsSettingsRenderTest.php +++ b/tests/src/Functional/UiPatternsSettingsRenderTest.php @@ -16,7 +16,7 @@ class UiPatternsSettingsRenderTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected $defaultTheme = 'stable'; + protected $defaultTheme = 'stable9'; /** * Disable schema validation when running tests. @@ -85,6 +85,7 @@ class UiPatternsSettingsRenderTest extends BrowserTestBase { 'input' => 'group_sub', 'result' => 'Group sub: group_sub', ], + '[machine_name]' => ['input' => 'key', 'result' => 'Machine name: key'], ]; // Select the layout. -- GitLab From de191f7c8316c29014ab9cdb142d2b5322dfc1c4 Mon Sep 17 00:00:00 2001 From: Pierre Dureau <31905-pdureau@users.noreply.drupalcode.org> Date: Fri, 27 Oct 2023 13:08:31 +0000 Subject: [PATCH 04/17] Resolve #3345071 "Pierre proposal" --- .docksal/addons/phpcs/phpcs | 66 +++++++ .docksal/docksal.env | 2 +- .phpunit.result.cache | 2 +- composer.json | 16 +- phpcs.xml.dist | 31 +++ .../UiPatternsSettingDataProvider.php | 45 +++++ src/Plugin/ComplexSettingTypeBase.php | 111 +++++++++++ src/Plugin/PatternSettingDataProviderBase.php | 89 +++++++++ .../PatternSettingDataProviderInterface.php | 46 +++++ .../BreadcrumbDataProvider.php | 104 ++++++++++ .../SettingDataProvider/MenuDataProvider.php | 184 ++++++++++++++++++ .../SettingType/LinksSettingType.php | 135 +++++++++++++ src/UiPatternsSettingsDataProviderManager.php | 48 +++++ .../UiPatterns/SettingDataProvider/Foo.php | 34 ++++ .../SettingType/SampleComplexSettingType.php | 19 ++ .../templates/pattern-foo-complex.html.twig | 8 + .../templates/settings.ui_patterns.yml | 16 ++ ...i_patterns_settings_data_provider.info.yml | 5 + tests/src/Kernel/ComplexSettingTypeTest.php | 72 +++++++ ui_patterns_settings.services.yml | 3 + 20 files changed, 1027 insertions(+), 9 deletions(-) create mode 100755 .docksal/addons/phpcs/phpcs create mode 100644 phpcs.xml.dist create mode 100644 src/Annotation/UiPatternsSettingDataProvider.php create mode 100644 src/Plugin/ComplexSettingTypeBase.php create mode 100644 src/Plugin/PatternSettingDataProviderBase.php create mode 100644 src/Plugin/PatternSettingDataProviderInterface.php create mode 100644 src/Plugin/UiPatterns/SettingDataProvider/BreadcrumbDataProvider.php create mode 100644 src/Plugin/UiPatterns/SettingDataProvider/MenuDataProvider.php create mode 100644 src/Plugin/UiPatterns/SettingType/LinksSettingType.php create mode 100644 src/UiPatternsSettingsDataProviderManager.php create mode 100644 tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingDataProvider/Foo.php create mode 100644 tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingType/SampleComplexSettingType.php create mode 100644 tests/modules/ui_patterns_settings_data_provider/templates/pattern-foo-complex.html.twig create mode 100644 tests/modules/ui_patterns_settings_data_provider/templates/settings.ui_patterns.yml create mode 100644 tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml create mode 100644 tests/src/Kernel/ComplexSettingTypeTest.php diff --git a/.docksal/addons/phpcs/phpcs b/.docksal/addons/phpcs/phpcs new file mode 100755 index 0000000..8aa0372 --- /dev/null +++ b/.docksal/addons/phpcs/phpcs @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +## Run PHP Code Sniffer Commands +## +## This command will allow for running Code Sniffer commands +## to help make sure is to coding standards. +## +## Running PHPCS +## fin phpcs cs "[directory name]" +## +## Running PHPCBF +## fin phpcs cbf "[directory name]" +## +## Usage: +## cs Run PHPCS +## cbf Run PHPCBF + +STANDARDS="" + +if [[ -n "${PHPCS_STANDARDS}" ]]; then + STANDARDS="${PHPCS_STANDARDS}" +fi + +if [[ -n "${PHPCS_EXTENSIONS}" ]]; then + EXTENSIONS="${PHPCS_EXTENSIONS}" +fi + +if [[ -f "${PROJECT_ROOT}/${DOCROOT}/sites/default/settings.php" ]] || [[ -f "${PROJECT_ROOT}/${DOCROOT}/sites/default/default.settings.php" ]]; then + STANDARDS="${STANDARDS:-"Drupal,DrupalPractice"}" + EXTENSIONS="${EXTENSIONS:-"php,module,inc,install,test,profile,theme,css,info,txt,md"}"; +elif [[ -f "${PROJECT_ROOT}/${DOCROOT}/wp-config.php" ]]; then + STANDARDS="${STANDARDS:-"WordPress"}" + EXTENSIONS="${EXTENSIONS:-"php"}" +fi + +COMMAND="" + +case "$1" in + cs) + shift + COMMAND="/var/vendor/phpcs" + ;; + cbf) + shift + COMMAND="phpcbf" + ;; + *) + fin help phpcs + exit + ;; +esac + +# If standard flag is used remove our default. +STANDARD_OPT="--standard=\"${STANDARDS}\"" +if [[ "$@" =~ "--standard=" ]]; then + STANDARD_OPT="" +fi + +# If extension flag is used remove our default. +EXTENSION_OPT="--extensions=\"${EXTENSIONS}\"" +if [[ "$@" =~ "--extensions=" ]]; then + EXTENSION_OPT="" +fi +print "$COMMAND $STANDARD_OPT $EXTENSION_OPT $@" +# run the command in the container. +fin exec "$COMMAND $STANDARD_OPT $EXTENSION_OPT $@" diff --git a/.docksal/docksal.env b/.docksal/docksal.env index 874d3aa..e8be01a 100644 --- a/.docksal/docksal.env +++ b/.docksal/docksal.env @@ -3,4 +3,4 @@ DOCROOT=build XDEBUG_ENABLED=0 WEB_IMAGE='docksal/web:2.1-apache2.4' DB_IMAGE='docksal/db:1.3-mysql-5.7' -CLI_IMAGE='docksal/cli:php8.1-3.2' +CLI_IMAGE='docksal/cli:php8.1' diff --git a/.phpunit.result.cache b/.phpunit.result.cache index b0218bf..7f05c5d 100644 --- a/.phpunit.result.cache +++ b/.phpunit.result.cache @@ -1 +1 @@ -{"version":1,"defects":{"Drupal\\Tests\\ui_patterns_settings\\Functional\\UiPatternsSettingsRenderTest::testRender":4},"times":{"Drupal\\Tests\\ui_patterns_settings\\Functional\\UiPatternsSettingsRenderTest::testRender":9.008}} \ No newline at end of file +{"version":1,"defects":{"Drupal\\Tests\\ui_patterns_settings\\Functional\\UiPatternsSettingsRenderTest::testRender":4,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testSomething":4,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testComplexSettingType":3,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testSettingsForm":3,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testPreprocess":4},"times":{"Drupal\\Tests\\ui_patterns_settings\\Functional\\UiPatternsSettingsRenderTest::testRender":1.98,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testSomething":0.198,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testComplexSettingType":0.197,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testSettingsForm":0.237,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testPreprocess":0.223}} \ No newline at end of file diff --git a/composer.json b/composer.json index dedac66..5dceecb 100644 --- a/composer.json +++ b/composer.json @@ -18,17 +18,18 @@ ], "require-dev": { "composer/installers": "^1.2", + "drupal/coder": "*", "drupal/core-composer-scaffold": "^8.8 || ^9 || ^10", - "drupal/ui_patterns_layout_builder": "~1", "drupal/core-dev": "^8.8 || ^9 || ^10", - "drupal/ui_patterns": "~1.3", + "drupal/core-recommended": "~10 || ^9", + "drupal/ds": "^3.15", "drupal/token": "~1.0", - "drush/drush": "~11", + "drupal/ui_patterns": "~1.3", "drupal/ui_patterns_field_formatters": "^2.0", - "drupal/core-recommended": "~10 || ^9", + "drupal/ui_patterns_layout_builder": "~1", + "drush/drush": "~11", "openeuropa/task-runner": "~2.0.0-alpha1", - "phpro/grumphp": "~1.5", - "drupal/ds": "^3.15" + "phpro/grumphp": "~1.5" }, "repositories": [ { @@ -81,7 +82,8 @@ "drupal/core-composer-scaffold": true, "phpro/grumphp": true, "phpstan/extension-installer": true, - "dealerdirect/phpcodesniffer-composer-installer": true + "dealerdirect/phpcodesniffer-composer-installer": true, + "oomphinc/composer-installers-extender": true } } } diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..b516332 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- Adapted from Acquia Coding Standards default ruleset. --> +<!-- @see https://github.com/acquia/coding-standards-php/blob/develop/example/phpcs.xml.dist --> + +<!-- https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset --> +<ruleset name="Example"> + + <description>An example PHP CodeSniffer configuration.</description> + + <!-- Set extensions to scan (taken from Coder 8.3.6). --> + <!-- @see https://git.drupalcode.org/project/coder/blob/8.3.6/coder_sniffer/Drupal/ruleset.xml#L8 --> + <arg name="extensions" value="php,module,inc,install,test,profile,theme,css,info,txt,md,yml"/> + + <arg name="colors"/> + <arg name="cache" value=".phpcs-cache"/> + <arg name="parallel" value="10"/> + + <file>docroot/modules/custom</file> + <file>docroot/themes/custom</file> + <file>tests</file> + + <exclude-pattern>*/behat</exclude-pattern> + <exclude-pattern>*/node_modules</exclude-pattern> + <exclude-pattern>*/vendor</exclude-pattern> + + <exclude-pattern>vendor/*</exclude-pattern> + + <rule ref="AcquiaDrupalStrict"/> + +</ruleset> diff --git a/src/Annotation/UiPatternsSettingDataProvider.php b/src/Annotation/UiPatternsSettingDataProvider.php new file mode 100644 index 0000000..12f9219 --- /dev/null +++ b/src/Annotation/UiPatternsSettingDataProvider.php @@ -0,0 +1,45 @@ +<?php + +namespace Drupal\ui_patterns_settings\Annotation; + +use Drupal\Component\Annotation\Plugin; + +/** + * Defines ui_patterns_settings_data_provider annotation object. + * + * @Annotation + */ +class UiPatternsSettingDataProvider extends Plugin { + + /** + * The plugin ID. + * + * @var string + */ + public $id; + + /** + * The human-readable name of the plugin. + * + * @var \Drupal\Core\Annotation\Translation + * + * @ingroup plugin_translatable + */ + public $title; + + /** + * The description of the plugin. + * + * @var \Drupal\Core\Annotation\Translation + * + * @ingroup plugin_translatable + */ + public $description; + + /** + * The setting type plugin. + * + * @var string + */ + public $settingType; +} diff --git a/src/Plugin/ComplexSettingTypeBase.php b/src/Plugin/ComplexSettingTypeBase.php new file mode 100644 index 0000000..9402abb --- /dev/null +++ b/src/Plugin/ComplexSettingTypeBase.php @@ -0,0 +1,111 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin; + +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Base class for setting types with data providers. + */ +abstract class ComplexSettingTypeBase extends PatternSettingTypeBase implements ContainerFactoryPluginInterface { + + /** + * The token service. + * + * @var \Drupal\ui_patterns_settings\UiPatternsSettingsDataProviderManager + */ + protected $dataProviderManger; + + /** + * The data provider plugin. + * + * @var \Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface + */ + protected $provider; + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + $plugin = parent::create($container, $configuration, $plugin_id, $plugin_definition); + $plugin->dataProviderManger = $container->get('plugin.manager.ui_patterns_settings_data_provider'); + return $plugin; + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { + $def = $this->getPatternSettingDefinition(); + $data_provider_definitions = $this->dataProviderManger->getDefinitionsBySettingType($this->pluginId); + $provider_plugins = []; + $provider_options = []; + foreach ($data_provider_definitions as $data_provider_definition) { + $data_provider_id = $data_provider_definition['id']; + $provider_plugins[$data_provider_id] = $this->dataProviderManger->createInstance($data_provider_id, []); + $provider_options[$data_provider_id] = $data_provider_definition['label']; + + } + $form[$def->getName()] = [ + '#type' => 'fieldset', + '#title' => $def->getLabel(), + ]; + + $provider_select_id = $def->getName(). '_provider'; + $form[$def->getName()]['provider'] = [ + '#type' => 'select', + '#title' => $this->t('Dataprovider'), + '#default_value' => $this->getValue($value['provider'] ?? NULL), + '#options' => $provider_options, + '#attributes'=> ['id' => $provider_select_id] + ]; + + $form[$def->getName()]['configuration'] = []; + + foreach ($data_provider_definitions as $data_provider_definition) { + $data_provider_id = $data_provider_definition['id']; + $provider_settings_form = $provider_plugins[$data_provider_id]->settingsForm($value['configuration'][$data_provider_id]['config'] ?? []); + if ($provider_settings_form) { + $form[$def->getName()]['configuration'][$data_provider_id] = ['#type' => 'container', + '#states' => [ + 'visible' => [ + 'select[id="' . $provider_select_id . '"]' => ['value' => $data_provider_id], + ], + ], + ]; + $form[$def->getName()]['configuration'][$data_provider_id]['config'] = $provider_settings_form; + } + } + return $form; + } + + /** + * {@inheritdoc} + */ + public function settingsPreprocess( + $value, + array $context, + PatternDefinitionSetting $def + ) { + $provider_id = $value['provider'] ?? NULL; + if ($provider_id) { + $instance = $this->dataProviderManger->createInstance($provider_id, []); + $this->provider = $instance; + return $instance->getData($value['configuration'][$provider_id]['config'] ?? []); + } + return []; + } + + /** + * {@inheritdoc} + */ + public function alterElement($value, PatternDefinitionSetting $def, &$element) { + if ($this->provider) { + $instance = $this->provider; + $instance->alterElement($value, $def, $element); + } + } + +} diff --git a/src/Plugin/PatternSettingDataProviderBase.php b/src/Plugin/PatternSettingDataProviderBase.php new file mode 100644 index 0000000..e66903e --- /dev/null +++ b/src/Plugin/PatternSettingDataProviderBase.php @@ -0,0 +1,89 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin; + +use Drupal\Component\Plugin\PluginBase; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Base class for ui_patterns_settings_data_provider plugins. + */ +abstract class PatternSettingDataProviderBase extends PluginBase implements PatternSettingDataProviderInterface, ContainerFactoryPluginInterface { + + use StringTranslationTrait; + + /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + + /** + * Return pattern definitions for setting . + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * {@inheritdoc} + */ + public function __construct( + array $configuration, + $plugin_id, + array $plugin_definition, + ModuleHandlerInterface $module_handler, + EntityTypeManagerInterface $entity_type_manager + ) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->entityTypeManager = $entity_type_manager; + $this->moduleHandler = $module_handler; + } + + /** + * + */ + public static function create( + ContainerInterface $container, + array $configuration, + $plugin_id, + $plugin_definition + ) { + $plugin = new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('module_handler'), + $container->get('entity_type.manager'), + ); + return $plugin; + } + + /** + * {@inheritdoc} + */ + public function label() { + // Cast the label to a string since it is a TranslatableMarkup object. + return (string) $this->pluginDefinition['label']; + } + + /** + * {@inheritdoc} + */ + public function settingsForm($value) { + return []; + } + + /** + * {@inheritdoc} + */ + public function alterElement($value, PatternDefinitionSetting $def, &$element) { + } + +} diff --git a/src/Plugin/PatternSettingDataProviderInterface.php b/src/Plugin/PatternSettingDataProviderInterface.php new file mode 100644 index 0000000..10c20e5 --- /dev/null +++ b/src/Plugin/PatternSettingDataProviderInterface.php @@ -0,0 +1,46 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin; + +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; + +/** + * Interface for ui_patterns_settings_data_provider plugins. + */ +interface PatternSettingDataProviderInterface { + + /** + * Returns the translated plugin label. + * + * @return string + * The translated title. + */ + public function label(); + + /** + * Return the configuration form. + * + * @return array + * The configuration form. + */ + public function settingsForm($value); + + /** + * @return array + * The provided data. + */ + public function getData($value); + + /** + * Allow setting data providers to alter render element. + * + * @param string $value + * The value. + * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def + * The pattern definition. + * @param array $element + * The render element. + */ + public function alterElement($value, PatternDefinitionSetting $def, &$element); + +} diff --git a/src/Plugin/UiPatterns/SettingDataProvider/BreadcrumbDataProvider.php b/src/Plugin/UiPatterns/SettingDataProvider/BreadcrumbDataProvider.php new file mode 100644 index 0000000..5210f64 --- /dev/null +++ b/src/Plugin/UiPatterns/SettingDataProvider/BreadcrumbDataProvider.php @@ -0,0 +1,104 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingDataProvider; + +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; +use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderBase; +use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Plugin implementation of the ui_patterns_settings_data_provider. + * + * @UiPatternsSettingDataProvider( + * id = "breadcrumb", + * label = @Translation("Breadcrumb"), + * description = @Translation("Data Provider for menus."), + * settingType = "links" + * ) + */ +class BreadcrumbDataProvider extends PatternSettingDataProviderBase implements PatternSettingDataProviderInterface { + + /** + * The current route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * The breadcrumb manager. + * + * @var \Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface + */ + protected $breadcrumbManager; + + /** + * + */ + public static function create( + ContainerInterface $container, + array $configuration, + $plugin_id, + $plugin_definition + ) { + $plugin = new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('module_handler'), + $container->get('entity_type.manager'), + ); + /** @var \Drupal\Core\StringTranslation\TranslationInterface $translation */ + $translation = $container->get('string_translation'); + $plugin->setStringTranslation($translation); + $plugin->breadcrumbManager = $container->get('breadcrumb'); + $plugin->routeMatch = $container->get('current_route_match'); + return $plugin; + } + + /** + * Get breadcrumb items. + * + * @return array + * List of items. + */ + private function getBreadcrumbItems(): array { + $breadcrumb = $this->breadcrumbManager->build($this->routeMatch); + $links = []; + foreach ($breadcrumb->getLinks() as $link) { + $links[] = [ + "title" => $link->getText(), + "url" => $link->getUrl()->toString(), + ]; + } + return $links; + } + + /** + * {@inheritdoc} + */ + public function settingsForm($value) { + return []; + } + + /** + * {@inheritdoc} + */ + public function getData($value) { + return $this->getBreadcrumbItems(); + } + + /** + * {@inheritdoc} + */ + public function alterElement($value, PatternDefinitionSetting $def, &$element) { + $breadcrumb = $this->breadcrumbManager->build($this->routeMatch); + $renderable = $breadcrumb->toRenderable(); + if (isset($renderable["#cache"])) { + $element["#cache"] = $element["#cache"] ?: []; + $element["#cache"] = array_merge($element["#cache"], $renderable["#cache"]); + } + } + +} diff --git a/src/Plugin/UiPatterns/SettingDataProvider/MenuDataProvider.php b/src/Plugin/UiPatterns/SettingDataProvider/MenuDataProvider.php new file mode 100644 index 0000000..304ae35 --- /dev/null +++ b/src/Plugin/UiPatterns/SettingDataProvider/MenuDataProvider.php @@ -0,0 +1,184 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingDataProvider; + +use Drupal\Core\Menu\MenuTreeParameters; +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; +use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderBase; +use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface; +use Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType\LinksSettingType; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Plugin implementation of the ui_patterns_settings_data_provider. + * + * @UiPatternsSettingDataProvider( + * id = "menu", + * label = @Translation("Menu"), + * description = @Translation("Data Provider for menus."), + * settingType = "links" + * ) + */ +class MenuDataProvider extends PatternSettingDataProviderBase implements PatternSettingDataProviderInterface { + + /** + * The current route match. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * The menu link tree. + * + * @var \Drupal\Core\Menu\MenuLinkTreeInterface + */ + protected $menuLinkTree; + + /** + * The menu ID. + * + * @var string + */ + protected $menuId; + + /** + * + */ + public static function create( + ContainerInterface $container, + array $configuration, + $plugin_id, + $plugin_definition + ) { + $plugin = new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('module_handler'), + $container->get('entity_type.manager'), + ); + /** @var \Drupal\Core\StringTranslation\TranslationInterface $translation */ + $translation = $container->get('string_translation'); + $plugin->setStringTranslation($translation); + $plugin->routeMatch = $container->get('current_route_match'); + $plugin->menuLinkTree = $container->get('menu.link_tree'); + return $plugin; + } + + /** + * Get menus list. + * + * @return array + * List of menus. + */ + private function getMenuList() { + $all_menus = $this->entityTypeManager->getStorage('menu')->loadMultiple(); + $menus = [ + "" => "(None)", + ]; + foreach ($all_menus as $id => $menu) { + $menus[$id] = $menu->label(); + } + asort($menus); + return $menus; + } + + /** + * {@inheritdoc} + */ + public function settingsForm($value) { + $value = $value ?? []; + $form = []; + $form["menu"] = [ + '#type' => 'select', + '#title' => 'Menu', + '#options' => $this->getMenuList(), + '#default_value' => \array_key_exists("menu", $value) ? $value["menu"] : "", + ]; + $options = range(0, $this->menuLinkTree->maxDepth()); + unset($options[0]); + $form['level'] = [ + '#type' => 'select', + '#title' => $this->t('Initial visibility level'), + '#default_value' => \array_key_exists("level", $value) ? $value["level"] : 1, + '#options' => $options, + '#required' => TRUE, + ]; + $options[0] = $this->t('Unlimited'); + $form['depth'] = [ + '#type' => 'select', + '#title' => $this->t('Number of levels to display'), + '#default_value' => \array_key_exists("depth", $value) ? $value["depth"] : 0, + '#options' => $options, + '#description' => $this->t('This maximum number includes the initial level and the final display is dependant of the pattern template.'), + '#required' => TRUE, + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function getData($value) { + if (!$value) { + return []; + } + $this->menuId = $value["menu"]; + return $this->getMenuItems($value); + } + + /** + * Get menu items. + * + * @return array + * List of items. + */ + private function getMenuItems($value): array { + $level = (int) \array_key_exists("level", $value) ? $value["level"] : 1; + $depth = (int) \array_key_exists("depth", $value) ? $value["depth"] : 0; + $parameters = new MenuTreeParameters(); + $parameters->setMinDepth($level); + + // When the depth is configured to zero, there is no depth limit. When depth + // is non-zero, it indicates the number of levels that must be displayed. + // Hence this is a relative depth that we must convert to an actual + // (absolute) depth, that may never exceed the maximum depth. + if ($depth > 0) { + $parameters->setMaxDepth(min($level + $depth - 1, $this->menuLinkTree->maxDepth())); + } + + $tree = $this->menuLinkTree->load($this->menuId, $parameters); + $manipulators = [ + ['callable' => 'menu.default_tree_manipulators:checkAccess'], + ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'], + ]; + + $tree = $this->menuLinkTree->transform($tree, $manipulators); + $tree = $this->menuLinkTree->build($tree); + if (\array_key_exists("#items", $tree)) { + $variables = [ + "items" => $tree["#items"], + ]; + $this->moduleHandler->invokeAll("preprocess_menu", [&$variables]); + $variables["items"] = LinksSettingType::normalize($variables["items"]); + return $variables["items"]; + } + return []; + } + + /** + * {@inheritdoc} + */ + public function alterElement($value, PatternDefinitionSetting $def, &$element) { + if (!$this->menuId) { + return; + } + $cache = $element["#cache"] ?? []; + $element["#cache"] = array_merge($cache, [ + "tags" => ['config:system.menu.' . $this->menuId], + ]); + } + +} diff --git a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php new file mode 100644 index 0000000..79b227b --- /dev/null +++ b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php @@ -0,0 +1,135 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingType; + +use Drupal\ui_patterns_settings\Plugin\ComplexSettingTypeBase; + +/** + * Complex setting type for links. + * + * @UiPatternsSettingType( + * id = "links", + * label = @Translation("Links") + * ) + */ +class LinksSettingType extends ComplexSettingTypeBase { + + /** + * Normalize menu items. + * + * Don't inject URL object into patterns templates, use "title" as item + * label and "url" as item target. + * + * @param array $items + * The items to convert. + * + * @return array + */ + public static function normalize(array $items): array { + foreach ($items as $index => &$item) { + if (!is_array($item)) { + unset($items[$index]); + continue; + } + if (array_key_exists("text", $item)) { + // Examples: links.html.twig, breadcrumb.html.twig, pager.html.twig, + // views_mini_pager.html.twig. + $item["title"] = $item["text"]; + unset($item["text"]); + } + if (!array_key_exists("title", $item)) { + $item["title"] = $index; + } + if (array_key_exists("href", $item)) { + // Examples: pager.html.twig, views_mini_pager.html.twig. + $item["url"] = $item["href"]; + unset($item["href"]); + } + if (!isset($item["url"]) && isset($item["link"])) { + // Example: links.html.twig. + $item["url"] = $item["link"]["#url"]; + $item["url"]->setOptions($item["link"]["#options"]); + unset($item["link"]); + } + if (array_key_exists("url", $item) && ($item["url"] instanceof Url)) { + // Examples: menu.html.twig, links.html.twig. + $url = $item["url"]; + $item["url"] = $url->toString(); + $options = $url->getOptions(); + if (isset($options["attributes"])) { + $item["link_attributes"] = new Attribute($options["attributes"]); + } + } + if (array_key_exists("below", $item)) { + $item["below"] = self::normalize($item["below"]); + } + } + $items = array_values($items); + return $items; + } + + /** + * Convert pager to menu. + * + * Convert pager data structure to menu data structure. Useful for + * pager.html.twig presenter template. + * + * @param array $items + * The pager items to convert. + * @param int $current + * The current page. + * + * @return array + */ + public static function convertPagerToMenu(array $pager, int $current): array { + $items = []; + if (isset($pager["first"])) { + $items[] = $pager["first"]; + } + if (isset($pager["previous"])) { + $items[] = $pager["previous"]; + } + if (isset($pager["pages"])) { + foreach ($pager["pages"] as $index => $item) { + $item["text"] = $index; + if ($index == $current) { + unset($item["href"]); + } + $items[] = $item; + } + } + if (isset($pager["next"])) { + $items[] = $pager["next"]; + } + if (isset($pager["last"])) { + $items[] = $pager["last"]; + } + return $items; + } + + /** + * Convert mini pager to menu. + * + * Convert views mini pager data structure to menu data structure. Useful for + * views-mini-pager.html.twig presenter template. + * + * @param array $items + * The pager items to convert. + * + * @return array + */ + public static function convertMiniPagerToMenu(array $pager): array { + $items = []; + if ($pager["previous"]) { + $items[] = $pager["previous"]; + } + $items[] = [ + "text" => $pager["current"], + ]; + if ($pager["next"]) { + $items[] = $pager["next"]; + } + return $items; + } + +} diff --git a/src/UiPatternsSettingsDataProviderManager.php b/src/UiPatternsSettingsDataProviderManager.php new file mode 100644 index 0000000..cf98a28 --- /dev/null +++ b/src/UiPatternsSettingsDataProviderManager.php @@ -0,0 +1,48 @@ +<?php + +namespace Drupal\ui_patterns_settings; + +use Drupal\Core\Cache\CacheBackendInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Plugin\DefaultPluginManager; + +/** + * UiPatternsSettingsDataProvider plugin manager. + */ +class UiPatternsSettingsDataProviderManager extends DefaultPluginManager { + + /** + * Constructs UiPatternsSettingsDataProviderPluginManager object. + * + * @param \Traversable $namespaces + * An object that implements \Traversable which contains the root paths + * keyed by the corresponding namespace to look for plugin implementations. + * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend + * Cache backend instance to use. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler to invoke the alter hook with. + */ + public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { + parent::__construct( + 'Plugin/UiPatterns/SettingDataProvider', + $namespaces, + $module_handler, + 'Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface', + 'Drupal\ui_patterns_settings\Annotation\UiPatternsSettingDataProvider' + ); + $this->alterInfo('ui_patterns_settings_data_provider_info'); + $this->setCacheBackend($cache_backend, 'ui_patterns_settings_data_provider_plugins'); + } + + public function getDefinitionsBySettingType($setting_type_id) { + $definitions = $this->getDefinitions(); + $results = []; + foreach ($definitions as $definition) { + if ($definition['settingType'] === $setting_type_id) { + $results[] = $definition; + } + } + return $results; + } + +} diff --git a/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingDataProvider/Foo.php b/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingDataProvider/Foo.php new file mode 100644 index 0000000..162ea13 --- /dev/null +++ b/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingDataProvider/Foo.php @@ -0,0 +1,34 @@ +<?php + +namespace Drupal\ui_patterns_settings_data_provider\Plugin\UiPatterns\SettingDataProvider; + +use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderBase; +use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface; + +/** + * Plugin implementation of the ui_patterns_settings_data_provider. + * + * @UiPatternsSettingDataProvider( + * id = "foo", + * label = @Translation("Foo"), + * description = @Translation("Foo description."), + * settingType = "sample_complex_setting_type" + * ) + */ +class Foo extends PatternSettingDataProviderBase implements PatternSettingDataProviderInterface { + + /** + * {@inheritdoc} + */ + public function settingsForm($value) { + return ['#type' => 'select', '#options' => ['foo' => 'Foo']]; + } + + /** + * {@inheritdoc} + */ + public function getData($value) { + return ['data' => 'done']; + } + +} diff --git a/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingType/SampleComplexSettingType.php b/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingType/SampleComplexSettingType.php new file mode 100644 index 0000000..3912a2e --- /dev/null +++ b/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingType/SampleComplexSettingType.php @@ -0,0 +1,19 @@ +<?php + +namespace Drupal\ui_patterns_settings_data_provider\Plugin\UIPatterns\SettingType; + +use Drupal\ui_patterns_settings\Plugin\ComplexSettingTypeBase; +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; + +/** + * Complex Setting Type. + * + * @UiPatternsSettingType( + * id = "sample_complex_setting_type", + * label = @Translation("Complex Setting Type") + * ) + */ +class SampleComplexSettingType extends ComplexSettingTypeBase { + + +} diff --git a/tests/modules/ui_patterns_settings_data_provider/templates/pattern-foo-complex.html.twig b/tests/modules/ui_patterns_settings_data_provider/templates/pattern-foo-complex.html.twig new file mode 100644 index 0000000..1a6f67e --- /dev/null +++ b/tests/modules/ui_patterns_settings_data_provider/templates/pattern-foo-complex.html.twig @@ -0,0 +1,8 @@ +<div style="border: 1px solid blue"> + {% for item in links %} + {{ item['title'] }} + {% endfor %} + {% for item in breadcrumb_lists %} + {{ item['title'] }} + {% endfor %} +</div> diff --git a/tests/modules/ui_patterns_settings_data_provider/templates/settings.ui_patterns.yml b/tests/modules/ui_patterns_settings_data_provider/templates/settings.ui_patterns.yml new file mode 100644 index 0000000..44f403d --- /dev/null +++ b/tests/modules/ui_patterns_settings_data_provider/templates/settings.ui_patterns.yml @@ -0,0 +1,16 @@ +foo_complex: + label: Foo Complex + fields: + dummy: + type: text + label: Dummy + settings: + complex_setting: + type: sample_complex_setting_type + label: Sample Complex Setting + links: + type: links + label: links + breadcrumb_lists: + type: links + label: breadcrumb_lists diff --git a/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml b/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml new file mode 100644 index 0000000..4e38253 --- /dev/null +++ b/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml @@ -0,0 +1,5 @@ +type: module +name: 'UI Patterns Settings Data Provider' +core_version_requirement: ^8 || ^9 || ^10 +dependencies: + - ui_patterns_settings:ui_patterns_settings diff --git a/tests/src/Kernel/ComplexSettingTypeTest.php b/tests/src/Kernel/ComplexSettingTypeTest.php new file mode 100644 index 0000000..cdaa1a1 --- /dev/null +++ b/tests/src/Kernel/ComplexSettingTypeTest.php @@ -0,0 +1,72 @@ +<?php + +namespace Drupal\Tests\ui_patterns_settings\Kernel; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\ui_patterns\Definition\PatternDefinition; +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; +use Drupal\ui_patterns_settings\UiPatternsSettings; + +/** + * Test ComplexSettingType. + * + * @group ui_patterns_settings + */ +class ComplexSettingTypeTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'ui_patterns_settings', + 'ui_patterns_settings_data_provider', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + // Mock required services here. + } + + private function getTestSettingType() { + /** @var \Drupal\ui_patterns_settings_data_provider\Plugin\UIPatterns\SettingType\SampleComplexSettingType $sample_complex_setting_type */ + $definition = new PatternDefinition([ + [ + 'sample' => [ + 'id' => 'sample', + ], + ], + ], 'sample'); + return UiPatternsSettings::createSettingType($definition, $this->getTestSettingDefinition()); + } + + private function getTestSettingDefinition() { + return new PatternDefinitionSetting('sample_complex_setting_type', [ + 'name' => 'sample_complex_setting_type', + 'type' => 'sample_complex_setting_type', + 'label' => 'sample_complex_setting_type', + ]); + } + + /** + * Test testSettingsForm. + */ + public function testSettingsForm() { + $sample_definition = $this->getTestSettingDefinition(); + $sample_complex_setting_type = $this->getTestSettingType(); + $fieldset = $sample_complex_setting_type->settingsForm([], '', $sample_definition, 'layout'); + self::assertArrayHasKey('sample_complex_setting_type', $fieldset); + self::assertArrayHasKey('provider', $fieldset['sample_complex_setting_type']); + self::assertArrayHasKey('foo', $fieldset['sample_complex_setting_type']['configuration']); + self::assertArrayHasKey('#type', $fieldset['sample_complex_setting_type']['configuration']['foo']['config']); + } + + public function testPreprocess() { + $sample_complex_setting_type = $this->getTestSettingType(); + $context = []; + $ary = $sample_complex_setting_type->preprocess(['provider' => 'foo'], $context); + self::assertArrayHasKey('data', $ary); + } +} diff --git a/ui_patterns_settings.services.yml b/ui_patterns_settings.services.yml index 18acd84..6eaffc5 100644 --- a/ui_patterns_settings.services.yml +++ b/ui_patterns_settings.services.yml @@ -2,6 +2,9 @@ services: plugin.manager.ui_patterns_settings: class: Drupal\ui_patterns_settings\UiPatternsSettingsManager arguments: ['@container.namespaces', '@module_handler', '@cache.discovery'] + plugin.manager.ui_patterns_settings_data_provider: + class: Drupal\ui_patterns_settings\UiPatternsSettingsDataProviderManager + parent: default_plugin_manager ui_patterns_settings.twig: class: Drupal\ui_patterns_settings\TwigExtension\UIPatternsSettingsExtension tags: -- GitLab From bc863098aaab0c43b009c234b73ad032444a6f69 Mon Sep 17 00:00:00 2001 From: Altcom_Neil <58718-altcom_nh@users.noreply.drupalcode.org> Date: Fri, 27 Oct 2023 15:13:34 +0200 Subject: [PATCH 05/17] Issue #3396611 by Altcom_Neil: Plugin Interface class name mismatch --- src/UiPatternsSettingsManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/UiPatternsSettingsManager.php b/src/UiPatternsSettingsManager.php index 73f131d..eb53b91 100644 --- a/src/UiPatternsSettingsManager.php +++ b/src/UiPatternsSettingsManager.php @@ -21,7 +21,7 @@ class UiPatternsSettingsManager extends DefaultPluginManager implements PluginMa * UiPatternsSettingsManager constructor. */ public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend) { - parent::__construct('Plugin/UiPatterns/SettingType', $namespaces, $module_handler, 'Drupal\ui_patterns_settings\SettingTypeInterface', 'Drupal\ui_patterns_settings\Annotation\UiPatternsSettingType'); + parent::__construct('Plugin/UiPatterns/SettingType', $namespaces, $module_handler, 'Drupal\ui_patterns_settings\Plugin\PatternSettingTypeInterface', 'Drupal\ui_patterns_settings\Annotation\UiPatternsSettingType'); $this->moduleHandler = $module_handler; $this->alterInfo('ui_patterns_settings_info'); $this->setCacheBackend($cache_backend, 'ui_patterns_settings', ['ui_patterns_settings']); -- GitLab From d6609ba84522b433db20573deb2692dfb1691f57 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Marty <48913-martygraphie@users.noreply.drupalcode.org> Date: Fri, 27 Oct 2023 15:23:47 +0200 Subject: [PATCH 06/17] Issue #3378871 by Martygraphie: Forgetting to set a pattern via field_group causes an 500 error when building the form's settings states --- src/Definition/PatternDefinitionSetting.php | 4 ++-- src/Form/SettingsFormBuilder.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Definition/PatternDefinitionSetting.php b/src/Definition/PatternDefinitionSetting.php index e66535c..a458a08 100644 --- a/src/Definition/PatternDefinitionSetting.php +++ b/src/Definition/PatternDefinitionSetting.php @@ -354,7 +354,7 @@ class PatternDefinitionSetting implements \ArrayAccess { /** * Get states property. * - * @return string + * @return array * Property value. */ public function getStates() { @@ -364,7 +364,7 @@ class PatternDefinitionSetting implements \ArrayAccess { /** * Set States property. * - * @param string $type + * @param array $states * Property value. * * @return $this diff --git a/src/Form/SettingsFormBuilder.php b/src/Form/SettingsFormBuilder.php index 0326b40..942bb3c 100644 --- a/src/Form/SettingsFormBuilder.php +++ b/src/Form/SettingsFormBuilder.php @@ -224,7 +224,7 @@ class SettingsFormBuilder { /** @var PatternDefinitionSetting $setting */ foreach ($settings as $setting_name => $setting) { $states = $setting->getStates(); - if (count($states) !== 0) { + if (!is_null($states) && count($states) !== 0) { foreach ($states as $visibilty => $conditions) { foreach ($conditions as $state) { if (isset($state['variant'])) { -- GitLab From cbb24f3a42f088be0b0669bca34d12ed2a12db84 Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Fri, 27 Oct 2023 15:24:50 +0200 Subject: [PATCH 07/17] Cleanup phpunit cache --- .gitignore | 3 ++- .phpunit.result.cache | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 .phpunit.result.cache diff --git a/.gitignore b/.gitignore index d753432..225938e 100755 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ /runner.yml /.docksal/docksal-local.env /.editorconfig -/.gitattributes \ No newline at end of file +/.gitattributes +/.phpunit.result.cache diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index 7f05c5d..0000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":1,"defects":{"Drupal\\Tests\\ui_patterns_settings\\Functional\\UiPatternsSettingsRenderTest::testRender":4,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testSomething":4,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testComplexSettingType":3,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testSettingsForm":3,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testPreprocess":4},"times":{"Drupal\\Tests\\ui_patterns_settings\\Functional\\UiPatternsSettingsRenderTest::testRender":1.98,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testSomething":0.198,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testComplexSettingType":0.197,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testSettingsForm":0.237,"Drupal\\Tests\\ui_patterns_settings\\Kernel\\ComplexSettingTypeTest::testPreprocess":0.223}} \ No newline at end of file -- GitLab From 207d6352c0ac0f11d54da616f643c6423d150419 Mon Sep 17 00:00:00 2001 From: Pierre <pierredureau@yahoo.fr> Date: Thu, 16 Nov 2023 20:11:30 +0100 Subject: [PATCH 08/17] Issue #3345071 by pdureau: Fix links setting type --- src/Plugin/ComplexSettingTypeBase.php | 2 +- .../SettingType/LinksSettingType.php | 83 +++++-------------- 2 files changed, 22 insertions(+), 63 deletions(-) diff --git a/src/Plugin/ComplexSettingTypeBase.php b/src/Plugin/ComplexSettingTypeBase.php index 9402abb..ead5ac2 100644 --- a/src/Plugin/ComplexSettingTypeBase.php +++ b/src/Plugin/ComplexSettingTypeBase.php @@ -95,7 +95,7 @@ abstract class ComplexSettingTypeBase extends PatternSettingTypeBase implements $this->provider = $instance; return $instance->getData($value['configuration'][$provider_id]['config'] ?? []); } - return []; + return $value; } /** diff --git a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php index 79b227b..083fb60 100644 --- a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php +++ b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php @@ -2,6 +2,8 @@ namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingType; +use Drupal\Core\Template\Attribute; +use Drupal\Core\Url; use Drupal\ui_patterns_settings\Plugin\ComplexSettingTypeBase; /** @@ -51,15 +53,7 @@ class LinksSettingType extends ComplexSettingTypeBase { $item["url"]->setOptions($item["link"]["#options"]); unset($item["link"]); } - if (array_key_exists("url", $item) && ($item["url"] instanceof Url)) { - // Examples: menu.html.twig, links.html.twig. - $url = $item["url"]; - $item["url"] = $url->toString(); - $options = $url->getOptions(); - if (isset($options["attributes"])) { - $item["link_attributes"] = new Attribute($options["attributes"]); - } - } + $item = self::normalizeUrl($item); if (array_key_exists("below", $item)) { $item["below"] = self::normalize($item["below"]); } @@ -69,67 +63,32 @@ class LinksSettingType extends ComplexSettingTypeBase { } /** - * Convert pager to menu. - * - * Convert pager data structure to menu data structure. Useful for - * pager.html.twig presenter template. + * Normaize URL in an item. * - * @param array $items - * The pager items to convert. - * @param int $current - * The current page. - * - * @return array + * Useful for: menu.html.twig, links.html.twig. */ - public static function convertPagerToMenu(array $pager, int $current): array { - $items = []; - if (isset($pager["first"])) { - $items[] = $pager["first"]; + private static function normalizeUrl(array $item): array { + if (!array_key_exists("url", $item)) { + return $item; } - if (isset($pager["previous"])) { - $items[] = $pager["previous"]; + $url = $item["url"]; + if (!($url instanceof Url)) { + return $item; } - if (isset($pager["pages"])) { - foreach ($pager["pages"] as $index => $item) { - $item["text"] = $index; - if ($index == $current) { - unset($item["href"]); - } - $items[] = $item; - } - } - if (isset($pager["next"])) { - $items[] = $pager["next"]; + if ($url->isRouted() && ($url->getRouteName() === '<nolink>')) { + unset($item["url"]); } - if (isset($pager["last"])) { - $items[] = $pager["last"]; + elseif ($url->isRouted() && ($url->getRouteName() === '<button>')) { + unset($item["url"]); } - return $items; - } - - /** - * Convert mini pager to menu. - * - * Convert views mini pager data structure to menu data structure. Useful for - * views-mini-pager.html.twig presenter template. - * - * @param array $items - * The pager items to convert. - * - * @return array - */ - public static function convertMiniPagerToMenu(array $pager): array { - $items = []; - if ($pager["previous"]) { - $items[] = $pager["previous"]; + else { + $item["url"] = $url->toString(); } - $items[] = [ - "text" => $pager["current"], - ]; - if ($pager["next"]) { - $items[] = $pager["next"]; + $options = $url->getOptions(); + if (isset($options["attributes"])) { + $item["link_attributes"] = new Attribute($options["attributes"]); } - return $items; + return $item; } } -- GitLab From 7eaf325a9d88f32c6a55f07351d5d4752926b5cf Mon Sep 17 00:00:00 2001 From: Florent Torregrosa <14238-florenttorregrosa@users.noreply.drupalcode.org> Date: Mon, 8 Jan 2024 11:34:54 +0100 Subject: [PATCH 09/17] Issue #3413129 by Grimreaper: Code cleanup --- .docksal/addons/phpcs/phpcs | 66 -------------------------- .docksal/commands/init | 3 -- .docksal/commands/run_tests | 10 ---- .docksal/docksal.env | 6 --- .docksal/docksal.yml | 28 ------------ .docksal/etc/php/php-cli.ini | 4 -- .docksal/etc/php/php.ini | 4 -- .github_changelog_generator | 5 -- .gitignore | 11 ----- .travis.yml | 37 --------------- CHANGELOG.md | 1 - composer.json | 89 ------------------------------------ docker-compose.yml | 67 --------------------------- grumphp | 16 ------- grumphp.drupal8.yml | 16 ------- phpcs.xml.dist | 31 ------------- runner.docksal.yml | 46 ------------------- runner.yml.dist | 48 ------------------- 18 files changed, 488 deletions(-) delete mode 100755 .docksal/addons/phpcs/phpcs delete mode 100755 .docksal/commands/init delete mode 100755 .docksal/commands/run_tests delete mode 100644 .docksal/docksal.env delete mode 100644 .docksal/docksal.yml delete mode 100644 .docksal/etc/php/php-cli.ini delete mode 100644 .docksal/etc/php/php.ini delete mode 100644 .github_changelog_generator delete mode 100644 .travis.yml delete mode 100644 CHANGELOG.md delete mode 100644 composer.json delete mode 100644 docker-compose.yml delete mode 100644 grumphp delete mode 100644 grumphp.drupal8.yml delete mode 100644 phpcs.xml.dist delete mode 100644 runner.docksal.yml delete mode 100644 runner.yml.dist diff --git a/.docksal/addons/phpcs/phpcs b/.docksal/addons/phpcs/phpcs deleted file mode 100755 index 8aa0372..0000000 --- a/.docksal/addons/phpcs/phpcs +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env bash - -## Run PHP Code Sniffer Commands -## -## This command will allow for running Code Sniffer commands -## to help make sure is to coding standards. -## -## Running PHPCS -## fin phpcs cs "[directory name]" -## -## Running PHPCBF -## fin phpcs cbf "[directory name]" -## -## Usage: -## cs Run PHPCS -## cbf Run PHPCBF - -STANDARDS="" - -if [[ -n "${PHPCS_STANDARDS}" ]]; then - STANDARDS="${PHPCS_STANDARDS}" -fi - -if [[ -n "${PHPCS_EXTENSIONS}" ]]; then - EXTENSIONS="${PHPCS_EXTENSIONS}" -fi - -if [[ -f "${PROJECT_ROOT}/${DOCROOT}/sites/default/settings.php" ]] || [[ -f "${PROJECT_ROOT}/${DOCROOT}/sites/default/default.settings.php" ]]; then - STANDARDS="${STANDARDS:-"Drupal,DrupalPractice"}" - EXTENSIONS="${EXTENSIONS:-"php,module,inc,install,test,profile,theme,css,info,txt,md"}"; -elif [[ -f "${PROJECT_ROOT}/${DOCROOT}/wp-config.php" ]]; then - STANDARDS="${STANDARDS:-"WordPress"}" - EXTENSIONS="${EXTENSIONS:-"php"}" -fi - -COMMAND="" - -case "$1" in - cs) - shift - COMMAND="/var/vendor/phpcs" - ;; - cbf) - shift - COMMAND="phpcbf" - ;; - *) - fin help phpcs - exit - ;; -esac - -# If standard flag is used remove our default. -STANDARD_OPT="--standard=\"${STANDARDS}\"" -if [[ "$@" =~ "--standard=" ]]; then - STANDARD_OPT="" -fi - -# If extension flag is used remove our default. -EXTENSION_OPT="--extensions=\"${EXTENSIONS}\"" -if [[ "$@" =~ "--extensions=" ]]; then - EXTENSION_OPT="" -fi -print "$COMMAND $STANDARD_OPT $EXTENSION_OPT $@" -# run the command in the container. -fin exec "$COMMAND $STANDARD_OPT $EXTENSION_OPT $@" diff --git a/.docksal/commands/init b/.docksal/commands/init deleted file mode 100755 index 1bac4d3..0000000 --- a/.docksal/commands/init +++ /dev/null @@ -1,3 +0,0 @@ -fin up -fin exec composer install -fin exec /var/www/vendor/bin/run drupal:site-install diff --git a/.docksal/commands/run_tests b/.docksal/commands/run_tests deleted file mode 100755 index a1539c2..0000000 --- a/.docksal/commands/run_tests +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -## Run phpunit tests -## -## Tests: -## - fin run_tests --filter 'UiPatternsSettingsRenderTest' - -set -e - -fin exec /var/www/vendor/bin/phpunit $* diff --git a/.docksal/docksal.env b/.docksal/docksal.env deleted file mode 100644 index e8be01a..0000000 --- a/.docksal/docksal.env +++ /dev/null @@ -1,6 +0,0 @@ -DOCKSAL_STACK=default -DOCROOT=build -XDEBUG_ENABLED=0 -WEB_IMAGE='docksal/web:2.1-apache2.4' -DB_IMAGE='docksal/db:1.3-mysql-5.7' -CLI_IMAGE='docksal/cli:php8.1' diff --git a/.docksal/docksal.yml b/.docksal/docksal.yml deleted file mode 100644 index 2c4378d..0000000 --- a/.docksal/docksal.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: "2.1" -services: - # Web - web: - extends: - file: ${HOME}/.docksal/stacks/services.yml - service: apache - depends_on: - - cli - - # DB - db: - extends: - file: ${HOME}/.docksal/stacks/services.yml - service: mysql - # CLI - cli: - extends: - file: ${HOME}/.docksal/stacks/services.yml - service: cli - labels: - - io.docksal.virtual-host=storybook.${VIRTUAL_HOST} - - io.docksal.virtual-port=3000 - environment: - - "XDEBUG_CONFIG=client_host=${DOCKSAL_HOST_IP} client_port=9000" - - "XDEBUG_MODE=debug" - - DOCKSAL=1 - - PHP_IDE_CONFIG=serverName=${VIRTUAL_HOST} diff --git a/.docksal/etc/php/php-cli.ini b/.docksal/etc/php/php-cli.ini deleted file mode 100644 index a764a8a..0000000 --- a/.docksal/etc/php/php-cli.ini +++ /dev/null @@ -1,4 +0,0 @@ -; PHP CLI settings -[php] -; Maximum amount of memory a script may consume -memory_limit = -1 \ No newline at end of file diff --git a/.docksal/etc/php/php.ini b/.docksal/etc/php/php.ini deleted file mode 100644 index c96b707..0000000 --- a/.docksal/etc/php/php.ini +++ /dev/null @@ -1,4 +0,0 @@ -; PHP CLI settings -[php] -; Maximum amount of memory a script may consume -memory_limit = -1 diff --git a/.github_changelog_generator b/.github_changelog_generator deleted file mode 100644 index 6d43718..0000000 --- a/.github_changelog_generator +++ /dev/null @@ -1,5 +0,0 @@ -merge_prefix=**Merged Pull Requests** -tag1='API change' -include-labels='API change,Bug,New feature' -enhancement_prefix=**New features** -enhancement-labels='New feature' diff --git a/.gitignore b/.gitignore index 225938e..a09c56d 100755 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1 @@ /.idea -/vendor -/composer.lock -/docs/_build -/build/ -/phpunit.xml -/docker-compose.override.yml -/runner.yml -/.docksal/docksal-local.env -/.editorconfig -/.gitattributes -/.phpunit.result.cache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fe179c3..0000000 --- a/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -sudo: required -language: php - -php: - - 7.3 - - 7.4 - -services: - - docker - -env: - global: - - DOCKER_COMPOSE_VERSION=1.25.5 - matrix: - - DRUPAL_VERSION=~8.8.7 GRUMPHP_CONFIG=grumphp.drupal8.yml - - DRUPAL_VERSION=~8.9.0 GRUMPHP_CONFIG=grumphp.drupal8.yml - - DRUPAL_VERSION=~9.0.0 GRUMPHP_CONFIG=grumphp.yml - - DRUPAL_VERSION=9.1.x-dev GRUMPHP_CONFIG=grumphp.yml - -matrix: - allow_failures: - - env: DRUPAL_VERSION=9.1.x-dev - -before_install: - - docker-compose up -d - -install: - - docker-compose exec -u root php composer require drupal/core-recommended:$DRUPAL_VERSION --dev - - docker-compose exec -u root php chown -R www-data:www-data build - -script: - - docker-compose exec -u www-data php ./vendor/bin/grumphp run -c $GRUMPHP_CONFIG - - docker-compose exec -u www-data php ./vendor/bin/phpunit - -notifications: - email: false - diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 420e6f2..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1 +0,0 @@ -# Change Log diff --git a/composer.json b/composer.json deleted file mode 100644 index 5dceecb..0000000 --- a/composer.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "name": "drupal/ui_patterns_settings", - "type": "drupal-module", - "description": "UI Patterns Settings.", - "keywords": [ - "drupal", - "web", - "ui" - ], - "license": "GPL-2.0+", - "minimum-stability": "dev", - "prefer-stable": true, - "authors": [ - { - "name": "Christian Wiedemann", - "email": "christian.wiedemann@key-tec.de" - } - ], - "require-dev": { - "composer/installers": "^1.2", - "drupal/coder": "*", - "drupal/core-composer-scaffold": "^8.8 || ^9 || ^10", - "drupal/core-dev": "^8.8 || ^9 || ^10", - "drupal/core-recommended": "~10 || ^9", - "drupal/ds": "^3.15", - "drupal/token": "~1.0", - "drupal/ui_patterns": "~1.3", - "drupal/ui_patterns_field_formatters": "^2.0", - "drupal/ui_patterns_layout_builder": "~1", - "drush/drush": "~11", - "openeuropa/task-runner": "~2.0.0-alpha1", - "phpro/grumphp": "~1.5" - }, - "repositories": [ - { - "type": "composer", - "url": "https://packages.drupal.org/8" - } - ], - "autoload": { - "psr-4": { - "Drupal\\ui_patterns_settings_settings\\": "./src" - } - }, - "autoload-dev": { - "psr-4": { - "Drupal\\Tests\\ui_patterns_settings_settings\\": "./tests/src" - } - }, - "scripts": { - "post-install-cmd": "./vendor/bin/run drupal:site-setup", - "post-update-cmd": "./vendor/bin/run drupal:site-setup" - }, - "extra": { - "enable-patching": true, - "composer-exit-on-patch-failure": true, - "drupal-scaffold": { - "locations": { - "web-root": "build/" - } - }, - "installer-paths": { - "build/core": [ - "type:drupal-core" - ], - "build/modules/contrib/{$name}": [ - "type:drupal-module" - ], - "build/profiles/contrib/{$name}": [ - "type:drupal-profile" - ], - "build/themes/contrib/{$name}": [ - "type:drupal-theme" - ] - } - }, - "config": { - "sort-packages": true, - "allow-plugins": { - "composer/installers": true, - "cweagans/composer-patches": true, - "drupal/core-composer-scaffold": true, - "phpro/grumphp": true, - "phpstan/extension-installer": true, - "dealerdirect/phpcodesniffer-composer-installer": true, - "oomphinc/composer-installers-extender": true - } - } -} diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index c9c010c..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,67 +0,0 @@ -version: "2" - -services: - - mariadb: - image: wodby/mariadb:10.3-3.8.4 - stop_grace_period: 30s - environment: - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: drupal - MYSQL_USER: drupal - MYSQL_PASSWORD: drupal - - php: - image: wodby/drupal-php:${TRAVIS_PHP_VERSION}-4.15.9 - environment: - DB_HOST: mariadb - DB_USER: drupal - DB_PASSWORD: drupal - DB_NAME: drupal - DB_DRIVER: mysql - PHP_XDEBUG: 1 - PHP_XDEBUG_DEFAULT_ENABLE: 1 - PHP_XDEBUG_REMOTE_CONNECT_BACK: 1 - PHP_XDEBUG_REMOTE_HOST: "10.254.254.254" - PHP_XDEBUG_IDEKEY: "PHPSTORM" - PHP_IDE_CONFIG: "serverName=ui_patterns" - volumes: - - ./:/var/www/html - - nginx: - image: wodby/nginx:1.15-5.0.0 - depends_on: - - php - environment: - NGINX_STATIC_OPEN_FILE_CACHE: "off" - NGINX_ERROR_LOG_LEVEL: debug - NGINX_BACKEND_HOST: php - NGINX_SERVER_ROOT: /var/www/html/build - NGINX_VHOST_PRESET: drupal8 - volumes: - - ./:/var/www/html - ports: - - "8080:80" - - # If you would like to see what is going on you can run the following on your host: - # docker run --rm -p 4444:4444 -p 5900:5900 --network="host" selenium/standalone-chrome-debug:latest - # Newer version of this image might run into this issue: - # @link https://github.com/elgalu/docker-selenium/issues/20 - selenium: - image: selenium/standalone-chrome-debug:3.11 - expose: - - '4444' - environment: - - DISPLAY=:99 - - SE_OPTS=-debug - - SCREEN_WIDTH=1280 - - SCREEN_HEIGHT=800 - - VNC_NO_PASSWORD=1 - ports: - - '4444:4444' - - "5900:5900" - volumes: - - /dev/shm:/dev/shm - -volumes: - codebase: diff --git a/grumphp b/grumphp deleted file mode 100644 index 7d9c0de..0000000 --- a/grumphp +++ /dev/null @@ -1,16 +0,0 @@ -parameters: - ascii: - failed: ~ - succeeded: ~ - tasks: - phpcs: - standard: vendor/drupal/coder/coder_sniffer/Drupal/ - ignore_patterns: - - build/ - - vendor/ - triggered_by: - - php - - module - - install - - inc - - theme diff --git a/grumphp.drupal8.yml b/grumphp.drupal8.yml deleted file mode 100644 index 79311e2..0000000 --- a/grumphp.drupal8.yml +++ /dev/null @@ -1,16 +0,0 @@ -grumphp: - ascii: - failed: ~ - succeeded: ~ - tasks: - phpcs: - standard: vendor/drupal/coder/coder_sniffer/Drupal/ - ignore_patterns: - - build/ - - vendor/ - triggered_by: - - php - - module - - install - - inc - - theme diff --git a/phpcs.xml.dist b/phpcs.xml.dist deleted file mode 100644 index b516332..0000000 --- a/phpcs.xml.dist +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- Adapted from Acquia Coding Standards default ruleset. --> -<!-- @see https://github.com/acquia/coding-standards-php/blob/develop/example/phpcs.xml.dist --> - -<!-- https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset --> -<ruleset name="Example"> - - <description>An example PHP CodeSniffer configuration.</description> - - <!-- Set extensions to scan (taken from Coder 8.3.6). --> - <!-- @see https://git.drupalcode.org/project/coder/blob/8.3.6/coder_sniffer/Drupal/ruleset.xml#L8 --> - <arg name="extensions" value="php,module,inc,install,test,profile,theme,css,info,txt,md,yml"/> - - <arg name="colors"/> - <arg name="cache" value=".phpcs-cache"/> - <arg name="parallel" value="10"/> - - <file>docroot/modules/custom</file> - <file>docroot/themes/custom</file> - <file>tests</file> - - <exclude-pattern>*/behat</exclude-pattern> - <exclude-pattern>*/node_modules</exclude-pattern> - <exclude-pattern>*/vendor</exclude-pattern> - - <exclude-pattern>vendor/*</exclude-pattern> - - <rule ref="AcquiaDrupalStrict"/> - -</ruleset> diff --git a/runner.docksal.yml b/runner.docksal.yml deleted file mode 100644 index 7222a68..0000000 --- a/runner.docksal.yml +++ /dev/null @@ -1,46 +0,0 @@ -drupal: - root: "build" - base_url: "http://ui-patterns-settings.docksal" - database: - host: "db" - port: "3306" - name: "default" - user: "root" - password: "root" - post_install: - - "./vendor/bin/drush en -y ui_patterns ui_patterns_library ui_patterns_ds ui_patterns_field_group ui_patterns_layouts ui_patterns_views ui_patterns_settings ui_patterns_settings_render_test" - - "./vendor/bin/drush en -y coffee config_devel" - - "./vendor/bin/drush en -y page_manager paragraphs panels" - - "./vendor/bin/drush cr" - settings: - settings: - container_yamls: - - "/var/www/${drupal.root}/sites/development.services.yml" - extension_discovery_scan_tests: true - cache: - bins: - dynamic_page_cache: "cache.backend.null" - page_cache: "cache.backend.null" - render: "cache.backend.null" - file_scan_ignore_directories: - - "vendor" - - "${drupal.root}" - -selenium: - host: "http://selenium:4444" - browser: "chrome" - -commands: - drupal:site-setup: - - { task: "symlink", from: "../../../../src", to: "${drupal.root}/modules/custom/ui_patterns_settings/src" } - - { task: "symlink", from: "../../../../tests", to: "${drupal.root}/modules/custom/ui_patterns_settings/tests" } - - { task: "symlink", from: "../../../../ui_patterns_settings.info.yml", to: "${drupal.root}/modules/custom/ui_patterns_settings/ui_patterns_settings.info.yml" } - - { task: "symlink", from: "../../../../ui_patterns_settings.module", to: "${drupal.root}/modules/custom/ui_patterns_settings/ui_patterns_settings.module" } - - { task: "symlink", from: "../../../../ui_patterns_settings.services.yml", to: "${drupal.root}/modules/custom/ui_patterns_settings/ui_patterns_settings.services.yml" } - # Generate settings.testing.php, it will be used when running functional tests. - - { task: "process-php", type: "write", config: "drupal.settings", source: "${drupal.root}/sites/default/default.settings.php", destination: "${drupal.root}/sites/default/settings.testing.php", override: true } - - { task: "run", command: "drupal:drush-setup" } - - { task: "run", command: "drupal:settings-setup" } - - { task: "run", command: "setup:phpunit" } - setup:phpunit: - - { task: "process", source: "phpunit.xml.dist", destination: "phpunit.xml" } diff --git a/runner.yml.dist b/runner.yml.dist deleted file mode 100644 index 6be0adf..0000000 --- a/runner.yml.dist +++ /dev/null @@ -1,48 +0,0 @@ -drupal: - root: "build" - base_url: "http://ui-patterns-settings.docksal" - database: - host: "db" - port: "3306" - name: "default" - user: "root" - password: "root" - post_install: - - "./vendor/bin/drush en -y ui_patterns layout_builder ui_patterns_layout_builder ui_patterns_library ui_patterns_layouts ui_patterns_views ui_patterns_settings ui_patterns_settings_render_test" - - "./vendor/bin/drush cr" - settings: - settings: - container_yamls: - - "/var/www/${drupal.root}/sites/development.services.yml" - extension_discovery_scan_tests: true - cache: - bins: - dynamic_page_cache: "cache.backend.null" - page_cache: "cache.backend.null" - render: "cache.backend.null" - file_scan_ignore_directories: - - "vendor" - - "${drupal.root}" - -selenium: - host: "http://selenium:4444" - browser: "chrome" - -commands: - drupal:site-setup: - - { task: "symlink", from: "../../../../config", to: "${drupal.root}/modules/custom/ui_patterns_settings/config" } - - { task: "symlink", from: "../../../../src", to: "${drupal.root}/modules/custom/ui_patterns_settings/src" } - - { task: "symlink", from: "../../../../js", to: "${drupal.root}/modules/custom/ui_patterns_settings/js" } - - { task: "symlink", from: "../../../../css", to: "${drupal.root}/modules/custom/ui_patterns_settings/css" } - - { task: "symlink", from: "../../../../tests", to: "${drupal.root}/modules/custom/ui_patterns_settings/tests" } - - { task: "symlink", from: "../../../../ui_patterns_settings.libraries.yml", to: "${drupal.root}/modules/custom/ui_patterns_settings/ui_patterns_settings.libraries.yml" } - - { task: "symlink", from: "../../../../ui_patterns_settings.info.yml", to: "${drupal.root}/modules/custom/ui_patterns_settings/ui_patterns_settings.info.yml" } - - { task: "symlink", from: "../../../../ui_patterns_settings.module", to: "${drupal.root}/modules/custom/ui_patterns_settings/ui_patterns_settings.module" } - - { task: "symlink", from: "../../../../ui_patterns_settings.services.yml", to: "${drupal.root}/modules/custom/ui_patterns_settings/ui_patterns_settings.services.yml" } - # Generate settings.testing.php, it will be used when running functional tests. - - { task: "process-php", type: "write", config: "drupal.settings", source: "${drupal.root}/sites/default/default.settings.php", destination: "${drupal.root}/sites/default/settings.testing.php", override: true } - - { task: "run", command: "drupal:drush-setup" } - - { task: "run", command: "drupal:settings-setup" } - - { task: "run", command: "setup:phpunit" } - setup:phpunit: - - { task: "process", source: "phpunit.xml.dist", destination: "phpunit.xml" } -- GitLab From 309e84d4b2d1827d3fc408bebd39ba46d25fa8c0 Mon Sep 17 00:00:00 2001 From: Florent Torregrosa <14238-florenttorregrosa@users.noreply.drupalcode.org> Date: Wed, 5 Jun 2024 14:24:56 +0000 Subject: [PATCH 10/17] Issue #3437139 by Grimreaper: LinksSettingType: add attributes of the link generator --- .../SettingType/LinksSettingType.php | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php index 083fb60..52a1cef 100644 --- a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php +++ b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php @@ -2,6 +2,8 @@ namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingType; +use Drupal\Component\Serialization\Json; +use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Template\Attribute; use Drupal\Core\Url; use Drupal\ui_patterns_settings\Plugin\ComplexSettingTypeBase; @@ -85,10 +87,71 @@ class LinksSettingType extends ComplexSettingTypeBase { $item["url"] = $url->toString(); } $options = $url->getOptions(); + self::setHrefLang($options); + self::setActiveClass($options, $url); if (isset($options["attributes"])) { $item["link_attributes"] = new Attribute($options["attributes"]); } return $item; } + /** + * Set hreflang attribute. + * + * Add a hreflang attribute if we know the language of this link's URL and + * hreflang has not already been set. + * + * @param array $options + * The URL options. + * + * @see \Drupal\Core\Utility\LinkGenerator::generate() + */ + private static function setHrefLang(array &$options): void { + if (isset($options['language']) + && ($options['language'] instanceof LanguageInterface) + && !isset($options['attributes']['hreflang']) + ) { + $options['attributes']['hreflang'] = $options['language']->getId(); + } + } + + /** + * Set the attributes to have the active class placed by JS. + * + * @param array $options + * The URL options. + * @param \Drupal\Core\Url $url + * The URL object. + * + * @see \Drupal\Core\Utility\LinkGenerator::generate() + */ + private static function setActiveClass(array &$options, Url $url): void { + // Set the "active" class if the 'set_active_class' option is not empty. + if (!empty($options['set_active_class']) && !$url->isExternal()) { + // Add a "data-drupal-link-query" attribute to let the + // drupal.active-link library know the query in a standardized manner. + if (!empty($options['query'])) { + $query = $options['query']; + ksort($query); + $options['attributes']['data-drupal-link-query'] = Json::encode($query); + } + + // Add a "data-drupal-link-system-path" attribute to let the + // drupal.active-link library know the path in a standardized manner. + if ($url->isRouted() && !isset($options['attributes']['data-drupal-link-system-path'])) { + // @todo System path is deprecated - use the route name and parameters. + $system_path = $url->getInternalPath(); + + // Special case for the front page. + if ($url->getRouteName() === '<front>') { + $system_path = '<front>'; + } + + if (!empty($system_path)) { + $options['attributes']['data-drupal-link-system-path'] = $system_path; + } + } + } + } + } -- GitLab From a7b01d95b08d8a2c3ea5f2ae0bd2563d4153ff75 Mon Sep 17 00:00:00 2001 From: Stangl David <51931-Duwid@users.noreply.drupalcode.org> Date: Wed, 5 Jun 2024 14:30:56 +0000 Subject: [PATCH 11/17] Issue #3403220 by mikemooney, Duwid, Christian.wiedemann: PHP 8.2 EnumerationSettingTypeBase options fix --- src/Plugin/EnumerationSettingTypeBase.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Plugin/EnumerationSettingTypeBase.php b/src/Plugin/EnumerationSettingTypeBase.php index 4d47476..b466d0e 100644 --- a/src/Plugin/EnumerationSettingTypeBase.php +++ b/src/Plugin/EnumerationSettingTypeBase.php @@ -71,7 +71,9 @@ abstract class EnumerationSettingTypeBase extends PatternSettingTypeBase { $options = []; } - $options += $this->getOptions($def); + if ($this->getOptions($def) !== NULL) { + $options += $this->getOptions($def); + } $form[$def->getName()] = [ '#type' => $this->getEnumerationType($def), '#title' => $def->getLabel(), -- GitLab From 06ce86242d6969265ccdcfebceade223545058f7 Mon Sep 17 00:00:00 2001 From: Florent Torregrosa <14238-florenttorregrosa@users.noreply.drupalcode.org> Date: Wed, 5 Jun 2024 16:03:46 +0000 Subject: [PATCH 12/17] Issue #3409221 by Grimreaper, huzooka, Ahmad Abbad, ekes, Walli, braintec, thejimbirch, kekkis, liber_t, kerrymick, DuaelFr, Rajab Natshah, steveoriol, catch, CarlosMonroy, very_random_man, herved: Fix TypeError: array_unshift(): Argument #1 ($array) must be of type array, null given in array_unshift() Caused by Deprecated Hooks in Drupal ~10.2.0 --- ui_patterns_settings.info.yml | 2 +- ui_patterns_settings.module | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/ui_patterns_settings.info.yml b/ui_patterns_settings.info.yml index a93111a..31c1fd0 100644 --- a/ui_patterns_settings.info.yml +++ b/ui_patterns_settings.info.yml @@ -2,7 +2,7 @@ name: UI Patterns Settings type: module description: Configure patterns with settings package: User interface -core_version_requirement: ^8 || ^9 || ^10 +core_version_requirement: ^10.2 dependencies: - ui_patterns:ui_patterns - token:token diff --git a/ui_patterns_settings.module b/ui_patterns_settings.module index 20a3458..e651a8f 100644 --- a/ui_patterns_settings.module +++ b/ui_patterns_settings.module @@ -7,6 +7,7 @@ use Drupal\Component\Utility\UrlHelper; use Drupal\Core\Url; +use Drupal\field\FieldStorageConfigInterface; use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; use Drupal\ui_patterns_settings\Plugin\Layout\PatternSettingsLayout; use Drupal\Core\Entity\EntityTypeInterface; @@ -82,13 +83,14 @@ function ui_patterns_settings_preprocess_media_library_element(&$variables) { } } + /** - * Implements hook_form_field_storage_config_edit_form_alter(). + * Implements hook_form_FORM_ID_alter() for 'field_config_edit_form'. */ -function ui_patterns_settings_form_field_storage_config_edit_form_alter(&$form, FormStateInterface $form_state) { +function ui_patterns_settings_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state): void { /** @var \Drupal\field\Entity\FieldStorageConfig $entity */ - $entity = $form_state->getFormObject()->getEntity(); - array_unshift($form['actions']['submit']['#submit'], 'ui_patterns_settings_form_field_storage_config_edit_form_submit'); + $entity = $form_state->getFormObject()->getEntity()->getFieldStorageDefinition(); + array_unshift($form['actions']['submit']['#submit'], 'ui_patterns_settings_form_field_config_edit_form_submit'); $definitions = UiPatterns::getPatternDefinitions(); $settings_options = []; @@ -98,22 +100,24 @@ function ui_patterns_settings_form_field_storage_config_edit_form_alter(&$form, $settings_options[$key] = $info['label']; } } + if (count($settings_options) > 0) { + $parent = &$form['field_storage']['subform']; $mapping = UiPatternsSettings::getConfigManager()->getMapping($entity->id()); - $form['settings']['use_pattern'] = [ + $parent['settings']['use_pattern'] = [ '#type' => 'checkbox', '#title' => t('Expose pattern setting'), '#default_value' => $mapping !== NULL, '#description' => '', ]; - $form['settings']['pattern_setting'] = [ + $parent['settings']['pattern_setting'] = [ '#type' => 'select', '#options' => $settings_options, '#title' => 'Pattern Setting', '#states' => [ 'invisible' => [ - ':input[name="settings[use_pattern]"]' => ['checked' => FALSE], + ':input[name$="[use_pattern]"]' => ['checked' => FALSE], ], ], '#default_value' => $mapping, @@ -122,12 +126,12 @@ function ui_patterns_settings_form_field_storage_config_edit_form_alter(&$form, } /** - * Implements hook_form_field_storage_config_edit_form_submit(). + * Form submit callback. */ -function ui_patterns_settings_form_field_storage_config_edit_form_submit(array $form, FormStateInterface $form_state) { - $settings = $form_state->getValue('settings'); - /** @var \Drupal\field\Entity\FieldStorageConfig $entity */ - $entity = $form_state->getFormObject()->getEntity(); +function ui_patterns_settings_form_field_config_edit_form_submit(array $form, FormStateInterface $form_state) { + $settings = $form_state->getValue(['field_storage', 'subform', 'settings']); + $entity = $form_state->getFormObject()->getEntity()->getFieldStorageDefinition(); + \assert($entity instanceof FieldStorageConfigInterface); if (isset($settings['use_pattern']) && $settings['use_pattern'] === 1) { UiPatternsSettings::getConfigManager()->addMapping($entity->id(), $settings['pattern_setting']); -- GitLab From 69cefcd4248d55ea1300d0a7ee41d4ec06634e6e Mon Sep 17 00:00:00 2001 From: Florent Torregrosa <14238-florenttorregrosa@users.noreply.drupalcode.org> Date: Wed, 5 Jun 2024 16:07:05 +0000 Subject: [PATCH 13/17] Issue #3435195 by Project Update Bot, Grimreaper: Automated Drupal 11... --- .../ui_patterns_settings_data_provider.info.yml | 2 +- .../ui_patterns_settings_render_test.info.yml | 2 +- ui_patterns_settings.info.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml b/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml index 4e38253..43f4846 100644 --- a/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml +++ b/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml @@ -1,5 +1,5 @@ type: module name: 'UI Patterns Settings Data Provider' -core_version_requirement: ^8 || ^9 || ^10 +package: 'Testing' dependencies: - ui_patterns_settings:ui_patterns_settings diff --git a/tests/modules/ui_patterns_settings_render_test/ui_patterns_settings_render_test.info.yml b/tests/modules/ui_patterns_settings_render_test/ui_patterns_settings_render_test.info.yml index 047efdc..dd256b5 100644 --- a/tests/modules/ui_patterns_settings_render_test/ui_patterns_settings_render_test.info.yml +++ b/tests/modules/ui_patterns_settings_render_test/ui_patterns_settings_render_test.info.yml @@ -1,3 +1,3 @@ type: module name: 'UI Patterns Settings Render Test' -core_version_requirement: ^8 || ^9 || ^10 +package: 'Testing' diff --git a/ui_patterns_settings.info.yml b/ui_patterns_settings.info.yml index 31c1fd0..0345acc 100644 --- a/ui_patterns_settings.info.yml +++ b/ui_patterns_settings.info.yml @@ -2,7 +2,7 @@ name: UI Patterns Settings type: module description: Configure patterns with settings package: User interface -core_version_requirement: ^10.2 +core_version_requirement: ^10.2 || ^11 dependencies: - ui_patterns:ui_patterns - token:token -- GitLab From eb2b8352f5d3b900c306b5b3fc3972f0509e5fc0 Mon Sep 17 00:00:00 2001 From: Florent Torregrosa <14238-florenttorregrosa@users.noreply.drupalcode.org> Date: Fri, 6 Sep 2024 19:45:18 +0000 Subject: [PATCH 14/17] Issue #3469755 by grimreaper: Links normalize drops link options --- src/Plugin/UiPatterns/SettingType/LinksSettingType.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php index 52a1cef..75569fd 100644 --- a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php +++ b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php @@ -30,7 +30,7 @@ class LinksSettingType extends ComplexSettingTypeBase { * @return array */ public static function normalize(array $items): array { - foreach ($items as $index => &$item) { + foreach ($items as $index => $item) { if (!is_array($item)) { unset($items[$index]); continue; @@ -52,13 +52,16 @@ class LinksSettingType extends ComplexSettingTypeBase { if (!isset($item["url"]) && isset($item["link"])) { // Example: links.html.twig. $item["url"] = $item["link"]["#url"]; - $item["url"]->setOptions($item["link"]["#options"]); + if (isset($item["link"]["#options"])) { + $item["url"]->mergeOptions($item["link"]["#options"]); + } unset($item["link"]); } $item = self::normalizeUrl($item); if (array_key_exists("below", $item)) { $item["below"] = self::normalize($item["below"]); } + $items[$index] = $item; } $items = array_values($items); return $items; -- GitLab From d5e73741d4e7a1a43a83ded441064a8e11e47f8c Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Sat, 14 Sep 2024 08:54:51 +0200 Subject: [PATCH 15/17] Issue #3455625 by zemike: New Setting type Access By role --- .../templates/settings.ui_patterns.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml b/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml index a7a1d70..a3133ae 100644 --- a/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml +++ b/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml @@ -100,6 +100,12 @@ foo_settings: key2: label: select_config 2 configuration: config key2 + role_checkboxes: + type: role_checkboxes + label: Role checkboxes + role_access: + type: role_checkboxes + label: Role Access language_checkboxes: type: language_checkboxes label: Language selection -- GitLab From c0a38b3b63ecd6e78237760ba7567f20dd17849c Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Sat, 14 Sep 2024 09:10:23 +0200 Subject: [PATCH 16/17] Issue #3455625 by zemike: New Setting type Access By role --- src/Plugin/RoleCheckboxesSettingTypeBase.php | 109 ++++++++++++++++++ .../SettingType/RoleAccessSettingType.php | 31 +++++ .../SettingType/RoleCheckboxesSettingType.php | 24 ++++ 3 files changed, 164 insertions(+) create mode 100644 src/Plugin/RoleCheckboxesSettingTypeBase.php create mode 100644 src/Plugin/UiPatterns/SettingType/RoleAccessSettingType.php create mode 100644 src/Plugin/UiPatterns/SettingType/RoleCheckboxesSettingType.php diff --git a/src/Plugin/RoleCheckboxesSettingTypeBase.php b/src/Plugin/RoleCheckboxesSettingTypeBase.php new file mode 100644 index 0000000..da13e44 --- /dev/null +++ b/src/Plugin/RoleCheckboxesSettingTypeBase.php @@ -0,0 +1,109 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin; + +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Role Checkboxes setting type. + * + * Provides an array of: + * - current_role_selected: True if the current role is part of the selection + * or nothing is selected + * - current_role: The current role. + * - selected: Array of selected roles. + * + * @UiPatternsSettingType( + * id = "role_checkboxes", + * label = @Translation("Role checkboxes") + * ) + */ +class RoleCheckboxesSettingTypeBase extends EnumerationSettingTypeBase { + + /** + * The current user. + * + * @var \Drupal\Core\Session\AccountProxyInterface + */ + protected $currentUser; + + /** + * {@inheritdoc} + */ + protected function emptyOption() { + return []; + } + + /** + * {@inheritdoc} + */ + protected function getValue($value) { + if ($value === NULL) { + return !is_array($this->getPatternSettingDefinition() + ->getDefaultValue()) ? [ + $this->getPatternSettingDefinition() + ->getDefaultValue(), + ] : $this->getPatternSettingDefinition()->getDefaultValue(); + } + else { + return $value ?? ""; + } + } + + /** + * {@inheritdoc} + */ + protected function getOptions(PatternDefinitionSetting $def) { + $roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple(); + $options = []; + foreach ($roles as $role) { + $options[$role->id()] = $role->label(); + } + return $options; + } + + /** + * {@inheritdoc} + */ + protected function getEnumerationType(PatternDefinitionSetting $def) { + return $def->getValue('enumeration_type') ?? 'checkboxes'; + } + + /** + * {@inheritdoc} + */ + public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { + $selected_options = []; + $defined_options = $this->getOptions($def); + + if (is_array($value)) { + foreach ($value as $checkbox_key => $checkbox_value) { + if ($checkbox_value != "0") { + $selected_options[$checkbox_key] = $defined_options[$checkbox_key] ?? $checkbox_value; + } + } + } + + $current_user_roles = $this->currentUser->getRoles(); + $selected_options_keys = array_keys($selected_options); + $settings = [ + 'current_role_selected' => count($selected_options) === 0 || !empty(array_intersect($current_user_roles, $selected_options_keys)), + 'selected' => $selected_options, + ]; + foreach ($current_user_roles as $current_role_id) { + $settings['current_role'][$current_role_id] = $defined_options[$current_role_id]; + } + return $settings; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition); + $instance->currentUser = $container->get('current_user'); + return $instance; + } + +} diff --git a/src/Plugin/UiPatterns/SettingType/RoleAccessSettingType.php b/src/Plugin/UiPatterns/SettingType/RoleAccessSettingType.php new file mode 100644 index 0000000..ae3742a --- /dev/null +++ b/src/Plugin/UiPatterns/SettingType/RoleAccessSettingType.php @@ -0,0 +1,31 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; + +use Drupal\ui_patterns_settings\Plugin\RoleCheckboxesSettingTypeBase; +use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; + +/** + * Hides render element for unchecked roles. + * + * Setting type to hide the render element if: + * Elements are checked and the current role is + * not part of the selection. + * + * @UiPatternsSettingType( + * id = "role_access", + * label = @Translation("Role Access") + * ) + */ +class RoleAccessSettingType extends RoleCheckboxesSettingTypeBase { + + /** + * {@inheritdoc} + */ + public function alterElement($value, PatternDefinitionSetting $def, &$element) { + if ($this->isLayoutBuilderRoute() === FALSE && $value['current_role_selected'] === FALSE) { + hide($element); + } + } + +} diff --git a/src/Plugin/UiPatterns/SettingType/RoleCheckboxesSettingType.php b/src/Plugin/UiPatterns/SettingType/RoleCheckboxesSettingType.php new file mode 100644 index 0000000..ade81e7 --- /dev/null +++ b/src/Plugin/UiPatterns/SettingType/RoleCheckboxesSettingType.php @@ -0,0 +1,24 @@ +<?php + +namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; + +use Drupal\ui_patterns_settings\Plugin\RoleCheckboxesSettingTypeBase; + +/** + * Role Checkboxes setting type. + * + * Provides an array of: + * - current_role_selected: True if the + * current role is part of the selection + * or nothing is selected + * - current_role: The current role. + * - selected: Array of selected role. + * + * @UiPatternsSettingType( + * id = "role_checkboxes", + * label = @Translation("Role checkboxes") + * ) + */ +class RoleCheckboxesSettingType extends RoleCheckboxesSettingTypeBase { + +} -- GitLab From 28b6858f824fa882cc632993f5fe97eb4395977d Mon Sep 17 00:00:00 2001 From: Christian Wiedemann <christian.wiedemann@key-tec.de> Date: Tue, 4 Feb 2025 20:52:39 +0100 Subject: [PATCH 17/17] Add inital media modul --- config/schema/ui_patterns_settings.schema.yml | 10 - .../ui_patterns_settings.sources.schema.yml | 10 + css/toggler.png | Bin 14513 -> 0 bytes css/ui_patterns_settings.css | 50 -- images/settings.png | Bin 25040 -> 0 bytes js/ui_pattern_settings.toggle_token.js | 49 -- .../UiPatternsSettingDataProvider.php | 45 -- src/Annotation/UiPatternsSettingType.php | 33 -- src/ConfigManager.php | 120 ----- src/Definition/PatternDefinitionSetting.php | 400 ---------------- src/Element/PatternSettings.php | 162 ------- src/Form/SettingsFormBuilder.php | 289 ------------ src/Plugin/ComplexSettingTypeBase.php | 111 ----- src/Plugin/EnumerationSettingTypeBase.php | 88 ---- .../LanguageCheckboxesSettingTypeBase.php | 112 ----- src/Plugin/Layout/PatternSettingsLayout.php | 29 -- src/Plugin/PatternSettingDataProviderBase.php | 89 ---- .../PatternSettingDataProviderInterface.php | 46 -- src/Plugin/PatternSettingTypeBase.php | 440 ------------------ src/Plugin/PatternSettingTypeInterface.php | 115 ----- src/Plugin/RoleCheckboxesSettingTypeBase.php | 109 ----- src/Plugin/TokenSettingTypeBase.php | 115 ----- .../BreadcrumbDataProvider.php | 104 ----- .../SettingDataProvider/MenuDataProvider.php | 184 -------- .../SettingType/AttributesSettingType.php | 51 -- .../SettingType/BooleanSettingType.php | 40 -- .../SettingType/CheckboxesSettingType.php | 57 --- .../SettingType/ColorWidgetSettingType.php | 76 --- .../SettingType/ColorisWidgetSettingType.php | 57 --- .../SettingType/EnumerationSettingType.php | 17 - .../UiPatterns/SettingType/GroupType.php | 40 -- .../SettingType/LanguageAccessSettingType.php | 31 -- .../LanguageCheckboxesSettingType.php | 28 -- .../SettingType/LinksSettingType.php | 160 ------- .../SettingType/MachineNameSettingType.php | 34 -- .../SettingType/MediaLibrarySettingType.php | 125 ----- .../SettingType/NumberSettingType.php | 34 -- .../SettingType/PublishSettingType.php | 51 -- .../SettingType/RadiosSettingType.php | 25 - .../SettingType/RoleAccessSettingType.php | 31 -- .../SettingType/RoleCheckboxesSettingType.php | 24 - .../SettingType/SelectSettingType.php | 32 -- .../SettingType/TextfieldSettingType.php | 33 -- .../SettingType/TokenSettingType.php | 17 - .../UiPatterns/SettingType/UrlSettingType.php | 60 --- .../SettingType/ValueSettingType.php | 34 -- src/Plugin/UiPatterns/Source/MediaSource.php | 143 ++++++ .../UiPatterns/Source/SettingFieldSource.php | 49 -- .../UIPatternsSettingsExtension.php | 56 --- src/UiPatternsSettings.php | 307 ------------ src/UiPatternsSettingsDataProviderManager.php | 48 -- src/UiPatternsSettingsManager.php | 65 --- tests/fixtures/TestDataSet.yml | 20 + .../UiPatterns/SettingDataProvider/Foo.php | 34 -- .../SettingType/SampleComplexSettingType.php | 19 - .../templates/pattern-foo-complex.html.twig | 8 - .../templates/settings.ui_patterns.yml | 16 - ...i_patterns_settings_data_provider.info.yml | 5 - .../templates/pattern-foo-settings.html.twig | 19 - .../templates/settings.ui_patterns.yml | 165 ------- .../ui_patterns_settings_render_test.info.yml | 3 - .../UiPatternsSettingsRenderTest.php | 114 ----- tests/src/Kernel/ComplexSettingTypeTest.php | 72 --- tests/src/Kernel/Source/MediaSourceTest.php | 32 ++ .../src/Kernel/UiPSSourcePluginsTestBase.php | 30 ++ ui_patterns_settings.info.yml | 2 +- ui_patterns_settings.libraries.yml | 12 - ui_patterns_settings.module | 330 ------------- ui_patterns_settings.services.yml | 15 +- 69 files changed, 237 insertions(+), 5094 deletions(-) delete mode 100644 config/schema/ui_patterns_settings.schema.yml create mode 100644 config/schema/ui_patterns_settings.sources.schema.yml delete mode 100644 css/toggler.png delete mode 100644 css/ui_patterns_settings.css delete mode 100644 images/settings.png delete mode 100644 js/ui_pattern_settings.toggle_token.js delete mode 100644 src/Annotation/UiPatternsSettingDataProvider.php delete mode 100644 src/Annotation/UiPatternsSettingType.php delete mode 100644 src/ConfigManager.php delete mode 100644 src/Definition/PatternDefinitionSetting.php delete mode 100644 src/Element/PatternSettings.php delete mode 100644 src/Form/SettingsFormBuilder.php delete mode 100644 src/Plugin/ComplexSettingTypeBase.php delete mode 100644 src/Plugin/EnumerationSettingTypeBase.php delete mode 100644 src/Plugin/LanguageCheckboxesSettingTypeBase.php delete mode 100644 src/Plugin/Layout/PatternSettingsLayout.php delete mode 100644 src/Plugin/PatternSettingDataProviderBase.php delete mode 100644 src/Plugin/PatternSettingDataProviderInterface.php delete mode 100644 src/Plugin/PatternSettingTypeBase.php delete mode 100644 src/Plugin/PatternSettingTypeInterface.php delete mode 100644 src/Plugin/RoleCheckboxesSettingTypeBase.php delete mode 100644 src/Plugin/TokenSettingTypeBase.php delete mode 100644 src/Plugin/UiPatterns/SettingDataProvider/BreadcrumbDataProvider.php delete mode 100644 src/Plugin/UiPatterns/SettingDataProvider/MenuDataProvider.php delete mode 100644 src/Plugin/UiPatterns/SettingType/AttributesSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/BooleanSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/CheckboxesSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/ColorWidgetSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/ColorisWidgetSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/EnumerationSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/GroupType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/LanguageAccessSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/LanguageCheckboxesSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/LinksSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/MachineNameSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/MediaLibrarySettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/NumberSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/PublishSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/RadiosSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/RoleAccessSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/RoleCheckboxesSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/SelectSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/TextfieldSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/TokenSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/UrlSettingType.php delete mode 100644 src/Plugin/UiPatterns/SettingType/ValueSettingType.php create mode 100644 src/Plugin/UiPatterns/Source/MediaSource.php delete mode 100644 src/Plugin/UiPatterns/Source/SettingFieldSource.php delete mode 100644 src/TwigExtension/UIPatternsSettingsExtension.php delete mode 100644 src/UiPatternsSettings.php delete mode 100644 src/UiPatternsSettingsDataProviderManager.php delete mode 100644 src/UiPatternsSettingsManager.php create mode 100644 tests/fixtures/TestDataSet.yml delete mode 100644 tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingDataProvider/Foo.php delete mode 100644 tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingType/SampleComplexSettingType.php delete mode 100644 tests/modules/ui_patterns_settings_data_provider/templates/pattern-foo-complex.html.twig delete mode 100644 tests/modules/ui_patterns_settings_data_provider/templates/settings.ui_patterns.yml delete mode 100644 tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml delete mode 100644 tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig delete mode 100644 tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml delete mode 100644 tests/modules/ui_patterns_settings_render_test/ui_patterns_settings_render_test.info.yml delete mode 100644 tests/src/Functional/UiPatternsSettingsRenderTest.php delete mode 100644 tests/src/Kernel/ComplexSettingTypeTest.php create mode 100644 tests/src/Kernel/Source/MediaSourceTest.php create mode 100644 tests/src/Kernel/UiPSSourcePluginsTestBase.php delete mode 100644 ui_patterns_settings.libraries.yml diff --git a/config/schema/ui_patterns_settings.schema.yml b/config/schema/ui_patterns_settings.schema.yml deleted file mode 100644 index 083e791..0000000 --- a/config/schema/ui_patterns_settings.schema.yml +++ /dev/null @@ -1,10 +0,0 @@ -ui_patterns_settings.settings: - type: config_object - label: 'UI Patterns settings config' - mapping: - mapping: - type: sequence - label: 'Mapping' - sequence: - type: string - label: 'Field mapping' diff --git a/config/schema/ui_patterns_settings.sources.schema.yml b/config/schema/ui_patterns_settings.sources.schema.yml new file mode 100644 index 0000000..d26b260 --- /dev/null +++ b/config/schema/ui_patterns_settings.sources.schema.yml @@ -0,0 +1,10 @@ +ui_patterns_source.media: + type: mapping + label: 'Source: Media' + mapping: + media: + type: mapping + label: 'Media' + mapping: + media_library_selection: + type: string diff --git a/css/toggler.png b/css/toggler.png deleted file mode 100644 index e8db53e8361249c25f17fdeb1911e0984679e4a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14513 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 Df7A(c diff --git a/css/ui_patterns_settings.css b/css/ui_patterns_settings.css deleted file mode 100644 index b67c0d7..0000000 --- a/css/ui_patterns_settings.css +++ /dev/null @@ -1,50 +0,0 @@ -.js-ui-patterns-settings__wrapper { - position: relative; -} - -#ui-patterns-settings-token-link { - display: none; -} - -.ui-patterns-settings-show-token-a { - display: block; -} - -.js-ui-patterns-settings__toggler { - position: absolute; - width: 14px; - height: 14px; - right: 0; - top: 0; - display: block; - cursor: pointer; - background-image: url("toggler.png"); - background-repeat: no-repeat; - background-size: cover; -} - -.js-ui-patterns-settings__wrapper .js-ui-patterns-settings__token-wrapper > * { - display: none !important; -} - -.js-ui-patterns-settings__wrapper.js-ui-patterns-settings--token-has-value > .js-ui-patterns-settings__input-wrapper > * { - display: none !important; -} - -.js-ui-patterns-settings__wrapper.js-ui-patterns-settings--token-has-value > .js-ui-patterns-settings__token-wrapper > * { - display: block !important; -} - -.ui-patterns-media-edit { - position: relative; -} - -.media-library-edit__link { - position: absolute; - right: 0; - z-index: 10; -} - -.media-library-form-element .fieldset-wrapper { - position: relative; -} diff --git a/images/settings.png b/images/settings.png deleted file mode 100644 index e4a07572c240b2fadc588eaadff5f4508064b576..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25040 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 b$A5!u|C;yRITXymz`)??>gTe~DWM4f=p@*? diff --git a/js/ui_pattern_settings.toggle_token.js b/js/ui_pattern_settings.toggle_token.js deleted file mode 100644 index 2bd98be..0000000 --- a/js/ui_pattern_settings.toggle_token.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @file - * JavaScript file for the UI Pattern settings module. - */ - -(function ($, Drupal, drupalSettings, DrupalCoffee) { - - 'use strict'; - - /** - * Attaches ui patterns settings module behaviors. - * - * Handles enable/disable token element. - * - * @type {Drupal~behavior} - * - * @prop {Drupal~behaviorAttach} attach - * Attach ui patterns settings toggle functionality to the page. - * - */ - Drupal.behaviors.ups_toggle_token = { - attach: function () { - once('ui-patterns-settings-show-token-link', '.js-ui-patterns-settings-show-token-link').forEach(function (elm) { - $(elm).after($('<a href="#" class="ui-patterns-settings-show-token-a">' + Drupal.t('Browse available token') + '</a>').click(function (event) { - event.preventDefault(); - $('#ui-patterns-settings-token-link:first a').click(); - })); - }); - - once('ui-patterns-settings-wrapper', '.js-ui-patterns-settings__wrapper').forEach(function (el) { - var wrapper = $(el); - var toggler = $('<div class="js-ui-patterns-settings__toggler" title="Use token"></div>'); - $(toggler).click(function () { - var tokenInput = $('.js-ui-patterns-settings__token', wrapper); - if ($(wrapper).hasClass('js-ui-patterns-settings--token-has-value')) { - tokenInput.attr('data-init-val', tokenInput.val()); - tokenInput.val(''); - wrapper.removeClass('js-ui-patterns-settings--token-has-value'); - } else { - tokenInput.val(tokenInput.attr('data-init-val')); - wrapper.addClass('js-ui-patterns-settings--token-has-value'); - } - }); - $('.js-ui-patterns-settings__input-wrapper', wrapper).append(toggler) - $('.js-ui-patterns-settings__token-wrapper', wrapper).append(toggler.clone(true)) - }); - } - }; -})(jQuery, Drupal, drupalSettings); diff --git a/src/Annotation/UiPatternsSettingDataProvider.php b/src/Annotation/UiPatternsSettingDataProvider.php deleted file mode 100644 index 12f9219..0000000 --- a/src/Annotation/UiPatternsSettingDataProvider.php +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Annotation; - -use Drupal\Component\Annotation\Plugin; - -/** - * Defines ui_patterns_settings_data_provider annotation object. - * - * @Annotation - */ -class UiPatternsSettingDataProvider extends Plugin { - - /** - * The plugin ID. - * - * @var string - */ - public $id; - - /** - * The human-readable name of the plugin. - * - * @var \Drupal\Core\Annotation\Translation - * - * @ingroup plugin_translatable - */ - public $title; - - /** - * The description of the plugin. - * - * @var \Drupal\Core\Annotation\Translation - * - * @ingroup plugin_translatable - */ - public $description; - - /** - * The setting type plugin. - * - * @var string - */ - public $settingType; -} diff --git a/src/Annotation/UiPatternsSettingType.php b/src/Annotation/UiPatternsSettingType.php deleted file mode 100644 index 935630a..0000000 --- a/src/Annotation/UiPatternsSettingType.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Annotation; - -use Drupal\Component\Annotation\Plugin; - -/** - * Defines a UI Patterns Setting Type annotation object. - * - * @see \Drupal\ui_patterns_settings\UiPatternsSettingManager - * @see plugin_api - * - * @Annotation - */ -class UiPatternsSettingType extends Plugin { - - /** - * The plugin ID. - * - * @var string - */ - public $id; - - /** - * The label of the plugin. - * - * @var \Drupal\Core\Annotation\Translation - * - * @ingroup plugin_translatable - */ - public $label; - -} diff --git a/src/ConfigManager.php b/src/ConfigManager.php deleted file mode 100644 index 27b6c30..0000000 --- a/src/ConfigManager.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings; - -use Drupal\Core\Config\ConfigFactoryInterface; - -/** - * UI Patterns setting factory class. - * - * @package Drupal\ui_patterns_settings - */ -class ConfigManager { - - /** - * The config. - * - * @var \Drupal\Core\Config\Config - */ - private $config; - - /** - * Storage array by type. - * - * @var array - */ - private $typeMap = []; - - /** - * Storage array by variant. - * - * @var array - */ - private $variantMap = []; - - /** - * Constructs a new Fast404ExceptionHtmlSubscriber. - * - * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory - * The configuration factory. - */ - public function __construct(ConfigFactoryInterface $config_factory) { - $this->config = $config_factory->getEditable('ui_patterns_settings.settings'); - } - - /** - * Add mapping. - */ - public function addMapping($field_id, $pattern_setting_id) { - $field_id = str_replace('.', '--', $field_id); - $map = $this->config->get('mapping'); - if ($pattern_setting_id !== NULL) { - $map[$field_id] = $pattern_setting_id; - } - else { - unset($map[$field_id]); - } - - $this->config->set('mapping', $map); - $this->config->save(); - } - - /** - * Find all variant mappings. - * - * @return string[] - * List of all variant mappings. - */ - public function findVariantMappings($type) { - if (isset($this->variantMap[$type])) { - return $this->variantMap[$type]; - } - $map = is_array($this->config->get('mapping')) ? $this->config->get('mapping') : []; - foreach ($map as $field_id => $pattern_string) { - [$pattern_id, $setting_id] = explode('::', $pattern_string); - [$entity_type_id, $field_name] = explode('--', $field_id); - if ($setting_id === 'variant') { - $this->variantMap[$type][] = $field_name; - } - } - if (!isset($this->variantMap[$type])) { - $this->variantMap[$type] = []; - } - return $this->variantMap[$type]; - } - - /** - * Gets all mapping by entity type. - * - * @return string[] - * List of mappings. - */ - public function getMappingByType($type) { - if (isset($this->typeMap[$type])) { - return $this->typeMap[$type]; - } - $map = is_array($this->config->get('mapping')) ? $this->config->get('mapping') : []; - - foreach ($map as $field_id => $pattern_id) { - [$field_type, $field_name] = explode('--', $field_id); - $this->typeMap[$field_type][$field_name] = $pattern_id; - } - if (!isset($this->typeMap[$type])) { - $this->typeMap[$type] = []; - } - return $this->typeMap[$type]; - } - - /** - * Get Mapping by field id. - * - * @return string - * The pattern. - */ - public function getMapping($field_id) { - $field_id = str_replace('.', '--', $field_id); - $map = $this->config->get('mapping'); - return $map[$field_id] ?? NULL; - } - -} diff --git a/src/Definition/PatternDefinitionSetting.php b/src/Definition/PatternDefinitionSetting.php deleted file mode 100644 index a458a08..0000000 --- a/src/Definition/PatternDefinitionSetting.php +++ /dev/null @@ -1,400 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Definition; - -use Drupal\ui_patterns\Definition\ArrayAccessDefinitionTrait; - -/** - * Pattern setting definition class. - * - * @package Drupal\ui_patterns_settings\Definition - */ -class PatternDefinitionSetting implements \ArrayAccess { - - use ArrayAccessDefinitionTrait; - - /** - * Default setting values. - * - * @var array - */ - protected $definition = [ - 'name' => NULL, - 'label' => NULL, - 'description' => NULL, - 'type' => NULL, - 'required' => FALSE, - 'default_value' => NULL, - 'group' => NULL, - 'forced_value' => NULL, - 'options' => NULL, - 'form_visible' => TRUE, - 'allow_token' => FALSE, - 'expose_as_field' => FALSE, - ]; - - /** - * PatternDefinitionSetting constructor. - */ - public function __construct($name, $value) { - if (is_scalar($value)) { - $this->definition['name'] = is_numeric($name) ? $value : $name; - $this->definition['label'] = $value; - $this->definition['type'] = 'textfield'; - $this->definition['preview'] = NULL; - $this->definition['group'] = NULL; - $this->definition['weight'] = NULL; - $this->definition['allow_token'] = FALSE; - $this->definition['allow_expose'] = FALSE; - $this->definition['expose_as_field'] = FALSE; - } - else { - $name_key = !isset($value['name']) ? $name : $value['name']; - $this->definition['name'] = $name_key; - $this->definition['group'] = $value['group'] ?? NULL; - $this->definition['weight'] = $value['weight'] ?? NULL; - $this->definition['states'] = $value['states'] ?? []; - $this->definition['type'] = $value['type'] ?? 'textfield'; - $this->definition['label'] = $value['label'] ?? $name_key; - $this->definition['required'] = $value['required'] ?? FALSE; - $this->definition['default_value'] = $value['default_value'] ?? NULL; - $this->definition['preview'] = $value['preview'] ?? NULL; - $unprocessed_options = $value['options'] ?? NULL; - unset($value['options']); - if (is_array($unprocessed_options)) { - $processed_options = []; - foreach ($unprocessed_options as $option_key => $option_value) { - if (is_array($option_value)) { - $processed_options[$option_key] = $option_value['label'] ?? 'undefined'; - } - else { - $processed_options[$option_key] = $option_value; - } - } - } else { - $processed_options = NULL; - } - $this->definition['options'] = $processed_options; - - $this->definition['allow_token'] = $value['allow_token'] ?? FALSE; - $this->definition['allow_expose'] = $value['allow_expose'] ?? FALSE; - $this->definition['expose_as_field'] = $value['expose_as_field'] ?? FALSE; - - $this->definition = $value + $this->definition; - } - } - - /** - * Overwrite setting definition. - * - * @param $definitions - * The overwritten definitions. - */ - public function setDefinitions($definitions) { - $this->definition = $definitions + $this->definition; - } - - /** - * Return any definition value. - * - * @return string - * The value. - */ - public function getValue($key) { - return $this->definition[$key] ?? NULL; - } - - /** - * Return array definition. - * - * @return array - * Array definition. - */ - public function toArray() { - return $this->definition; - } - - /** - * Get Name property. - * - * @return mixed - * Property value. - */ - public function getName() { - return $this->definition['name']; - } - - /** - * Get Group property. - * - * @return mixed - * Property value. - */ - public function getGroup() { - return $this->definition['group']; - } - - /** - * Get Label property. - * - * @return mixed - * Property value. - */ - public function getLabel() { - return $this->definition['label']; - } - - /** - * Get required property. - * - * @return mixed - * Property value. - */ - public function getRequired() { - return $this->definition['required']; - } - - /** - * Get allow token property. - * - * @return bool - * Property value. - */ - public function getAllowToken() { - return $this->definition['allow_token']; - } - - /** - * Get options array. - * - * @return mixed - * Property option. - */ - public function getOptions() { - return $this->definition['options']; - } - - /** - * Get default value property. - * - * @return mixed - * Property value. - */ - public function getDefaultValue() { - return $this->definition['default_value']; - } - - /** - * Set default value property. - * - * @return mixed - * Property value. - */ - public function setDefaultValue($defaultValue) { - $this->definition['default_value'] = $defaultValue; - return $this; - } - - /** - * Get weight value property. - * - * @return mixed - * Property value. - */ - public function getWeight() { - return $this->definition['weight']; - } - - /** - * Set weight property. - * - * @return mixed - * Property value. - */ - public function setWeight($weight) { - $this->definition['weight'] = $weight; - return $this; - } - - /** - * Set allow token value property. - * - * @param bool $allow_token - * Property value. - * - * @return $this - */ - public function setAllowToken($allow_token) { - $this->definition['allow_token'] = $allow_token; - return $this; - } - - /** - * Get default value property. - * - * @return mixed - * Property value. - */ - public function getForcedValue() { - return $this->definition['forced_value']; - } - - /** - * Get preview property. - * - * @return mixed - * Property value. - */ - public function getPreview() { - return $this->definition['preview']; - } - - /** - * Set default value property. - * - * @return mixed - * Property value. - */ - public function setForcedValue($forcedValue) { - $this->definition['forced_value'] = $forcedValue; - return $this; - } - - /** - * Get exposable property. - * - * @return string - * Property value. - */ - public function allowExpose() { - return $this->definition['allow_expose']; - } - - /** - * Set Exposable property. - * - * @param string $allow_expose - * Property value. - * - * @return $this - */ - public function setAllowExpose($allow_expose) { - $this->definition['allow_expose'] = $allow_expose; - return $this; - } - - /** - * Get Description property. - * - * @return string - * Property value. - */ - public function getDescription() { - return $this->definition['description']; - } - - /** - * Set Description property. - * - * @param string $description - * Property value. - * - * @return $this - */ - public function setDescription($description) { - $this->definition['description'] = $description; - return $this; - } - - /** - * Is form visible property. - * - * @return bool - * Property value. - */ - public function isFormVisible() { - return $this->definition['form_visible']; - } - - /** - * Set form visible property. - * - * @param bool $visible - * Property value. - * - * @return $this - */ - public function setFormVisible($visible) { - $this->definition['form_visible'] = $visible; - return $this; - } - /** - * Get Type property. - * - * @return string - * Property value. - */ - public function getExposeAsField() { - return $this->definition['expose_as_field']; - } - - /** - * Set Expose property. - * - * @param string $type - * Property value. - * - * @return $this - */ - public function setExposeAsField($expose_as_field) { - $this->definition['expose_as_field'] = $expose_as_field; - return $this; - } - - /** - * Get states property. - * - * @return array - * Property value. - */ - public function getStates() { - return $this->definition['states']; - } - - /** - * Set States property. - * - * @param array $states - * Property value. - * - * @return $this - */ - public function setStates($states) { - $this->definition['states'] = $states; - return $this; - } - - /** - * Get Type property. - * - * @return string - * Property value. - */ - public function getType() { - return $this->definition['type']; - } - - /** - * Set Type property. - * - * @param string $type - * Property value. - * - * @return $this - */ - public function setType($type) { - $this->definition['type'] = $type; - return $this; - } - -} diff --git a/src/Element/PatternSettings.php b/src/Element/PatternSettings.php deleted file mode 100644 index 55d67c6..0000000 --- a/src/Element/PatternSettings.php +++ /dev/null @@ -1,162 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Element; - -use Drupal\Core\Security\TrustedCallbackInterface; -use Drupal\Core\Template\Attribute; -use Drupal\ui_patterns\UiPatterns; -use Drupal\ui_patterns_settings\UiPatternsSettings; -use Drupal\Core\Entity\EntityMalformedException; - -/** - * Renders a pattern element. - */ -class PatternSettings implements TrustedCallbackInterface { - - /** - * Process settings for preview. - * - * @param array $element - * Render array. - * - * @return array - * Render array. - */ - public static function processPreviewSettings(array $element) { - return PatternSettings::processSettings($element, TRUE); - } - - /** - * Process settings. - * - * @param array $element - * Render array. - * @param bool $preview - * True when called in pattern preview mode. - * - * @return array - * Render array. - */ - public static function processSettings(array $element, $preview = FALSE) { - $alter_context = []; - $context = $element['#context']; - $pattern_id = $element['#id']; - /** @var \Drupal\Core\Entity\ContentEntityBase $entity */ - $entity = $context->getProperty('entity'); - if ($context->getType() === 'layout' && $entity !== NULL) { - $mappings = UiPatternsSettings::getConfigManager()->findVariantMappings($entity->getEntityTypeId()); - foreach ($mappings as $field_name) { - if ($entity->hasField($field_name) && !empty($entity->get($field_name)->value)) { - $element['#variant'] = $entity->get($field_name)->value; - } - } - } - - // Handling variant token for layout builder. - if (empty($element['#variant_token']) && isset($element['#layout'])) { - /** @var \Drupal\ui_patterns_layout_builder\Plugin\Layout\PatternLayoutBuilder $layout */ - $layout = $element['#layout']; - $configuration = $layout->getConfiguration(); - $element['#variant_token'] = $configuration['pattern']['variant_token'] ?? NULL; - } - - // Handle Variant token. - if (!empty($element['#variant_token'])) { - $variant_token = $element['#variant_token']; - $token_data = []; - if ($entity !== NULL) { - $token_data[$entity->getEntityTypeId()] = $entity; - } - try { - $element['#variant'] = \Drupal::token()->replace($variant_token, $token_data, ['clear' => TRUE]); - } - catch (EntityMalformedException $e) { - if (!ui_patterns_settings_is_layout_builder_route()) { - throw $e; - } - // Do nothing inside layout builder. - } - } - $variant_alter_context['#pattern_id'] = $pattern_id; - if (isset($element['#layout'])) { - $variant_alter_context['#layout'] = $element['#layout']; - } - $variant_alter_context['#pattern_context'] = $context; - $variant = $element['#variant']; - \Drupal::moduleHandler()->alter('ui_pattern_settings_variant', $variant, $variant_alter_context); - $element['#variant'] = $variant; - // Make sure we don't render anything in case fields are empty. - if (self::hasSettings($element)) { - $settings = $element['#settings'] ?? []; - // Handling display suite pattern. - if (empty($settings)) { - $settings = $element['#ds_configuration']['layout']['settings']['pattern']['settings'] ?? []; - } - // Handling layout builder. - if (empty($settings) && isset($element['#layout'])) { - /** @var \Drupal\ui_patterns_layout_builder\Plugin\Layout\PatternLayoutBuilder $layout */ - $layout = $element['#layout']; - $configuration = $layout->getConfiguration(); - $settings = $configuration['pattern']['settings'] ?? []; - } - $entity = $context->getProperty('entity'); - $variant = $element['#variant'] ?? NULL; - $settings = UiPatternsSettings::preprocess($pattern_id, $settings, $variant, $preview, $entity, $element); - if (isset($element['#layout'])) { - $alter_context['#layout'] = $element['#layout']; - } - $alter_context['#pattern_id'] = $pattern_id; - $alter_context['#variant'] = $variant; - $alter_context['#pattern_context'] = $context; - \Drupal::moduleHandler()->alter('ui_pattern_settings_settings', $settings, $alter_context); - unset($element['#settings']); - foreach ($settings as $name => $setting) { - $key = '#' . $name; - if (!isset($element[$key])) { - $element[$key] = $setting; - } - else { - if ($setting instanceof Attribute && $element[$key] instanceof Attribute) { - $element[$key] = new Attribute(array_merge($setting->toArray(), $element[$key]->toArray())); - } - elseif (is_array($element[$key]) && is_array($setting)) { - $element[$key] = array_merge($element[$key], $setting); - } elseif (empty($element[$key]) && !empty($setting)) { - // Handle Exposed fields. Overwrite expose fields if the setting is provided - // but the variable prefilled with an empty field. (e.g. component blocks) - $setting_definition = UiPatternsSettings::getPatternDefinitionSetting(UiPatterns::getPatternDefinition($pattern_id), $name); - if ($setting_definition !== NULL && $setting_definition->getExposeAsField()) { - $element[$key] = $setting; - } - } - } - } - } - return $element; - } - - /** - * Whereas pattern has settings or not. - * - * @return bool - * TRUE or FALSE. - */ - public static function hasSettings($element) { - $definition = UiPatterns::getPatternDefinition($element['#id']); - $settings = UiPatternsSettings::getPatternDefinitionSettings($definition); - if ($definition != NULL && count($settings) != 0) { - return TRUE; - } - else { - return FALSE; - } - } - - /** - * {@inheritdoc} - */ - public static function trustedCallbacks() { - return ['processSettings', 'processPreviewSettings']; - } - -} diff --git a/src/Form/SettingsFormBuilder.php b/src/Form/SettingsFormBuilder.php deleted file mode 100644 index 942bb3c..0000000 --- a/src/Form/SettingsFormBuilder.php +++ /dev/null @@ -1,289 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Form; - -use Drupal\Component\Utility\NestedArray; -use Drupal\Core\Entity\ContentEntityType; -use Drupal\Core\Form\FormState; -use Drupal\Core\Render\Element; -use Drupal\Core\Render\Element\Form; -use Drupal\ui_patterns\Definition\PatternDefinition; -use Drupal\ui_patterns\UiPatterns; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\UiPatternsSettings; -use Drupal\ui_patterns_settings\UiPatternsSettingsManager; - -/** - * Build settings in manage display form. - */ -class SettingsFormBuilder { - - /** - * Build a hidden tree link token for performance reasons. - * - * Forms with class .js-ui-patterns-settings-show-token-link will - * generate Browse token button which click on the hidden link. - * This will reduce the number of browse buttons. - * - * @param array $form - * The form. - */ - private static function buildTokenLink(array &$form) { - - // Detecting current entity type. - // We don't have access to - $request = \Drupal::request(); - $entity_type_id = $request->attributes->get('entity_type_id'); - if (empty($entity_type_id)) { - /** @var \Drupal\layout_builder\Plugin\SectionStorage\DefaultsSectionStorage $section_storage */ - $section_storage = $request->attributes->get('section_storage'); - if ($section_storage !== NULL) { - $entity_type_id = explode('.', $section_storage->getStorageId())[0]; - } - } - - if (!empty($entity_type_id)) { - $content_entity_types[] = $entity_type_id; - } else { - $entity_type_definations = \Drupal::entityTypeManager()->getDefinitions(); - /** @var EntityTypeInterface $definition */ - foreach ($entity_type_definations as $definition) { - if ($definition instanceof ContentEntityType) { - $content_entity_types[] = $definition->id(); - } - } - } - - $form['token_link'] = [ - '#prefix' => '<div id="ui-patterns-settings-token-link">', - '#suffix' => '</div>', - '#theme' => 'token_tree_link', - '#token_types' => $content_entity_types, - '#show_restricted' => FALSE, - '#show_nested' => FALSE, - '#global_types' => TRUE, - '#click_insert' => TRUE, - '#recursion_limit' => 3, - '#weight' => 90, - ]; - } - - /** - * Build pattern settings fieldset. - * - * @param array $form - * Form array. - * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition - * The pattern definition. - * @param array $configuration - * The pattern configuration. - */ - public static function layoutForm(array &$form, PatternDefinition $definition, array $configuration) { - $settings = UiPatternsSettings::getPatternDefinitionSettings($definition); - self::buildTokenLink($form); - - $form['#attached']['library'][] = 'ui_patterns_settings/widget'; - if (UiPatternsSettingsManager::allowVariantToken($definition)) { - $variant_token_value = isset($configuration['pattern']['variant_token']) ? $configuration['pattern']['variant_token'] : NULL; - $form['variant_token'] = [ - '#type' => 'textfield', - '#title' => 'Variant token', - '#attributes' => ['class' => ['js-ui-patterns-settings-show-token-link']], - '#default_value' => $variant_token_value, - ]; - } - - $form['variant']['#attributes']['class'][] = 'ui-patterns-variant-selector-' . $definition->id(); - if (!empty($settings)) { - foreach ($settings as $key => $setting) { - if (empty($setting->getType()) || !$setting->isFormVisible()) { - continue; - } - - if (!isset($form['settings'])) { - $form['settings'] = [ - '#type' => 'fieldset', - '#title' => t('Settings'), - ]; - } - $setting_value = $configuration['pattern']['settings'][$key] ?? NULL; - $token_value = $configuration['pattern']['settings'][$key . "_token"] ?? ""; - $settingType = UiPatternsSettings::createSettingType($definition, $setting); - $form['settings'] += $settingType->buildConfigurationForm([], $setting_value, $token_value, 'layouts_display'); - } - SettingsFormBuilder::buildVariantsForm(".ui-patterns-variant-selector-" . $definition->id(), $form['settings'], $definition); - SettingsFormBuilder::buildStatesForm(".ui-patterns-variant-selector-" . $definition->id(), $form['settings'], $definition); - } - } - - /** - * Build pattern settings for display form. - * - * @param array $form - * Form array. - * @param array $configuration - * Configurations array. - */ - public static function displayForm(array &$form, array $configuration) { - $form['#attached']['library'][] = 'ui_patterns_settings/widget'; - self::buildTokenLink($form); - foreach (UiPatterns::getPatternDefinitions() as $pattern_id => $definition) { - $settings = UiPatternsSettings::getPatternDefinitionSettings($definition); - $form['variants'][$pattern_id]['#attributes']['class'][] = 'ui-patterns-variant-selector-' . $pattern_id; - if (UiPatternsSettingsManager::allowVariantToken($definition)) { - $variant_token_value = $configuration['variants_token'][$pattern_id] ?? NULL; - $form['variants']['#weight'] = 20; - $form['pattern_mapping']['#weight'] = 30; - $form['pattern_settings']['#weight'] = 40; - $form['variants_token'] = [ - '#type' => 'container', - '#title' => t('Pattern Variant'), - '#weight' => 25, - '#states' => [ - 'visible' => [ - 'select[id="patterns-select"]' => ['value' => $pattern_id], - ], - ], - ]; - $form['variants_token'][$pattern_id] = [ - '#type' => 'textfield', - '#title' => t('Variant token'), - '#default_value' => $variant_token_value, - '#attributes' => ['class' => ['js-ui-patterns-settings-show-token-link']], - '#states' => [ - 'visible' => [ - 'select[id="patterns-select"]' => ['value' => $pattern_id], - ], - ], - ]; - } - if (!empty($settings)) { - foreach ($settings as $key => $setting) { - if (empty($setting->getType()) || !$setting->isFormVisible()) { - continue; - } - if (!isset($form['pattern_settings'][$pattern_id])) { - $form['pattern_settings'][$pattern_id] = [ - '#type' => 'fieldset', - '#title' => t('Settings'), - '#states' => [ - 'visible' => [ - 'select[id="patterns-select"]' => ['value' => $pattern_id], - ], - ], - ]; - } - $fieldset = &$form['pattern_settings'][$pattern_id]; - $settingType = UiPatternsSettings::createSettingType($definition, $setting); - $setting_value = $configuration['pattern_settings'][$pattern_id][$key] ?? NULL; - $token_value = $configuration['pattern_settings'][$pattern_id][$key . "_token"] ?? NULL; - $fieldset += $settingType->buildConfigurationForm([], $setting_value, $token_value, 'display'); - } - SettingsFormBuilder::buildVariantsForm('.ui-patterns-variant-selector-' . $pattern_id, $fieldset, $definition); - SettingsFormBuilder::buildStatesForm('.ui-patterns-variant-selector-' . $pattern_id, $fieldset, $definition); - } - } - if (!empty($form['pattern_settings'])) { - $form['pattern_settings']['#element_validate'][] = - [static::class, 'cleanSettings']; - } - } - - /** - * Clean form values before being saved to configuration. - * - * @param array $element - * The pattern_settings fieldset element. - * @param \Drupal\Core\Form\FormState $form_state - * The form state. - * @param array $form - * The complete form array. - */ - public static function cleanSettings(array $element, FormState $form_state, array $form) { - $values = $form_state->getValues(); - $pattern_config = NestedArray::getValue($values, array_slice($element['#parents'], 0, -1)); - if (!empty($pattern_config['pattern_settings'])) { - // Only keep settings related to the selected pattern. - $pattern_settings = array_intersect_key($pattern_config['pattern_settings'], [$pattern_config['pattern'] => TRUE]); - $form_state->setValueForElement($element, $pattern_settings); - } - } - - /** - * Build settings form. - * - * @param string $select_selector - * The id of the variant select field. - * @param array $fieldset - * The fieldset. - * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition - * The pattern definition. - */ - private static function buildStatesForm($variant_selector, array &$fieldset, PatternDefinition $definition) { - $settings = UiPatternsSettings::getPatternDefinitionSettings($definition); - /** @var PatternDefinitionSetting $setting */ - foreach ($settings as $setting_name => $setting) { - $states = $setting->getStates(); - if (!is_null($states) && count($states) !== 0) { - foreach ($states as $visibilty => $conditions) { - foreach ($conditions as $state) { - if (isset($state['variant'])) { - $fieldset[$setting_name]['#states'][$visibilty][][$variant_selector]['value'] = $state['variant']; - if (isset($fieldset[$setting_name . '_token'])) { - $fieldset[$setting_name . '_token']['#states'][$visibilty][][$variant_selector]['value'] = $state['variant']; - } - } - if (isset($state['setting'])) { - $setting_select = '.js-ui-patterns-settings-' . $state['setting']; - $fieldset[$setting_name]['#states'][$visibilty][][$setting_select]['value'] = $state['value']; - if (isset($fieldset[$setting_name . '_token'])) { - $fieldset[$setting_name . '_token']['#states'][$visibilty][][$setting_select]['value'] = $state['value']; - } - } - } - } - } - } - } - - /** - * Hide all settings which are configured by the variant. - * - * @param string $select_selector - * The id of the variant select field. - * @param array $fieldset - * The fieldset. - * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition - * The pattern definition. - */ - private static function buildVariantsForm($select_selector, array &$fieldset, PatternDefinition $definition) { - $variants = $definition->getVariants(); - foreach ($variants as $variant) { - $variant_ary = $variant->toArray(); - $settings = $variant_ary['settings'] ?? []; - - // Variants may have definition overwrites. - // This should not lead to hide them. So unset them before. - foreach ($settings as $name => $setting) { - if (is_array($setting) && isset($setting['definition']) && empty($setting['value'])) { - unset($settings[$name]); - } - } - - foreach ($settings as $name => $setting) { - if (isset($fieldset[$name])) { - // Add an or before a new state begins. - if (isset($fieldset[$name]['#states']['invisible']) && count($fieldset[$name]['#states']['invisible']) != 0) { - $fieldset[$name]['#states']['invisible'][] = 'or'; - } - // Hide configured setting. - $fieldset[$name]['#states']['invisible'][][$select_selector]['value'] = $variant->getName(); - if (isset($fieldset[$name . '_token'])) { - $fieldset[$name . '_token']['#states']['invisible'][][$select_selector]['value'] = $variant->getName(); - } - } - } - } - } - -} diff --git a/src/Plugin/ComplexSettingTypeBase.php b/src/Plugin/ComplexSettingTypeBase.php deleted file mode 100644 index ead5ac2..0000000 --- a/src/Plugin/ComplexSettingTypeBase.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Base class for setting types with data providers. - */ -abstract class ComplexSettingTypeBase extends PatternSettingTypeBase implements ContainerFactoryPluginInterface { - - /** - * The token service. - * - * @var \Drupal\ui_patterns_settings\UiPatternsSettingsDataProviderManager - */ - protected $dataProviderManger; - - /** - * The data provider plugin. - * - * @var \Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface - */ - protected $provider; - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - $plugin = parent::create($container, $configuration, $plugin_id, $plugin_definition); - $plugin->dataProviderManger = $container->get('plugin.manager.ui_patterns_settings_data_provider'); - return $plugin; - } - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $def = $this->getPatternSettingDefinition(); - $data_provider_definitions = $this->dataProviderManger->getDefinitionsBySettingType($this->pluginId); - $provider_plugins = []; - $provider_options = []; - foreach ($data_provider_definitions as $data_provider_definition) { - $data_provider_id = $data_provider_definition['id']; - $provider_plugins[$data_provider_id] = $this->dataProviderManger->createInstance($data_provider_id, []); - $provider_options[$data_provider_id] = $data_provider_definition['label']; - - } - $form[$def->getName()] = [ - '#type' => 'fieldset', - '#title' => $def->getLabel(), - ]; - - $provider_select_id = $def->getName(). '_provider'; - $form[$def->getName()]['provider'] = [ - '#type' => 'select', - '#title' => $this->t('Dataprovider'), - '#default_value' => $this->getValue($value['provider'] ?? NULL), - '#options' => $provider_options, - '#attributes'=> ['id' => $provider_select_id] - ]; - - $form[$def->getName()]['configuration'] = []; - - foreach ($data_provider_definitions as $data_provider_definition) { - $data_provider_id = $data_provider_definition['id']; - $provider_settings_form = $provider_plugins[$data_provider_id]->settingsForm($value['configuration'][$data_provider_id]['config'] ?? []); - if ($provider_settings_form) { - $form[$def->getName()]['configuration'][$data_provider_id] = ['#type' => 'container', - '#states' => [ - 'visible' => [ - 'select[id="' . $provider_select_id . '"]' => ['value' => $data_provider_id], - ], - ], - ]; - $form[$def->getName()]['configuration'][$data_provider_id]['config'] = $provider_settings_form; - } - } - return $form; - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess( - $value, - array $context, - PatternDefinitionSetting $def - ) { - $provider_id = $value['provider'] ?? NULL; - if ($provider_id) { - $instance = $this->dataProviderManger->createInstance($provider_id, []); - $this->provider = $instance; - return $instance->getData($value['configuration'][$provider_id]['config'] ?? []); - } - return $value; - } - - /** - * {@inheritdoc} - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element) { - if ($this->provider) { - $instance = $this->provider; - $instance->alterElement($value, $def, $element); - } - } - -} diff --git a/src/Plugin/EnumerationSettingTypeBase.php b/src/Plugin/EnumerationSettingTypeBase.php deleted file mode 100644 index b466d0e..0000000 --- a/src/Plugin/EnumerationSettingTypeBase.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\field\Entity\FieldStorageConfig; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; - -/** - * Base class for enumerations like radios or select. - */ -abstract class EnumerationSettingTypeBase extends PatternSettingTypeBase { - - /** - * Returns empty option. - * - * @return array - * The empty option. - */ - protected function emptyOption() { - return ["" => $this->t("Please select")]; - } - - /** - * Returns the enumeration type. - * - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def - * The pattern definition setting. - * - * @return string - * The enumeration type. - */ - protected function getEnumerationType(PatternDefinitionSetting $def) { - return $def->getValue('enumeration_type'); - } - - /** - * {@inheritdoc} - */ - public function alterFieldStorage(FieldStorageConfig $storage_config) { - $storage_config->setSetting('allowed_values_function', 'ui_patterns_settings_allowed_values_function'); - } - - /** - * {@inheritdoc} - */ - public function fieldStorageExposableTypes() { - return ['list_string']; - } - - /** - * Returns the enumeration options. - * - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def - * The pattern definition. - * - * @return mixed - * The options. - */ - protected function getOptions(PatternDefinitionSetting $def) { - return $def->getOptions(); - } - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - if ($def->getRequired() == FALSE) { - $options = $this->emptyOption(); - } - else { - $options = []; - } - - if ($this->getOptions($def) !== NULL) { - $options += $this->getOptions($def); - } - $form[$def->getName()] = [ - '#type' => $this->getEnumerationType($def), - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $this->getValue($value), - '#options' => $options, - ]; - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - -} diff --git a/src/Plugin/LanguageCheckboxesSettingTypeBase.php b/src/Plugin/LanguageCheckboxesSettingTypeBase.php deleted file mode 100644 index faaf951..0000000 --- a/src/Plugin/LanguageCheckboxesSettingTypeBase.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\Core\Language\LanguageManagerInterface; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Language Checkboxes setting type. - * - * Provides an array of: - * - current_language_selected: True if the - * current language is part of the selection - * or nothing is selected - * - current_language: The current language. - * - selected: Array of selected languages. - * - * @UiPatternsSettingType( - * id = "language_checkboxes", - * label = @Translation("Language checkboxes") - * ) - */ -class LanguageCheckboxesSettingTypeBase extends EnumerationSettingTypeBase { - - /** - * The language manager. - * - * @var \Drupal\Core\Language\LanguageManagerInterface - */ - protected LanguageManagerInterface $languageManager; - - /** - * {@inheritdoc} - */ - protected function emptyOption() { - return []; - } - - /** - * {@inheritdoc} - */ - protected function getValue($value) { - if ($value === NULL) { - return !is_array($this->getPatternSettingDefinition() - ->getDefaultValue()) ? [ - $this->getPatternSettingDefinition() - ->getDefaultValue(), - ] : $this->getPatternSettingDefinition()->getDefaultValue(); - } - else { - return $value ?? ""; - } - } - - /** - * {@inheritdoc} - */ - protected function getOptions(PatternDefinitionSetting $def) { - $languages = $this->languageManager->getLanguages(); - $options = []; - foreach ($languages as $language) { - $options[$language->getId()] = $language->getName(); - } - return $options; - } - - /** - * {@inheritdoc} - */ - protected function getEnumerationType(PatternDefinitionSetting $def) { - return $def->getValue('enumeration_type') ?? 'checkboxes'; - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - $selected_options = []; - $defined_options = $this->getOptions($def); - if (is_array($value)) { - foreach ($value as $checkbox_key => $checkbox_value) { - if ($checkbox_value != "0") { - $selected_options[$checkbox_key] = $defined_options[$checkbox_value] ?? $checkbox_value; - } - } - } - $current_language = $this->languageManager->getCurrentLanguage(); - return [ - 'current_language_selected' => count($selected_options) === 0 || isset($selected_options[$current_language->getId()]), - 'current_language' => [ - $current_language->getId() => $current_language->getName(), - ], - 'selected' => $selected_options, - ]; - } - - /** - * {@inheritdoc} - */ - public static function create( - ContainerInterface $container, - array $configuration, - $plugin_id, - $plugin_definition - ) { - $plugin = parent::create($container, $configuration, $plugin_id, $plugin_definition); - $plugin->languageManager = $container->get('language_manager'); - return $plugin; - } - -} diff --git a/src/Plugin/Layout/PatternSettingsLayout.php b/src/Plugin/Layout/PatternSettingsLayout.php deleted file mode 100644 index 5dfbcc2..0000000 --- a/src/Plugin/Layout/PatternSettingsLayout.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\Layout; - -use Drupal\ui_patterns_layouts\Plugin\Layout\PatternLayout; - -/** - * Layout class for patterns with settings. - * - * @package Drupal\ui_patterns_settings\Plugin\Layout - */ -class PatternSettingsLayout extends PatternLayout { - - /** - * {@inheritdoc} - */ - public function build(array $regions) { - $build = parent::build($regions); - $configuration = $this->getConfiguration(); - if (isset($configuration['pattern']['settings'])) { - $build['#settings'] = $configuration['pattern']['settings']; - } - if (isset($configuration['pattern']['variant_token'])) { - $build['#variant_token'] = $configuration['pattern']['variant_token']; - } - return $build; - } - -} diff --git a/src/Plugin/PatternSettingDataProviderBase.php b/src/Plugin/PatternSettingDataProviderBase.php deleted file mode 100644 index e66903e..0000000 --- a/src/Plugin/PatternSettingDataProviderBase.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\Component\Plugin\PluginBase; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Base class for ui_patterns_settings_data_provider plugins. - */ -abstract class PatternSettingDataProviderBase extends PluginBase implements PatternSettingDataProviderInterface, ContainerFactoryPluginInterface { - - use StringTranslationTrait; - - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * Return pattern definitions for setting . - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * {@inheritdoc} - */ - public function __construct( - array $configuration, - $plugin_id, - array $plugin_definition, - ModuleHandlerInterface $module_handler, - EntityTypeManagerInterface $entity_type_manager - ) { - parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->entityTypeManager = $entity_type_manager; - $this->moduleHandler = $module_handler; - } - - /** - * - */ - public static function create( - ContainerInterface $container, - array $configuration, - $plugin_id, - $plugin_definition - ) { - $plugin = new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('module_handler'), - $container->get('entity_type.manager'), - ); - return $plugin; - } - - /** - * {@inheritdoc} - */ - public function label() { - // Cast the label to a string since it is a TranslatableMarkup object. - return (string) $this->pluginDefinition['label']; - } - - /** - * {@inheritdoc} - */ - public function settingsForm($value) { - return []; - } - - /** - * {@inheritdoc} - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element) { - } - -} diff --git a/src/Plugin/PatternSettingDataProviderInterface.php b/src/Plugin/PatternSettingDataProviderInterface.php deleted file mode 100644 index 10c20e5..0000000 --- a/src/Plugin/PatternSettingDataProviderInterface.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; - -/** - * Interface for ui_patterns_settings_data_provider plugins. - */ -interface PatternSettingDataProviderInterface { - - /** - * Returns the translated plugin label. - * - * @return string - * The translated title. - */ - public function label(); - - /** - * Return the configuration form. - * - * @return array - * The configuration form. - */ - public function settingsForm($value); - - /** - * @return array - * The provided data. - */ - public function getData($value); - - /** - * Allow setting data providers to alter render element. - * - * @param string $value - * The value. - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def - * The pattern definition. - * @param array $element - * The render element. - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element); - -} diff --git a/src/Plugin/PatternSettingTypeBase.php b/src/Plugin/PatternSettingTypeBase.php deleted file mode 100644 index 85e96f8..0000000 --- a/src/Plugin/PatternSettingTypeBase.php +++ /dev/null @@ -1,440 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\Component\Plugin\ConfigurableInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Field\FieldItemList; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\Plugin\PluginBase; -use Drupal\field\Entity\FieldStorageConfig; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Base class for UI Patterns Setting plugins. - */ -abstract class PatternSettingTypeBase extends PluginBase implements - ConfigurableInterface, - PatternSettingTypeInterface, - ContainerFactoryPluginInterface { - - /** - * Returns a list of plugin dependencies. - * - * @return bool - * True if all dependencies exist. - */ - protected function getSettingTypeDependencies() { - return []; - } - - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - private $moduleHandler; - - /** - * The route match. - * - * @var \Drupal\Core\Routing\RouteMatchInterface - */ - private $routeMatch; - - /** - * Return pattern definitions for setting . - * - * @var \Drupal\ui_patterns\Definition\PatternDefinition - */ - private $patternDefinition; - - /** - * Return pattern definitions for setting . - * - * @var \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting - */ - private $patternSettingDefinition; - - /** - * Return pattern definitions for setting . - * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface - */ - protected $entityTypeManager; - - /** - * {@inheritdoc} - */ - public function __construct( - array $configuration, - $plugin_id, - array $plugin_definition, - ModuleHandlerInterface $module_handler, - EntityTypeManagerInterface $entity_type_manager - ) { - $configuration += $this->defaultConfiguration(); - $this->patternSettingDefinition = $configuration['pattern_setting_definition']; - $this->patternDefinition = $configuration['pattern_definition']; - $this->moduleHandler = $module_handler; - $this->entityTypeManager = $entity_type_manager; - unset($configuration['pattern_setting_definition']); - unset($configuration['pattern_definition']); - parent::__construct($configuration, $plugin_id, $plugin_definition); - } - - /** - * Return value if set otherwise take the default value. - * - * @param mixed $value - * The provided value. - * - * @return string - * The value for this setting - */ - protected function getValue($value) { - if ($value === NULL) { - return $this->getPatternSettingDefinition()->getDefaultValue(); - } - else { - return $value ?? ""; - } - } - - /** - * Return pattern setting definition. - * - * @return \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting - * Pattern setting definition. - */ - protected function getPatternSettingDefinition() { - return $this->patternSettingDefinition; - } - - /** - * {@inheritdoc} - */ - public static function create( - ContainerInterface $container, - array $configuration, - $plugin_id, - $plugin_definition - ) { - $plugin = new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('module_handler'), - $container->get('entity_type.manager') - ); - /** @var \Drupal\Core\StringTranslation\TranslationInterface $translation */ - $translation = $container->get('string_translation'); - - $plugin->setStringTranslation($translation); - $plugin->routeMatch = $container->get('current_route_match'); - return $plugin; - } - - /** - * {@inheritdoc} - */ - public function alterFieldStorage(FieldStorageConfig $storage_config) { - } - - /** - * {@inheritdoc} - */ - public function label() { - $plugin_definition = $this->getPluginDefinition(); - return $plugin_definition['label']; - } - - /** - * {@inheritdoc} - */ - public function getDescription() { - $plugin_definition = $this->getPluginDefinition(); - return $plugin_definition['description'] ?? ''; - } - - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return []; - } - - /** - * {@inheritdoc} - */ - public function getConfiguration() { - return $this->configuration; - } - - /** - * {@inheritdoc} - */ - public function setConfiguration(array $configuration) { - $this->configuration = $configuration + $this->defaultConfiguration(); - } - - /** - * {@inheritdoc} - */ - public function calculateDependencies() { - return []; - } - - /** - * {@inheritdoc} - */ - public function preprocess($value, array $context) { - $def = $this->getPatternSettingDefinition(); - $value = $this->settingsPreprocess($value, $context, $def); - return $value; - } - - /** - * Checks if current route is a layout builder route. - * - * @return bool - * True if it is a layout builder route. - */ - protected function isLayoutBuilderRoute() { - if (preg_match('/^(layout_builder\.([^.]+\.)?)/', $this->routeMatch->getRouteName())) { - return TRUE; - } - return FALSE; - } - - /** - * {@inheritdoc} - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element) { - - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess( - $value, - array $context, - PatternDefinitionSetting $def - ) { - return $value; - } - - /** - * Returns the bind form field. - * - * @param array $form - * The form definition array for the settings configuration form. - * @param string $value - * The stored default value. - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def - * The pattern definition. - * - * @return array - * The form. - */ - protected function tokenForm( - array $form, - $value, - PatternDefinitionSetting $def - ) { - $form[$def->getName() . "_token"] = [ - '#type' => 'textfield', - '#title' => $this->t("Token for %label", ['%label' => $def->getLabel()]), - '#default_value' => $this->getValue($value), - '#attributes' => [ - 'class' => [ - 'js-ui-patterns-settings-show-token-link', - 'js-ui-patterns-settings__token', - ], - ], - '#wrapper_attributes' => ['class' => ['js-ui-patterns-settings__token-wrapper']], - ]; - return $form; - } - - /** - * Check required input fields in layout forms. - * - * @param array $element - * The element to validate. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The form state. - * @param array $form - * The form. - */ - public static function validateLayout( - array $element, - FormStateInterface &$form_state, - array &$form - ) { - $parents = $element['#parents']; - $value = $form_state->getValue($parents); - $parents[count($parents) - 1] = $parents[count($parents) - 1] . '_token'; - $token_value = $form_state->getValue($parents); - if (empty($value) && empty($token_value)) { - // Check if a variant is selected and the value - // is provided by the variant. - $variant = $form_state->getValue( - [ - 'layout_configuration', - 'pattern', - 'variant', - ] - ); - if (!empty($variant)) { - $variant_def = $element['#pattern_definition']->getVariant($variant); - $variant_ary = $variant_def->toArray(); - if (!empty( - $variant_ary['settings'][$element['#pattern_setting_definition']->getName( - )] - )) { - return; - } - } - - $form_state->setError( - $element, - t( - '@name field is required.', - ['@name' => $element['#title']] - ) - ); - } - } - - /** - * Add validation and basics classes to the raw input field. - * - * @param array $input - * The input field. - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def - * The pattern definition. - * @param string $form_type - * The form type. Either layouts_display or display. - */ - protected function handleInput( - array &$input, - PatternDefinitionSetting $def, - $form_type - ) { - $input['#attributes']['class'][] = 'js-ui-patterns-settings__input js-ui-patterns-settings-' . $def->getName(); - $input['#wrapper_attributes']['class'][] = 'js-ui-patterns-settings__input-wrapper'; - if ($def->getRequired()) { - $input['#title'] .= ' *'; - if ($form_type === 'layouts_display') { - $input['#element_validate'][] = [ - PatternSettingTypeBase::class, - 'validateLayout', - ]; - } - } - } - - /** - * {@inheritdoc} - * - * Creates a generic configuration form for all settings types. - * Individual settings plugins can add elements to this form by - * overriding PatternSettingTypeBaseInterface::settingsForm(). - * Most plugins should not override this method unless they - * need to alter the generic form elements. - * - * @see \Drupal\Core\Block\BlockBase::blockForm() - */ - public function buildConfigurationForm( - array $form, - $value, - $token_value, - $form_type - ) { - $dependencies = $this->getSettingTypeDependencies(); - $def = $this->getPatternSettingDefinition(); - foreach ($dependencies as $dependency) { - if (!$this->moduleHandler->moduleExists($dependency)) { - $form[$def->getName( - )] = ['#markup' => "Missing SettingType {$def->getName()} dependency {$dependency}."]; - return $form; - } - } - - $form = $this->settingsForm($form, $value, $def, $form_type); - $form[$def->getName()]['#pattern_setting_definition'] = $def; - $form[$def->getName()]['#pattern_definition'] = $this->patternDefinition; - - if (!empty($def->getWeight())) { - $form[$def->getName()]['#weight'] = $def->getWeight(); - } - - if ($def->getAllowToken()) { - $form = $this->tokenForm($form, $token_value, $def); - if (isset($form[$def->getName() . '_token'])) { - $classes = 'js-ui-patterns-settings__wrapper'; - if (!empty($token_value)) { - $classes .= ' js-ui-patterns-settings--token-has-value'; - } - $form[$def->getName()]['#prefix'] = '<div class="' . $classes . '">'; - $form[$def->getName() . '_token']['#suffix'] = '</div>'; - $form[$def->getName() . '_token']['#pattern_setting_definition'] = $def; - $form[$def->getName( - ) . '_token']['#pattern_definition'] = $this->patternDefinition; - } - } - return $form; - } - - /** - * Set the right group before drupal #group attribute is processed. - * - * @param array $element - * The form field. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The pattern definition. - * @param mixed $form - * The form. - * - * @return array - * The processed element. - */ - public static function formGroupProcess( - array &$element, - FormStateInterface $form_state = NULL, - &$form = [] - ) { - if (isset($element['#pattern_setting_definition'])) { - $setting_definition = $element['#pattern_setting_definition']; - if ($setting_definition->getGroup() !== NULL) { - $parents = $element['#parents']; - array_pop($parents); - $parents[] = $setting_definition->getGroup(); - $element['#group'] = implode('][', $parents); - } - } - return $element; - } - - /** - * {@inheritdoc} - */ - public function fieldStorageExposableTypes() { - return []; - } - - /** - * {@inheritdoc} - */ - public function preprocessExposedField(FieldItemList $items) { - foreach ($items as $item) { - return $item->value; - } - } - -} diff --git a/src/Plugin/PatternSettingTypeInterface.php b/src/Plugin/PatternSettingTypeInterface.php deleted file mode 100644 index 49bf7c3..0000000 --- a/src/Plugin/PatternSettingTypeInterface.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\Component\Plugin\ConfigurableInterface; -use Drupal\Core\Field\FieldItemList; -use Drupal\field\Entity\FieldStorageConfig; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; - -/** - * Defines an interface for UI Patterns setting type plugins. - */ -interface PatternSettingTypeInterface extends ConfigurableInterface { - - /** - * Returns the configuration form elements specific to this settings plugin.. - * - * @param array $form - * The form definition array for the settings configuration form. - * @param string $value - * The stored default value. - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def - * The pattern definition. - * @param string $form_type - * The form type. Either layout or layouts_display or display. - * - * @return array - * The configuration form. - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type); - - /** - * Preprocess setting variable. - * - * @param string $value - * The stored value. - * @param array $context - * Context informations. - * Keys: - * - entity. - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def - * The pattern definition. - * - * @return string - * The processed value. - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def); - - /** - * Returns the processed setting variable. - * - * @param string $value - * The stored value. - * @param array $context - * Context informations. - * - * @return mixed - * The processed value. - */ - public function preprocess($value, array $context); - - /** - * Returns the processed setting variable for an exposed field. - * - * @param \Drupal\Core\Field\FieldItemList $field - * The stored value. - * - * @return mixed - * The processed value. - */ - public function preprocessExposedField(FieldItemList $field); - - /** - * Returns the settings configuration form. - * - * @param array $form - * The form definition array for the settings configuration form. - * @param string $value - * The stored default value. - * @param string $token_value - * The stored token value. - * @param string $form_type - * The form type. Either layout or layouts_display or display. - */ - public function buildConfigurationForm(array $form, $value, $token_value, $form_type); - - /** - * Alter the storage of a connected field storage. - * - * @param \Drupal\field\Entity\FieldStorageConfig $storage_config - * The storage type. - */ - public function alterFieldStorage(FieldStorageConfig $storage_config); - - /** - * Returns the list to matching field types. - * - * @return array - * The list of exposable field types - */ - public function fieldStorageExposableTypes(); - - /** - * Allow setting types to alter render element. - * - * @param string $value - * The value. - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $def - * The pattern definition. - * @param array $element - * The render element. - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element); - -} diff --git a/src/Plugin/RoleCheckboxesSettingTypeBase.php b/src/Plugin/RoleCheckboxesSettingTypeBase.php deleted file mode 100644 index da13e44..0000000 --- a/src/Plugin/RoleCheckboxesSettingTypeBase.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Role Checkboxes setting type. - * - * Provides an array of: - * - current_role_selected: True if the current role is part of the selection - * or nothing is selected - * - current_role: The current role. - * - selected: Array of selected roles. - * - * @UiPatternsSettingType( - * id = "role_checkboxes", - * label = @Translation("Role checkboxes") - * ) - */ -class RoleCheckboxesSettingTypeBase extends EnumerationSettingTypeBase { - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountProxyInterface - */ - protected $currentUser; - - /** - * {@inheritdoc} - */ - protected function emptyOption() { - return []; - } - - /** - * {@inheritdoc} - */ - protected function getValue($value) { - if ($value === NULL) { - return !is_array($this->getPatternSettingDefinition() - ->getDefaultValue()) ? [ - $this->getPatternSettingDefinition() - ->getDefaultValue(), - ] : $this->getPatternSettingDefinition()->getDefaultValue(); - } - else { - return $value ?? ""; - } - } - - /** - * {@inheritdoc} - */ - protected function getOptions(PatternDefinitionSetting $def) { - $roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple(); - $options = []; - foreach ($roles as $role) { - $options[$role->id()] = $role->label(); - } - return $options; - } - - /** - * {@inheritdoc} - */ - protected function getEnumerationType(PatternDefinitionSetting $def) { - return $def->getValue('enumeration_type') ?? 'checkboxes'; - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - $selected_options = []; - $defined_options = $this->getOptions($def); - - if (is_array($value)) { - foreach ($value as $checkbox_key => $checkbox_value) { - if ($checkbox_value != "0") { - $selected_options[$checkbox_key] = $defined_options[$checkbox_key] ?? $checkbox_value; - } - } - } - - $current_user_roles = $this->currentUser->getRoles(); - $selected_options_keys = array_keys($selected_options); - $settings = [ - 'current_role_selected' => count($selected_options) === 0 || !empty(array_intersect($current_user_roles, $selected_options_keys)), - 'selected' => $selected_options, - ]; - foreach ($current_user_roles as $current_role_id) { - $settings['current_role'][$current_role_id] = $defined_options[$current_role_id]; - } - return $settings; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition); - $instance->currentUser = $container->get('current_user'); - return $instance; - } - -} diff --git a/src/Plugin/TokenSettingTypeBase.php b/src/Plugin/TokenSettingTypeBase.php deleted file mode 100644 index 4913ee3..0000000 --- a/src/Plugin/TokenSettingTypeBase.php +++ /dev/null @@ -1,115 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin; - -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\Utility\Token; -use Drupal\Core\Entity\EntityMalformedException; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Base class for setting types with tokens. - */ -abstract class TokenSettingTypeBase extends PatternSettingTypeBase implements ContainerFactoryPluginInterface { - - /** - * The token service. - * - * @var \Drupal\Core\Utility\Token - */ - protected $tokenService; - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - $plugin = parent::create($container, $configuration, $plugin_id, $plugin_definition); - $plugin->setTokenService($container->get('token')); - return $plugin; - } - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $def = $this->getPatternSettingDefinition(); - $value = $this->getValue($value); - $description = $def->getDescription() != NULL ? $def->getDescription() : ""; - - $form[$def->getName()] = [ - '#type' => 'container', - ]; - - $form[$def->getName()]['input'] = [ - '#type' => 'textfield', - '#title' => $def->getLabel(), - '#description' => $description, - '#default_value' => $this->getValue($value), - '#attributes' => ['class' => ['js-ui-patterns-settings-show-token-link']], - ]; - $this->handleInput($form[$def->getName()]['input'], $def, $form_type); - - return $form; - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - $return_value = ''; - - if (is_array($value) && isset($value['input'])) { - $value = $value['input']; - } - - if (is_string($value)) { - $token_data = []; - /** @var \Drupal\Core\Entity\EntityInterface $entity */ - $entity = $context['entity'] ?? NULL; - if ($entity !== NULL) { - $token_data[$entity->getEntityTypeId()] = $entity; - } - try { - $return_value = $this->getTokenService()->replace($value, $token_data, ['clear' => TRUE]); - } - catch (EntityMalformedException $e) { - if (!ui_patterns_settings_is_layout_builder_route()) { - throw $e; - } - // Do nothing inside layout builder. - } - } - - return $return_value; - } - - /** - * Sets the token service. - * - * @param \Drupal\Core\Utility\Token $token_service - * The token service. - * - * @return self - * The token service. - */ - public function setTokenService(Token $token_service) { - $this->tokenService = $token_service; - return $this; - } - - /** - * Gets the token service. - * - * @return \Drupal\Core\Utility\Token - * The token service. - */ - public function getTokenService() { - if (!$this->tokenService) { - $this->tokenService = \Drupal::token(); - } - - return $this->tokenService; - } - -} diff --git a/src/Plugin/UiPatterns/SettingDataProvider/BreadcrumbDataProvider.php b/src/Plugin/UiPatterns/SettingDataProvider/BreadcrumbDataProvider.php deleted file mode 100644 index 5210f64..0000000 --- a/src/Plugin/UiPatterns/SettingDataProvider/BreadcrumbDataProvider.php +++ /dev/null @@ -1,104 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingDataProvider; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderBase; -use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Plugin implementation of the ui_patterns_settings_data_provider. - * - * @UiPatternsSettingDataProvider( - * id = "breadcrumb", - * label = @Translation("Breadcrumb"), - * description = @Translation("Data Provider for menus."), - * settingType = "links" - * ) - */ -class BreadcrumbDataProvider extends PatternSettingDataProviderBase implements PatternSettingDataProviderInterface { - - /** - * The current route match. - * - * @var \Drupal\Core\Routing\RouteMatchInterface - */ - protected $routeMatch; - - /** - * The breadcrumb manager. - * - * @var \Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface - */ - protected $breadcrumbManager; - - /** - * - */ - public static function create( - ContainerInterface $container, - array $configuration, - $plugin_id, - $plugin_definition - ) { - $plugin = new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('module_handler'), - $container->get('entity_type.manager'), - ); - /** @var \Drupal\Core\StringTranslation\TranslationInterface $translation */ - $translation = $container->get('string_translation'); - $plugin->setStringTranslation($translation); - $plugin->breadcrumbManager = $container->get('breadcrumb'); - $plugin->routeMatch = $container->get('current_route_match'); - return $plugin; - } - - /** - * Get breadcrumb items. - * - * @return array - * List of items. - */ - private function getBreadcrumbItems(): array { - $breadcrumb = $this->breadcrumbManager->build($this->routeMatch); - $links = []; - foreach ($breadcrumb->getLinks() as $link) { - $links[] = [ - "title" => $link->getText(), - "url" => $link->getUrl()->toString(), - ]; - } - return $links; - } - - /** - * {@inheritdoc} - */ - public function settingsForm($value) { - return []; - } - - /** - * {@inheritdoc} - */ - public function getData($value) { - return $this->getBreadcrumbItems(); - } - - /** - * {@inheritdoc} - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element) { - $breadcrumb = $this->breadcrumbManager->build($this->routeMatch); - $renderable = $breadcrumb->toRenderable(); - if (isset($renderable["#cache"])) { - $element["#cache"] = $element["#cache"] ?: []; - $element["#cache"] = array_merge($element["#cache"], $renderable["#cache"]); - } - } - -} diff --git a/src/Plugin/UiPatterns/SettingDataProvider/MenuDataProvider.php b/src/Plugin/UiPatterns/SettingDataProvider/MenuDataProvider.php deleted file mode 100644 index 304ae35..0000000 --- a/src/Plugin/UiPatterns/SettingDataProvider/MenuDataProvider.php +++ /dev/null @@ -1,184 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingDataProvider; - -use Drupal\Core\Menu\MenuTreeParameters; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderBase; -use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface; -use Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType\LinksSettingType; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Plugin implementation of the ui_patterns_settings_data_provider. - * - * @UiPatternsSettingDataProvider( - * id = "menu", - * label = @Translation("Menu"), - * description = @Translation("Data Provider for menus."), - * settingType = "links" - * ) - */ -class MenuDataProvider extends PatternSettingDataProviderBase implements PatternSettingDataProviderInterface { - - /** - * The current route match. - * - * @var \Drupal\Core\Routing\RouteMatchInterface - */ - protected $routeMatch; - - /** - * The menu link tree. - * - * @var \Drupal\Core\Menu\MenuLinkTreeInterface - */ - protected $menuLinkTree; - - /** - * The menu ID. - * - * @var string - */ - protected $menuId; - - /** - * - */ - public static function create( - ContainerInterface $container, - array $configuration, - $plugin_id, - $plugin_definition - ) { - $plugin = new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('module_handler'), - $container->get('entity_type.manager'), - ); - /** @var \Drupal\Core\StringTranslation\TranslationInterface $translation */ - $translation = $container->get('string_translation'); - $plugin->setStringTranslation($translation); - $plugin->routeMatch = $container->get('current_route_match'); - $plugin->menuLinkTree = $container->get('menu.link_tree'); - return $plugin; - } - - /** - * Get menus list. - * - * @return array - * List of menus. - */ - private function getMenuList() { - $all_menus = $this->entityTypeManager->getStorage('menu')->loadMultiple(); - $menus = [ - "" => "(None)", - ]; - foreach ($all_menus as $id => $menu) { - $menus[$id] = $menu->label(); - } - asort($menus); - return $menus; - } - - /** - * {@inheritdoc} - */ - public function settingsForm($value) { - $value = $value ?? []; - $form = []; - $form["menu"] = [ - '#type' => 'select', - '#title' => 'Menu', - '#options' => $this->getMenuList(), - '#default_value' => \array_key_exists("menu", $value) ? $value["menu"] : "", - ]; - $options = range(0, $this->menuLinkTree->maxDepth()); - unset($options[0]); - $form['level'] = [ - '#type' => 'select', - '#title' => $this->t('Initial visibility level'), - '#default_value' => \array_key_exists("level", $value) ? $value["level"] : 1, - '#options' => $options, - '#required' => TRUE, - ]; - $options[0] = $this->t('Unlimited'); - $form['depth'] = [ - '#type' => 'select', - '#title' => $this->t('Number of levels to display'), - '#default_value' => \array_key_exists("depth", $value) ? $value["depth"] : 0, - '#options' => $options, - '#description' => $this->t('This maximum number includes the initial level and the final display is dependant of the pattern template.'), - '#required' => TRUE, - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function getData($value) { - if (!$value) { - return []; - } - $this->menuId = $value["menu"]; - return $this->getMenuItems($value); - } - - /** - * Get menu items. - * - * @return array - * List of items. - */ - private function getMenuItems($value): array { - $level = (int) \array_key_exists("level", $value) ? $value["level"] : 1; - $depth = (int) \array_key_exists("depth", $value) ? $value["depth"] : 0; - $parameters = new MenuTreeParameters(); - $parameters->setMinDepth($level); - - // When the depth is configured to zero, there is no depth limit. When depth - // is non-zero, it indicates the number of levels that must be displayed. - // Hence this is a relative depth that we must convert to an actual - // (absolute) depth, that may never exceed the maximum depth. - if ($depth > 0) { - $parameters->setMaxDepth(min($level + $depth - 1, $this->menuLinkTree->maxDepth())); - } - - $tree = $this->menuLinkTree->load($this->menuId, $parameters); - $manipulators = [ - ['callable' => 'menu.default_tree_manipulators:checkAccess'], - ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'], - ]; - - $tree = $this->menuLinkTree->transform($tree, $manipulators); - $tree = $this->menuLinkTree->build($tree); - if (\array_key_exists("#items", $tree)) { - $variables = [ - "items" => $tree["#items"], - ]; - $this->moduleHandler->invokeAll("preprocess_menu", [&$variables]); - $variables["items"] = LinksSettingType::normalize($variables["items"]); - return $variables["items"]; - } - return []; - } - - /** - * {@inheritdoc} - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element) { - if (!$this->menuId) { - return; - } - $cache = $element["#cache"] ?? []; - $element["#cache"] = array_merge($cache, [ - "tags" => ['config:system.menu.' . $this->menuId], - ]); - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/AttributesSettingType.php b/src/Plugin/UiPatterns/SettingType/AttributesSettingType.php deleted file mode 100644 index b006d16..0000000 --- a/src/Plugin/UiPatterns/SettingType/AttributesSettingType.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\Component\Utility\Html; -use Drupal\Core\Template\Attribute; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Attributes setting type. - * - * @UiPatternsSettingType( - * id = "attributes", - * label = @Translation("Attributes") - * ) - */ -class AttributesSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $value = $this->getValue($value); - $description = $def->getDescription() != NULL ? $def->getDescription() : $this->t('E.g. role="navigation" class="class-1"'); - $form[$def->getName()] = [ - '#type' => 'textfield', - '#title' => $def->getLabel(), - '#description' => $description, - '#default_value' => $value, - ]; - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - - /** - * {@inheritdoc} - */ - public function preprocess($value, array $context) { - $value = parent::preprocess($value, $context); - $parse_html = '<div ' . $value . '></div>'; - $attributes = []; - foreach (Html::load($parse_html)->getElementsByTagName('div') as $div) { - foreach ($div->attributes as $attr) { - $attributes[$attr->nodeName] = $attr->nodeValue; - } - } - return new Attribute($attributes); - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/BooleanSettingType.php b/src/Plugin/UiPatterns/SettingType/BooleanSettingType.php deleted file mode 100644 index 2ce436e..0000000 --- a/src/Plugin/UiPatterns/SettingType/BooleanSettingType.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Checkbox setting type. - * - * @UiPatternsSettingType( - * id = "boolean", - * label = @Translation("true/false") - * ) - */ -class BooleanSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $value = $this->getValue($value); - $form[$def->getName()] = [ - '#type' => 'checkbox', - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $value, - ]; - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - - /** - * {@inheritdoc} - */ - public function fieldStorageExposableTypes() { - return ['boolean']; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/CheckboxesSettingType.php b/src/Plugin/UiPatterns/SettingType/CheckboxesSettingType.php deleted file mode 100644 index 1194c90..0000000 --- a/src/Plugin/UiPatterns/SettingType/CheckboxesSettingType.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Checkbox setting type. - * - * @UiPatternsSettingType( - * id = "checkboxes", - * label = @Translation("Checkboxes") - * ) - */ -class CheckboxesSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - $selected_options = []; - $defined_options = $def->getOptions(); - if (is_array($value)) { - foreach ($value as $checkbox_key => $checkbox_value) { - if ($checkbox_value != "0" && isset($defined_options[$checkbox_value])) { - $selected_options[$checkbox_key] = $checkbox_value; - } - } - } - return $selected_options; - } - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $def = $this->getPatternSettingDefinition(); - $value = $this->getValue($value); - if (is_scalar($value)) { - $value = [$value]; - } - if (empty($value)) { - $value = []; - } - $form[$def->getName()] = [ - '#type' => 'checkboxes', - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $value, - '#options' => $def->getOptions(), - ]; - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/ColorWidgetSettingType.php b/src/Plugin/UiPatterns/SettingType/ColorWidgetSettingType.php deleted file mode 100644 index 1141824..0000000 --- a/src/Plugin/UiPatterns/SettingType/ColorWidgetSettingType.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\EnumerationSettingTypeBase; - -/** - * Colorwidget setting type. - * - * @UiPatternsSettingType( - * id = "colorwidget", - * label = @Translation("Color Widget") - * ) - */ -class ColorWidgetSettingType extends EnumerationSettingTypeBase { - - /** - * {@inheritdoc} - */ - protected function getSettingTypeDependencies() { - return ['colorwidget']; - } - - /** - * {@inheritdoc} - */ - protected function getEnumerationType(PatternDefinitionSetting $def) { - return 'colorwidget'; - } - - /** - * {@inheritdoc} - */ - protected function emptyOption() { - return []; - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - return $value['colorwidget'] ?? NULL; - } - - /** - * {@inheritdoc} - */ - protected function getValue($value) { - if ($value === NULL) { - return $this->getPatternSettingDefinition()->getDefaultValue(); - } - else { - return $value['colorwidget'] ?? $value; - } - } - - /** - * {@inheritdoc} - */ - protected function handleInput(array &$input, PatternDefinitionSetting $def, $form_type) { - parent::handleInput($input, $def, $form_type); - - foreach ($input['#options'] as $key => $label) { - $css_color = 'transparent'; - if (str_contains($label, '/')) { - [$label, $css_color] = explode('/', $label); - } - $input['#colors'][$key] = [ - 'label' => $label, - 'css_color' => $css_color, - ]; - } - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/ColorisWidgetSettingType.php b/src/Plugin/UiPatterns/SettingType/ColorisWidgetSettingType.php deleted file mode 100644 index c1b8a2d..0000000 --- a/src/Plugin/UiPatterns/SettingType/ColorisWidgetSettingType.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\EnumerationSettingTypeBase; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Coloriswidget setting type. - * - * @UiPatternsSettingType( - * id = "coloriswidget", - * label = @Translation("Coloris Widget") - * ) - */ -class ColorisWidgetSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - protected function getSettingTypeDependencies() { - return ['coloris']; - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess( - $value, - array $context, - PatternDefinitionSetting $def - ) { - if (is_string($value) && !empty($value)) { - return $value; - } - return $value['coloris'] ?? ''; - } - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $options = $def->getOptions() ?? []; - $swatches = array_keys($options); - $form[$def->getName()] = [ - '#type' => 'coloriswidget', - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $this->getValue($value), - '#swatches' => $swatches - ]; - - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/EnumerationSettingType.php b/src/Plugin/UiPatterns/SettingType/EnumerationSettingType.php deleted file mode 100644 index d21af52..0000000 --- a/src/Plugin/UiPatterns/SettingType/EnumerationSettingType.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Plugin\EnumerationSettingTypeBase; - -/** - * Enumerations setting type. - * - * @UiPatternsSettingType( - * id = "enumeration", - * label = @Translation("Enumeration") - * ) - */ -class EnumerationSettingType extends EnumerationSettingTypeBase { - -} diff --git a/src/Plugin/UiPatterns/SettingType/GroupType.php b/src/Plugin/UiPatterns/SettingType/GroupType.php deleted file mode 100644 index 3133df9..0000000 --- a/src/Plugin/UiPatterns/SettingType/GroupType.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Group (fieldgroup/details) setting type. - * - * @UiPatternsSettingType( - * id = "group", - * label = @Translation("Group") - * ) - */ -class GroupType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $def = $this->getPatternSettingDefinition(); - $form[$def->getName()] = [ - '#type' => !empty($def->getValue('group_type')) ? $def->getValue('group_type') : 'fieldset', - '#title' => $def->getLabel(), - ]; - if (!empty($def->getDescription())) { - $form[$def->getName()]['#description'] = $def->getDescription(); - } - return $form; - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - return NULL; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/LanguageAccessSettingType.php b/src/Plugin/UiPatterns/SettingType/LanguageAccessSettingType.php deleted file mode 100644 index 1149ed5..0000000 --- a/src/Plugin/UiPatterns/SettingType/LanguageAccessSettingType.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\LanguageCheckboxesSettingTypeBase; - -/** - * Hides render element for unchecked languages. - * - * Setting type to hide the render element if: - * Elements are checked and the current language is - * not part of the selection. - * - * @UiPatternsSettingType( - * id = "language_access", - * label = @Translation("Language Access") - * ) - */ -class LanguageAccessSettingType extends LanguageCheckboxesSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element) { - if ($this->isLayoutBuilderRoute() === FALSE && $value['current_language_selected'] === FALSE) { - hide($element); - } - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/LanguageCheckboxesSettingType.php b/src/Plugin/UiPatterns/SettingType/LanguageCheckboxesSettingType.php deleted file mode 100644 index 560c2b6..0000000 --- a/src/Plugin/UiPatterns/SettingType/LanguageCheckboxesSettingType.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\Core\Language\LanguageManagerInterface; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\EnumerationSettingTypeBase; -use Drupal\ui_patterns_settings\Plugin\LanguageCheckboxesSettingTypeBase; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Language Checkboxes setting type. - * - * Provides an array of: - * - current_language_selected: True if the - * current language is part of the selection - * or nothing is selected - * - current_language: The current language. - * - selected: Array of selected languages. - * - * @UiPatternsSettingType( - * id = "language_checkboxes", - * label = @Translation("Language checkboxes") - * ) - */ -class LanguageCheckboxesSettingType extends LanguageCheckboxesSettingTypeBase { - -} diff --git a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php b/src/Plugin/UiPatterns/SettingType/LinksSettingType.php deleted file mode 100644 index 75569fd..0000000 --- a/src/Plugin/UiPatterns/SettingType/LinksSettingType.php +++ /dev/null @@ -1,160 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingType; - -use Drupal\Component\Serialization\Json; -use Drupal\Core\Language\LanguageInterface; -use Drupal\Core\Template\Attribute; -use Drupal\Core\Url; -use Drupal\ui_patterns_settings\Plugin\ComplexSettingTypeBase; - -/** - * Complex setting type for links. - * - * @UiPatternsSettingType( - * id = "links", - * label = @Translation("Links") - * ) - */ -class LinksSettingType extends ComplexSettingTypeBase { - - /** - * Normalize menu items. - * - * Don't inject URL object into patterns templates, use "title" as item - * label and "url" as item target. - * - * @param array $items - * The items to convert. - * - * @return array - */ - public static function normalize(array $items): array { - foreach ($items as $index => $item) { - if (!is_array($item)) { - unset($items[$index]); - continue; - } - if (array_key_exists("text", $item)) { - // Examples: links.html.twig, breadcrumb.html.twig, pager.html.twig, - // views_mini_pager.html.twig. - $item["title"] = $item["text"]; - unset($item["text"]); - } - if (!array_key_exists("title", $item)) { - $item["title"] = $index; - } - if (array_key_exists("href", $item)) { - // Examples: pager.html.twig, views_mini_pager.html.twig. - $item["url"] = $item["href"]; - unset($item["href"]); - } - if (!isset($item["url"]) && isset($item["link"])) { - // Example: links.html.twig. - $item["url"] = $item["link"]["#url"]; - if (isset($item["link"]["#options"])) { - $item["url"]->mergeOptions($item["link"]["#options"]); - } - unset($item["link"]); - } - $item = self::normalizeUrl($item); - if (array_key_exists("below", $item)) { - $item["below"] = self::normalize($item["below"]); - } - $items[$index] = $item; - } - $items = array_values($items); - return $items; - } - - /** - * Normaize URL in an item. - * - * Useful for: menu.html.twig, links.html.twig. - */ - private static function normalizeUrl(array $item): array { - if (!array_key_exists("url", $item)) { - return $item; - } - $url = $item["url"]; - if (!($url instanceof Url)) { - return $item; - } - if ($url->isRouted() && ($url->getRouteName() === '<nolink>')) { - unset($item["url"]); - } - elseif ($url->isRouted() && ($url->getRouteName() === '<button>')) { - unset($item["url"]); - } - else { - $item["url"] = $url->toString(); - } - $options = $url->getOptions(); - self::setHrefLang($options); - self::setActiveClass($options, $url); - if (isset($options["attributes"])) { - $item["link_attributes"] = new Attribute($options["attributes"]); - } - return $item; - } - - /** - * Set hreflang attribute. - * - * Add a hreflang attribute if we know the language of this link's URL and - * hreflang has not already been set. - * - * @param array $options - * The URL options. - * - * @see \Drupal\Core\Utility\LinkGenerator::generate() - */ - private static function setHrefLang(array &$options): void { - if (isset($options['language']) - && ($options['language'] instanceof LanguageInterface) - && !isset($options['attributes']['hreflang']) - ) { - $options['attributes']['hreflang'] = $options['language']->getId(); - } - } - - /** - * Set the attributes to have the active class placed by JS. - * - * @param array $options - * The URL options. - * @param \Drupal\Core\Url $url - * The URL object. - * - * @see \Drupal\Core\Utility\LinkGenerator::generate() - */ - private static function setActiveClass(array &$options, Url $url): void { - // Set the "active" class if the 'set_active_class' option is not empty. - if (!empty($options['set_active_class']) && !$url->isExternal()) { - // Add a "data-drupal-link-query" attribute to let the - // drupal.active-link library know the query in a standardized manner. - if (!empty($options['query'])) { - $query = $options['query']; - ksort($query); - $options['attributes']['data-drupal-link-query'] = Json::encode($query); - } - - // Add a "data-drupal-link-system-path" attribute to let the - // drupal.active-link library know the path in a standardized manner. - if ($url->isRouted() && !isset($options['attributes']['data-drupal-link-system-path'])) { - // @todo System path is deprecated - use the route name and parameters. - $system_path = $url->getInternalPath(); - - // Special case for the front page. - if ($url->getRouteName() === '<front>') { - $system_path = '<front>'; - } - - if (!empty($system_path)) { - $options['attributes']['data-drupal-link-system-path'] = $system_path; - } - } - } - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/MachineNameSettingType.php b/src/Plugin/UiPatterns/SettingType/MachineNameSettingType.php deleted file mode 100644 index 916f0be..0000000 --- a/src/Plugin/UiPatterns/SettingType/MachineNameSettingType.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * MachineName setting type. - * - * @UiPatternsSettingType( - * id = "machine_name", - * label = @Translation("Machine name") - * ) - */ -class MachineNameSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $form[$def->getName()] = [ - '#type' => 'textfield', - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $this->getValue($value), - '#pattern' => "[A-Za-z]+[\w\-]*", - ]; - - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/MediaLibrarySettingType.php b/src/Plugin/UiPatterns/SettingType/MediaLibrarySettingType.php deleted file mode 100644 index 680d5b3..0000000 --- a/src/Plugin/UiPatterns/SettingType/MediaLibrarySettingType.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\Component\Utility\UrlHelper; -use Drupal\Core\Field\FieldItemList; -use Drupal\Core\Url; -use Drupal\media\Entity\Media; -use Drupal\media_library\MediaLibraryUiBuilder; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Media Library setting type. - * - * @UiPatternsSettingType( - * id = "media_library", - * label = @Translation("Media Library") - * ) - */ -class MediaLibrarySettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - protected function getSettingTypeDependencies() { - return ['media_library_form_element', 'media_library_edit']; - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - if (intval($value)) { - $media_id = $value; - $media = Media::load($media_id); - if ($media === NULL) { - return ''; - } - } - else { - return ''; - } - - $image_style = $def->getValue('image_style'); - if (empty($image_style) === FALSE) { - $image_uri = $media->field_media_image->entity !== NULL ? $media->field_media_image->entity->uri->value : NULL; - if ($image_uri !== NULL) { - return [ - '#theme' => 'image_style', - '#style_name' => $image_style, - '#uri' => $image_uri, - ]; - } - } - - $responsive_image_style = $def->getValue('responsive_image_style'); - if (empty($responsive_image_style) === FALSE) { - $image_uri = $media->field_media_image->entity !== NULL ? $media->field_media_image->entity->uri->value : NULL; - if ($image_uri !== NULL) { - return [ - '#theme' => 'responsive_image', - '#responsive_image_style_id' => $responsive_image_style, - '#uri' => $image_uri, - ]; - } - } - - $view_mode = $def->getValue('view_mode'); - if (empty($view_mode)) { - return $value; - } - $view_mode_builder = $this->entityTypeManager->getViewBuilder('media'); - return $view_mode_builder->view($media, $view_mode); - } - - /** - * {@inheritdoc} - */ - public function fieldStorageExposableTypes() { - return ['entity_reference']; - } - - public function preprocessExposedField(FieldItemList $items) { - foreach ($items as $item) { - if ($item->entity !== NULL) { - return $item->entity->id(); - } - } - } - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $media_id = $this->getValue($value); - - $media = $media_id !== NULL && is_numeric($media_id) ? Media::load($media_id) : NULL; - $media_id = $media !== NULL ? $media_id : NULL; - $form[$def->getName()] = [ - '#type' => 'media_library', - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $media_id, - ]; - if ($media !== NULL && $def->getValue('show_edit_button') === TRUE) { - $form[$def->getName()]['#ui_patterns_media_edit_button'] = TRUE; - } - - $allowed_bundles = $def->getValue('allowed_bundles'); - if (!empty($allowed_bundles)) { - $form[$def->getName()]['#allowed_bundles'] = $allowed_bundles; - } - else { - $form[$def->getName()]['#allowed_bundles'] = ['image']; - } - $cardinality = $def->getValue('cardinality'); - if (!empty($cardinality)) { - $form[$def->getName()]['#cardinality'] = $cardinality; - } - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/NumberSettingType.php b/src/Plugin/UiPatterns/SettingType/NumberSettingType.php deleted file mode 100644 index 8d30a27..0000000 --- a/src/Plugin/UiPatterns/SettingType/NumberSettingType.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Number setting type. - * - * @UiPatternsSettingType( - * id = "number", - * label = @Translation("Number") - * ) - */ -class NumberSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $form[$def->getName()] = [ - '#type' => 'number', - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $this->getValue($value), - '#min' => $def['min'] ?? NULL, - '#max' => $def['max'] ?? NULL, - ]; - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/PublishSettingType.php b/src/Plugin/UiPatterns/SettingType/PublishSettingType.php deleted file mode 100644 index a96a81b..0000000 --- a/src/Plugin/UiPatterns/SettingType/PublishSettingType.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Unpublish render array. - * - * @UiPatternsSettingType( - * id = "publish", - * label = @Translation("Publish ") - * ) - */ -class PublishSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element) { - if ($this->isLayoutBuilderRoute() === FALSE && $value === FALSE) { - hide($element); - } - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - if ($value === NULL) { - return $def->getDefaultValue(); - } - return $value !== 0; - } - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $form[$def->getName()] = [ - '#type' => 'checkbox', - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $this->getValue($value), - ]; - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/RadiosSettingType.php b/src/Plugin/UiPatterns/SettingType/RadiosSettingType.php deleted file mode 100644 index 14b9337..0000000 --- a/src/Plugin/UiPatterns/SettingType/RadiosSettingType.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\EnumerationSettingTypeBase; - -/** - * Radios setting type. - * - * @UiPatternsSettingType( - * id = "radios", - * label = @Translation("Radios") - * ) - */ -class RadiosSettingType extends EnumerationSettingTypeBase { - - /** - * {@inheritdoc} - */ - protected function getEnumerationType(PatternDefinitionSetting $def) { - return 'radios'; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/RoleAccessSettingType.php b/src/Plugin/UiPatterns/SettingType/RoleAccessSettingType.php deleted file mode 100644 index ae3742a..0000000 --- a/src/Plugin/UiPatterns/SettingType/RoleAccessSettingType.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Plugin\RoleCheckboxesSettingTypeBase; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; - -/** - * Hides render element for unchecked roles. - * - * Setting type to hide the render element if: - * Elements are checked and the current role is - * not part of the selection. - * - * @UiPatternsSettingType( - * id = "role_access", - * label = @Translation("Role Access") - * ) - */ -class RoleAccessSettingType extends RoleCheckboxesSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function alterElement($value, PatternDefinitionSetting $def, &$element) { - if ($this->isLayoutBuilderRoute() === FALSE && $value['current_role_selected'] === FALSE) { - hide($element); - } - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/RoleCheckboxesSettingType.php b/src/Plugin/UiPatterns/SettingType/RoleCheckboxesSettingType.php deleted file mode 100644 index ade81e7..0000000 --- a/src/Plugin/UiPatterns/SettingType/RoleCheckboxesSettingType.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Plugin\RoleCheckboxesSettingTypeBase; - -/** - * Role Checkboxes setting type. - * - * Provides an array of: - * - current_role_selected: True if the - * current role is part of the selection - * or nothing is selected - * - current_role: The current role. - * - selected: Array of selected role. - * - * @UiPatternsSettingType( - * id = "role_checkboxes", - * label = @Translation("Role checkboxes") - * ) - */ -class RoleCheckboxesSettingType extends RoleCheckboxesSettingTypeBase { - -} diff --git a/src/Plugin/UiPatterns/SettingType/SelectSettingType.php b/src/Plugin/UiPatterns/SettingType/SelectSettingType.php deleted file mode 100644 index 590ce1c..0000000 --- a/src/Plugin/UiPatterns/SettingType/SelectSettingType.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\EnumerationSettingTypeBase; - -/** - * Select setting type. - * - * @UiPatternsSettingType( - * id = "select", - * label = @Translation("Select") - * ) - */ -class SelectSettingType extends EnumerationSettingTypeBase { - - /** - * {@inheritdoc} - */ - protected function getOptions(PatternDefinitionSetting $def) { - return $def->getOptions(); - } - - /** - * {@inheritdoc} - */ - protected function getEnumerationType(PatternDefinitionSetting $def) { - return 'select'; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/TextfieldSettingType.php b/src/Plugin/UiPatterns/SettingType/TextfieldSettingType.php deleted file mode 100644 index 7f1ab2a..0000000 --- a/src/Plugin/UiPatterns/SettingType/TextfieldSettingType.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Textfield setting type. - * - * @UiPatternsSettingType( - * id = "textfield", - * label = @Translation("Textfield") - * ) - */ -class TextfieldSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - $form[$def->getName()] = [ - '#type' => 'textfield', - '#title' => $def->getLabel(), - '#description' => $def->getDescription(), - '#default_value' => $this->getValue($value), - ]; - - $this->handleInput($form[$def->getName()], $def, $form_type); - return $form; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/TokenSettingType.php b/src/Plugin/UiPatterns/SettingType/TokenSettingType.php deleted file mode 100644 index 2f53d55..0000000 --- a/src/Plugin/UiPatterns/SettingType/TokenSettingType.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Plugin\TokenSettingTypeBase; - -/** - * Token setting type. - * - * @UiPatternsSettingType( - * id = "token", - * label = @Translation("Token") - * ) - */ -class TokenSettingType extends TokenSettingTypeBase { - -} diff --git a/src/Plugin/UiPatterns/SettingType/UrlSettingType.php b/src/Plugin/UiPatterns/SettingType/UrlSettingType.php deleted file mode 100644 index 8d415a7..0000000 --- a/src/Plugin/UiPatterns/SettingType/UrlSettingType.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\Core\Field\FieldItemList; -use Drupal\Core\Url; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\TokenSettingTypeBase; - -/** - * Url setting type. - * - * @UiPatternsSettingType( - * id = "url", - * label = @Translation("Url") - * ) - */ -class UrlSettingType extends TokenSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function fieldStorageExposableTypes() { - return ['link']; - } - - /** - * {@inheritdoc} - */ - public function preprocessExposedField(FieldItemList $items) { - foreach ($items as $item) { - return $item->getUrl(); - } - } - - /** - * {@inheritdoc} - */ - public function settingsPreprocess($value, array $context, PatternDefinitionSetting $def) { - $value = parent::settingsPreprocess($value, $context, $def); - if (empty($value)) { - return ""; - } - try { - $url = Url::fromUri($value)->toString(); - } - catch (\Exception $e) { - // Not a valid uri. Try user input: - try { - $url = Url::fromUserInput($value)->toString(); - } - catch (\Exception $e) { - // Not a valid url. - return '#'; - } - } - return $url; - } - -} diff --git a/src/Plugin/UiPatterns/SettingType/ValueSettingType.php b/src/Plugin/UiPatterns/SettingType/ValueSettingType.php deleted file mode 100644 index eb5ca41..0000000 --- a/src/Plugin/UiPatterns/SettingType/ValueSettingType.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; - -/** - * Value setting type. - * - * @UiPatternsSettingType( - * id = "value", - * label = @Translation("Value") - * ) - */ -class ValueSettingType extends PatternSettingTypeBase { - - /** - * {@inheritdoc} - */ - public function buildConfigurationForm( - array $form, - $value, - $token_value, - $form_type - ) { - return []; - } - - public function settingsForm(array $form, $value, PatternDefinitionSetting $def, $form_type) { - return []; - } - -} diff --git a/src/Plugin/UiPatterns/Source/MediaSource.php b/src/Plugin/UiPatterns/Source/MediaSource.php new file mode 100644 index 0000000..a6ac2dc --- /dev/null +++ b/src/Plugin/UiPatterns/Source/MediaSource.php @@ -0,0 +1,143 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\Source; + +use Drupal\Core\Entity\EntityTypeManager; +use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\media\Entity\Media; +use Drupal\ui_patterns\Attribute\Source; +use Drupal\ui_patterns\SourcePluginBase; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Plugin implementation of the source. + */ +#[Source( + id: 'media', + label: new TranslatableMarkup('Media'), + description: new TranslatableMarkup('Provides a Media source..'), + prop_types: ['slot'] +)] +class MediaSource extends SourcePluginBase { + + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManager + */ + protected ?EntityTypeManager $entityTypeManager; + + /** + * {@inheritdoc} + */ + public static function create( + ContainerInterface $container, + array $configuration, + $plugin_id, + $plugin_definition, + ) { + $plugin = parent::create( + $container, + $configuration, + $plugin_id, + $plugin_definition + ); + $plugin->entityTypeManager = $container->get('entity_type.manager'); + return $plugin; + } + + /** + * {@inheritdoc} + */ + public function defaultSettings(): array { + return [ + 'media' => NULL, + ]; + } + + /** + * {@inheritdoc} + */ + public function getPropValue(): mixed { + + $media = $this->getMedia(); + if ($media === NULL) { + return ''; + } + $view_mode = $this->getSetting('view_mode') ?? 'default'; + if ($view_mode === NULL) { + return $media->id(); + } + $view_mode_builder = $this->entityTypeManager->getViewBuilder('media'); + return $view_mode_builder->view($media, $view_mode); + + } + + /** + * Returns the referenced media object. + */ + protected function getMedia(): ?Media { + $media_id = $this->getSetting('media')['media_library_selection'] ?? NULL; + return $media_id !== NULL && is_numeric($media_id) ? Media::load($media_id) : NULL; + } + + /** + * {@inheritdoc} + */ + public function configureForm(array $form, FormStateInterface $form_state): array { + $configuration = $this->getConfiguration(); + $form = parent::configureForm($form, $form_state); + /** @var \Drupal\media\Entity\MediaType $bundles */ + $bundles = $this->entityTypeManager->getStorage('media_type')->loadMultiple(); + $bundle_options = []; + foreach ($bundles as $bundle_id => $bundle) { + $bundle_options[$bundle_id] = $bundle->label(); + } + $form['allowed_bundles'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Bundles'), + '#options' => $bundle_options, + '#default_value' => $configuration['configure']['allowed_bundles'] ?? FALSE, + ]; + $form['show_edit_button'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Show Edit button'), + '#default_value' => $configuration['configure']['show_edit_button'] ?? FALSE, + ]; + + return $form; + } + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state): array { + $form = parent::settingsForm($form, $form_state); + $configure = $this->getConfiguration()['configure']; + $media = $this->getMedia(); + $media_id = $media?->id(); + $form['media'] = [ + '#type' => 'media_library', + '#default_value' => $media_id, + ]; + + $this->addRequired($form['media']); + if ($media !== NULL && isset($configure['show_edit_button']) + && $configure['show_edit_button'] === TRUE) { + $form['media']['#ui_patterns_media_edit_button'] = TRUE; + } + + $allowed_bundles = $configure['allowed_bundles'] ?? ['image']; + if (!empty($allowed_bundles)) { + $form['media']['#allowed_bundles'] = $allowed_bundles; + } + else { + $form['media']['#allowed_bundles'] = ['image']; + } + $form['media']['#cardinality'] = $configure['cardinality'] ?? 1; + return $form; + } + +} diff --git a/src/Plugin/UiPatterns/Source/SettingFieldSource.php b/src/Plugin/UiPatterns/Source/SettingFieldSource.php deleted file mode 100644 index 239b69c..0000000 --- a/src/Plugin/UiPatterns/Source/SettingFieldSource.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\Plugin\UiPatterns\Source; - -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\ui_patterns\Plugin\PatternSourceBase; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Defines UI Patterns Settings fields source plugin. - * - * @UiPatternsSource( - * id = "settings_field", - * label = @Translation("Seting Fields (UI Pattern settings)"), - * provider = "ui_patterns_settings", - * tags = { - * "field_properties" - * } - * ) - */ -class SettingFieldSource extends PatternSourceBase implements ContainerFactoryPluginInterface { - - /** - * {@inheritdoc} - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition) { - parent::__construct($configuration, $plugin_id, $plugin_definition); - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $configuration, - $plugin_id, - $plugin_definition - ); - } - - /** - * {@inheritdoc} - */ - public function getSourceFields() { - $sources = []; - return $sources; - } - -} diff --git a/src/TwigExtension/UIPatternsSettingsExtension.php b/src/TwigExtension/UIPatternsSettingsExtension.php deleted file mode 100644 index 66b9cad..0000000 --- a/src/TwigExtension/UIPatternsSettingsExtension.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings\TwigExtension; - -use Drupal\ui_patterns\UiPatterns; -use Drupal\ui_patterns_settings\UiPatternsSettings; -use Twig\Extension\AbstractExtension; -use Twig\TwigFunction; - -/** - * UI Patterns Twig Extension. - * - * @package Drupal\ui_patterns_settings\TwigExtension - */ -class UIPatternsSettingsExtension extends AbstractExtension { - - /** - * {@inheritdoc} - */ - public function getName() { - return 'ui_patterns_settings'; - } - - /** - * {@inheritdoc} - */ - public function getFunctions() { - return [ - new TwigFunction( - 'pattern_configuration', - [$this, 'patternConfiguration'] - ), - ]; - } - - /** - * Returns pattern configuration. - * - * @param string $pattern_id - * The pattern id. - * @param string $variant_id - * The variant id. - * @param string $config_name - * The config name. - * - * @return mixed|null - * The pattern config - */ - public function patternConfiguration($pattern_id, $variant_id, $config_name) { - $definition = UiPatterns::getPatternDefinition($pattern_id); - if ($definition !== NULL) { - return UiPatternsSettings::getPatternConfiguration($definition, $variant_id, $config_name); - } - } - -} diff --git a/src/UiPatternsSettings.php b/src/UiPatternsSettings.php deleted file mode 100644 index dad1efe..0000000 --- a/src/UiPatternsSettings.php +++ /dev/null @@ -1,307 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings; - -use Drupal\Core\Entity\ContentEntityBase; -use Drupal\Core\Entity\EntityInterface; -use Drupal\ui_patterns\Definition\PatternDefinition; -use Drupal\ui_patterns\UiPatterns; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\Core\Entity\EntityMalformedException; - -/** - * UI Patterns setting factory class. - * - * @package Drupal\ui_patterns_settings - */ -class UiPatternsSettings { - - /** - * Cached pattern definition settings. - * - * @var \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting[] - */ - private static $settings; - - /** - * Get pattern manager setting instance. - * - * @return \Drupal\ui_patterns_settings\UiPatternsSettingsManager - * UI Patterns setting manager instance. - */ - public static function getManager() { - return \Drupal::service('plugin.manager.ui_patterns_settings'); - } - - /** - * Get config manager instance. - * - * @return \Drupal\ui_patterns_settings\ConfigManager - * UI Patterns setting config manager. - */ - public static function getConfigManager() { - return \Drupal::service('ui_patterns_settings.config_manager'); - } - - /** - * Preprocess exposed settings variables. - * - * @param \Drupal\Core\Entity\ContentEntityBase $entity - * The entity. - * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition - * The pattern definition. - * - * @return array - * The processed variables. - */ - private static function preprocessExposedFields(ContentEntityBase $entity, PatternDefinition $definition) { - $processed_settings = []; - $mapping = self::getConfigManager()->getMappingByType($entity->getEntityTypeId()); - foreach ($mapping as $field => $pattern_setting) { - if ($entity->hasField($field)) { - [$pattern_id, $setting_id] = explode('::', $pattern_setting); - if ($setting_id !== 'variant') { - $pattern_definition = UiPatterns::getPatternDefinition($pattern_id); - $setting_definition = UiPatternsSettings::getPatternDefinitionSetting($pattern_definition, $setting_id); - if ($setting_definition !== NULL) { - $settingType = UiPatternsSettings::createSettingType($definition, $setting_definition); - $processed_settings[$setting_id] = $settingType->preprocessExposedField($entity->get($field)); - } - } - } - } - return $processed_settings; - } - - /** - * Preprocess all settings variables. - * - * @param string $pattern_id - * Pattern ID for which to preprocess. - * @param array $settings - * The stored settings. - * @param string $variant - * The variant. - * @param bool $preview - * Is preview. - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity of the pattern. Useful for dynamic settings. - * - * @return array - * The processed settings. - */ - public static function preprocess($pattern_id, array $settings, $variant, $preview, EntityInterface $entity = NULL, &$element = NULL) { - $processed_settings = []; - $definition = UiPatterns::getPatternDefinition($pattern_id); - $context = []; - $context['entity'] = $entity; - if ($entity instanceof ContentEntityBase) { - $processed_settings = self::preprocessExposedFields($entity, $definition); - } - $settings_definition = UiPatternsSettings::getPatternDefinitionSettings($definition); - foreach ($settings_definition as $key => $setting_definition) { - if ($setting_definition->getForcedValue()) { - $value = $setting_definition->getForcedValue(); - } - elseif (!empty($settings[$key . '_token'])) { - $token_value = $settings[$key . '_token']; - $token_data = []; - if ($entity !== NULL) { - $token_data[$entity->getEntityTypeId()] = $entity; - } - try { - $value = \Drupal::token() - ->replace($token_value, $token_data, ['clear' => TRUE]); - } - catch (EntityMalformedException $e) { - if (!ui_patterns_settings_is_layout_builder_route()) { - throw $e; - } - // Do nothing inside layout builder. - } - } - // Use exposed field value if no other setting is provided - elseif (isset($processed_settings[$key]) && empty($settings[$key])) { - $value = $processed_settings[$key]; - } - elseif (isset($settings[$key])) { - $value = $settings[$key]; - } - elseif ($preview && !empty($setting_definition->getPreview())) { - $value = $setting_definition->getPreview(); - } - else { - $value = $setting_definition->getDefaultValue(); - } - if (!empty($variant) && $definition->hasVariant($variant)) { - $variant_ob = $definition->getVariant($variant); - if ($variant_ob != NULL) { - $variant_ary = $variant_ob->toArray(); - if (isset($variant_ary['settings']) && isset($variant_ary['settings'][$key])) { - // Overwrite settings definition. - // Allow variants to overwrite settings configuration. - if (isset($variant_ary['settings'][$key]['definition']) && is_array($variant_ary['settings'][$key]['definition'])) { - $value = $variant_ary['settings'][$key]['value'] ?? $value; - if (isset($variant_ary['settings'][$key]['definition'])) { - $setting_definition = clone $setting_definition; - $setting_definition->setDefinitions($variant_ary['settings'][$key]['definition']); - } - } else { - $value = $variant_ary['settings'][$key]; - } - } - } - } - $setting_type = UiPatternsSettings::createSettingType($definition, $setting_definition); - $processed_value = $setting_type->preprocess($value, $context); - $setting_type->alterElement($processed_value, $setting_definition, $element); - $processed_settings[$key] = $processed_value; - } - return $processed_settings; - - } - - /** - * Exposed pattern setting definitions. - * - * Returns a list of all exposed pattern setting definitions - * filtered by the provided field storage type. - * - * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition - * The pattern definition. - * @param string $field_storage_type - * The field storage type. - * - * @return array - * The configuration array. - * Key: pattern::setting. - * Keys: - * 'label' = 'The setting label' - * 'definition' = The pattern definition - */ - public static function getExposedPatternDefinition(PatternDefinition $definition, $field_storage_type) { - $additional = $definition->getAdditional(); - $exposed = []; - if (isset($additional['allow_variant_expose']) && - $additional['allow_variant_expose'] === TRUE && $field_storage_type === 'list_string') { - $exposed[$definition->id() . '::variant'] = [ - 'label' => $definition->getLabel() . ' Variants', - 'definition' => $definition, - ]; - } - - $settings = self::getPatternDefinitionSettings($definition); - /** @var \Drupal\ui_patterns\Definition\PatternDefinitionSetting $setting */ - foreach ($settings as $setting) { - if ($setting->allowExpose() - ) { - $setting_type = self::createSettingType($definition, $setting); - if (in_array($field_storage_type, $setting_type->fieldStorageExposableTypes())) { - $exposed[$definition->id() . '::' . $setting->getName()] = [ - 'label' => $definition->getLabel() . ' ' . $setting->getLabel(), - 'definition' => $definition, - ]; - } - } - } - return $exposed; - } - - /** - * Get pattern configuration for a pattern definition. - * - * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition - * The definition. - * @param string $variant - * The pattern variant. - * @param string $name - * The configuration key. - * - * @return mixed - * Setting pattern configuration. - */ - public static function getPatternConfiguration(PatternDefinition $definition, $variant = NULL, $name = NULL) { - $additional = $definition->getAdditional(); - $configuration = $additional['configuration'] ?? []; - // Check for variant configuration - if (!empty($variant)) { - $variant_ob = $definition->getVariant($variant); - if ($variant_ob != NULL) { - $variant_ary = $variant_ob->toArray(); - if (isset($variant_ary['configuration'])) { - $configuration = array_merge($configuration, $variant_ary['configuration']); - } - } - } - // Check for settings configuration - if (isset($additional['settings'][$name]['options'])) { - foreach ($additional['settings'][$name]['options'] as $option_key => $option_value) { - if (is_array($option_value) && isset($option_value['configuration'])) { - $configuration[$name][$option_key] = $option_value['configuration']; - } - } - } - if ($name !== NULL && isset($configuration[$name])) { - return $configuration[$name]; - } - return $configuration; - } - - /** - * Get setting definition for a pattern and a setting name. - * - * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition - * The pattern definition. - * @param string $setting_name - * The setting name. - */ - public static function getPatternDefinitionSetting(PatternDefinition $definition, $setting_name) { - $definitions = self::getPatternDefinitionSettings($definition); - return $definitions[$setting_name] ?? NULL; - } - - /** - * Get setting definitions for a pattern definition. - * - * @param \Drupal\ui_patterns\Definition\PatternDefinition $definition - * The definition. - * - * @return \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting[] - * Setting pattern definitons. - */ - public static function getPatternDefinitionSettings(PatternDefinition $definition) { - if (isset(self::$settings[$definition->id()])) { - return self::$settings[$definition->id()]; - } - $additional = $definition->getAdditional(); - $settings_ary = $additional['settings'] ?? []; - $settings = []; - if (!empty($settings_ary)) { - foreach ($settings_ary as $key => $setting_ary) { - $settings[$key] = new PatternDefinitionSetting($key, $setting_ary); - } - } - self::$settings[$definition->id()] = $settings; - return $settings; - } - - /** - * Create setting type plugin. - * - * @param \Drupal\ui_patterns\Definition\PatternDefinition $pattern_definition - * The pattern definition. - * @param \Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting $setting_defintion - * The setting definition. - * - * @return \Drupal\ui_patterns_settings\Plugin\PatternSettingTypeInterface - * UI Patterns setting manager instance. - */ - public static function createSettingType(PatternDefinition $pattern_definition, PatternDefinitionSetting $setting_defintion) { - $configuration = []; - $configuration['pattern_setting_definition'] = $setting_defintion; - $configuration['pattern_definition'] = $pattern_definition; - return \Drupal::service('plugin.manager.ui_patterns_settings') - ->createInstance($setting_defintion->getType(), $configuration); - } - -} diff --git a/src/UiPatternsSettingsDataProviderManager.php b/src/UiPatternsSettingsDataProviderManager.php deleted file mode 100644 index cf98a28..0000000 --- a/src/UiPatternsSettingsDataProviderManager.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings; - -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Plugin\DefaultPluginManager; - -/** - * UiPatternsSettingsDataProvider plugin manager. - */ -class UiPatternsSettingsDataProviderManager extends DefaultPluginManager { - - /** - * Constructs UiPatternsSettingsDataProviderPluginManager object. - * - * @param \Traversable $namespaces - * An object that implements \Traversable which contains the root paths - * keyed by the corresponding namespace to look for plugin implementations. - * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend - * Cache backend instance to use. - * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler - * The module handler to invoke the alter hook with. - */ - public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) { - parent::__construct( - 'Plugin/UiPatterns/SettingDataProvider', - $namespaces, - $module_handler, - 'Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface', - 'Drupal\ui_patterns_settings\Annotation\UiPatternsSettingDataProvider' - ); - $this->alterInfo('ui_patterns_settings_data_provider_info'); - $this->setCacheBackend($cache_backend, 'ui_patterns_settings_data_provider_plugins'); - } - - public function getDefinitionsBySettingType($setting_type_id) { - $definitions = $this->getDefinitions(); - $results = []; - foreach ($definitions as $definition) { - if ($definition['settingType'] === $setting_type_id) { - $results[] = $definition; - } - } - return $results; - } - -} diff --git a/src/UiPatternsSettingsManager.php b/src/UiPatternsSettingsManager.php deleted file mode 100644 index eb53b91..0000000 --- a/src/UiPatternsSettingsManager.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings; - -use Drupal\Component\Plugin\Factory\DefaultFactory; -use Drupal\Component\Plugin\PluginManagerInterface; -use Drupal\Core\Cache\CacheBackendInterface; -use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Plugin\DefaultPluginManager; -use Drupal\Core\StringTranslation\StringTranslationTrait; -use Drupal\ui_patterns\Definition\PatternDefinition; - -/** - * Provides the UI Patterns Settings plugin manager. - */ -class UiPatternsSettingsManager extends DefaultPluginManager implements PluginManagerInterface { - - use StringTranslationTrait; - - /** - * UiPatternsSettingsManager constructor. - */ - public function __construct(\Traversable $namespaces, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend) { - parent::__construct('Plugin/UiPatterns/SettingType', $namespaces, $module_handler, 'Drupal\ui_patterns_settings\Plugin\PatternSettingTypeInterface', 'Drupal\ui_patterns_settings\Annotation\UiPatternsSettingType'); - $this->moduleHandler = $module_handler; - $this->alterInfo('ui_patterns_settings_info'); - $this->setCacheBackend($cache_backend, 'ui_patterns_settings', ['ui_patterns_settings']); - } - - /** - * Returns TRUE if a variant token can configured. - * - * @param \Drupal\ui_patterns\Definition\PatternDefinition $pattern_definition - * The pattern definition. - * - * @return bool - * Returns TRUE if a variant token can configured. - */ - public static function allowVariantToken(PatternDefinition $pattern_definition) { - $ary = $pattern_definition->getAdditional(); - if (isset($ary['allow_variant_token']) && $ary['allow_variant_token'] === TRUE) { - return TRUE; - } - else { - return FALSE; - } - } - - /** - * {@inheritdoc} - */ - public function createInstance($plugin_id, array $configuration = []) { - $plugin_definition = $this->getDefinition($plugin_id); - $plugin_class = DefaultFactory::getPluginClass($plugin_id, $plugin_definition); - // If the plugin provides a factory method, pass the container to it. - if (is_subclass_of($plugin_class, 'Drupal\Core\Plugin\ContainerFactoryPluginInterface')) { - $plugin = $plugin_class::create(\Drupal::getContainer(), $configuration, $plugin_id, $plugin_definition); - } - else { - $plugin = new $plugin_class($configuration, $plugin_id, $plugin_definition); - } - return $plugin; - } - -} diff --git a/tests/fixtures/TestDataSet.yml b/tests/fixtures/TestDataSet.yml new file mode 100644 index 0000000..5911789 --- /dev/null +++ b/tests/fixtures/TestDataSet.yml @@ -0,0 +1,20 @@ +--- +media_main: + component: + component_id: ui_patterns_test:test-component + slots: + slot: + sources: + - + source_id: media + source: + media_id: 112 + + output: + slots: + slot: + - + normalized_value: '12' + + + entity: {} diff --git a/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingDataProvider/Foo.php b/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingDataProvider/Foo.php deleted file mode 100644 index 162ea13..0000000 --- a/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingDataProvider/Foo.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings_data_provider\Plugin\UiPatterns\SettingDataProvider; - -use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderBase; -use Drupal\ui_patterns_settings\Plugin\PatternSettingDataProviderInterface; - -/** - * Plugin implementation of the ui_patterns_settings_data_provider. - * - * @UiPatternsSettingDataProvider( - * id = "foo", - * label = @Translation("Foo"), - * description = @Translation("Foo description."), - * settingType = "sample_complex_setting_type" - * ) - */ -class Foo extends PatternSettingDataProviderBase implements PatternSettingDataProviderInterface { - - /** - * {@inheritdoc} - */ - public function settingsForm($value) { - return ['#type' => 'select', '#options' => ['foo' => 'Foo']]; - } - - /** - * {@inheritdoc} - */ - public function getData($value) { - return ['data' => 'done']; - } - -} diff --git a/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingType/SampleComplexSettingType.php b/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingType/SampleComplexSettingType.php deleted file mode 100644 index 3912a2e..0000000 --- a/tests/modules/ui_patterns_settings_data_provider/src/Plugin/UiPatterns/SettingType/SampleComplexSettingType.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -namespace Drupal\ui_patterns_settings_data_provider\Plugin\UIPatterns\SettingType; - -use Drupal\ui_patterns_settings\Plugin\ComplexSettingTypeBase; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; - -/** - * Complex Setting Type. - * - * @UiPatternsSettingType( - * id = "sample_complex_setting_type", - * label = @Translation("Complex Setting Type") - * ) - */ -class SampleComplexSettingType extends ComplexSettingTypeBase { - - -} diff --git a/tests/modules/ui_patterns_settings_data_provider/templates/pattern-foo-complex.html.twig b/tests/modules/ui_patterns_settings_data_provider/templates/pattern-foo-complex.html.twig deleted file mode 100644 index 1a6f67e..0000000 --- a/tests/modules/ui_patterns_settings_data_provider/templates/pattern-foo-complex.html.twig +++ /dev/null @@ -1,8 +0,0 @@ -<div style="border: 1px solid blue"> - {% for item in links %} - {{ item['title'] }} - {% endfor %} - {% for item in breadcrumb_lists %} - {{ item['title'] }} - {% endfor %} -</div> diff --git a/tests/modules/ui_patterns_settings_data_provider/templates/settings.ui_patterns.yml b/tests/modules/ui_patterns_settings_data_provider/templates/settings.ui_patterns.yml deleted file mode 100644 index 44f403d..0000000 --- a/tests/modules/ui_patterns_settings_data_provider/templates/settings.ui_patterns.yml +++ /dev/null @@ -1,16 +0,0 @@ -foo_complex: - label: Foo Complex - fields: - dummy: - type: text - label: Dummy - settings: - complex_setting: - type: sample_complex_setting_type - label: Sample Complex Setting - links: - type: links - label: links - breadcrumb_lists: - type: links - label: breadcrumb_lists diff --git a/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml b/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml deleted file mode 100644 index 43f4846..0000000 --- a/tests/modules/ui_patterns_settings_data_provider/ui_patterns_settings_data_provider.info.yml +++ /dev/null @@ -1,5 +0,0 @@ -type: module -name: 'UI Patterns Settings Data Provider' -package: 'Testing' -dependencies: - - ui_patterns_settings:ui_patterns_settings diff --git a/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig b/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig deleted file mode 100644 index ad13d83..0000000 --- a/tests/modules/ui_patterns_settings_render_test/templates/pattern-foo-settings.html.twig +++ /dev/null @@ -1,19 +0,0 @@ -{% set configuration = pattern_configuration('foo_settings', '', 'config') %} -<div style="border: 1px solid blue"> - <div class="textfield">Textfield: {{ textfield }}</div> - <div class="number">Number: {{ number }}</div> - <div class="token">Token: {{ token }}</div> - <div class="boolean">Boolean: {{ boolean }}</div> - <div class="url">Url: {{ url }}</div> - <div class="select">Select: {{ select }}</div> - <div class="enumeration">Enumeration: {{ enumeration }}</div> - <div class="checkboxes">Checkboxes: {% for i in checkboxes %} {{- i -}} {% endfor %}</div> - <div class="language_checkboxes">language_checkboxes: {% for index, language in language_checkboxes.selected %} {{- index -}}-{{ language }} {% endfor %}</div> - <div class="attributes">Attributes: {{ attributes }}</div> - <div class="config">Configuration: {{ configuration }}</div> - <div class="group_sub">Group sub: {{ group_sub }}</div> - <div class="media_style">Media Style: {{ media_style }}</div> - <div class="select_config">select_config: {{ pattern_configuration('foo_settings', '', 'select_config')[select_config] }}</div> - <div class="value">Value: {{ setting_value }}</div> - <div class="machine_name">Machine name: {{ machine_name }}</div> -</div> diff --git a/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml b/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml deleted file mode 100644 index a3133ae..0000000 --- a/tests/modules/ui_patterns_settings_render_test/templates/settings.ui_patterns.yml +++ /dev/null @@ -1,165 +0,0 @@ -foo_settings: - label: Foo settings - fields: - dummy: - type: text - label: Dummy - allow_variant_token: true - allow_variant_expose: true - variants: - default: - label: Default - blue: - label: Blue - settings: - textfield: blue - setting_value: '%select_states' - media_style: - definition: - image_style: 'large' - settings: - setting_value: - type: value - label: Value Setting - default_value: text preview - textfield: - type: textfield - label: Textfield - allow_token: true - preview: text preview - required: true - number: - type: number - label: Number - preview: 10 - required: true - token: - type: token - label: Token - preview: Token - media_library: - type: media_library - label: Media Library - view_mode: 'default' - media_style: - type: media_library - label: Media Style - allow_expose: true - image_style: 'medium' - url: - type: url - label: Url - preview: Url - allow_expose: true - expose_as_field: true - boolean: - type: boolean - allow_token: true - label: Boolean - preview: 1 - allow_expose: true - colorwidget: - type: colorwidget - label: Colorwidget - options: - key: value/#000000 - white: White/#ffffff - enumeration: - type: enumeration - enumeration_type: select - label: Enumeration - options: - key: value - select: - type: select - label: Select - allow_expose: true - options: - key: value - key2: value2 - select_states: - type: select - label: Select States - states: - visible: - - - variant: blue - - - setting: select_config - value: key2 - options: - key: value - key2: value2 - select_config: - type: select - label: Select Config - options: - key: - label: select_config 1 - configuration: config key - key2: - label: select_config 2 - configuration: config key2 - role_checkboxes: - type: role_checkboxes - label: Role checkboxes - role_access: - type: role_checkboxes - label: Role Access - language_checkboxes: - type: language_checkboxes - label: Language selection - language_access: - type: language_access - label: Language access - publish: - type: publish - label: Publish - default_value: true - checkboxes: - type: checkboxes - label: Checkboxes - options: - box1: Box1 - box2: Box2 - attributes: - type: attributes - label: Attributes - group: - type: group - label: Group - group_type: container - group_sub: - type: textfield - label: Textfield - group: group - tabs: - type: group - label: Tabs - group_type: horizontal_tabs - tab: - type: group - label: Tab - group_type: details - group: tabs - tab_2: - type: group - label: Tab 2 - group_type: details - group: tabs - tab_element: - type: textfield - label: Textfield - group: tab - tab_element2: - type: select - label: Textfield 2 - group: tab_2 - options: - option1: Option 1 - machine_name: - type: machine_name - label: Machine name - - configuration: - config: config_value diff --git a/tests/modules/ui_patterns_settings_render_test/ui_patterns_settings_render_test.info.yml b/tests/modules/ui_patterns_settings_render_test/ui_patterns_settings_render_test.info.yml deleted file mode 100644 index dd256b5..0000000 --- a/tests/modules/ui_patterns_settings_render_test/ui_patterns_settings_render_test.info.yml +++ /dev/null @@ -1,3 +0,0 @@ -type: module -name: 'UI Patterns Settings Render Test' -package: 'Testing' diff --git a/tests/src/Functional/UiPatternsSettingsRenderTest.php b/tests/src/Functional/UiPatternsSettingsRenderTest.php deleted file mode 100644 index 02ba933..0000000 --- a/tests/src/Functional/UiPatternsSettingsRenderTest.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php - -namespace Drupal\Tests\ui_patterns_settings\Functional; - -use Drupal\Tests\BrowserTestBase; -use Drupal\Tests\ui_patterns\Traits\TwigDebugTrait; - -/** - * Test pattern preview rendering. - * - * @group ui_patterns_setting - * @name ui_patterns_setting - */ -class UiPatternsSettingsRenderTest extends BrowserTestBase { - - /** - * {@inheritdoc} - */ - protected $defaultTheme = 'stable9'; - - /** - * Disable schema validation when running tests. - * - * @var bool - * - * @todo Fix this by providing actual schema validation. - */ - protected $strictConfigSchema = FALSE; - - use TwigDebugTrait; - - /** - * {@inheritdoc} - */ - protected static $modules = [ - 'node', - 'ui_patterns', - 'ui_patterns_ds', - 'ui_patterns_library', - 'ui_patterns_layouts', - 'ui_patterns_settings', - 'field_ui', - 'token', - 'ds', - 'ui_patterns_settings_render_test', - ]; - - /** - * Tests pattern preview suggestions. - */ - public function testRender() { - - $assert_session = $this->assertSession(); - - $this->drupalCreateContentType(['type' => 'article']); - $created_node = $this->drupalCreateNode([ - 'title' => - t('Hello Settings'), - 'type' => 'article', - ]); - $this->enableTwigDebugMode(); - - $user = $this->drupalCreateUser([], NULL, TRUE); - $this->drupalLogin($user); - - // Define mapping for each setting type. - $mappings = [ - '[textfield]' => ['input' => 'Text', 'result' => 'Textfield: Text'], - '[number]' => ['input' => '10', 'result' => 'Number: 10'], - '[token][input]' => ['input' => '[node:nid]', 'result' => 'Token: 1'], - '[boolean]' => ['input' => '1', 'result' => 'Boolean: 1'], - '[select]' => ['input' => 'key', 'result' => 'Select: key'], - '[select_config]' => ['input' => 'key', 'result' => 'select_config: config key'], - '[enumeration]' => ['input' => 'key', 'result' => 'Enumeration: key'], - /*'[colorwidget][colorwidget]' => [ - 'input' => 'key', - 'result' => 'Colorwidget: key', - ],*/ - '[checkboxes][box1]' => ['input' => TRUE, 'result' => 'Checkboxes: Box1'], - '[attributes]' => [ - 'input' => 'class="class"', - 'result' => 'Attributes: class="class"', - ], - '[group_sub]' => [ - 'input' => 'group_sub', - 'result' => 'Group sub: group_sub', - ], - '[machine_name]' => ['input' => 'key', 'result' => 'Machine name: key'], - ]; - - // Select the layout. - $edit = [ - 'ds_layout' => 'pattern_foo_settings', - ]; - $this->drupalGet('/admin/structure/types/manage/article/display'); - $this->submitForm($edit, 'Save'); - - // Fill settings. - $edit = []; - foreach ($mappings as $key => $mapping) { - $edit['layout_configuration[pattern][settings]' . $key] = $mapping['input']; - } - $this->drupalGet('/admin/structure/types/manage/article/display'); - $this->submitForm($edit, 'Save'); - - // Check values. - $this->drupalGet('/node/' . $created_node->id()); - foreach ($mappings as $key => $mapping) { - $assert_session->responseContains($mapping['result']); - } - $assert_session->responseContains('Configuration: config_value'); - } - -} diff --git a/tests/src/Kernel/ComplexSettingTypeTest.php b/tests/src/Kernel/ComplexSettingTypeTest.php deleted file mode 100644 index cdaa1a1..0000000 --- a/tests/src/Kernel/ComplexSettingTypeTest.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -namespace Drupal\Tests\ui_patterns_settings\Kernel; - -use Drupal\KernelTests\KernelTestBase; -use Drupal\ui_patterns\Definition\PatternDefinition; -use Drupal\ui_patterns_settings\Definition\PatternDefinitionSetting; -use Drupal\ui_patterns_settings\UiPatternsSettings; - -/** - * Test ComplexSettingType. - * - * @group ui_patterns_settings - */ -class ComplexSettingTypeTest extends KernelTestBase { - - /** - * {@inheritdoc} - */ - protected static $modules = [ - 'ui_patterns_settings', - 'ui_patterns_settings_data_provider', - ]; - - /** - * {@inheritdoc} - */ - protected function setUp(): void { - parent::setUp(); - // Mock required services here. - } - - private function getTestSettingType() { - /** @var \Drupal\ui_patterns_settings_data_provider\Plugin\UIPatterns\SettingType\SampleComplexSettingType $sample_complex_setting_type */ - $definition = new PatternDefinition([ - [ - 'sample' => [ - 'id' => 'sample', - ], - ], - ], 'sample'); - return UiPatternsSettings::createSettingType($definition, $this->getTestSettingDefinition()); - } - - private function getTestSettingDefinition() { - return new PatternDefinitionSetting('sample_complex_setting_type', [ - 'name' => 'sample_complex_setting_type', - 'type' => 'sample_complex_setting_type', - 'label' => 'sample_complex_setting_type', - ]); - } - - /** - * Test testSettingsForm. - */ - public function testSettingsForm() { - $sample_definition = $this->getTestSettingDefinition(); - $sample_complex_setting_type = $this->getTestSettingType(); - $fieldset = $sample_complex_setting_type->settingsForm([], '', $sample_definition, 'layout'); - self::assertArrayHasKey('sample_complex_setting_type', $fieldset); - self::assertArrayHasKey('provider', $fieldset['sample_complex_setting_type']); - self::assertArrayHasKey('foo', $fieldset['sample_complex_setting_type']['configuration']); - self::assertArrayHasKey('#type', $fieldset['sample_complex_setting_type']['configuration']['foo']['config']); - } - - public function testPreprocess() { - $sample_complex_setting_type = $this->getTestSettingType(); - $context = []; - $ary = $sample_complex_setting_type->preprocess(['provider' => 'foo'], $context); - self::assertArrayHasKey('data', $ary); - } -} diff --git a/tests/src/Kernel/Source/MediaSourceTest.php b/tests/src/Kernel/Source/MediaSourceTest.php new file mode 100644 index 0000000..aecb567 --- /dev/null +++ b/tests/src/Kernel/Source/MediaSourceTest.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns_settings\Kernel\Source; + +use Drupal\Tests\ui_patterns_settings\Kernel\UiPSSourcePluginsTestBase; + +/** + * Test MediaSource. + * + * @coversDefaultClass \Drupal\ui_patterns_settings\Plugin\UiPatterns\Source\MediaSource + * @group ui_patterns_settings + */ +class MediaSourceTest extends UiPSSourcePluginsTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'ui_patterns_settings', + ]; + + + /** + * Test TokenSource Plugin. + */ + public function testPlugin(): void { + $this->runSourcePluginTests('media_', __DIR__ . "/../../fixtures/TestDataSet.yml"); + } + +} diff --git a/tests/src/Kernel/UiPSSourcePluginsTestBase.php b/tests/src/Kernel/UiPSSourcePluginsTestBase.php new file mode 100644 index 0000000..06e142f --- /dev/null +++ b/tests/src/Kernel/UiPSSourcePluginsTestBase.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\ui_patterns_settings\Kernel; + +use Drupal\Tests\ui_patterns\Kernel\SourcePluginsTestBase; + +/** + * Base class to test source plugins. + * + * @group ui_patterns + */ +class UiPSSourcePluginsTestBase extends SourcePluginsTestBase { + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + $this->installConfig(['ui_patterns_settings']); + + } + + public function runSourcePluginTests(?string $test_starts_with = NULL, ?string $tests_path = NULL): void { + parent::runSourcePluginTests($test_starts_with, __DIR__ . "/../../fixtures/TestDataSet.yml"); + } + + +} diff --git a/ui_patterns_settings.info.yml b/ui_patterns_settings.info.yml index 0345acc..b0ea5a3 100644 --- a/ui_patterns_settings.info.yml +++ b/ui_patterns_settings.info.yml @@ -2,7 +2,7 @@ name: UI Patterns Settings type: module description: Configure patterns with settings package: User interface -core_version_requirement: ^10.2 || ^11 +core_version_requirement: ^10.3 || ^11 dependencies: - ui_patterns:ui_patterns - token:token diff --git a/ui_patterns_settings.libraries.yml b/ui_patterns_settings.libraries.yml deleted file mode 100644 index bd78124..0000000 --- a/ui_patterns_settings.libraries.yml +++ /dev/null @@ -1,12 +0,0 @@ -widget: - version: VERSION - js: - js/ui_pattern_settings.toggle_token.js: {} - css: - component: - css/ui_patterns_settings.css: {} - dependencies: - - core/jquery - - core/once - - core/drupal - - core/drupalSettings diff --git a/ui_patterns_settings.module b/ui_patterns_settings.module index e651a8f..fba211c 100644 --- a/ui_patterns_settings.module +++ b/ui_patterns_settings.module @@ -5,333 +5,3 @@ * Contains ui_patterns_settings.module. */ -use Drupal\Component\Utility\UrlHelper; -use Drupal\Core\Url; -use Drupal\field\FieldStorageConfigInterface; -use Drupal\ui_patterns_settings\Plugin\PatternSettingTypeBase; -use Drupal\ui_patterns_settings\Plugin\Layout\PatternSettingsLayout; -use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\field\Entity\FieldStorageConfig; -use Drupal\ui_patterns_settings\UiPatternsSettings; -use Drupal\ui_patterns\UiPatterns; -use Drupal\ui_patterns\Definition\PatternDefinition; -use Drupal\ui_patterns_settings\Form\SettingsFormBuilder; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Render\Element; -use Drupal\media_library\MediaLibraryUiBuilder; - -/** - * Implements hook_ui_patterns_layouts_display_settings_form_alter(). - */ -function ui_patterns_settings_ui_patterns_layouts_display_settings_form_alter(&$form, PatternDefinition $definition, $configuration) { - SettingsFormBuilder::layoutForm($form, $definition, $configuration); -} - -function ui_patterns_settings_build_media_edit_button($media_id) { - $media_entity_type = \Drupal::entityTypeManager()->getStorage('media')->getEntityType(); - $edit_template = $media_entity_type->getLinkTemplate('edit-form'); - $edit_url_query_params = [ - 'media_library_edit' => 'ajax', - 'media_library_edit_entity_id' => $media_id, - ]; - $edit_url = Url::fromUserInput(str_replace('{media}', $media_id, $edit_template) . '?' . UrlHelper::buildQuery($edit_url_query_params)); - $dialog_options = MediaLibraryUiBuilder::dialogOptions(); - return [ - '#type' => 'link', - '#title' => '', - '#url' => $edit_url, - '#attributes' => [ - 'class' => [ - 'js-media-library-edit-link', - 'media-library-edit__link', - 'use-ajax', - ], - 'target' => '_blank', - 'data-dialog-options' => json_encode([ - 'height' => $dialog_options['height'], - 'width' => $dialog_options['width'], - 'classes' => ['ui-dialog-content' => 'media-library-edit__modal'], - ]), - 'data-dialog-type' => 'dialog', - ], - '#attached' => [ - 'library' => [ - 'media_library_edit/admin', - 'core/drupal.dialog.ajax', - ], - ], - ]; - -} -/** - * Implements hook_preprocess_media_library_element(). - */ -function ui_patterns_settings_preprocess_media_library_element(&$variables) { - $element = $variables['element']; - if (isset($element['#ui_patterns_media_edit_button']) && !empty($element['#value']) && isset($variables['content']['selection'])) { - foreach (Element::children($variables['content']['selection']) as $child) { - $selection = &$variables['content']['selection'][$child]; - $media_id = $selection['preview']['target_id']['#value'] ?? NULL; - if ($media_id !== NULL) { - // Remove js-media-library-item - if (($key = array_search('js-media-library-item', $selection['#attributes']['class'])) !== false) { - unset($selection['#attributes']['class'][$key]); - } - $selection['media_edit'] = ui_patterns_settings_build_media_edit_button($media_id); - } - } - - } -} - -/** - * Implements hook_form_FORM_ID_alter() for 'field_config_edit_form'. - */ -function ui_patterns_settings_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state): void { - /** @var \Drupal\field\Entity\FieldStorageConfig $entity */ - $entity = $form_state->getFormObject()->getEntity()->getFieldStorageDefinition(); - array_unshift($form['actions']['submit']['#submit'], 'ui_patterns_settings_form_field_config_edit_form_submit'); - - $definitions = UiPatterns::getPatternDefinitions(); - $settings_options = []; - foreach ($definitions as $definition) { - $infos = UiPatternsSettings::getExposedPatternDefinition($definition, $entity->getType()); - foreach ($infos as $key => $info) { - $settings_options[$key] = $info['label']; - } - } - - if (count($settings_options) > 0) { - $parent = &$form['field_storage']['subform']; - $mapping = UiPatternsSettings::getConfigManager()->getMapping($entity->id()); - $parent['settings']['use_pattern'] = [ - '#type' => 'checkbox', - '#title' => t('Expose pattern setting'), - '#default_value' => $mapping !== NULL, - '#description' => '', - ]; - - $parent['settings']['pattern_setting'] = [ - '#type' => 'select', - '#options' => $settings_options, - '#title' => 'Pattern Setting', - '#states' => [ - 'invisible' => [ - ':input[name$="[use_pattern]"]' => ['checked' => FALSE], - ], - ], - '#default_value' => $mapping, - ]; - } -} - -/** - * Form submit callback. - */ -function ui_patterns_settings_form_field_config_edit_form_submit(array $form, FormStateInterface $form_state) { - $settings = $form_state->getValue(['field_storage', 'subform', 'settings']); - $entity = $form_state->getFormObject()->getEntity()->getFieldStorageDefinition(); - \assert($entity instanceof FieldStorageConfigInterface); - - if (isset($settings['use_pattern']) && $settings['use_pattern'] === 1) { - UiPatternsSettings::getConfigManager()->addMapping($entity->id(), $settings['pattern_setting']); - } - else { - UiPatternsSettings::getConfigManager()->addMapping($entity->id(), NULL); - } - -} - -/** - * Implements hook_entity_field_storage_info_alter(). - */ -function ui_patterns_settings_entity_field_storage_info_alter(&$fields, EntityTypeInterface $entity_type) { - /** @var \Drupal\field\Entity\FieldStorageConfig $field */ - foreach ($fields as $field) { - if ($field instanceof FieldStorageConfig) { - if (($mapping = UiPatternsSettings::getConfigManager() - ->getMapping($field->id())) !== NULL) { - [$pattern_id, $setting_id] = explode('::', $mapping); - try { - $pattern_definition = UiPatterns::getPatternDefinition($pattern_id); - $settings_definition = UiPatternsSettings::getPatternDefinitionSetting($pattern_definition, $setting_id); - if ($pattern_definition !== NULL - && $settings_definition !== NULL - ) { - $type = UiPatternsSettings::createSettingType($pattern_definition, $settings_definition); - $type->alterFieldStorage($field); - } - elseif ($pattern_definition !== NULL && $setting_id === 'variant') { - $field->setSetting('allowed_values_function', 'ui_patterns_settings_allowed_values_function'); - } - else { - \Drupal::messenger()->addError('No pattern setting %setting found'); - } - } catch (\Exception $e) { - \Drupal::messenger()->addError($e->getMessage()); - } - } - } - } -} - -/** - * The storage config. - * - * @param \Drupal\field\Entity\FieldStorageConfig $storage_config - * The field storage config. - * - * @return string[] - * The allowed list of the enumeration. - */ -function ui_patterns_settings_allowed_values_function(FieldStorageConfig $storage_config) { - [$pattern, $setting_key] = explode('::', UiPatternsSettings::getConfigManager()->getMapping($storage_config->id())); - $pattern_definition = UiPatterns::getPatternDefinition($pattern); - $settings_definition = UiPatternsSettings::getPatternDefinitionSetting($pattern_definition, $setting_key); - if ($pattern_definition !== NULL && $settings_definition !== NULL) { - return $settings_definition->getOptions(); - } - elseif ($pattern_definition !== NULL && $setting_key === 'variant') { - return $pattern_definition->getVariantsAsOptions(); - } - return []; -} - -/** - * Implements hook_ui_patterns_display_form_alter(). - */ -function ui_patterns_settings_ui_patterns_display_settings_form_alter(array &$form, $configuration) { - SettingsFormBuilder::displayForm($form, $configuration); -} - -/** - * Preprocess hook. - * - * @param array $variables - * Theme variables. - */ -function ui_patterns_settings_preprocess_field__pattern_ds_field_template(array &$variables) { - $pattern_id = $variables['ds-config']['settings']['pattern']; - $settings = $variables['ds-config']['settings']['pattern_settings'][$pattern_id] ?? NULL; - foreach ($variables['items'] as $delta => $item) { - $variables['pattern']['pattern_' . $delta]['#settings'] = $settings; - } -} - -/** - * Preprocess variables for the pattern_views_row theme hook. - * - * @param array $variables - * Theme variables. - */ -function ui_patterns_settings_preprocess_pattern_views_row(array &$variables) { - $pattern_id = $variables['options']['pattern']; - $settings = $variables['options']['pattern_settings'][$pattern_id] ?? NULL; - $variables['pattern']['#settings'] = $settings; -} - -/** - * Implements hook_element_info_alter(). - */ -function ui_patterns_settings_element_info_alter(array &$info) { - - foreach ($info as &$elm) { - if (isset($elm['#process'])) { - array_unshift($elm['#process'], [ - PatternSettingTypeBase::class, - "formGroupProcess", - ]); - } - } - - if (isset($info['pattern'])) { - $info['pattern']['#pre_render'][] = [ - "Drupal\ui_patterns_settings\Element\PatternSettings", - "processSettings", - ]; - } - - if (isset($info['pattern_preview'])) { - $info['pattern_preview']['#pre_render'][] = [ - "Drupal\ui_patterns_settings\Element\PatternSettings", - "processPreviewSettings", - ]; - } - -} - -/** - * Implements hook_theme_registry_alter(). - * - * Add settings variables to the pattern theme. - */ -function ui_patterns_settings_theme_registry_alter(&$theme_registry) { - foreach (UiPatterns::getManager()->getPatterns() as $pattern) { - $definition = $pattern->getPluginDefinition(); - if (isset($theme_registry['pattern_' . $definition->id()])) { - $settings = UiPatternsSettings::getPatternDefinitionSettings($definition); - foreach ($settings as $key => $setting) { - $theme_registry['pattern_' . $definition->id()]['variables'][$key] = NULL; - } - } - } -} - -/** - * Implements hook_field_group_build_pre_render_alter(). - */ -function ui_patterns_settings_field_group_pre_render_alter(&$element, $group, $rendering_object) { - if (!isset($group->format_settings['pattern'])) { - return; - } - - $pattern_id = $group->format_settings['pattern'] ?? NULL; - $element['#settings'] = $group->format_settings['pattern_settings'][$pattern_id] ?? NULL; - $element['#variant'] = $group->format_settings['pattern_variant'] ?? NULL; - if (!empty($group->format_settings['variants_token'])) { - $element['#variant_token'] = $group->format_settings['variants_token'][$pattern_id] ?? NULL; - } -} - -/** - * Returns true if current route is a layout builder route. - * - * @return bool - * True if is layout builder route - */ -function ui_patterns_settings_is_layout_builder_route() { - $route_name = \Drupal::routeMatch()->getRouteName(); - if (preg_match('/^(layout_builder\.([^.]+\.)?)/', $route_name)) { - return TRUE; - } - else { - return FALSE; - } -} - -/** - * Implements hook_layout_alter(). - */ -function ui_patterns_settings_layout_alter(&$definitions) { - /** @var \Drupal\Core\Layout\LayoutDefinition $definition */ - foreach ($definitions as $definition) { - if ($definition->getClass() == '\Drupal\ui_patterns_layouts\Plugin\Layout\PatternLayout') { - $definition->setClass(PatternSettingsLayout::class); - } - } -} - -/** - * Implements hook_ui_patterns_info_alter(). - */ -function ui_patterns_settings_ui_patterns_info_alter(&$definitions) { - /** @var PatternDefinition $definition */ - foreach ($definitions as $definition) { - $settings = UiPatternsSettings::getPatternDefinitionSettings($definition); - foreach ($settings as $setting) { - if ($setting->getExposeAsField()) { - $definition->setField($setting->getName(), $setting->getLabel()); - } - } - } -} diff --git a/ui_patterns_settings.services.yml b/ui_patterns_settings.services.yml index 6eaffc5..ad189dd 100644 --- a/ui_patterns_settings.services.yml +++ b/ui_patterns_settings.services.yml @@ -1,14 +1 @@ -services: - plugin.manager.ui_patterns_settings: - class: Drupal\ui_patterns_settings\UiPatternsSettingsManager - arguments: ['@container.namespaces', '@module_handler', '@cache.discovery'] - plugin.manager.ui_patterns_settings_data_provider: - class: Drupal\ui_patterns_settings\UiPatternsSettingsDataProviderManager - parent: default_plugin_manager - ui_patterns_settings.twig: - class: Drupal\ui_patterns_settings\TwigExtension\UIPatternsSettingsExtension - tags: - - { name: twig.extension } - ui_patterns_settings.config_manager: - class: Drupal\ui_patterns_settings\ConfigManager - arguments: ['@config.factory'] +services: {} -- GitLab