Skip to content
Snippets Groups Projects
Commit 73d0110d authored by GitLab CI's avatar GitLab CI
Browse files

Merge branch 'develop' into 'main'

Merging develop into main

See merge request !382
parents 2557bdd7 01d2ac85
No related branches found
No related tags found
1 merge request!382Merging develop into main
Pipeline #1383950 passed
Showing
with 0 additions and 4326 deletions
This diff is collapsed.
diff --git a/core/lib/Drupal/Core/Layout/LayoutDefault.php b/core/lib/Drupal/Core/Layout/LayoutDefault.php
index bd3780987a..8fc99d76ea 100644
--- a/core/lib/Drupal/Core/Layout/LayoutDefault.php
+++ b/core/lib/Drupal/Core/Layout/LayoutDefault.php
@@ -8,6 +8,7 @@
use Drupal\Core\Plugin\ContextAwarePluginTrait;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\Core\Plugin\PluginWithFormsTrait;
use Drupal\Core\Plugin\PreviewAwarePluginInterface;
/**
@@ -17,6 +18,7 @@ class LayoutDefault extends PluginBase implements LayoutInterface, PluginFormInt
use ContextAwarePluginAssignmentTrait;
use ContextAwarePluginTrait;
+ use PluginWithFormsTrait;
/**
* Whether the plugin is being rendered in preview mode.
@@ -127,6 +129,13 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['label'] = $form_state->getValue('label');
}
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormClass($operation) {
+ return $this->getPluginDefinition()->get('forms')[$operation] ?? static::class;
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/core/lib/Drupal/Core/Layout/LayoutInterface.php b/core/lib/Drupal/Core/Layout/LayoutInterface.php
index 33858a546d..2e62ba85da 100644
--- a/core/lib/Drupal/Core/Layout/LayoutInterface.php
+++ b/core/lib/Drupal/Core/Layout/LayoutInterface.php
@@ -7,11 +7,12 @@
use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\PluginWithFormsInterface;
/**
* Provides an interface for static Layout plugins.
*/
-interface LayoutInterface extends PluginInspectionInterface, DerivativeInspectionInterface, ConfigurableInterface, DependentPluginInterface, ContextAwarePluginInterface {
+interface LayoutInterface extends PluginInspectionInterface, DerivativeInspectionInterface, ConfigurableInterface, DependentPluginInterface, ContextAwarePluginInterface, PluginWithFormsInterface {
/**
* Build a render array for layout with regions.
diff --git a/core/modules/layout_builder/src/Controller/ChooseSectionController.php b/core/modules/layout_builder/src/Controller/ChooseSectionController.php
index 46b969e2f8..bc22d1f004 100644
--- a/core/modules/layout_builder/src/Controller/ChooseSectionController.php
+++ b/core/modules/layout_builder/src/Controller/ChooseSectionController.php
@@ -4,8 +4,10 @@
use Drupal\Core\Ajax\AjaxHelperTrait;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Layout\LayoutInterface;
use Drupal\Core\Layout\LayoutPluginManagerInterface;
use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\Core\Plugin\PluginWithFormsInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
@@ -52,6 +54,23 @@ public static function create(ContainerInterface $container) {
);
}
+ /**
+ * Determines if the layout provides a configuration form.
+ *
+ * @param \Drupal\Core\Layout\LayoutInterface $layout
+ * The layout plugin.
+ *
+ * @return bool
+ * TRUE if the layout has a configure form, FALSE otherwise.
+ */
+ protected function hasConfigurationForm(LayoutInterface $layout) {
+ if ($layout instanceof PluginWithFormsInterface && $layout->hasFormClass('configure')) {
+ return TRUE;
+ }
+
+ return $layout instanceof PluginFormInterface;
+ }
+
/**
* Choose a layout plugin to add as a section.
*
@@ -78,7 +97,7 @@ public function build(SectionStorageInterface $section_storage, int $delta) {
],
],
'#url' => Url::fromRoute(
- $layout instanceof PluginFormInterface ? 'layout_builder.configure_section' : 'layout_builder.add_section',
+ $this->hasConfigurationForm($layout) ? 'layout_builder.configure_section' : 'layout_builder.add_section',
[
'section_storage_type' => $section_storage->getStorageType(),
'section_storage' => $section_storage->getStorageId(),
diff --git a/core/modules/layout_builder/src/Element/LayoutBuilder.php b/core/modules/layout_builder/src/Element/LayoutBuilder.php
index 451927e540..8234a476ab 100644
--- a/core/modules/layout_builder/src/Element/LayoutBuilder.php
+++ b/core/modules/layout_builder/src/Element/LayoutBuilder.php
@@ -3,8 +3,10 @@
namespace Drupal\layout_builder\Element;
use Drupal\Core\Ajax\AjaxHelperTrait;
+use Drupal\Core\Layout\LayoutInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\Core\Plugin\PluginWithFormsInterface;
use Drupal\Core\Render\Attribute\RenderElement;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\RenderElement as RenderElementBase;
@@ -325,6 +327,7 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s
$build['#attributes']['class'][] = 'layout-builder__layout';
$build['#attributes']['data-layout-builder-highlight-id'] = $this->sectionUpdateHighlightId($delta);
+ $has_configure_form = $this->hasConfigurationForm($layout);
return [
'#type' => 'container',
'#attributes' => [
@@ -354,12 +357,12 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s
// link, and is only visible when the move block dialog is open.
'section_label' => [
'#markup' => $this->t('<span class="layout-builder__section-label" aria-hidden="true">@section</span>', ['@section' => $section_label]),
- '#access' => !$layout instanceof PluginFormInterface,
+ '#access' => !$has_configure_form,
],
'configure' => [
'#type' => 'link',
'#title' => $this->t('Configure @section', ['@section' => $section_label]),
- '#access' => $layout instanceof PluginFormInterface,
+ '#access' => $has_configure_form,
'#url' => Url::fromRoute('layout_builder.configure_section', [
'section_storage_type' => $storage_type,
'section_storage' => $storage_id,
@@ -379,4 +382,21 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s
];
}
+ /**
+ * Determines if the layout provides a configuration form.
+ *
+ * @param \Drupal\Core\Layout\LayoutInterface $layout
+ * The layout plugin.
+ *
+ * @return bool
+ * TRUE if the layout has a configure form, FALSE otherwise.
+ */
+ protected function hasConfigurationForm(LayoutInterface $layout) {
+ if ($layout instanceof PluginWithFormsInterface && $layout->hasFormClass('configure')) {
+ return TRUE;
+ }
+
+ return $layout instanceof PluginFormInterface;
+ }
+
}
diff --git a/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module b/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module
index fa027a6b01..443bbcfdfa 100644
--- a/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module
+++ b/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module
@@ -13,6 +13,7 @@
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
+use Drupal\layout_builder_test\PluginForm\CustomLayoutForm;
/**
* Implements hook_plugin_filter_TYPE__CONSUMER_alter().
@@ -177,6 +178,27 @@ function layout_builder_test_module_implements_alter(&$implementations, $hook) {
}
}
+/**
+ * Implements hook_layout_alter().
+ */
+function layout_builder_test_layout_alter(&$definitions) {
+ /** @var \Drupal\Core\Layout\LayoutDefinition[] $definitions */
+ $forms['configure'] = CustomLayoutForm::class;
+ $definitions['layout_builder_test_no_form_plugin']->set('forms', $forms);
+ if (isset($definitions['layout_test_plugin'])) {
+ $definitions['layout_test_plugin']->set('forms', $forms);
+ }
+}
+
+/**
+ * Implements hook_preprocess_HOOK() for layout templates.
+ */
+function layout_builder_test_preprocess_layout(&$variables) {
+ if (isset($variables['settings']['custom_element'])) {
+ $variables['content']['main']['custom_element']['#markup'] = $variables['settings']['custom_element'];
+ }
+}
+
/**
* Implements hook_theme().
*/
diff --git a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
index 631159a8b3..24f0ff05e7 100644
--- a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
+++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
@@ -458,6 +458,46 @@ public function testPreviewAwareTemplates() {
$assert_session->pageTextNotContains('This is a preview, indeed');
}
+ /**
+ * Tests a layout with a custom form.
+ */
+ public function testCustomForm() {
+ $assert_session = $this->assertSession();
+ $page = $this->getSession()->getPage();
+
+ $this->drupalLogin($this->drupalCreateUser(['configure any layout']));
+
+ LayoutBuilderEntityViewDisplay::load('node.bundle_with_section_field.default')
+ ->enableLayoutBuilder()
+ ->setOverridable()
+ ->save();
+
+ $this->drupalGet('node/1');
+ $page->clickLink('Layout');
+
+ // Test a custom plugin form that is specified by the plugin annotation.
+ $page->clickLink('Add section');
+ $page->clickLink('Layout Builder Test Custom Form Plugin');
+ $page->fillField('layout_settings[custom_element]', 'This is a custom form specified by the plugin');
+ $page->pressButton('Add section');
+ $assert_session->pageTextContains('This is a custom form specified by the plugin');
+
+ // Test a custom plugin form that is altered onto a plugin that has no form.
+ $page->clickLink('Add section');
+ $page->clickLink('Layout Builder Test No Form Plugin');
+ $page->fillField('layout_settings[custom_element]', 'This had no form now it does');
+ $page->pressButton('Add section');
+ $assert_session->pageTextContains('This had no form now it does');
+
+ // Test a custom plugin form that is altered onto a plugin that has an
+ // existing form.
+ $page->clickLink('Add section');
+ $page->clickLink('Layout Builder Test No Form Plugin');
+ $page->fillField('layout_settings[custom_element]', 'This had an existing form now it has more');
+ $page->pressButton('Add section');
+ $assert_session->pageTextContains('This had an existing form now it has more');
+ }
+
/**
* Tests that extra fields work before and after enabling Layout Builder.
*/
diff --git a/core/lib/Drupal/Core/Layout/LayoutDefault.php b/core/lib/Drupal/Core/Layout/LayoutDefault.php
index 607b34a48cd91bf740f3e6eda563a8de8b659467..bb97f8b42ffd61d185ed25eab2d91b12dc91c3d5 100644
--- a/core/lib/Drupal/Core/Layout/LayoutDefault.php
+++ b/core/lib/Drupal/Core/Layout/LayoutDefault.php
@@ -8,6 +8,7 @@
use Drupal\Core\Plugin\ContextAwarePluginTrait;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\Core\Plugin\PluginWithFormsTrait;
use Drupal\Core\Plugin\PreviewAwarePluginInterface;
/**
@@ -17,6 +18,7 @@ class LayoutDefault extends PluginBase implements LayoutInterface, PluginFormInt
use ContextAwarePluginAssignmentTrait;
use ContextAwarePluginTrait;
+ use PluginWithFormsTrait;
/**
* Whether the plugin is being rendered in preview mode.
@@ -126,6 +128,13 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
$this->configuration['label'] = $form_state->getValue('label');
}
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormClass($operation) {
+ return $this->getPluginDefinition()->get('forms')[$operation] ?? static::class;
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/core/lib/Drupal/Core/Layout/LayoutInterface.php b/core/lib/Drupal/Core/Layout/LayoutInterface.php
index 33858a546d7fc0f2696c408873f4b9bf51cb9b7c..2e62ba85da65ed7029abd5df9571348e9bfcd7fa 100644
--- a/core/lib/Drupal/Core/Layout/LayoutInterface.php
+++ b/core/lib/Drupal/Core/Layout/LayoutInterface.php
@@ -7,11 +7,12 @@
use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\Plugin\PluginWithFormsInterface;
/**
* Provides an interface for static Layout plugins.
*/
-interface LayoutInterface extends PluginInspectionInterface, DerivativeInspectionInterface, ConfigurableInterface, DependentPluginInterface, ContextAwarePluginInterface {
+interface LayoutInterface extends PluginInspectionInterface, DerivativeInspectionInterface, ConfigurableInterface, DependentPluginInterface, ContextAwarePluginInterface, PluginWithFormsInterface {
/**
* Build a render array for layout with regions.
diff --git a/core/modules/layout_builder/src/Controller/ChooseSectionController.php b/core/modules/layout_builder/src/Controller/ChooseSectionController.php
index 46b969e2f8ba15a75da1be3b0f9a3bb71f30e138..bc22d1f004b7a828155a811758026e7d631a1ed9 100644
--- a/core/modules/layout_builder/src/Controller/ChooseSectionController.php
+++ b/core/modules/layout_builder/src/Controller/ChooseSectionController.php
@@ -4,8 +4,10 @@
use Drupal\Core\Ajax\AjaxHelperTrait;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Layout\LayoutInterface;
use Drupal\Core\Layout\LayoutPluginManagerInterface;
use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\Core\Plugin\PluginWithFormsInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
@@ -52,6 +54,23 @@ public static function create(ContainerInterface $container) {
);
}
+ /**
+ * Determines if the layout provides a configuration form.
+ *
+ * @param \Drupal\Core\Layout\LayoutInterface $layout
+ * The layout plugin.
+ *
+ * @return bool
+ * TRUE if the layout has a configure form, FALSE otherwise.
+ */
+ protected function hasConfigurationForm(LayoutInterface $layout) {
+ if ($layout instanceof PluginWithFormsInterface && $layout->hasFormClass('configure')) {
+ return TRUE;
+ }
+
+ return $layout instanceof PluginFormInterface;
+ }
+
/**
* Choose a layout plugin to add as a section.
*
@@ -78,7 +97,7 @@ public function build(SectionStorageInterface $section_storage, int $delta) {
],
],
'#url' => Url::fromRoute(
- $layout instanceof PluginFormInterface ? 'layout_builder.configure_section' : 'layout_builder.add_section',
+ $this->hasConfigurationForm($layout) ? 'layout_builder.configure_section' : 'layout_builder.add_section',
[
'section_storage_type' => $section_storage->getStorageType(),
'section_storage' => $section_storage->getStorageId(),
diff --git a/core/modules/layout_builder/src/Element/LayoutBuilder.php b/core/modules/layout_builder/src/Element/LayoutBuilder.php
index 5c91b1e39208a7895c6cb664c1f5e793c8d9522c..e8c83d975fd37c8c80af9f97b0fd47c942f1f615 100644
--- a/core/modules/layout_builder/src/Element/LayoutBuilder.php
+++ b/core/modules/layout_builder/src/Element/LayoutBuilder.php
@@ -3,8 +3,10 @@
namespace Drupal\layout_builder\Element;
use Drupal\Core\Ajax\AjaxHelperTrait;
+use Drupal\Core\Layout\LayoutInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\Core\Plugin\PluginWithFormsInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\RenderElement;
use Drupal\Core\Url;
@@ -337,6 +339,7 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s
$build['#attributes']['class'][] = 'layout-builder__layout';
$build['#attributes']['data-layout-builder-highlight-id'] = $this->sectionUpdateHighlightId($delta);
+ $has_configure_form = $this->hasConfigurationForm($layout);
return [
'#type' => 'container',
'#attributes' => [
@@ -366,12 +369,12 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s
// link, and is only visible when the move block dialog is open.
'section_label' => [
'#markup' => $this->t('<span class="layout-builder__section-label" aria-hidden="true">@section</span>', ['@section' => $section_label]),
- '#access' => !$layout instanceof PluginFormInterface,
+ '#access' => !$has_configure_form,
],
'configure' => [
'#type' => 'link',
'#title' => $this->t('Configure @section', ['@section' => $section_label]),
- '#access' => $layout instanceof PluginFormInterface,
+ '#access' => $has_configure_form,
'#url' => Url::fromRoute('layout_builder.configure_section', [
'section_storage_type' => $storage_type,
'section_storage' => $storage_id,
@@ -391,4 +394,21 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s
];
}
+ /**
+ * Determines if the layout provides a configuration form.
+ *
+ * @param \Drupal\Core\Layout\LayoutInterface $layout
+ * The layout plugin.
+ *
+ * @return bool
+ * TRUE if the layout has a configure form, FALSE otherwise.
+ */
+ protected function hasConfigurationForm(LayoutInterface $layout) {
+ if ($layout instanceof PluginWithFormsInterface && $layout->hasFormClass('configure')) {
+ return TRUE;
+ }
+
+ return $layout instanceof PluginFormInterface;
+ }
+
}
diff --git a/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module b/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module
index cd6070f53ff33d4f20ef609513ff335c57b63c60..8b6b00419be68eb7d48072f6e0d223f25f9c400c 100644
--- a/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module
+++ b/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module
@@ -13,6 +13,7 @@
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
+use Drupal\layout_builder_test\PluginForm\CustomLayoutForm;
/**
* Implements hook_plugin_filter_TYPE__CONSUMER_alter().
@@ -131,3 +132,24 @@ function layout_builder_test_module_implements_alter(&$implementations, $hook) {
] + $implementations;
}
}
+
+/**
+ * Implements hook_layout_alter().
+ */
+function layout_builder_test_layout_alter(&$definitions) {
+ /** @var \Drupal\Core\Layout\LayoutDefinition[] $definitions */
+ $forms['configure'] = CustomLayoutForm::class;
+ $definitions['layout_builder_test_no_form_plugin']->set('forms', $forms);
+ if (isset($definitions['layout_test_plugin'])) {
+ $definitions['layout_test_plugin']->set('forms', $forms);
+ }
+}
+
+/**
+ * Implements hook_preprocess_HOOK() for layout templates.
+ */
+function layout_builder_test_preprocess_layout(&$variables) {
+ if (isset($variables['settings']['custom_element'])) {
+ $variables['content']['main']['custom_element']['#markup'] = $variables['settings']['custom_element'];
+ }
+}
diff --git a/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/Layout/LayoutBuilderTestCustomFormPlugin.php b/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/Layout/LayoutBuilderTestCustomFormPlugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..059a3eb4d8847695d1cbc02fee806c72b9cf94d6
--- /dev/null
+++ b/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/Layout/LayoutBuilderTestCustomFormPlugin.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\layout_builder_test\Plugin\Layout;
+
+use Drupal\Core\Layout\LayoutDefault;
+
+/**
+ * @Layout(
+ * id = "layout_builder_test_custom_form_plugin",
+ * label = @Translation("Layout Builder Test Custom Form Plugin"),
+ * regions = {
+ * "main" = {
+ * "label" = @Translation("Main Region")
+ * }
+ * },
+ * forms = {
+ * "configure" = "Drupal\layout_builder_test\PluginForm\CustomLayoutForm",
+ * },
+ * )
+ */
+class LayoutBuilderTestCustomFormPlugin extends LayoutDefault {
+
+}
diff --git a/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/Layout/LayoutBuilderTestNoFormPlugin.php b/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/Layout/LayoutBuilderTestNoFormPlugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..4cef17f51f56591ab331a465274c6fc8e241adc3
--- /dev/null
+++ b/core/modules/layout_builder/tests/modules/layout_builder_test/src/Plugin/Layout/LayoutBuilderTestNoFormPlugin.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace Drupal\layout_builder_test\Plugin\Layout;
+
+use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Layout\LayoutInterface;
+use Drupal\Core\Plugin\PluginBase;
+use Drupal\Core\Plugin\PluginWithFormsTrait;
+
+/**
+ * Provides a plugin that does not extend \Drupal\Core\Layout\LayoutDefault.
+ *
+ * @Layout(
+ * id = "layout_builder_test_no_form_plugin",
+ * label = @Translation("Layout Builder Test No Form Plugin"),
+ * regions = {
+ * "main" = {
+ * "label" = @Translation("Main Region")
+ * }
+ * },
+ * )
+ */
+class LayoutBuilderTestNoFormPlugin extends PluginBase implements LayoutInterface {
+
+ use PluginWithFormsTrait;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function build(array $regions) {
+ $build = $regions;
+ $build['#settings'] = $this->getConfiguration();
+ $build['#layout'] = $this->pluginDefinition;
+ $build['#theme'] = $this->pluginDefinition->getThemeHook();
+ return $build;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getConfiguration() {
+ return $this->configuration;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function setConfiguration(array $configuration) {
+ $this->configuration = NestedArray::mergeDeep($this->defaultConfiguration(), $configuration);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function defaultConfiguration() {
+ return [
+ 'label' => '',
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ return [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormClass($operation) {
+ return $this->getPluginDefinition()->get('forms')[$operation] ?? NULL;
+ }
+
+}
diff --git a/core/modules/layout_builder/tests/modules/layout_builder_test/src/PluginForm/CustomLayoutForm.php b/core/modules/layout_builder/tests/modules/layout_builder_test/src/PluginForm/CustomLayoutForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..8499f8bde1faa443b4d8220f50599d92c43291c2
--- /dev/null
+++ b/core/modules/layout_builder/tests/modules/layout_builder_test/src/PluginForm/CustomLayoutForm.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\layout_builder_test\PluginForm;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\PluginFormBase;
+use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Provides a custom form for a layout plugin.
+ */
+class CustomLayoutForm extends PluginFormBase {
+
+ use StringTranslationTrait;
+
+ /**
+ * The plugin.
+ *
+ * @var \Drupal\Core\Layout\LayoutInterface
+ */
+ protected $plugin;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+ $form = $this->plugin instanceof PluginFormInterface ? $this->plugin->buildConfigurationForm($form, $form_state) : [];
+ $form['custom_element'] = [
+ '#title' => $this->t('Custom element'),
+ '#type' => 'textfield',
+ '#default_value' => $this->plugin->getConfiguration()['custom_element'] ?? '',
+ ];
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+ if ($this->plugin instanceof PluginFormInterface) {
+ $this->plugin->submitConfigurationForm($form, $form_state);
+ }
+ $configuration = $this->plugin->getConfiguration();
+ $configuration['custom_element'] = $form_state->getValue('custom_element');
+ $this->plugin->setConfiguration($configuration);
+ }
+
+}
diff --git a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
index f135ac4cb17ca6155dde107c2a04205677e82a5d..ec692e9b45cd777fdc324a366aaf7a89f6614a68 100644
--- a/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
+++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
@@ -963,6 +963,46 @@ public function testLayoutBuilderChooseBlocksAlter() {
$assert_session->linkExists('Changed');
}
+ /**
+ * Tests a layout with a custom form.
+ */
+ public function testCustomForm() {
+ $assert_session = $this->assertSession();
+ $page = $this->getSession()->getPage();
+
+ $this->drupalLogin($this->drupalCreateUser(['configure any layout']));
+
+ LayoutBuilderEntityViewDisplay::load('node.bundle_with_section_field.default')
+ ->enableLayoutBuilder()
+ ->setOverridable()
+ ->save();
+
+ $this->drupalGet('node/1');
+ $page->clickLink('Layout');
+
+ // Test a custom plugin form that is specified by the plugin annotation.
+ $page->clickLink('Add section');
+ $page->clickLink('Layout Builder Test Custom Form Plugin');
+ $page->fillField('layout_settings[custom_element]', 'This is a custom form specified by the plugin');
+ $page->pressButton('Add section');
+ $assert_session->pageTextContains('This is a custom form specified by the plugin');
+
+ // Test a custom plugin form that is altered onto a plugin that has no form.
+ $page->clickLink('Add section');
+ $page->clickLink('Layout Builder Test No Form Plugin');
+ $page->fillField('layout_settings[custom_element]', 'This had no form now it does');
+ $page->pressButton('Add section');
+ $assert_session->pageTextContains('This had no form now it does');
+
+ // Test a custom plugin form that is altered onto a plugin that has an
+ // existing form.
+ $page->clickLink('Add section');
+ $page->clickLink('Layout Builder Test No Form Plugin');
+ $page->fillField('layout_settings[custom_element]', 'This had an existing form now it has more');
+ $page->pressButton('Add section');
+ $assert_session->pageTextContains('This had an existing form now it has more');
+ }
+
/**
* Tests that extra fields work before and after enabling Layout Builder.
*/
diff --git a/src/ConfigReverter.php b/src/ConfigReverter.php
index 90d046b8bff50f6cac969a433604a6af79de4674..81395829023ae89f07a20b3cea7734ae8786e78f 100644
--- a/src/ConfigReverter.php
+++ b/src/ConfigReverter.php
@@ -2,6 +2,7 @@
namespace Drupal\config_update;
+use Drupal\Component\Utility\Crypt;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
@@ -108,11 +109,12 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
// Save it as a new config entity or simple config.
if ($type === 'system.simple') {
- $this->configFactory->getEditable($full_name)->setData($value)->save();
+ $this->configFactory->getEditable($full_name)->setData($value)->set('_core', ['default_config_hash' => Crypt::hashBase64(serialize($value))])->save();
}
else {
$entity_storage = $this->entityManager->getStorage($type);
$entity = $entity_storage->createFromStorageRecord($value);
+ $entity->set('_core', ['default_config_hash' => Crypt::hashBase64(serialize($value))]);
$entity->save();
}
@@ -156,10 +158,9 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
// hash (which is part of the _core config key's value).
if ($type === 'system.simple') {
$config = $this->configFactory->getEditable($full_name);
- $core = $config->get('_core');
$config
->setData($value)
- ->set('_core', $core)
+ ->set('_core', ['default_config_hash' => Crypt::hashBase64(serialize($value))])
->save();
}
else {
@@ -168,9 +169,8 @@ class ConfigReverter implements ConfigRevertInterface, ConfigDeleteInterface {
$id = $value[$id_key];
$entity_storage = $this->entityManager->getStorage($type);
$entity = $entity_storage->load($id);
- $core = $entity->get('_core');
$entity = $entity_storage->updateFromStorageRecord($entity, $value);
- $entity->set('_core', $core);
+ $entity->set('_core', ['default_config_hash' => Crypt::hashBase64(serialize($value))]);
$entity->save();
}
diff --git a/src/EntityImportSourceManager.php b/src/EntityImportSourceManager.php
index eec012051537b67e4079a6d0886c9fdb81620fc5..29c8668a97335ab75798f6521d7bb0e480b8cf00 100644
--- a/src/EntityImportSourceManager.php
+++ b/src/EntityImportSourceManager.php
@@ -78,6 +78,7 @@ class EntityImportSourceManager implements EntityImportSourceManagerInterface {
protected function getDefinitions() {
$definitions = [];
+ require_once 'core/modules/content_translation/src/Plugin/migrate/source/I18nQueryTrait.php';
foreach ($this->migrateSourceManager->getDefinitions() as $plugin_id => $definition) {
$interface = 'Drupal\entity_import\Plugin\migrate\source\EntityImportSourceInterface';
diff --git a/src/BookExport.php b/src/BookExport.php
index d130610b..edcf8541 100644
--- a/src/BookExport.php
+++ b/src/BookExport.php
@@ -131,7 +131,6 @@ class BookExport {
*/
protected function bookNodeExport(NodeInterface $node, $children = '') {
$build = $this->viewBuilder->view($node, 'print', NULL);
- unset($build['#theme']);
return [
'#theme' => 'book_node_export_html',
diff --git a/architect.info.yml b/architect.info.yml
index 58e1fc9b3e7d9cc4d143613a0808c98a9d07ec01..d6a66420948fb0e7e9964069ec2ed18745d68053 100644
--- a/architect.info.yml
+++ b/architect.info.yml
@@ -1,7 +1,8 @@
name: Architect
type: theme
description: the ARCHITECT Theme - A DESIGN SAVVY THEME USING UIKITTY.
-core: 8.x
+# core: 8.x
+core_version_requirement: ^8.8 || ^9
base theme: uikitty
libraries:
- architect/default
diff --git a/uikitty.info.yml b/uikitty.info.yml
index 0a44d98b8e56bf3a5065409e852d868dc8bd739c..df7117253a9b3e089023d81402ab0224b2ed264a 100644
--- a/uikitty.info.yml
+++ b/uikitty.info.yml
@@ -1,7 +1,8 @@
name: uikitty
type: theme
description: A building block theme using uikit awesomeness.
-core: 8.x
+# core: 8.x
+core_version_requirement: ^8.8 || ^9
base theme: classy
libraries:
- uikitty/global
@@ -22,4 +23,4 @@ regions:
offcanvas: 'Off-canvas'
ckeditor_stylesheets:
- - uikit/css/uikit.almost-flat.min.css
\ No newline at end of file
+ - uikit/css/uikit.almost-flat.min.css
diff --git a/uikitty.theme b/uikitty.theme
index 15609cc19631ad86d47683e8a473f3542bed957d..aa61fd2c233a61f742a7e586e5e237da8fd55025 100644
--- a/uikitty.theme
+++ b/uikitty.theme
@@ -36,5 +36,5 @@ function uikitty_theme_suggestions_menu_alter(array &$suggestions, array $variab
function uikitty_preprocess_html(&$variables) {
$current_path = \Drupal::service('path.current')->getPath();
- $variables['current_path'] = \Drupal::service('path.alias_manager')->getAliasByPath($current_path);
-}
\ No newline at end of file
+ $variables['current_path'] = \Drupal::service('path_alias.manager')->getAliasByPath($current_path);
+}
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index 9530c8fbf8..4ac5503e69 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -167,8 +167,8 @@ protected function buildTableNameCondition($table_name, $operator = '=', $add_pr
* @return bool
* TRUE if the given table exists, otherwise FALSE.
*/
- public function tableExists($table, bool $add_prefix = TRUE) {
- $condition = $this->buildTableNameCondition($table, '=', $add_prefix);
+ public function tableExists($table) {
+ $condition = $this->buildTableNameCondition($table);
$condition->compile($this->connection, $this);
// Normally, we would heartily discourage the use of string
// concatenation for conditionals like this however, we
diff --git a/content_lock.module b/content_lock.module
index 0bae073d352baebf7cb934e1243c0ad87ab61703..e11bf199b891b1019566a06104c0529054d11103 100644
--- a/content_lock.module
+++ b/content_lock.module
@@ -95,16 +95,17 @@ function content_lock_form_alter(&$form, FormStateInterface $form_state, $form_i
if ($lock_service->isJsLock($entity_type)) {
$form['#attached']['library'][] = 'content_lock/drupal.content_lock.lock_form';
+ $args = [
+ 'entity' => $entity->id(),
+ 'langcode' => $entity->language()->getId(),
+ 'form_op' => $form_op,
+ ];
$form['#attached']['drupalSettings']['content_lock'] = [
Html::cleanCssIdentifier($form_id) => [
- 'lockUrl' => Url::fromRoute('content_lock.create_lock.' . $entity_type,
- [
- 'entity' => $entity->id(),
- 'langcode' => $entity->language()->getId(),
- 'form_op' => $form_op,
- ],
- ['query' => ['destination' => Drupal::request()->getRequestUri()]]
- )->toString(),
+ 'lockUrl' => Url::fromRoute('content_lock.create_lock.' . $entity_type, $args, [
+ 'query' => ['destination' => Drupal::request()->getRequestUri()],
+ ])->toString(),
+ 'releaseUrl' => Url::fromRoute('content_lock.release_lock.' . $entity_type, $args)->toString(),
],
];
diff --git a/js/content_lock_form.js b/js/content_lock_form.js
index 2661f311e9c689cfc7bc303edd43b96c53eec6ca..58827cb7302130a213cabd1f234501570dc99363 100644
--- a/js/content_lock_form.js
+++ b/js/content_lock_form.js
@@ -73,5 +73,16 @@
});
}
};
+
+ var onBeforeUnLoadEvent = false;
+
+ window.onunload = window.onbeforeunload= function() {
+ if (!onBeforeUnLoadEvent) {
+ onBeforeUnLoadEvent = true;
+ if (typeof navigator.sendBeacon === 'function') {
+ navigator.sendBeacon(settings.releaseUrl);
+ }
+ }
+ };
};
})(jQuery, Drupal, once);
diff --git a/src/ContentLock/ContentLock.php b/src/ContentLock/ContentLock.php
index 5d6f693fc4526e0c93f8a81a7c1063ec39e69872..dea173950eda995e41d599f03d39ca02be475ca4 100644
--- a/src/ContentLock/ContentLock.php
+++ b/src/ContentLock/ContentLock.php
@@ -344,6 +344,7 @@ class ContentLock implements ContentLockInterface {
*/
public function locking($entity_id, $langcode, $form_op, $uid, $entity_type = 'node', $quiet = FALSE, $destination = NULL) {
$translation_lock = $this->isTranslationLockEnabled($entity_type);
+ $js_lock = $this->isJsLock($entity_type);
if (!$translation_lock) {
$langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED;
}
@@ -371,12 +372,20 @@ class ContentLock implements ContentLockInterface {
if ($this->verbose() && !$quiet) {
if ($translation_lock) {
- $this->messenger->addStatus($this->t('This content translation is now locked against simultaneous editing. This content translation will remain locked if you navigate away from this page without saving or unlocking it.'));
+ $message = 'This content translation is now locked against simultaneous editing.';
+ if (!$js_lock) {
+ $message .= ' This content translation will remain locked if you navigate away from this page without saving or unlocking it.';
+ }
}
else {
- $this->messenger->addStatus($this->t('This content is now locked against simultaneous editing. This content will remain locked if you navigate away from this page without saving or unlocking it.'));
+ $message = 'This content is now locked against simultaneous editing.';
+ if (!$js_lock) {
+ $message .= ' This content will remain locked if you navigate away from this page without saving or unlocking it.';
+ }
}
+ $this->messenger->addStatus($this->t($message));
}
+
// Post locking hook.
$this->moduleHandler->invokeAll('content_lock_locked', [
$entity_id,
@@ -424,11 +433,18 @@ class ContentLock implements ContentLockInterface {
// Locked by current user.
if ($this->verbose() && !$quiet) {
if ($translation_lock) {
- $this->messenger->addStatus($this->t('This content translation is now locked by you against simultaneous editing. This content translation will remain locked if you navigate away from this page without saving or unlocking it.'));
+ $message = 'This content translation is now locked by you against simultaneous editing.';
+ if (!$js_lock) {
+ $message .= ' This content translation will remain locked if you navigate away from this page without saving or unlocking it.';
+ }
}
else {
- $this->messenger->addStatus($this->t('This content is now locked by you against simultaneous editing. This content will remain locked if you navigate away from this page without saving or unlocking it.'));
+ $message = 'This content is now locked by you against simultaneous editing.';
+ if (!$js_lock) {
+ $message .= ' This content will remain locked if you navigate away from this page without saving or unlocking it.';
+ }
}
+ $this->messenger->addStatus($this->t($message));
}
// Send success flag.
diff --git a/src/Controller/ContentLockController.php b/src/Controller/ContentLockController.php
index b0270fb2242492a1f0c62c8070173f9ed7e99298..5d214cac26d4fda3edbfe33366d536a484d43379 100644
--- a/src/Controller/ContentLockController.php
+++ b/src/Controller/ContentLockController.php
@@ -5,7 +5,6 @@ namespace Drupal\content_lock\Controller;
use Drupal\content_lock\Ajax\LockFormCommand;
use Drupal\content_lock\ContentLock\ContentLockInterface;
use Drupal\Core\Ajax\AjaxResponse;
-use Drupal\Core\Ajax\AppendCommand;
use Drupal\Core\Ajax\PrependCommand;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\ContentEntityInterface;
@@ -78,19 +77,31 @@ class ContentLockController extends ControllerBase {
// Render status messages from locking service.
$response->addCommand(new PrependCommand('', ['#type' => 'status_messages']));
-
- if ($lock) {
- $language = $this->languageManager()->getLanguage($langcode);
- $url = $entity->toUrl('canonical', ['language' => $language]);
- $unlock_button = $this->lockService->unlockButton($entity->getEntityTypeId(), $entity->id(), $langcode, $form_op, $url->toString());
- $response->addCommand(new AppendCommand('.content-lock-actions.form-actions', $unlock_button));
- }
}
$response->addCommand(new LockFormCommand($lockable, $lock));
return $response;
}
+ /**
+ * Custom callback for the release lock route.
+ *
+ * @param \Symfony\Component\HttpFoundation\Request $request
+ * The current request.
+ * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+ * The locked entity.
+ * @param string $langcode
+ * The langcode.
+ * @param string $form_op
+ * The form op.
+ *
+ * @see \Drupal\content_lock\Routing\ContentLockRoutes::routes()
+ */
+ public function releaseCall(Request $request, ContentEntityInterface $entity, $langcode, $form_op) {
+ $this->lockService->release($entity->id(), $entity->language()->getId(), $form_op, $this->currentUser()->id(), $entity->getEntityTypeId());
+ return [];
+ }
+
/**
* Custom access checker for the create lock requirements route.
*
diff --git a/src/Form/ContentLockSettingsForm.php b/src/Form/ContentLockSettingsForm.php
index c5baea93f91a5321599cb13ee62bab0ac755a659..4f8e372b80d7ff213c2ab2a95c52a294949f2b52 100644
--- a/src/Form/ContentLockSettingsForm.php
+++ b/src/Form/ContentLockSettingsForm.php
@@ -184,9 +184,9 @@ class ContentLockSettingsForm extends ConfigFormBase {
$form['entities'][$definition->id()]['settings']['js_lock'] = [
'#type' => 'checkbox',
- '#title' => $this->t('Lock form using JS.'),
- '#default_value' => in_array($definition->id(), $config->get('types_js_lock') ?: []),
- '#description' => $this->t('Activating this options activates the lock when the user is on the form. This helps if modules interacting with form without a user interacting with the form, like the prefetch_cache module.'),
+ '#title' => $this->t('Lock and release form using JS.'),
+ '#default_value' => in_array($definition->id(), $config->get('types_js_lock')?: []),
+ '#description' => $this->t('Activating this options activates the lock when the user is on the form. This helps if modules interacting with form without a user interacting with the form, like the prefetch_cache module. The form is automatically released when navigating away from the page.'),
];
if (!empty($definition->getHandlerClasses()['form'])) {
diff --git a/src/Routing/ContentLockRoutes.php b/src/Routing/ContentLockRoutes.php
index a0004621619ce7f11f31bd642cf1402847fb94df..289bdff22c16b99a05ad310b3ac34dae69978b08 100644
--- a/src/Routing/ContentLockRoutes.php
+++ b/src/Routing/ContentLockRoutes.php
@@ -76,6 +76,22 @@ class ContentLockRoutes implements ContainerInjectionInterface {
],
]
);
+ $routes['content_lock.release_lock.' . $definition->id()] = new Route(
+ '/admin/lock/release/' . $definition->id() . '/{entity}/{langcode}/{form_op}',
+ [
+ '_controller' => '\Drupal\content_lock\Controller\ContentLockController::releaseCall',
+ ],
+ [
+ '_custom_access' => '\Drupal\content_lock\Controller\ContentLockController::access',
+ ],
+ [
+ 'parameters' => [
+ 'entity' => [
+ 'type' => 'entity:' . $definition->id(),
+ ],
+ ],
+ ]
+ );
}
}
return $routes;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
diff --git a/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php b/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
index 51e0acca397a35054ce08568a32d1ca76cdc8912..840478e2a98964b70b28f7f61d2fdceda4a8ffea 100644
--- a/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
+++ b/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
@@ -134,12 +134,12 @@ class InlineEntityFormSimple extends InlineEntityFormBase {
$submitted_values = $form_state->getValue($parents);
$values = [];
foreach ($items as $delta => $value) {
- if ($element = NestedArray::getValue(
- $form,
- [$field_name, 'widget', $delta]
- )) {
+ if (
+ ($element = NestedArray::getValue($form, [$field_name, 'widget', $delta]))
/** @var \Drupal\Core\Entity\EntityInterface $entity */
- $entity = $element['inline_entity_form']['#entity'];
+ && ($entity = $element['inline_entity_form']['#entity'] ?? NULL)
+ ) {
+ // @todo Can this be unset? If yes, can the '0' fallback clash?
$weight = $submitted_values[$delta]['_weight'] ?? 0;
$values[$weight] = ['entity' => $entity];
}
diff --git a/fakeobjects.install b/fakeobjects.install
index c664d41134301a481031235484bb759b7b5beae1..8f6925ce601bef811ef46598251c192c9e899eae 100644
--- a/fakeobjects.install
+++ b/fakeobjects.install
@@ -12,7 +12,7 @@ function fakeobjects_requirements($phase) {
$requirements = [];
if ($phase == 'install' || $phase == 'runtime') {
- $plugin_detected = file_exists(DRUPAL_ROOT . '/libraries/fakeobjects/plugin.js');
+ $plugin_detected = file_exists(DRUPAL_ROOT . '/libraries/ckeditor.fakeobjects/plugin.js');
if ($plugin_detected) {
$requirements['fakeobjects'] = [
@@ -26,7 +26,7 @@ function fakeobjects_requirements($phase) {
'title' => t('FakeObjects'),
'value' => t('Plugin not detected'),
'severity' => REQUIREMENT_ERROR,
- 'description' => t('Before you can use the FakeObjects module, you need to download the plugin from ckeditor.com and place it in /libraries/fakeobjects. Check the README.txt for more information. <a href=":plugin_url">Get the plugin here</a>.', [':plugin_url' => 'http://ckeditor.com/addon/fakeobjects']),
+ 'description' => t('Before you can use the FakeObjects module, you need to download the plugin from ckeditor.com and place it in /libraries/ckeditor.fakeobjects. Check the README.txt for more information. <a href=":plugin_url">Get the plugin here</a>.', [':plugin_url' => 'http://ckeditor.com/addon/fakeobjects']),
];
}
}
diff --git a/src/Plugin/CKEditorPlugin/FakeObjects.php b/src/Plugin/CKEditorPlugin/FakeObjects.php
index e405394fdc2a59be87974b0592f3fa38672b72d0..dd222dc702a9c22f635febf777a33cfc869ecbeb 100644
--- a/src/Plugin/CKEditorPlugin/FakeObjects.php
+++ b/src/Plugin/CKEditorPlugin/FakeObjects.php
@@ -19,7 +19,7 @@ class FakeObjects extends CKEditorPluginBase {
* {@inheritdoc}
*/
public function getFile() {
- return 'libraries/fakeobjects/plugin.js';
+ return 'libraries/ckeditor.fakeobjects/plugin.js';
}
/**
diff --git a/src/ConfigImporterExporter.php b/src/ConfigImporterExporter.php
index 1c0196151a0d8f0d0390e4043b27a5d0b5f7e9ca..88dc5cc47600e025e7c6a825869f92ae4f2a3e4c 100644
--- a/src/ConfigImporterExporter.php
+++ b/src/ConfigImporterExporter.php
@@ -230,7 +230,7 @@ class ConfigImporterExporter {
$written_files = [];
if ($file_names) {
- $data = $config->get();
+ $data = $config->getRawData();
$config_name = $config->getName();
unset($data['_core']);
if ($entity_type_id = $this->configManager->getEntityTypeIdByName($config_name)) {
diff --git a/src/EventSubscriber/ConfigDevelAutoExportSubscriber.php b/src/EventSubscriber/ConfigDevelAutoExportSubscriber.php
index 44dc76ecbb3de80ed6132171f9876151491a4268..406eb508aa08a00b9ddf0a399874c71e4748d7ce 100644
--- a/src/EventSubscriber/ConfigDevelAutoExportSubscriber.php
+++ b/src/EventSubscriber/ConfigDevelAutoExportSubscriber.php
@@ -98,7 +98,7 @@ class ConfigDevelAutoExportSubscriber extends ConfigDevelSubscriberBase implemen
public function writeBackConfig(Config $config, array $file_names) {
// TODO: use the config_devel.importer_exporter service.
if ($file_names) {
- $data = $config->get();
+ $data = $config->getRawData();
$config_name = $config->getName();
unset($data['_core']);
if ($entity_type_id = $this->configManager->getEntityTypeIdByName($config_name)) {
diff --git a/core/modules/book/src/Plugin/migrate/destination/Book.php b/core/modules/book/src/Plugin/migrate/destination/Book.php
index dcc5056c89af907650b90e5b02d5bb2df8531456..55496aed7fc0693a956bbfa1634a19ed2b200132 100644
--- a/core/modules/book/src/Plugin/migrate/destination/Book.php
+++ b/core/modules/book/src/Plugin/migrate/destination/Book.php
@@ -3,6 +3,7 @@
namespace Drupal\book\Plugin\migrate\destination;
use Drupal\Core\Entity\EntityInterface;
+use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
use Drupal\migrate\Row;
@@ -34,6 +35,12 @@ protected function updateEntity(EntityInterface $entity, Row $row) {
else {
$entity->book = $row->getDestinationProperty('book');
}
+ if (($mid = $entity->book['pid']) && ($menuLink = MenuLinkContent::load($mid)) && $url = $menuLink->getUrlObject()) {
+ $parameters = $url->getRouteParameters();
+ if (isset($parameters['node'])) {
+ $entity->book['pid'] = $parameters['node'];
+ }
+ }
return parent::updateEntity($entity, $row);
}
diff --git a/core/modules/menu_link_content/src/Plugin/migrate/source/MenuLink.php b/core/modules/menu_link_content/src/Plugin/migrate/source/MenuLink.php
index 1b186a6e04a18749d3ccb7e09194364c5e485c44..f28ab3ec2f46c2df995ea588f0b2b316b3380ef2 100644
--- a/core/modules/menu_link_content/src/Plugin/migrate/source/MenuLink.php
+++ b/core/modules/menu_link_content/src/Plugin/migrate/source/MenuLink.php
@@ -23,7 +23,7 @@ public function query() {
$query = $this->select('menu_links', 'ml')
->fields('ml');
$and = $query->andConditionGroup()
- ->condition('ml.module', 'menu')
+ ->condition('ml.module', ['menu', 'book'], 'IN')
->condition('ml.router_path', ['admin/build/menu-customize/%', 'admin/structure/menu/manage/%'], 'NOT IN');
$condition = $query->orConditionGroup()
->condition('ml.customized', 1)
diff --git a/ldap_authentication/ldap_authentication.module b/ldap_authentication/ldap_authentication.module
index 07ac1740eac87f464f5801babcbbda94a07102bd..3fb89b4fec4550c70d04fde73aa6f7587c5f382b 100644
--- a/ldap_authentication/ldap_authentication.module
+++ b/ldap_authentication/ldap_authentication.module
@@ -169,6 +169,11 @@ function ldap_authentication_form_user_form_alter(&$form, FormStateInterface $fo
*/
function ldap_authentication_show_password_field($user = NULL): bool {
+ $config = \Drupal::config('ldap_authentication.settings');
+ if ($config->get('authenticationMode') === 'exclusive') {
+ return FALSE;
+ }
+
if (!$user) {
$user = \Drupal::currentUser();
}
@@ -182,8 +187,7 @@ function ldap_authentication_show_password_field($user = NULL): bool {
$authmap = \Drupal::service('externalauth.authmap');
$authname = $authmap->get($user->id(), 'ldap_user');
if ($authname) {
- $password_option = \Drupal::config('ldap_authentication.settings')
- ->get('passwordOption');
+ $password_option = $config->get('passwordOption');
return $password_option === 'allow';
}
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment