Make WordPress Core

Opened 7 years ago

Closed 6 years ago

#43228 closed defect (bug) (wontfix)

register_theme_directory() needs to delete the `theme_roots` transient

Reported by: johnbillion's profile johnbillion Owned by: johnbillion's profile johnbillion
Milestone: Priority: normal
Severity: normal Version:
Component: Themes Keywords: has-unit-tests needs-patch
Focuses: Cc:

Description

Calling register_theme_directory( '/path/to/themes' ) adds an element to the global $wp_theme_directories array.

When WordPress attempts to load the active theme, it ultimately calls get_theme_roots() which first checks for a cached value in the theme_roots transient before looking at the $wp_theme_directories global. This transient does not get deleted when register_theme_directory() is called, therefore if get_theme_roots() gets called before register_theme_directory() then the theme directory registration will silently fail due to the use of a stale cache of registered theme directories.

get_theme_roots() is ultimately called by several theme-related functions, such as wp_get_themes() and wp_get_theme(), so it's reasonable to expect that get_theme_roots() might get called before register_theme_directory().

register_theme_directory() should delete the theme_roots cache in order to avoid this problem.

This bug has manifested itself in the WP-CLI theme test scaffolding command, which calls register_theme_directory() on the muplugins_loaded hook, which means the theme_roots transient has already been populated with registered theme directories.

Attachments (2)

43228.diff (340 bytes) - added by johnbillion 7 years ago.
43228.tests.diff (799 bytes) - added by soulseekah 7 years ago.
The tests.

Download all attachments as: .zip

Change History (13)

@johnbillion
7 years ago

#1 @johnbillion
7 years ago

  • Keywords has-patch added; needs-patch removed

Patch. Needs some tests.

@soulseekah
7 years ago

The tests.

#2 @soulseekah
7 years ago

  • Keywords has-unit-tests added; needs-unit-tests removed

Why not use wp_clean_themes_cache() instead? It gives us the benefit of regenerating the cache and clearing the theme updates cache in case the newly added directory contains outdated themes.

Both versions make the tests pass. The test fails without @johnbillion's patch or the wp_clean_themes_cache() version thereof.

Last edited 7 years ago by soulseekah (previous) (diff)

#3 @johnbillion
7 years ago

  • Milestone changed from Awaiting Review to 5.0
  • Owner set to johnbillion
  • Status changed from new to reviewing

#4 @johnbillion
7 years ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 42788:

Themes: Ensure the theme roots cache is cleared when registering a theme directory.

Props soulseekah, johnbillion

Fixes #43228

#5 @gitlost
7 years ago

The call to wp_clean_themes_cache() shouldn't be done on installing I think, so need somthing like

	if ( ! wp_installing() ) {
		wp_clean_themes_cache();
	}

otherwise get WordPress database error notices from wpdb, see https://travis-ci.org/wp-cli/wp-cli/jobs/349573438

#6 @afragen
7 years ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

Calling wp_clean_themes_cache() this early in the load process renders the filter 'extra_themes_headers' in get_file_data() of wp-includes/functions.php useless as a call from any other source.

@johnbillion this breaks stuff. Try adding any additional theme headers using the above filter hook and you will see.

Last edited 7 years ago by afragen (previous) (diff)

#7 @afragen
7 years ago

  • Keywords dev-feedback added

#8 @dd32
7 years ago

register_theme_directory() is intended to run on every page load AFAICT, so ultimately deleting the theme_roots transient or update_themes option isn't a viable option for calling within register_theme_directory().

I suspect that calling search_theme_directories( true ) within the branch that actually appends within register_theme_directory() will be a bit better, but it'll still cause unexpected IO to happen when the theme roots hasn't actually changed from what's in the transient (ie. this directory was registered on the last page load too).

I think that search_theme_directories() and get_theme_roots() needs to hash $wp_theme_directories and include that as part of it's transient name, which should solve both the reported issue and the issue of extra IO.

Either way, The patch as committed needs reverting.

#9 @johnbillion
7 years ago

In 42816:

Themes: Revert [42788] as it breaks a lot of things.

See #43228

#10 @johnbillion
7 years ago

  • Keywords needs-patch added; has-patch dev-feedback removed
  • Milestone changed from 5.0 to Future Release

#11 @johnbillion
6 years ago

  • Milestone Future Release deleted
  • Resolution set to wontfix
  • Status changed from reopened to closed
Note: See TracTickets for help on using tickets.