I want to organize themes like:
wp-content/themes/themeshop/theme1
wp-content/themes/themeshop/theme2
wp-content/themes/themeshop/theme3
Now from my understanding, this organization works perfectly at the folder level. I dropped themes in subdirectories and everything seems to work fine. Now is it possible to duplicate this categorization in the Administration backend on the themes page?
Updated plugin version available at GitHub.
I first saw your Question at [wp-hackers] list, and, after implementing the solution, was about to publish a Q&A for that. Well, it’s already here, and has a bounty put on it 🙂
As Daniel Bachhuber points out in the thread:
WordPress.com puts themes inside of subdirectories
/wp-content/themes/public
/wp-content/themes/premium
I came up with this solution to show that in the backend:
-
in Multisite, we can add a column in the Themes’ screen and show the info with manage_themes_custom_column
and manage_themes-network_columns
.
-
in single sites installations, the only entry point I found was in theme_action_links
.
<?php
/**
* Plugin Name: Theme Folders Categories
* Plugin URI: http://wordpress.stackexchange.com/q/96361/12615
* Version: 1.0
* Author: Rodolfo Buaiz
* Author URI: http://wordpress.stackexchange.com/users/12615/brasofilo
* License: GPLv2 or later
*/
class WPhackersSE_Theme_Folders
{
public function __construct()
{
add_action( 'plugins_loaded', array( $this, 'start_up' ) );
}
/**
* Hooks for Network themes and Single Site themes
* Nothing happens on sub-sites of a Network
*/
public function start_up()
{
if( is_network_admin() )
{
add_filter( 'manage_themes-network_columns', array( $this, 'column_register' ) );
add_action( 'manage_themes_custom_column', array( $this, 'column_display' ), 10, 3 );
add_action( 'admin_head-themes.php', array( $this, 'network_theme_category_css' ) );
}
elseif( !is_multisite() )
{
add_filter( 'theme_action_links', array( $this, 'theme_folder_single_site' ), 10, 2 );
add_action( 'admin_head-themes.php', array( $this, 'theme_category_css' ) );
}
}
/**
* Add custom category (folder) column in network themes
*
* @param array $columns
* @return array
*/
public function column_register( $columns )
{
$columns['theme_folder'] = 'Category';
return $columns;
}
/**
* Display custom row in network themes
* $stylesheet contains a string "folder/theme_name"
* $theme is a WP_Theme object
*
* @param string $column_name
* @param string $stylesheet
* @param object $theme
* @return string
*/
public function column_display( $column_name, $stylesheet, $theme )
{
if( 'theme_folder' != $column_name )
return;
echo $this->make_button( $stylesheet );
}
/**
* Adjust column width and button style in Multisite screen
*/
public function network_theme_category_css()
{
echo "<style type="text/css">
#theme_folder { width: 10% }
{$this->button_style()}
</style>";
}
/**
* Show theme category (folder) in single site theme action row
* $theme is a WP_Theme object
*
* @param array $actions
* @param object $theme
* @return array
*/
public function theme_folder_single_site( $actions, $theme )
{
array_unshift( $actions, $this->make_button( $theme->stylesheet ) );
return $actions;
}
/**
* Adjust button style in Single site screen
*/
public function theme_category_css()
{
echo "<style type="text/css">{$this->button_style()}</style>";
}
/**
* Common button for Multi and Single sites
* The category name is extracted from a string "folder/themefolder"
*
* @param object $theme
* @return string
*/
private function make_button( $stylesheet )
{
$button_category = sprintf(
'<a href="javascript:void(0)" class="button-secondary theme-folder" title="%1$s">%1$s</a>',
dirname( $stylesheet )
);
return $button_category;
}
/**
* Common style for Multi and Single sites
*
* @return string
*/
private function button_style()
{
return '.theme-folder {
cursor: default !important;
line-height: 15px !important;
height: 17px !important;
background-image: -webkit-gradient(linear, left top, left bottom, from(#DCFEDE), to(#CBEBCD)) !important;
background-image: -webkit-linear-gradient(top, #DCFEDE, #CBEBCD) !important;
background-image: -moz-linear-gradient(top, #DCFEDE, #CBEBCD) !important;
background-image: -o-linear-gradient(top, #DCFEDE, #CBEBCD) !important;
background-image: linear-gradient(to bottom, #DCFEDE, #CBEBCD) !important;
}';
}
}
new WPhackersSE_Theme_Folders;
Result in Multisite:
Folders /themes/clientes/
and /themes/brasofilo/
). There’s no output in sub-sites of the network.

Much probably it’s possible to add a filter here.
Result in a single site:
Multisite not enabled. Folders /themes/defaults/
and /themes/others/
.

This screen is really limited in terms of customization. I agree with @Ralf912 analysis.
Important note: after moving active themes into sub-folders, all sites lose its theme configuration, each site theme has to be set again.