Loading core/lib/Drupal/Core/Extension/Plugin/Validation/Constraint/ExtensionExistsConstraintValidator.php +14 −0 Original line number Diff line number Diff line Loading @@ -61,12 +61,26 @@ public function validate(mixed $extension_name, Constraint $constraint) { switch ($constraint->type) { case 'module': // This constraint may be used to validate nullable (optional) values. if ($extension_name === NULL) { return; } // Some plugins are shipped in `core/lib`, which corresponds to the // special `core` extension name. // For example: \Drupal\Core\Menu\Plugin\Block\LocalActionsBlock. if ($extension_name === 'core') { return; } if (!$this->moduleHandler->moduleExists($extension_name)) { $this->context->addViolation($constraint->moduleMessage, $variables); } break; case 'theme': // This constraint may be used to validate nullable (optional) values. if ($extension_name === NULL) { return; } if (!$this->themeHandler->themeExists($extension_name)) { $this->context->addViolation($constraint->themeMessage, $variables); } Loading core/tests/Drupal/KernelTests/Core/Extension/ExtensionExistsConstraintValidatorTest.php +21 −1 Original line number Diff line number Diff line Loading @@ -31,8 +31,13 @@ public function testValidation(): void { /** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data */ $typed_data = $this->container->get('typed_data_manager'); $data = $typed_data->create($definition, 'user'); // `core` provides many plugins without the need to install a module. $data = $typed_data->create($definition, 'core'); $violations = $data->validate(); $this->assertCount(0, $violations); $data->setValue('user'); $violations = $data->validate(); $this->assertCount(1, $violations); $this->assertSame("Module 'user' is not installed.", (string) $violations->get(0)->getMessage()); Loading @@ -40,6 +45,10 @@ public function testValidation(): void { $this->enableModules(['user']); $this->assertCount(0, $data->validate()); // NULL should not trigger a validation error: a value may be nullable. $data->setValue(NULL); $this->assertCount(0, $data->validate()); $definition->setConstraints(['ExtensionExists' => 'theme']); $data = $typed_data->create($definition, 'stark'); Loading @@ -56,6 +65,17 @@ public function testValidation(): void { ->create($definition, 'stark'); $this->assertCount(0, $data->validate()); // `core` provides many plugins without the need to install a module, but it // does not work for themes. $data = $typed_data->create($definition, 'core'); $violations = $data->validate(); $this->assertCount(1, $violations); $this->assertSame("Theme 'core' is not installed.", (string) $violations->get(0)->getMessage()); // NULL should not trigger a validation error: a value may be nullable. $data->setValue(NULL); $this->assertCount(0, $data->validate()); // Anything but a module or theme should raise an exception. $definition->setConstraints(['ExtensionExists' => 'profile']); $this->expectExceptionMessage("Unknown extension type: 'profile'"); Loading Loading
core/lib/Drupal/Core/Extension/Plugin/Validation/Constraint/ExtensionExistsConstraintValidator.php +14 −0 Original line number Diff line number Diff line Loading @@ -61,12 +61,26 @@ public function validate(mixed $extension_name, Constraint $constraint) { switch ($constraint->type) { case 'module': // This constraint may be used to validate nullable (optional) values. if ($extension_name === NULL) { return; } // Some plugins are shipped in `core/lib`, which corresponds to the // special `core` extension name. // For example: \Drupal\Core\Menu\Plugin\Block\LocalActionsBlock. if ($extension_name === 'core') { return; } if (!$this->moduleHandler->moduleExists($extension_name)) { $this->context->addViolation($constraint->moduleMessage, $variables); } break; case 'theme': // This constraint may be used to validate nullable (optional) values. if ($extension_name === NULL) { return; } if (!$this->themeHandler->themeExists($extension_name)) { $this->context->addViolation($constraint->themeMessage, $variables); } Loading
core/tests/Drupal/KernelTests/Core/Extension/ExtensionExistsConstraintValidatorTest.php +21 −1 Original line number Diff line number Diff line Loading @@ -31,8 +31,13 @@ public function testValidation(): void { /** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data */ $typed_data = $this->container->get('typed_data_manager'); $data = $typed_data->create($definition, 'user'); // `core` provides many plugins without the need to install a module. $data = $typed_data->create($definition, 'core'); $violations = $data->validate(); $this->assertCount(0, $violations); $data->setValue('user'); $violations = $data->validate(); $this->assertCount(1, $violations); $this->assertSame("Module 'user' is not installed.", (string) $violations->get(0)->getMessage()); Loading @@ -40,6 +45,10 @@ public function testValidation(): void { $this->enableModules(['user']); $this->assertCount(0, $data->validate()); // NULL should not trigger a validation error: a value may be nullable. $data->setValue(NULL); $this->assertCount(0, $data->validate()); $definition->setConstraints(['ExtensionExists' => 'theme']); $data = $typed_data->create($definition, 'stark'); Loading @@ -56,6 +65,17 @@ public function testValidation(): void { ->create($definition, 'stark'); $this->assertCount(0, $data->validate()); // `core` provides many plugins without the need to install a module, but it // does not work for themes. $data = $typed_data->create($definition, 'core'); $violations = $data->validate(); $this->assertCount(1, $violations); $this->assertSame("Theme 'core' is not installed.", (string) $violations->get(0)->getMessage()); // NULL should not trigger a validation error: a value may be nullable. $data->setValue(NULL); $this->assertCount(0, $data->validate()); // Anything but a module or theme should raise an exception. $definition->setConstraints(['ExtensionExists' => 'profile']); $this->expectExceptionMessage("Unknown extension type: 'profile'"); Loading