New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix incorrect usage of setup_theme action for theme supports #5574
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, so am approving based on code alone. My only question is whether this hook was selected on purpose? E.g., could there be some unintentional side effects where some block data or settings get instantiated between setup_theme
and after_setup_theme
and assume that theme support has already been established?
I assume not, since all tests are still passing.
@@ -521,7 +521,7 @@ | |||
*/ | |||
// Theme. | |||
add_action( 'setup_theme', 'create_initial_theme_features', 0 ); | |||
add_action( 'setup_theme', '_add_default_theme_supports', 1 ); | |||
add_action( 'after_setup_theme', '_add_default_theme_supports', 1 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I remember (been a while), this hook was selected to align to the above hook that creates the theme features. Notice the priority order:
- 0 for creating the initial theme features
- 1 for adding the default theme supports
Here's the PR that added it #2029.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hellofromtonya I understand that the _add_default_theme_supports()
function must be called after create_initial_theme_features()
, but I don't think it needs to be right after.
Looking at the PR #2029, I don't see any discussion or reasoning on why it was decided to use the setup_theme
action immediately after the create_initial_theme_features()
callback. Given the lack of an explanation, I assume it was simply chosen because that's what create_initial_theme_features()
used, and because the _add_default_theme_supports()
should fire after that.
The problem with that approach is: While the available theme features in general should be registered on setup_theme
, actually adding theme supports based on the current theme needs to happen only on after_setup_theme
, as outlined in the PR description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the available theme features in general should be registered on setup_theme, actually adding theme supports based on the current theme needs to happen only on
after_setup_theme
, as outlined in the PR description.
Why should Core itself register to 'after_theme_setup'
? Shouldn't it set itself up before themes get loaded into memory?
Because without the activated theme loaded into memory, how would Core know what default supports to add? _add_default_theme_supports()
checks if the activated theme is a block theme. Aha.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should Core itself register to
'after_theme_setup'
? Shouldn't it set itself up before themes get loaded into memory?
Because before the after_setup_theme
, the current theme is still being set up, including potentially overriding what the current theme is, as the Customizer does. So only after the setup_theme
action (i.e. during the after_setup_theme
action) we truly know what the current theme is.
It's also worth noting that all features that _add_default_theme_supports()
adds are not block theme specific. These features are added in classic themes as well, including all classic default themes of the past 5+ years. The themes do it on after_setup_theme
, so core should do it too. The reason that core even handles it for block themes is to avoid the need for block theme developers to implement a functions.php
file just for these default features, which improves the developer experience.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's also worth noting that all features that _add_default_theme_supports() adds are not block theme specific.
For clarity, I was referring to:
function _add_default_theme_supports() {
if ( ! wp_is_block_theme() ) {
return;
}
where the function bails out if the theme is not a block theme. More specifically, I was mentally wrestling with: what is the state of that check when hooked into setup_theme
?
Was it working as intended?
Backtracing the logic, yes, it does work, because wp_get_theme()
can be populated by the activated theme in the 'stylesheet'
option. Thus, the theme did not need to be set up for this to work.
That part of the logic working though is not necessarily relevant to the bug being reported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me clarify with an example of how this being hooked into setup_theme
does not work as expected:
- Your site uses a block theme (e.g. Twenty Twenty-Three).
- On Appearance > Themes, you click "Live Preview" for a classic theme, e.g. Twenty Twenty-One.
- In the live preview, Twenty Twenty-One will now have all the "theme supports" from
_add_default_theme_supports()
, which is a bug, as those theme supports should only be added when the theme is a block theme. Now the theme features added based on the assumption that the current theme is a block theme are present, even though the previewed theme is a classic theme.
The reason for that is that at the setup_theme
action, WordPress still "thinks" the current theme is a block theme and thus adds the theme supports. The Customizer however overrides the current theme for the preview to be the classic theme only after that, and this logic has been present in WordPress core for many many years, far longer than when this bug was introduced. Therefore the after_setup_theme
action must be used for this.
The problem with the existing code is not that there is no theme set up. The problem is that the incorrect theme is set up at that point when considering the live preview.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my previous points, please also see https://developer.wordpress.org/reference/hooks/after_setup_theme/:
[This action] is generally used to perform basic setup, registration, and init actions for a theme.
add_theme_support()
is part of this basic setup, and should not be used on setup_theme
. Themes are not even able to hook into setup_theme
as it runs before the current theme files are being loaded.
Also https://developer.wordpress.org/reference/hooks/setup_theme/:
Fires before the theme is loaded.
Note the "before". This action must not be used to initialize specific logic that is part of the theme.
I share the concerns @joemcgill expressed:
While it fixes Customizer theme live preview, what might it do to block powered sites? Is something dependent upon on it? Not sure, but should be validated with careful testing within the editors and front-end. |
I have checked the WordPress core codebase for further usage of the |
@hellofromtonya I've tested this PR using the Site Editor for a bit, with both Twenty Twenty-Three and Twenty Twenty-Four, and couldn't find any problems. It also fixes the original Customizer bug. I personally think this change is safe to make, though of course any additional testing would be appreciated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed this patch does fix the reported bug as live theme previews are restored in Customer.
Also confirmed, the patch does not change the behavior for block themes.
See my testing report in the Trac ticket.
LGTM 👍 Ready for commit.
Committed in https://core.trac.wordpress.org/changeset/57009 |
This fixes the bug of using the
setup_theme
action for adding theme support, which is incorrect for such purposes, as at that point the current theme is not set up yet. For example, Customizer previewing, which may exchange the current theme at runtime only fires onsetup_theme
.Therefore any code depending on the current theme must only run after that, i.e. on
after_setup_theme
. This is also the hook which theme authors have been encouraged for more than a decade to use to add theme supports.See https://core.trac.wordpress.org/ticket/59732#comment:2 for additional context.
Trac ticket: https://core.trac.wordpress.org/ticket/59732
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.