summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules')
-rw-r--r--core/modules/package_manager/tests/src/Build/TemplateProjectTestBase.php2
-rw-r--r--core/modules/system/tests/src/Kernel/Block/StubPathMatcher.php21
-rw-r--r--core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php7
-rw-r--r--core/modules/workspaces/src/Hook/EntityOperations.php2
-rw-r--r--core/modules/workspaces/src/Hook/FormOperations.php38
-rw-r--r--core/modules/workspaces/tests/src/Functional/WorkspaceFormValidationTest.php72
6 files changed, 127 insertions, 15 deletions
diff --git a/core/modules/package_manager/tests/src/Build/TemplateProjectTestBase.php b/core/modules/package_manager/tests/src/Build/TemplateProjectTestBase.php
index 16cd486ad750..18b63b8376bd 100644
--- a/core/modules/package_manager/tests/src/Build/TemplateProjectTestBase.php
+++ b/core/modules/package_manager/tests/src/Build/TemplateProjectTestBase.php
@@ -441,6 +441,8 @@ END;
$requirements['symfony/polyfill-php81'],
$requirements['symfony/polyfill-php82'],
$requirements['symfony/polyfill-php83'],
+ // Needed for PHP 8.4 features while PHP 8.3 is the minimum.
+ $requirements['symfony/polyfill-php84'],
);
// If this package requires any Drupal core packages, ensure it allows
// any version.
diff --git a/core/modules/system/tests/src/Kernel/Block/StubPathMatcher.php b/core/modules/system/tests/src/Kernel/Block/StubPathMatcher.php
new file mode 100644
index 000000000000..c2bd82782b05
--- /dev/null
+++ b/core/modules/system/tests/src/Kernel/Block/StubPathMatcher.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\system\Kernel\Block;
+
+use Drupal\Core\Path\PathMatcher;
+
+/**
+ * A class extending PatchMatcher for testing purposes.
+ */
+class StubPathMatcher extends PathMatcher {
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isFrontPage(): bool {
+ return FALSE;
+ }
+
+}
diff --git a/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
index e2ceead3475d..6d4ff90d5f46 100644
--- a/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
+++ b/core/modules/system/tests/src/Kernel/Block/SystemMenuBlockTest.php
@@ -341,6 +341,13 @@ class SystemMenuBlockTest extends KernelTestBase {
* @dataProvider configExpandedTestCases
*/
public function testConfigExpanded($active_route, $menu_block_level, $expected_items): void {
+ // Replace the path.matcher service so it always returns FALSE when
+ // checking whether a route is the front page. Otherwise, the default
+ // service throws an exception when checking routes because all of these
+ // are mocked.
+ $service_definition = $this->container->getDefinition('path.matcher');
+ $service_definition->setClass(StubPathMatcher::class);
+
$block = $this->blockManager->createInstance('system_menu_block:' . $this->menu->id(), [
'region' => 'footer',
'id' => 'machine_name',
diff --git a/core/modules/workspaces/src/Hook/EntityOperations.php b/core/modules/workspaces/src/Hook/EntityOperations.php
index 08e2dc70cc89..f193795cc410 100644
--- a/core/modules/workspaces/src/Hook/EntityOperations.php
+++ b/core/modules/workspaces/src/Hook/EntityOperations.php
@@ -297,7 +297,7 @@ class EntityOperations {
*
* Alters entity forms to disallow concurrent editing in multiple workspaces.
*/
- #[Hook('form_alter')]
+ #[Hook('form_alter', order: Order::First)]
public function entityFormAlter(array &$form, FormStateInterface $form_state, string $form_id): void {
if (!$form_state->getFormObject() instanceof EntityFormInterface) {
return;
diff --git a/core/modules/workspaces/src/Hook/FormOperations.php b/core/modules/workspaces/src/Hook/FormOperations.php
index 85f374582398..61b775ea3cd0 100644
--- a/core/modules/workspaces/src/Hook/FormOperations.php
+++ b/core/modules/workspaces/src/Hook/FormOperations.php
@@ -29,20 +29,24 @@ class FormOperations {
return;
}
- // Add a validation step for every form if we are in a workspace.
- $this->addWorkspaceValidation($form);
+ // If a form hasn't already been marked as safe or not to submit in a
+ // workspace, check the generic interfaces.
+ if (!$form_state->has('workspace_safe')) {
+ $form_object = $form_state->getFormObject();
+ $workspace_safe = $form_object instanceof WorkspaceSafeFormInterface
+ || ($form_object instanceof WorkspaceDynamicSafeFormInterface && $form_object->isWorkspaceSafeForm($form, $form_state));
- // If a form has already been marked as safe or not to submit in a
- // workspace, we don't have anything else to do.
- if ($form_state->has('workspace_safe')) {
- return;
+ $form_state->set('workspace_safe', $workspace_safe);
}
- $form_object = $form_state->getFormObject();
- $workspace_safe = $form_object instanceof WorkspaceSafeFormInterface
- || ($form_object instanceof WorkspaceDynamicSafeFormInterface && $form_object->isWorkspaceSafeForm($form, $form_state));
-
- $form_state->set('workspace_safe', $workspace_safe);
+ // Add a validation step for every other form.
+ if ($form_state->get('workspace_safe') !== TRUE) {
+ $form['workspace_safe'] = [
+ '#type' => 'value',
+ '#value' => FALSE,
+ ];
+ $this->addWorkspaceValidation($form);
+ }
}
/**
@@ -59,8 +63,14 @@ class FormOperations {
}
}
- if (isset($element['#validate'])) {
+ if (isset($element['#submit'])) {
$element['#validate'][] = [static::class, 'validateDefaultWorkspace'];
+
+ // Ensure that the workspace validation is always shown, even when the
+ // form element is limiting validation errors.
+ if (isset($element['#limit_validation_errors']) && $element['#limit_validation_errors'] !== FALSE) {
+ $element['#limit_validation_errors'][] = ['workspace_safe'];
+ }
}
}
@@ -68,8 +78,8 @@ class FormOperations {
* Validation handler which sets a validation error for all unsupported forms.
*/
public static function validateDefaultWorkspace(array &$form, FormStateInterface $form_state): void {
- if ($form_state->get('workspace_safe') !== TRUE) {
- $form_state->setError($form, new TranslatableMarkup('This form can only be submitted in the default workspace.'));
+ if ($form_state->get('workspace_safe') !== TRUE && isset($form_state->getCompleteForm()['workspace_safe'])) {
+ $form_state->setErrorByName('workspace_safe', new TranslatableMarkup('This form can only be submitted in the default workspace.'));
}
}
diff --git a/core/modules/workspaces/tests/src/Functional/WorkspaceFormValidationTest.php b/core/modules/workspaces/tests/src/Functional/WorkspaceFormValidationTest.php
new file mode 100644
index 000000000000..efd3bef34c21
--- /dev/null
+++ b/core/modules/workspaces/tests/src/Functional/WorkspaceFormValidationTest.php
@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\workspaces\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+use Drupal\workspaces\Entity\Workspace;
+
+/**
+ * Tests Workspaces form validation.
+ *
+ * @group workspaces
+ */
+class WorkspaceFormValidationTest extends BrowserTestBase {
+
+ use WorkspaceTestUtilities;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected static $modules = ['block', 'form_test', 'workspaces'];
+
+ /**
+ * {@inheritdoc}
+ */
+ protected $defaultTheme = 'stark';
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->drupalLogin($this->drupalCreateUser(['administer workspaces']));
+ $this->setupWorkspaceSwitcherBlock();
+ }
+
+ /**
+ * Tests partial form validation through #limit_validation_errors.
+ */
+ public function testValidateLimitErrors(): void {
+ $stage = Workspace::load('stage');
+ $this->switchToWorkspace($stage);
+
+ $edit = [
+ 'test' => 'test1',
+ 'test_numeric_index[0]' => 'test2',
+ 'test_substring[foo]' => 'test3',
+ ];
+ $path = 'form-test/limit-validation-errors';
+
+ // Submit the form by pressing all the 'Partial validate' buttons.
+ $this->drupalGet($path);
+ $this->submitForm($edit, 'Partial validate');
+ $this->assertSession()->pageTextContains('This form can only be submitted in the default workspace.');
+
+ $this->drupalGet($path);
+ $this->submitForm($edit, 'Partial validate (numeric index)');
+ $this->assertSession()->pageTextContains('This form can only be submitted in the default workspace.');
+
+ $this->drupalGet($path);
+ $this->submitForm($edit, 'Partial validate (substring)');
+ $this->assertSession()->pageTextContains('This form can only be submitted in the default workspace.');
+
+ // Now test full form validation.
+ $this->drupalGet($path);
+ $this->submitForm($edit, 'Full validate');
+ $this->assertSession()->pageTextContains('This form can only be submitted in the default workspace.');
+ }
+
+}