Categorising themes by folders in backend

I want to organize themes like:

  1. wp-content/themes/themeshop/theme1
  2. wp-content/themes/themeshop/theme2
  3. 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?

Related posts

Leave a Reply

2 comments

  1. 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.

    multisite theme categories

    Much probably it’s possible to add a filter here.


    Result in a single site:
    Multisite not enabled. Folders /themes/defaults/ and /themes/others/.

    single site theme categories

    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.

  2. I think you are looking for an action hook or a filter to exclude your themes from the standard list of themes and create an extra list representing the folder structure. Or simplier grouping hemes by the folder they are in.

    If you open wp-admin/themes.php, you will see there is no action hook or filter. There are also no action hooks or filters in the used functions or the list class (WP_Themes_List_Table) where you can modify the list of themes.

    The only thing you can do is recode the complete process of displaying themes on the themes page and replace the link to the themes.php in the admin menu to your own script.