diff --git a/core/modules/system/src/Controller/SystemController.php b/core/modules/system/src/Controller/SystemController.php
index 0980b0a3f6a6c815078e61e243a8ae7095dd2612..22bade6f8c7803816951f5fbe4b240c6c3c44a90 100644
--- a/core/modules/system/src/Controller/SystemController.php
+++ b/core/modules/system/src/Controller/SystemController.php
@@ -250,7 +250,17 @@ public function themesPage() {
}
if (!empty($theme->status)) {
if (!$theme->is_default) {
- if ($theme->getName() != $admin_theme) {
+ $theme_uninstallable = TRUE;
+ if ($theme->getName() == $admin_theme) {
+ $theme_uninstallable = FALSE;
+ }
+ // Check it isn't the base of theme of an installed theme.
+ foreach ($theme->required_by as $themename => $dependency) {
+ if (!empty($themes[$themename]->status)) {
+ $theme_uninstallable = FALSE;
+ }
+ }
+ if ($theme_uninstallable) {
$theme->operations[] = array(
'title' => $this->t('Uninstall'),
'url' => Url::fromRoute('system.theme_uninstall'),
diff --git a/core/modules/system/src/Tests/System/ThemeTest.php b/core/modules/system/src/Tests/System/ThemeTest.php
index 5078156a34ab0c98af340198bd997565a4cd8dec..1534675aa14380946653f6a4ca8b2d3e696284bf 100644
--- a/core/modules/system/src/Tests/System/ThemeTest.php
+++ b/core/modules/system/src/Tests/System/ThemeTest.php
@@ -267,4 +267,64 @@ function testInvalidTheme() {
$this->assertText(t('This theme requires the base theme @base_theme to operate correctly.', array('@base_theme' => 'not_real_test_basetheme')));
$this->assertText(t('This theme requires the theme engine @theme_engine to operate correctly.', array('@theme_engine' => 'not_real_engine')));
}
+
+ /**
+ * Test uninstalling of themes works.
+ */
+ function testUninstallingThemes() {
+ // Install Bartik and set it as the default theme.
+ \Drupal::service('theme_handler')->install(array('bartik'));
+ // Set up seven as the admin theme.
+ \Drupal::service('theme_handler')->install(array('seven'));
+ $edit = array(
+ 'admin_theme' => 'seven',
+ 'use_admin_theme' => TRUE,
+ );
+ $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
+ $this->drupalGet('admin/appearance');
+ $this->clickLink(t('Set as default'));
+
+ // Check that seven cannot be uninstalled as it is the admin theme.
+ $this->assertNoRaw('Uninstall Seven theme', 'A link to uninstall the Seven theme does not appear on the theme settings page.');
+ // Check that bartik cannot be uninstalled as it is the default theme.
+ $this->assertNoRaw('Uninstall Bartik theme', 'A link to uninstall the Bartik theme does not appear on the theme settings page.');
+ // Check that the classy theme cannot be uninstalled as it is a base theme
+ // of seven and bartik.
+ $this->assertNoRaw('Uninstall Classy theme', 'A link to uninstall the Classy theme does not appear on the theme settings page.');
+
+ // Install Stark and set it as the default theme.
+ \Drupal::service('theme_handler')->install(array('stark'));
+
+ $edit = array(
+ 'admin_theme' => 'stark',
+ 'use_admin_theme' => TRUE,
+ );
+ $this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
+
+ // Check that seven can be uninstalled now.
+ $this->assertRaw('Uninstall Seven theme', 'A link to uninstall the Seven theme does appear on the theme settings page.');
+ // Check that the classy theme still cannot be uninstalled as it is a
+ // base theme of bartik.
+ $this->assertNoRaw('Uninstall Classy theme', 'A link to uninstall the Classy theme does not appear on the theme settings page.');
+
+ // Change the default theme to stark, stark is third in the list.
+ $this->clickLink(t('Set as default'), 2);
+
+ // Check that bartik can be uninstalled now.
+ $this->assertRaw('Uninstall Bartik theme', 'A link to uninstall the Bartik theme does appear on the theme settings page.');
+
+ // Check that the classy theme still can't be uninstalled as neither of it's
+ // base themes have been.
+ $this->assertNoRaw('Uninstall Classy theme', 'A link to uninstall the Classy theme does not appear on the theme settings page.');
+
+ // Uninstall each of the three themes starting with Bartik.
+ $this->clickLink(t('Uninstall'));
+ $this->assertRaw('The Bartik theme has been uninstalled');
+ // Seven is the second in the list.
+ $this->clickLink(t('Uninstall'));
+ $this->assertRaw('The Seven theme has been uninstalled');
+ // Now uninstall classy.
+ $this->clickLink(t('Uninstall'));
+ $this->assertRaw('The Classy theme has been uninstalled');
+ }
}