Moving a Theme Between Theme Roots

TL;DR:

> mv wp-content/themes/foo wp-content/themes-private/foo
> wp shell
wp> update_option( 'template_root', '/themes-private' );
wp> update_option( 'stylesheet_root', '/themes-private' );
wp> delete_site_transient( 'theme_roots' );

Background

WordPress allows you to have multiple theme directories inside your content folder, via register_theme_directory(). Having multiple theme folders is great, because it lets you organize large codebases better, pull themes from multiple version control repositories (without a mess of externals/submodules), etc.

Every registered directory has a corresponding theme root, which is just its relative path to the content folder. For example, if you have the default /home/foo/public_html/wp-content/themes folder, and then register /home/foo/public_html/wp-content/themes-private as an additional folder, then the theme roots will be /themes and /themes-private.

Problems Moving Between Theme Roots

As great as having multiple theme directories is, you may[1] run into a problem if you try to move an active theme from one root to another, in the form of this nasty fatal when loading the front end:

The theme directory "{theme slug}" does not exist.

This happens because locate_template() relies on TEMPLATEPATH and STYLESHEETPATH, which are ultimately  based on get_option( 'template_root' ) and get_option( 'stylesheet_root' ). Those are only set/updated when switching themes, so they’re stuck at the old values until you fix them.

The theme_roots site transient also maps theme slugs to theme roots, and needs to be refreshed.

The Solution

Fixing them is as simple as calling update_option() and delete_site_transient() from WP-CLI or an mu-plugin:

> mv wp-content/themes/foo wp-content/themes-private/foo
> wp shell
wp> update_option( 'template_root', '/themes-private' );
wp> update_option( 'stylesheet_root', '/themes-private' );
wp> delete_site_transient( 'theme_roots' );

 

[1] – Because the options are only set when switching themes, you may not run into the problem at all.

[2] – You can also delete them instead of updating them, but I haven’t looked into potential side-effects of that.

 

Leave a Reply

Your email address will not be published. Required fields are marked *