Drupal\Core\Theme\Registry usually works like this:
- In the constructor, $theme_name is NULL.
- When first needed, Registry->init() is called with $this->themeName, which at this time is NULL.
- This fills $this->theme with the current theme, whereas $this->themeName is still NULL.
- Later, $this->registry[$this->theme->getName()] may be filled with theme registry entries for the current theme.
- Later, $this->runtimeRegistry[$this->theme->getName()] may be filled with the runtime registry for the current theme.
- There is no situation where $this->theme or $this->themeName or the result of $this->theme->getName() would be changed after its first initialization.
(at least I found none)
And if it would happen, it would probably break things.
Proposed change
We should remove all artifacts that suggest that Theme\Registry would support more than one theme:
$this->registry[$theme_name] becomes $this->registry.
$this->runtimeRegistry[$theme_name] becomes $this->runtimeRegistry.
$this->themeName should be initialized in $this->init().
- The parameter
$theme_name in $this->init() is redundant, and should be removed.
Follow-up
In a follow-up issue, we could make a proxy split, like so:
One class where $theme_name and $theme object are passed into the constructor.
This will contain most of the logic.
In this class we no longer need to worry about whether it has been initialized or not.
Another class which acts as a proxy layer, and which lazily creates the "real thing" when it is needed.
Comments
Comment #2
donquixote commentedComment #3
donquixote commentedLet's see if this breaks anything.
Locally this is a branch with various distinct commits:
EDIT: This will fail.
Comment #5
donquixote commentedIn #3 I forgot half of the required changes.
Trying again.
Comment #6
donquixote commentedComment #8
donquixote commentedTrying a patch which has only the CS changes and not the functional changes.
Comment #10
donquixote commentedI just notice that Registry->initialized is never set to TRUE in init()!!
Ouch.
This is a bug in 8.6.x.
Comment #11
donquixote commentedThe effect is:
Every call To ThemeManager->render() calls Registry->getRuntime()
which calls Registry->init()
which calls Registry->themeManager->getActiveTheme()
This means that, as soon as themeManager->activeTheme changes, ThemeManager->render() will render in the new active theme.
We could say this is great, it means theming functionality is always up to date.
But at what cost?
We repeat the same redundant operation each time we execute a theme hook. This is not right.
Comment #12
donquixote commentedTesting my hypothesis about ->initialized.
Comment #14
donquixote commented#12/#13 shows:
Drupal\Core\Theme\Registry::$initializedalways stays FALSE.$this->initializedinRegistry::init()is pointless.$this->themeManager->getActiveTheme()repeatedly.We can assume that this has a performance impact.
Comment #15
donquixote commentedSome clarification:
The problem here is NOT the "theme system" itself with its "theme hooks", which some consider archaic and want to modernize.
You can think what you want about this, but it is not the problem here.
The real problem here is how different components deal with the possibility that the "active theme" can change mid-request.
So, it is a question of how information and state travels in our architecture, the order in which stuff happens in bootstrap, how per-theme logic is organized.
This needs to be cleaned up, no matter if we switch to plugins or whatever else has been suggested afterwards.
Comment #16
donquixote commentedThis issue is not "Needs review". The patches were just to see what would happen.
Comment #26
andypostThere's a case when at least 2 themes are required - when you collect layouts from frontend (default theme) to display them as list at "manage display" pages (in admin theme)