How to: get main plugin/theme file?

There’re the functions get_theme_data(); & get_plugin_data(); – which both use get_file_data(); that needs a specific file as $input.

I got a set of classes that may be used by a plugin or a theme, without a specific location. Everything works, but I don’t know how i would determine what the main plugin or theme file is – I mean the one containing the comment header that holds the information (Version, Author, etc.) about the Theme/Plugin.

Related posts

Leave a Reply

3 comments

  1. You can get theme’s main file using following:

    $theme_info_file = trailingslashit( get_template_directory() ) . 'style.css';
    

    To get the plugin’s main file you need to know the plugin name. And then you can use following function:

    function get_plugin_file( $plugin_name ) {
        require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
        $plugins = get_plugins();
        foreach( $plugins as $plugin_file => $plugin_info ) {
            if ( $plugin_info['Name'] == $plugin_name ) return $plugin_file;
        }
        return null;
    }
    

    For example to get the plugin main file for Akismet.

    $akismet_plugin_file =  trailingslashit( WP_PLUGIN_DIR ) . get_plugin_file( 'Akismet' );
    
  2. How do get the comment header data of a theme OR plugin…

    … that holds a specific class.

    The following shows how you can drop a class inside any plugin or theme and still be able to get any theme or plugin data from the comment header. This is useful for updating settings/db-options for example.

    You don’t know:

    1. if it’s a plugin, mu-plugin or a theme
    2. and how deeply nested your container/root theme or plugin folder is.

    Notes:

    1. Works for mu-plugins too.
    2. Might not work if an additional theme directory was registered later (thanks to @toscho for the hint).
    3. Performance test for a theme shows 0.0042 sec. loading time on 1.000 runs.
    4. The following functions are meant to reside in a class.

    /**
     * Plugin root
     * @return Full Path to plugin folder
     */
    public function set_root_path() 
    {
        $_path = trailingslashit( str_replace( basename( __FILE__ ), "", plugin_basename( __FILE__ ) ) );
    
        // Allow overriding the location
        $_path = apply_filters( __CLASS__.'_root', $_path );
    
        return $this->_path = $_path;
    }
    
    
    /**
     * Gets the data of the base 'theme' / 'plugin' / 'wpmuplugin'
     * Performance: average loading time on a local (not vanilla) install for 1.000 runs: 0.0042 sec.
     * 
     * @param (mixed) $value
     * @return (array) $value | Theme/Plugin comment header data OR false on failure | default: 'Version'
     */
    public function get_data( $value = 'Version' )
    {
        // Class basename - String to Array
        $_path_data = explode( '/', $this->_path );
        // Get rid of the last element, as it's only a trailing slash
        array_pop( $_path_data );
        // reverse for faster processing
        krsort( $_path_data );
    
        // Themes basename
        $theme_roots = get_theme_roots();
        // In case some used register_theme_directory(); before
        // Might not work if an additional themes directory will be registered later
        // Thanks to @Thomas Scholz <http://toscho.de> for the hint
        if ( is_array( $theme_roots ) )
        {    
            foreach ( $_path_data as $_path_part )
            {
                foreach( $theme_roots as $root )
                {
                    if ( in_array( $root, $_path_data ) )
                        $_theme_root = $root;
                }
            }
        }
        else 
        {
            // Get rid of the leading slash
            $_theme_root = str_replace( '/', '', $theme_roots );
        }
    
        // Plugins basename
        $_plugin_root = basename( WP_PLUGIN_DIR );
    
    
        # >>>> get file & load data
        $base_file = '';
        // Themes
        if ( in_array( $_theme_root, $_path_data ) )
        {
            foreach ( search_theme_directories() as $folder => $data )
            {
                foreach ( $_path_data as $_path_part )
                {
                    if ( $_path_part == $folder )
                        $base_file = trailingslashit( $data['theme_root'] ).$data['theme_file'];
                }
            }
    
            $file_data = get_theme_data( $base_file );
        }
        // Plugins
        elseif( in_array( $_plugin_root, $_path_data ) )
        {
            $plugins = get_plugins();
            foreach ( $plugins as $plugin_file => $plugin_info )
            {
                $data   = explode( '/', $plugin_file );
                $file   = $data[1];
                foreach ( $_path_data as $_path_part )
                {
                    if ( $_path_part !== $file )
                        $base_file = WP_CONTENT_DIR.$_type.'/'.$data[0].'/'.$data[1];
                }
            }
    
            $file_data = get_plugin_data( $base_file );
        }
        // WPMU Plugins
        else
        {
            // MU plugins basename - compatible for older MU too
            // Thanks (again) to @Thomas Scholz <http://toscho.de> for the hint that mu plugins really exists
            $mu_plugin_dir = ! version_compare( $GLOBALS['wp_version'], '3.0.0', '>=' ) ? MUPLUGINDIR : WPMU_PLUGIN_DIR;
            $_mu_plugin_root = basename( $mu_plugin_dir );
    
            if ( ! in_array( $_mu_plugin_root, $_path_data ) )
                return false;
    
            $mu_plugins = get_mu_plugins();
            foreach ( $mu_plugins as $mu_plugin_file => $mu_plugin_info )
            {
                $data   = explode( '/', $mu_plugin_file );
                $file   = $data[1];
                foreach ( $_path_data as $_path_part )
                {
                    if ( $_path_part !== $file )
                        $base_file = WP_CONTENT_DIR.$_type.'/'.$data[0].'/'.$data[1];
                }
            }
    
            $file_data = get_plugin_data( $base_file );
        }
        # <<<< get file & load data
    
    
        // return
        if ( ! empty ( $file_data ) )
            return $file_data[ $value ];
    
        // return false to determine that we couldn't load the comment header data
        return false;
    }
    

    Usage Example:

    echo $this->get_data( 'Author' ); // The Plugin or Theme Author
    echo $this->get_data( 'Version' ); // The Plugin or Theme Version
    echo $this->get_data( 'Name' ); // The Plugin or Theme Name
    
  3. In a recent project I did, I used the following to get the main plugin file & data of my plugin from another file within my plugin, without having to hardcode anything:

    get_plugins( '/' . explode( '/', plugin_basename( __FILE__ ) )[0] );
    

    This will return the following:

    array (size=1)
      'main_plugin_file.php' => 
        array (size=11)
          'Name' => string 'Plugin Name' (length=11)
          'PluginURI' => string 'http://wordpress.org/plugins/plugin-folder/' (length=41)
          'Version' => string '1.0' (length=3)
          'Description' => string 'BlaBlaBla Something awesome.' (length=148)
          'Author' => string 'Max GJ Panas' (length=12)
          'AuthorURI' => string 'http://maxpanas.com' (length=19)
          'TextDomain' => string 'plugin-name' (length=11)
          'DomainPath' => string '/languages' (length=10)
          'Network' => boolean false
          'Title' => string 'Plugin Name' (length=11)
          'AuthorName' => string 'Max GJ Panas' (length=12)
    

    You can use this in whichever file within your plugin and it should work just fine and you shouldn’t need to worry about any of the files being renamed, paths changed, etc.

    To get the “path to main plugin file with plugin data” used by various functions such as is_plugin_active() and is_plugin_active_for_network(), from a file that is not the the main plugin file, use the following code:

     $plugin_dir  = explode( '/', plugin_basename( __FILE__ ) )[0];
     $plugin_file = array_keys( get_plugins( "/$plugin_dir" ) )[0];
    
     if ( is_plugin_active_for_network( "$plugin_dir/$plugin_file" ) ) // for example.
       // do stuff...