Updated: Comment #8

Problem/Motivation

Immediately after installation, visiting the theme settings page for a specific theme (e.g. admin/appearance/settings) results in a 404.

Steps to reproduce

  1. Install 8.x standard.
  2. Navigate to /admin/appearance/settings/bartik. You will get a 404.
  3. Go to admin/config/development/performance and clear the site cache.
  4. Visit /admin/appearance/settings/bartik again. The theme settings page now works.

The cause is as follows:

  • RouteSubscriber::createSystemThemeRoutes() calls list_themes() to create a route for each theme, and checks $theme->status to ensure routes are not created for disabled themes.
  • list_themes() calls _system_rebuild_theme_status() during the installer. However, that function does not set the theme status on the theme objects.
  • The theme status is normally set by system_rebuild_theme_status() (no underscore), but we can't use that because it also sets theme data in state, and state is not available yet when these routes are added during installation.

Proposed resolution

  • Patch in #8 resolves the issue by making list_themes() explicitly load the theme status from config under this circumstance.
  • Another option might be to move the config check only from system_rebuild_theme_data() to _system_rebuild_theme_data(), but this might have other repercussions since the latter helper function is sort of designed to depend on low-level stuff and the filesystem.
  • The proper way to fix this is probably an entire refactor of the module handler to remove dependencies on this tangled mass of procedural code.

Note: There are tests for this path in Drupal\color\Tests\ColorTest, but they do not fail, presumably because of other cache clears done in SimpleTest. This also makes it difficult to add a test for this bug using SimpleTest.

Remaining tasks

  • Determine if it is possible to test this with the current architecture.
  • Patch needs review. It's something of a workaround, but it resolves the problem.

Comments

xjm’s picture

Title: The requested page "/admin/appearance/settings/bartik" could not be found after installation » The requested page "/admin/appearance/settings/bartik" could not be found after installation (cache issue)
Status: Active » Needs review
StatusFileSize
new1.15 KB

The attached test does not fail, so clearly SimpleTest is doing some cache clearing that doesn't happen during normal installation.

xjm’s picture

The route is added here:
http://drupalcode.org/project/drupal.git/blob/refs/heads/8.x:/core/modul...

  foreach (list_themes(TRUE) as $theme) {
    if (!empty($theme->status)) {
      $items['admin/appearance/settings/' . $theme->name] = array(
        'title' => $theme->info['name'],
        'route_name' => 'system_theme_settings_' . $theme->name,
        'type' => MENU_LOCAL_TASK,
      );
    }
  }
xjm’s picture

Maybe this is #2004334: Separate Tabs (MENU_LOCAL_TASK) from hook_menu()?

Edit: It's also broken before that commit.

xjm’s picture

So this fixes the problem:

diff --git a/core/modules/system/lib/Drupal/system/Routing/RouteSubscriber.php b
index 616955c..374a071 100644
--- a/core/modules/system/lib/Drupal/system/Routing/RouteSubscriber.php
+++ b/core/modules/system/lib/Drupal/system/Routing/RouteSubscriber.php
@@ -34,13 +34,11 @@ static function getSubscribedEvents() {
   public function createSystemThemeRoutes(RouteBuildEvent $event) {
     $collection = $event->getRouteCollection();
     foreach (list_themes() as $theme) {
-      if (!empty($theme->status)) {
         $route = new Route('admin/appearance/settings/' . $theme->name, array(
           '_form' => '\Drupal\system\Form\ThemeSettingsForm', 'theme_name' => $
           '_permission' => 'administer themes',
         ));
         $collection->add('system_theme_settings_' . $theme->name, $route);
-      }
     }
   }

This does not:

diff --git a/core/modules/system/lib/Drupal/system/Routing/RouteSubscriber.php b
index 616955c..8246f2d 100644
--- a/core/modules/system/lib/Drupal/system/Routing/RouteSubscriber.php
+++ b/core/modules/system/lib/Drupal/system/Routing/RouteSubscriber.php
@@ -33,7 +33,7 @@ static function getSubscribedEvents() {
    */
   public function createSystemThemeRoutes(RouteBuildEvent $event) {
     $collection = $event->getRouteCollection();
-    foreach (list_themes() as $theme) {
+    foreach (list_themes(TRUE) as $theme) {
       if (!empty($theme->status)) {
         $route = new Route('admin/appearance/settings/' . $theme->name, array(
           '_form' => '\Drupal\system\Form\ThemeSettingsForm', 'theme_name' => $

This means that $theme->status is somehow cached incorrectly, even after system_list_reset() is called.

I think to test this properly, we have to entirely refactor system_list(). :) @tim.plunkett pointed me at #2024083: [META] Improve the extension system (modules, profiles, themes).

xjm’s picture

xjm’s picture

xjm’s picture

xjm’s picture

StatusFileSize
new919 bytes

This fixes it. No effing clue how to test it without refactoring the entire call chain for system listings, since we can't have a failing web test because of the cache clearing in SimpleTest, and given the sprawling complexity of static calls that is required to add these routes, I think I have a better chance of unit testing my cat.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Title: The requested page "/admin/appearance/settings/bartik" could not be found after installation (cache issue) » The requested page "/admin/appearance/settings/bartik" could not be found after installation

It turned out to not be precisely a cache issue after all.

xjm’s picture

Issue summary: View changes

Updated issue summary.

msonnabaum’s picture

I've also run into this in a few patches already. It *might* be fixed by #2021959: Refactor module handling responsibilities out of DrupalKernel. Worth checking out before we do a workaround like this.

xjm’s picture

Looks like #2021959: Refactor module handling responsibilities out of DrupalKernel doesn't actually solve the problem, unfortunately.

xjm’s picture

This test also doesn't fail:

diff --git a/core/modules/system/lib/Drupal/system/Tests/InstallerTest.php b/cor
index 43824bf..72df060 100644
--- a/core/modules/system/lib/Drupal/system/Tests/InstallerTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/InstallerTest.php
@@ -149,6 +149,9 @@ protected function drupalGet($path, array $options = array()
    * Ensures that the user page is available after every test installation.
    */
   public function testInstaller() {
+    $themes = list_themes(TRUE);
+    $this->assertEqual($themes['stark']->status, 1);
+
     $this->drupalGet('user');
     $this->assertResponse(200);
   }

Turns out all the installer tests actually extend from WebTestBase.

BarisW’s picture

Same error here. Just clearing caches fixes the problem, even without the patch applied.
Wouldn't a cache-clear after installation be sufficient?

xjm’s picture

@BarisW, did you try the patch in #8?

BarisW’s picture

No I did not as a cache clear resolved the problem as well. Do you want me to try it without a cache clear and with the patch applied?

BarisW’s picture

Status: Needs review » Reviewed & tested by the community

I've applied the patch and re-installed Drupal. Now the links work as expected, even without clearing caches.

xjm’s picture

Status: Reviewed & tested by the community » Needs review

Thanks @BarisW!

The patch here still needs technical review, though, so setting to NR for that. See the @todo.

effulgentsia’s picture

StatusFileSize
new4.78 KB

How about this instead?

effulgentsia’s picture

effulgentsia’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue tags: +Needs followup

Yeah that's way better. :)

+++ b/core/includes/module.incundefined
@@ -38,13 +38,21 @@ function system_list($type) {
+    // site operation, the state backend might be down. Because we have a
+    // fallback to rebuild this data from the file system, we hide the error.

Where's the fallback? the if empty($theme_data) hunk below?

+++ b/core/includes/module.incundefined
@@ -38,13 +38,21 @@ function system_list($type) {
+    catch (Exception $e) {
+    }

+++ b/core/modules/system/system.moduleundefined
@@ -2861,13 +2861,21 @@ function system_rebuild_theme_data() {
+  catch (Exception $e) {
+  }

Can we catch something more specific?

@fubhy linked a mess of other theme-related issues:
#2029819: Implement a ThemeHandler to manage themes (@see ModuleHandler)
#2024043: Add Module, Theme, Profile, and Extension value objects
#2024083: [META] Improve the extension system (modules, profiles, themes)
#1798732: Convert install_task, install_time and install_current_batch to use the state system

Let's add a posptoned followup for the theme status issue to fix system_list() for themes.

xjm’s picture

Issue tags: -Needs followup

#18: theme-settings-2040037-18.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Needs followup

The last submitted patch, theme-settings-2040037-18.patch, failed testing.

mtift’s picture

StatusFileSize
new4.79 KB

This is basically just a re-roll of #18

Where's the fallback? the if empty($theme_data) hunk below?

I think the hunk is back

Can we catch something more specific?

I couldn't find any other calls to Drupal::state() wrapped in try-catch blocks. We have a ConfigException, but I don't think we have anything like "StateException." So I guess we could create one like that extends RuntimeException, like this

class StateException extends RuntimeException {}

But, honestly, I'm not sure what that gets us. @xjm: did you have something in mind?

(And like a bazillion other issues, this one will need a re-roll if #2053489: Standardize on \Drupal throughout core gets in.)

mtift’s picture

Status: Needs work » Needs review
socketwench’s picture

Status: Needs review » Reviewed & tested by the community

Patch #23 works for me. ^_^

neclimdul’s picture

Status: Reviewed & tested by the community » Needs work

Ran into this separately. The problem is actually miss-described here. Or at least there's another solution. Conversion to the new route system will solve the problem.

neclimdul’s picture

StatusFileSize
new1.59 KB

To be more clear because that was a terrible comment, this is all that's needed to solve the 404 and conversion to yaml local tasks after #2076283: Allow local task plugins on paths with a dynamic value (like a node) solves tabs not showing up.

neclimdul’s picture

Status: Needs work » Needs review
StatusFileSize
new3.18 KB

with the route subscriber removed.

tim.plunkett’s picture

We just renamed all of the routes, it should be system.theme_settings now.

Status: Needs review » Needs work

The last submitted patch, drupal8.theme-system.2040037-28.patch, failed testing.

neclimdul’s picture

OK, I can't get the simple version of this patch to work anymore. I've got a more in depth conversion that does solve this that I can work or we can roll with the shifting around in #23.

neclimdul’s picture

Status: Needs work » Needs review
Issue tags: -Needs followup
StatusFileSize
new6.64 KB

#23 went in with #2089635: Convert non-test non-form page callbacks to routes and controllers. (thanks tim just stealing my code like that ;))

Follow up to fix/update tabs.

dawehner’s picture

+++ b/core/modules/system/lib/Drupal/system/Plugin/Derivative/ThemeLocalTask.php
@@ -0,0 +1,36 @@
+ * Provides block plugin definitions for custom menus.
+ *
+ * @see \Drupal\system\Plugin\Block\SystemMenuBlock
+ */

Just a copy and paste of another derivative.

neclimdul’s picture

StatusFileSize
new77.8 KB

Dangit, I saw that a while back while waiting for the param patch and forgot to fix it.

neclimdul’s picture

StatusFileSize
new1.01 KB

oh and interdiff because i wasn't lazy just forgetful.

Status: Needs review » Needs work

The last submitted patch, drupal8.theme-system.2040037-34.patch, failed testing.

neclimdul’s picture

Status: Needs work » Needs review
dawehner’s picture

Status: Needs review » Needs work

This seems to be an rerole failure.

neclimdul’s picture

Status: Needs work » Needs review
StatusFileSize
new6.4 KB
dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Manual testing worked fine.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

Patch no longer applies.

mtift’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new6.02 KB

Reroll

markhalliwell’s picture

Status: Needs review » Reviewed & tested by the community

Re-roll just took out the system theme stuff, back to RTBC.

neclimdul’s picture

looks great thanks! theme stuff was just to get rid of test warning and someone fixed it first.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

Patch no longer applies.

tim.plunkett’s picture

Status: Needs work » Needs review
StatusFileSize
new6.2 KB

This was trying to add system.local_tasks.yml but HEAD has it now.

tim.plunkett’s picture

Issue tags: -Needs reroll

.

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you!

xano’s picture

#46: theme-2040037-46.patch queued for re-testing.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

Patch no longer applies.

xano’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new6.38 KB
neclimdul’s picture

Status: Needs review » Closed (duplicate)

#2102125: Big Local Task Conversion actually has these changes. We might consider committing it instead, its pretty close.

neclimdul’s picture

Issue summary: View changes

Updated issue summary.