diff options
Diffstat (limited to 'core/modules')
15 files changed, 127 insertions, 21 deletions
diff --git a/core/modules/block_content/src/BlockContentTypeInterface.php b/core/modules/block_content/src/BlockContentTypeInterface.php index aaf7957b8952..9c12709b2a55 100644 --- a/core/modules/block_content/src/BlockContentTypeInterface.php +++ b/core/modules/block_content/src/BlockContentTypeInterface.php @@ -3,19 +3,12 @@ namespace Drupal\block_content; use Drupal\Core\Config\Entity\ConfigEntityInterface; +use Drupal\Core\Entity\EntityDescriptionInterface; use Drupal\Core\Entity\RevisionableEntityBundleInterface; /** * Provides an interface defining a block type entity. */ -interface BlockContentTypeInterface extends ConfigEntityInterface, RevisionableEntityBundleInterface { - - /** - * Returns the description of the block type. - * - * @return string - * The description of the type of this block. - */ - public function getDescription(); +interface BlockContentTypeInterface extends ConfigEntityInterface, RevisionableEntityBundleInterface, EntityDescriptionInterface { } diff --git a/core/modules/block_content/src/Entity/BlockContentType.php b/core/modules/block_content/src/Entity/BlockContentType.php index ecbc6c3866d2..fa6fe3955038 100644 --- a/core/modules/block_content/src/Entity/BlockContentType.php +++ b/core/modules/block_content/src/Entity/BlockContentType.php @@ -100,6 +100,13 @@ class BlockContentType extends ConfigEntityBundleBase implements BlockContentTyp /** * {@inheritdoc} */ + public function setDescription($description): static { + return $this->set('description', $description); + } + + /** + * {@inheritdoc} + */ public function shouldCreateNewRevision() { return $this->revision; } diff --git a/core/modules/block_content/tests/src/Functional/BlockContentTypeTest.php b/core/modules/block_content/tests/src/Functional/BlockContentTypeTest.php index fba8362cd2cd..2ec82c2195b8 100644 --- a/core/modules/block_content/tests/src/Functional/BlockContentTypeTest.php +++ b/core/modules/block_content/tests/src/Functional/BlockContentTypeTest.php @@ -58,14 +58,26 @@ class BlockContentTypeTest extends BlockContentTestBase { } /** - * Tests the order of the block content types on the add page. + * Tests the block types on the block/add page. */ - public function testBlockContentAddPageOrder(): void { - $this->createBlockContentType(['id' => 'bundle_1', 'label' => 'Bundle 1']); - $this->createBlockContentType(['id' => 'bundle_2', 'label' => 'Aaa Bundle 2']); + public function testBlockContentAddPage(): void { + $this->createBlockContentType([ + 'id' => 'bundle_1', + 'label' => 'Bundle 1', + 'description' => 'Bundle 1 description', + ]); + $this->createBlockContentType([ + 'id' => 'bundle_2', + 'label' => 'Aaa Bundle 2', + 'description' => 'Bundle 2 description', + ]); $this->drupalLogin($this->adminUser); $this->drupalGet('block/add'); + // Ensure bundles are ordered by their label, not id. $this->assertSession()->pageTextMatches('/Aaa Bundle 2(.*)Bundle 1/'); + // Block type descriptions should display. + $this->assertSession()->pageTextContains('Bundle 1 description'); + $this->assertSession()->pageTextContains('Bundle 2 description'); } /** diff --git a/core/modules/block_content/tests/src/Kernel/BlockContentTest.php b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php index bb0186431e9a..fe07b3d5652e 100644 --- a/core/modules/block_content/tests/src/Kernel/BlockContentTest.php +++ b/core/modules/block_content/tests/src/Kernel/BlockContentTest.php @@ -38,6 +38,19 @@ class BlockContentTest extends KernelTestBase { } /** + * Tests BlockContentType functionality. + */ + public function testBlockContentType(): void { + $type = BlockContentType::create([ + 'id' => 'foo', + 'label' => 'Foo', + ]); + $this->assertSame('', $type->getDescription()); + $type->setDescription('Test description'); + $this->assertSame('Test description', $type->getDescription()); + } + + /** * Tests the editing links for BlockContentBlock. */ public function testOperationLinks(): void { diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 1fb4071ba47d..d68a04fcbc8a 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -125,8 +125,12 @@ function node_get_type_label(NodeInterface $node) { * * @return string * The node type description. + * + * @deprecated in drupal:11.3.0 and is removed from drupal:12.0.0. Use $node_type->getDescription() instead. + * @see https://www.drupal.org/node/3531945 */ function node_type_get_description(NodeTypeInterface $node_type) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.3.0 and is removed from drupal:12.0.0. Use $node_type->getDescription() instead. See https://www.drupal.org/node/3531945', E_USER_DEPRECATED); return $node_type->getDescription(); } diff --git a/core/modules/system/src/Controller/SystemController.php b/core/modules/system/src/Controller/SystemController.php index b340555c6289..fc253ac2f7cf 100644 --- a/core/modules/system/src/Controller/SystemController.php +++ b/core/modules/system/src/Controller/SystemController.php @@ -280,8 +280,6 @@ class SystemController extends ControllerBase { continue; } - // @todo Add logic for not displaying hidden modules in - // https://drupal.org/node/3117829. $module_name = $modules[$dependency]->info['name']; $theme->module_dependencies_list[$dependency] = $modules[$dependency]->status ? $this->t('@module_name', ['@module_name' => $module_name]) : $this->t('@module_name (<span class="admin-disabled">disabled</span>)', ['@module_name' => $module_name]); diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php index 90dc9ead38b7..13297f3578c3 100644 --- a/core/modules/system/src/Form/ModulesListForm.php +++ b/core/modules/system/src/Form/ModulesListForm.php @@ -375,8 +375,6 @@ class ModulesListForm extends FormBase { // If this module requires other modules, add them to the array. /** @var \Drupal\Core\Extension\Dependency $dependency_object */ foreach ($module->requires as $dependency => $dependency_object) { - // @todo Add logic for not displaying hidden modules in - // https://drupal.org/node/3117829. if ($incompatible = $this->checkDependencyMessage($modules, $dependency, $dependency_object)) { $row['#requires'][$dependency] = $incompatible; $row['enable']['#disabled'] = TRUE; diff --git a/core/modules/system/src/Form/ModulesUninstallForm.php b/core/modules/system/src/Form/ModulesUninstallForm.php index c999f37fe23f..97f76abe40e3 100644 --- a/core/modules/system/src/Form/ModulesUninstallForm.php +++ b/core/modules/system/src/Form/ModulesUninstallForm.php @@ -106,7 +106,8 @@ class ModulesUninstallForm extends FormBase { include_once DRUPAL_ROOT . '/core/includes/install.inc'; // Get a list of all available modules that can be uninstalled. - $uninstallable = array_filter($this->moduleExtensionList->getList(), function ($module) { + $modules = $this->moduleExtensionList->getList(); + $uninstallable = array_filter($modules, function ($module) { return empty($module->info['required']) && $module->status; }); @@ -199,7 +200,13 @@ class ModulesUninstallForm extends FormBase { // we can allow this module to be uninstalled. foreach (array_keys($module->required_by) as $dependent) { if ($this->updateRegistry->getInstalledVersion($dependent) !== $this->updateRegistry::SCHEMA_UNINSTALLED) { - $form['modules'][$module->getName()]['#required_by'][] = $dependent; + $module_name = $modules[$dependent]->info['name']; + if ($dependent != strtolower(str_replace(' ', '_', $module_name))) { + $form['modules'][$module->getName()]['#required_by'][] = $module_name . " (" . $dependent . ")"; + } + else { + $form['modules'][$module->getName()]['#required_by'][] = $module_name; + } $form['uninstall'][$module->getName()]['#disabled'] = TRUE; } } diff --git a/core/modules/system/templates/details.html.twig b/core/modules/system/templates/details.html.twig index 20e4ea7193e3..dcb1cf354ce5 100644 --- a/core/modules/system/templates/details.html.twig +++ b/core/modules/system/templates/details.html.twig @@ -34,7 +34,11 @@ </div> {% endif %} - {{ description }} + {%- if description -%} + {% set description_attributes = create_attribute({id: attributes['aria-describedby']}) %} + <div{{ description_attributes }}>{{ description }}</div> + {%- endif -%} + {{ children }} {{ value }} </details> diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupDetailsForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupDetailsForm.php index 9babda83ddc0..226eb705802d 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupDetailsForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestGroupDetailsForm.php @@ -48,6 +48,11 @@ class FormTestGroupDetailsForm extends FormBase { 'data-summary-attribute' => 'test', ], ]; + $form['description_attributes'] = [ + '#type' => 'details', + '#title' => 'Details element with description', + '#description' => 'I am a details description', + ]; return $form; } diff --git a/core/modules/system/tests/modules/system_test/src/Controller/OptionalServiceSystemTestController.php b/core/modules/system/tests/modules/system_test/src/Controller/OptionalServiceSystemTestController.php new file mode 100644 index 000000000000..b57e4c883972 --- /dev/null +++ b/core/modules/system/tests/modules/system_test/src/Controller/OptionalServiceSystemTestController.php @@ -0,0 +1,21 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\system_test\Controller; + +use Drupal\Core\Controller\ControllerBase; +use Drupal\dblog\Logger\DbLog; +use Symfony\Component\DependencyInjection\Attribute\Autowire; + +/** + * A controller that specifies an optional dependency. + */ +class OptionalServiceSystemTestController extends ControllerBase { + + public function __construct( + #[Autowire('logger.dblog')] + public readonly ?DbLog $dbLog, + ) {} + +} diff --git a/core/modules/system/tests/src/Functional/Form/ElementTest.php b/core/modules/system/tests/src/Functional/Form/ElementTest.php index 4a9755fac7f5..0ebf9e4ce774 100644 --- a/core/modules/system/tests/src/Functional/Form/ElementTest.php +++ b/core/modules/system/tests/src/Functional/Form/ElementTest.php @@ -38,6 +38,7 @@ class ElementTest extends BrowserTestBase { $this->testFormAutocomplete(); $this->testFormElementErrors(); $this->testDetailsSummaryAttributes(); + $this->testDetailsDescriptionAttributes(); } /** @@ -230,4 +231,13 @@ class ElementTest extends BrowserTestBase { $this->assertSession()->elementExists('css', 'summary[data-summary-attribute="test"]'); } + /** + * Tests description attributes of details. + */ + protected function testDetailsDescriptionAttributes(): void { + $this->drupalGet('form-test/group-details'); + $this->assertSession()->elementExists('css', 'details[aria-describedby="edit-description-attributes--description"]'); + $this->assertSession()->elementExists('css', 'div[id="edit-description-attributes--description"]'); + } + } diff --git a/core/modules/system/tests/src/Functional/Module/UninstallTest.php b/core/modules/system/tests/src/Functional/Module/UninstallTest.php index aeace5bb488b..6d1b93cc50db 100644 --- a/core/modules/system/tests/src/Functional/Module/UninstallTest.php +++ b/core/modules/system/tests/src/Functional/Module/UninstallTest.php @@ -22,7 +22,15 @@ class UninstallTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected static $modules = ['module_test', 'user', 'views', 'node']; + protected static $modules = [ + 'ckeditor5', + 'filter', + 'module_test', + 'node', + 'user', + 'views', + 'views_ui', + ]; /** * {@inheritdoc} @@ -118,6 +126,13 @@ class UninstallTest extends BrowserTestBase { // Delete the node to allow node to be uninstalled. $node->delete(); + // Ensure dependent module full names are shown. + $this->assertSession()->pageTextContains('Required by: Views UI'); + // Ensure matching machine names do not display. + $this->assertSession()->pageTextNotContains('Required by: Views UI (views_ui)'); + // Ensure machine names that do not match do display. + $this->assertSession()->pageTextContains('Text Editor (editor)'); + // Uninstall module_test. $edit = []; $edit['uninstall[module_test]'] = TRUE; diff --git a/core/modules/user/src/Hook/UserRequirements.php b/core/modules/user/src/Hook/UserRequirements.php index f317ced58bc4..46155e55e3cb 100644 --- a/core/modules/user/src/Hook/UserRequirements.php +++ b/core/modules/user/src/Hook/UserRequirements.php @@ -49,6 +49,7 @@ class UserRequirements { $query->addExpression('LOWER(mail)', 'lower_mail'); $query->isNotNull('mail'); $query->groupBy('lower_mail'); + $query->groupBy('langcode'); $query->having('COUNT(uid) > :matches', [':matches' => 1]); $conflicts = $query->countQuery()->execute()->fetchField(); diff --git a/core/modules/user/tests/src/Kernel/UserRequirementsTest.php b/core/modules/user/tests/src/Kernel/UserRequirementsTest.php index 146ab9c8b904..746370a15d61 100644 --- a/core/modules/user/tests/src/Kernel/UserRequirementsTest.php +++ b/core/modules/user/tests/src/Kernel/UserRequirementsTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Drupal\Tests\user\Kernel; use Drupal\KernelTests\KernelTestBase; +use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\user\Traits\UserCreationTrait; /** @@ -70,4 +71,21 @@ class UserRequirementsTest extends KernelTestBase { $this->assertArrayNotHasKey('conflicting emails', $output); } + /** + * Tests that the requirements check does not flag user translations. + */ + public function testTranslatedUserEmail(): void { + \Drupal::service('module_installer')->install(['language']); + ConfigurableLanguage::createFromLangcode('is')->save(); + + $output = $this->moduleHandler->invoke('user', 'runtime_requirements'); + $this->assertArrayNotHasKey('conflicting emails', $output); + + $user = $this->createUser([], 'User A', FALSE, ['mail' => 'unique@example.com']); + $user->addTranslation('is')->save(); + + $output = $this->moduleHandler->invoke('user', 'runtime_requirements'); + $this->assertArrayNotHasKey('conflicting emails', $output); + } + } |