diff --git a/core/modules/system/src/Form/PrepareModulesEntityUninstallForm.php b/core/modules/system/src/Form/PrepareModulesEntityUninstallForm.php index f682b42..a8d4924 100644 --- a/core/modules/system/src/Form/PrepareModulesEntityUninstallForm.php +++ b/core/modules/system/src/Form/PrepareModulesEntityUninstallForm.php @@ -8,6 +8,7 @@ use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Provides a form removing module content entities data before uninstallation. @@ -91,6 +92,9 @@ public function getCancelUrl() { */ public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) { $this->entityTypeId = $entity_type_id; + if (!$this->entityTypeManager->hasDefinition($this->entityTypeId)) { + throw new NotFoundHttpException(); + } $form = parent::buildForm($form, $form_state); $storage = $this->entityTypeManager->getStorage($entity_type_id); @@ -103,7 +107,15 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t // Display a list of the 10 entity labels, if possible. $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); - if ($entity_type->hasKey('label')) { + if ($count == 0) { + $form['total'] = [ + '#markup' => $this->t( + 'There are 0 @entity_type_plural to delete.', + ['@entity_type_plural' => $entity_type->getPluralLabel()] + ), + ]; + } + elseif ($entity_type->hasKey('label')) { $recent_entity_ids = $storage->getQuery() ->sort($entity_type->getKey('id'), 'DESC') ->pager(10) @@ -120,12 +132,34 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t '#theme' => 'item_list', '#items' => $labels, ]; + $more_count = $count - count($labels); $form['total'] = [ - '#markup' => $this->t('And @count more @entity_type_plural.', ['@count' => $count - count($labels), '@entity_type_plural' => $entity_type->getPluralLabel()]), - '#access' => $count > count($labels), + '#markup' => $this->formatPlural( + $more_count, + 'And @count more @entity_type_singular.', + 'And @count more @entity_type_plural.', + [ + '@entity_type_singular' => $entity_type->getSingularLabel(), + '@entity_type_plural' => $entity_type->getPluralLabel(), + ] + ), + '#access' => (bool) $more_count, ]; } } + else { + $form['total'] = [ + '#markup' => $this->formatPlural( + $count, + 'This will delete @count @entity_type_singular.', + 'This will delete @count @entity_type_plural.', + [ + '@entity_type_singular' => $entity_type->getSingularLabel(), + '@entity_type_plural' => $entity_type->getPluralLabel(), + ] + ) + ]; + } $form['description']['#prefix'] = '
'; $form['description']['#suffix'] = '
'; @@ -134,6 +168,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t // Make "Cancel" the default button, "Delete" a secondary red link. $form['actions']['cancel']['#weight'] = -1; $form['actions']['submit']['#button_type'] = 'danger'; + $form['actions']['submit']['#access'] = (bool) $count; return $form; } diff --git a/core/modules/system/src/Tests/Module/PrepareUninstallTest.php b/core/modules/system/src/Tests/Module/PrepareUninstallTest.php index 14c7b27..dd89e31 100644 --- a/core/modules/system/src/Tests/Module/PrepareUninstallTest.php +++ b/core/modules/system/src/Tests/Module/PrepareUninstallTest.php @@ -2,6 +2,7 @@ namespace Drupal\system\Tests\Module; +use Drupal\Component\Utility\Unicode; use Drupal\simpletest\WebTestBase; use Drupal\taxonomy\Tests\TaxonomyTestTrait; @@ -33,7 +34,7 @@ class PrepareUninstallTest extends WebTestBase { * * @var array */ - public static $modules = ['node', 'taxonomy']; + public static $modules = ['node', 'taxonomy', 'entity_test']; /** * {@inheritdoc} @@ -44,8 +45,8 @@ public function setUp() { $admin_user = $this->drupalCreateUser(['administer modules']); $this->drupalLogin($admin_user); - // Create 12 nodes. - for ($i = 1; $i <= 6; $i++) { + // Create 10 nodes. + for ($i = 1; $i <= 5; $i++) { $this->nodes[] = $this->drupalCreateNode(['type' => 'page']); $this->nodes[] = $this->drupalCreateNode(['type' => 'article']); } @@ -105,12 +106,30 @@ public function testUninstall() { // Delete Node data. $this->drupalGet('admin/modules/uninstall/entity/node'); - for ($i = 11; $i >= 2; $i--) { - $this->assertText($this->nodes[$i]->label()); + // All 10 nodes should be listed. + foreach ($this->nodes as $node) { + $this->assertText($node->label()); } - $this->assertText('And 2 more content items.'); + + // Ensures there is no more count when not necessary. + $this->assertNoText('And 0 more content'); $this->assertText('This action cannot be undone.'); $this->assertText('Make a backup of your database if you want to be able to restore these items.'); + + // Create another node so we have 11. + $this->nodes[] = $this->drupalCreateNode(['type' => 'page']); + $this->drupalGet('admin/modules/uninstall/entity/node'); + // Ensures singular case is used when a single entity is left after listing + // the first 10's labels. + $this->assertText('And 1 more content item.'); + + // Create another node so we have 12. + $this->nodes[] = $this->drupalCreateNode(['type' => 'article']); + $this->drupalGet('admin/modules/uninstall/entity/node'); + // Ensures singular case is used when a single entity is left after listing + // the first 10's labels. + $this->assertText('And 2 more content items.'); + $this->drupalPostForm(NULL, [], t('Delete all content items')); // Check we are redirected to the uninstall page and data has been removed. @@ -127,6 +146,34 @@ public function testUninstall() { $this->drupalPostForm(NULL, [], t('Uninstall')); $this->assertText('The selected modules have been uninstalled.'); $this->assertNoText('Allows content to be submitted to the site and displayed on pages.'); + + // Ensure the proper response when accessing a non-existent entity type. + $this->drupalGet('admin/modules/uninstall/entity/node'); + $this->assertResponse(404, 'Entity types that do not exist result in a 404.'); + + // Test an entity type which does not have any existing entities. + $this->drupalGet('admin/modules/uninstall/entity/entity_test_no_label'); + $this->assertText('There are 0 entity test without label entities to delete.'); + $button_xpath = '//input[@type="submit"][@value="Delete all entity test without label entities"]'; + $this->assertNoFieldByXPath($button_xpath, NULL, 'Button with value "Delete all entity test without label entities" not found'); + + // Test an entity type without a label. + /** @var \Drupal\Core\Entity\EntityStorageInterface $storage */ + $storage = $this->container->get('entity.manager') + ->getStorage('entity_test_no_label'); + $storage->create([ + 'id' => Unicode::strtolower($this->randomMachineName()), + 'name' => $this->randomMachineName(), + ])->save(); + $this->drupalGet('admin/modules/uninstall/entity/entity_test_no_label'); + $this->assertText('This will delete 1 entity test without label.'); + $this->assertFieldByXPath($button_xpath, NULL, 'Button with value "Delete all entity test without label entities" found'); + $storage->create([ + 'id' => Unicode::strtolower($this->randomMachineName()), + 'name' => $this->randomMachineName(), + ])->save(); + $this->drupalGet('admin/modules/uninstall/entity/entity_test_no_label'); + $this->assertText('This will delete 2 entity test without label entities.'); } }