3

I have a theme where the developer used get_tempalate_part() a lot, and these parts are scattered across theme subdirectories as well as in directories in a plugin that was created to assist with the theme.

Here is the code I'm using to understand the primary template being called (the parent template, for lack of better words):

add_action('wp_head', 'show_template');
function show_template() {
    global $template;
    print_r($template);
}

show_template();

This works fine, but it shows only the location of the parent template file. What code can I use to find out what and where from the template parts are being called?

1

4 Answers 4

3

You can view the template part by using get_template_part($slug) It’s one of those hidden gems inside of WordPress that don’t get the attention they deserve. The get_template_part function is essentially a PHP include or require, on steroids:

It already knows where your theme is located and it will look for the requested file in that theme’s directory

It doesn’t issue a warning or fatal out if the requested file does not exist

It can search for other suitable files, if the requested one is not found

It knows about child themes and parent themes

Long story short, the get_template_part function allows you to break your theme down into smaller templates (or template parts), which can be reused across your other templates.

For example:

get_template_part( 'navigation', get_post_type() );

Where get_post_type() will return the name of the post type that is currently shown, so if we’re on a Post, it’ll attempt to load navigation-post.php and fallback to navigation.php. If we’re on a Page, navigation-page.php and navigation.php. If we’re looking at a custom post type, say a Book, it will look for navigation-book.php and fall back to navigation.php.

The real power of get_template_part comes from a function called locate_template, which does the whole searching in parent theme and child theme folders, and the reverting to other templates in a stack. The get_template_part function simply builds an array of templates for locate_template to look for. Here’s a quick example:

get_template_part( 'one', 'two' );

Creates an array of “one-two.php” and “one.php” (in that specific order) and passes it on to locate_template, which then loops through that array and looks for the files in the child and parent themes directories. The order is really important here, it’s kind of why file names have priority over their locations (parent theme or child theme) and explains the reason behind the lookup sequence.

It’s also worth noting, that functions such as get_header, get_sidebar and get_footer are very similar to get_template_part with a sort of hard-coded first argument.

get_template_part is located in wp-includes/general-template.php and locate_template is in wp-includes/template.php.

1

Use this line, late in footer.php:

echo '<ul><li>'.implode('</li><li>', str_replace(str_replace('\\', '/', ABSPATH).'wp-content/', '', array_slice(str_replace('\\', '/', get_included_files()), (array_search(str_replace('\\', '/', ABSPATH).'wp-includes/template-loader.php', str_replace('\\', '/', get_included_files())) + 1)))).'</li></ul>';

Written at:

How do you find out which template page is serving the current page?

if admin-bar stuff path is showing at the top, or any other file, change the filename template-loader.php in this line of code to: whatever filname you need to break from.

if you need this in the admin bar, use the right priotity (earliest) to make shure no files are entered at the end of this list. For example:

add_action('admin_bar_menu', 'my_adminbar_template_monitor', -5);

priority -5 make shure it loads first. The key is to render this line at the right moment.

Do some changes if your server using dubble-slashes.

More at: How do you find out which template page is serving the current page?

0

An easy way is to add some echo to each template file. Like <!--folder/filename.php-->

Best wrap that inside an if so it's only shown during debugging.

0

If you look at the code for the get_tempalate_part() function you'll see you can hook into the action get_template_part_{$slug}". As the variable $slug is an unknown, you'll have to get the variable from the template file itself.

The next example gets the theme template file used for the current page with the filter template_include. Then it uses the tokenizer to retrieve the $slug(s) from the get_template_part() function(s) inside the file. With the slug(s) known the get_template_part_{$slug} action is used to get the template paths. The templates paths are printed in the footer of the theme.

Note: The slugs used in get_template_part() inside the theme template files needs to be a string. If the theme uses another method of adding the parameter to the function (variable, constant etc) the slug (and therefore the path) will not be found. Don't use this example in production.

Display_Get_Template_Part_Path_In_Footer::on_load();

class Display_Get_Template_Part_Path_In_Footer {

    static $templates = array();

    public static function on_load() {
        add_filter( 'template_include',  array( __CLASS__, 'read_theme_template' ), 99 );
        add_action( 'wp_footer', array( __CLASS__, 'wp_footer' ), 100 );
    }

    public static function wp_footer() {
        // print templates in footer
        if ( !empty( self::$templates ) ) {
            echo '<pre>';
            print_r( array_unique( self::$templates ) );
            echo '</pre>';
        } else {
            echo "<p>no get_template_part() found</p>";
        }
    }

    public static function read_theme_template( $template ) {

        $tokens = token_get_all( file_get_contents( $template ) );

        foreach ( $tokens as $index => $token ) {

            $name = is_array( $token ) ? token_name( $token[0] ): '';
            $value = is_array( $token ) ? $token[1] : $token;

            if ( !( ( 'T_STRING' ===  $name ) && ( 'get_template_part' === $value ) ) ) {
                continue;
            }

            // function name 'get_template_part' found, get next tokens
            $next = isset( $tokens[ $index + 1 ] ) ? $tokens[ $index + 1 ] : '';
            $next_id = isset( $tokens[ $index + 1 ][0] ) ? $tokens[ $index + 1 ][0] : '';
            $second_next = isset( $tokens[ $index + 2 ] ) ? $tokens[ $index + 2 ] : '';

            if ( '(' === $next || ( T_WHITESPACE === $next_id ) && ( '(' === $second_next ) ) {

                $slug = self::get_template_slug( $tokens, $index+1 );
                if ( !empty( $slug ) ) {
                    add_action( "get_template_part_{$slug}", array( __CLASS__, 'get_template_part' ), 15, 2 );
                }
            }
        }

        return $template;
    }

    // get's first T_CONSTANT_ENCAPSED_STRING ($slug argument)
    public static function get_template_slug( $tokens, $index ) {

        $slug = '';
        $brackets = 0;
        $function_tokens = array_slice( $tokens, $index );

        foreach ( $function_tokens as $key => $token ) {

            $name = isset( $token[0] ) ? token_name( $token[0] ) : '';

            if ( $token === '(' ) {
                ++$brackets;
                continue;
            }

            if ( $brackets === 0 ) {
                continue;
            }

            if ( ( ( $token === ')' ) && ( --$brackets === 0 ) ) || ( ',' === $token ) ) {
                break;
            }

            if ( ( 'T_CONSTANT_ENCAPSED_STRING' === $name ) ) {
                $slug = sanitize_title( $token[1] );
                break;
            }
        }

        return $slug;
    }

    // function copied from WP Core (returns template path)
    public static function get_template_part( $slug, $name = null ) {
        $templates = array();
        $name = (string) $name;
        if ( '' !== $name )
            $templates[] = "{$slug}-{$name}.php";

        $templates[] = "{$slug}.php";

        // get template without loading the file
        self::$templates[] = locate_template( $templates, false, false );
    }

}
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.