[wp-trac] [WordPress Trac] #60025: Changeset 57156 breaks themes that relied on update_option( 'stylesheet', '...' )

WordPress Trac noreply at wordpress.org
Tue Dec 19 02:35:34 UTC 2023


#60025: Changeset 57156 breaks themes that relied on update_option( 'stylesheet',
'...' )
--------------------------+------------------------
 Reporter:  blindmikey    |       Owner:  joemcgill
     Type:  defect (bug)  |      Status:  accepted
 Priority:  normal        |   Milestone:  6.4.3
Component:  Themes        |     Version:  6.4.2
 Severity:  critical      |  Resolution:
 Keywords:  needs-patch   |     Focuses:
--------------------------+------------------------
Changes (by joemcgill):

 * status:  reviewing => accepted
 * milestone:  Awaiting Review => 6.4.3


Comment:

 After spending some time trying to diagnose what's happening here, I think
 this bug was introduced by [56635], which deprecated the `TEMPLATEPATH`
 and `STYLESHEET` path constants in favor of `get_template_directory()` and
 `get_stylesheet_directory()`, respectively.

 The Sage theme, and probably others, were relying a specific race
 condition of `get_template_directory()`, where it initially gets called by
 `wp_templating_constants()` in `wp-settings.php` before the active theme's
 `functions.php` file is loaded, and thus, before filters the theme has
 added are applied. This resulted in the `TEMPLATEPATH` environment
 variable always being set to the value of `get_option( 'template' )` which
 was then used by `locate_template()` and a few other functions. After this
 environment value is set, the theme then filters the value of
 `get_template_directory()` back to the original location so that templates
 are loaded from a different path than what `get_template_directory()` will
 return.

 A reduced test case to reproduce this behavior is to do something like
 this in your functions.php file:

 {{{#!php
 <?php
 // Set the template path option to a different location.
 update_option( 'template', __DIR__ . '/templates' );

 // Filter `get_template()` back to the theme root.
 add_filter('template', function () {
     return __DIR__;
 });
 }}}

 The reason this issue was only visible starting in WP 6.4.2, is that the
 original change shipped in 6.4.0 cached the value of
 `get_template_directory()` to a static global variable the first time the
 function was called, similar to how the value was first set as the
 environment variable by `wp_templating_constants()`. However, this led to
 bugs like #59847. Once that cached value was reverted in [57156], the
 change in behavior to `locate_template()` became observable.

 We could consider fully reverting the change from [56635], but it I think
 doing so would be choosing to support unintended behavior here, since
 `get_stylesheet()` and `get_template()` (and their respective DB options)
 are meant to store the directory name of the current theme and parent
 theme (if applicable), not the path to where the theme stores it's
 template files (despite the fact that the naming convention used is easy
 to misunderstand).

 I think the proposed workaround here—filtering the `template_directory`
 and `stylesheet_directory` values is a better solution if you need the
 store templates in a different directory than the theme root, but we also
 may need to consider revising `locate_template()` to prefer the unfiltered
 template and stylesheet option values, rather than the filtered value to
 maintain backwards compatibility, or introduce a new filter to
 `locate_template()` that would more easily allow themes to load their
 templates from a different location without resorting to these types of
 workarounds.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/60025#comment:6>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list