2

I am following a tutorial that will hopefully allow me to insert templates straight from my plugin into WordPress. I am using the template_include filter, I can't get my head around how the whole filter process works.

Here is the code.

public function view_project_template( $template ) {

    global $post;

    if (!isset( $this->templates[get_post_meta($post->ID, '_wp_page_template', true ) ] ) ) {
        return $template;
    }

    $file = plugin_dir_path(__FILE__) . get_post_meta( $post->ID, '_wp_page_template', true );

    if ( file_exists( $file ) ) {
        return $file;
    }
    else {
        echo $file;
    }

    return $template;

}

I understand the filter takes one argument $template but then at the end when I return $template I haven't affected it in anyway. How does this then affect the filter? Would be great to get this cleared up.

0

3 Answers 3

1

You are using the filter wrongly, that is why you might not get the desired result. Lets first look at the template_include filter which you can check out in wp-includes/template-loader.php (current version 4.3.1)

44  if ( defined('WP_USE_THEMES') && WP_USE_THEMES ) :
45          $template = false;
46          if     ( is_404()            && $template = get_404_template()            ) :
47          elseif ( is_search()         && $template = get_search_template()         ) :
48          elseif ( is_front_page()     && $template = get_front_page_template()     ) :
49          elseif ( is_home()           && $template = get_home_template()           ) :
50          elseif ( is_post_type_archive() && $template = get_post_type_archive_template() ) :
51          elseif ( is_tax()            && $template = get_taxonomy_template()       ) :
52          elseif ( is_attachment()     && $template = get_attachment_template()     ) :
53                  remove_filter('the_content', 'prepend_attachment');
54          elseif ( is_single()         && $template = get_single_template()         ) :
55          elseif ( is_page()           && $template = get_page_template()           ) :
56          elseif ( is_singular()       && $template = get_singular_template()       ) :
57          elseif ( is_category()       && $template = get_category_template()       ) :
58          elseif ( is_tag()            && $template = get_tag_template()            ) :
59          elseif ( is_author()         && $template = get_author_template()         ) :
60          elseif ( is_date()           && $template = get_date_template()           ) :
61          elseif ( is_archive()        && $template = get_archive_template()        ) :
62          elseif ( is_comments_popup() && $template = get_comments_popup_template() ) :
63          elseif ( is_paged()          && $template = get_paged_template()          ) :
64          else :
65                  $template = get_index_template();
66          endif;
67          /**
68           * Filter the path of the current template before including it.
69           *
70           * @since 3.0.0
71           *
72           * @param string $template The path of the template to include.
73           */
74          if ( $template = apply_filters( 'template_include', $template ) )
75                  include( $template );
76          return;
77  endif;

Because we are on a real page, the value of $template that is passed to the filter in line 74 will be the value of get_page_template() (because is_page() returned true) which value is filterable through the {$type}_template filter located in get_query_template() (which is used by get_page_template()).

OK, so we can tackle this two ways, either use template_include or page_template (remember the {$type}_template filter, here $type === 'page'). If you are going to use template_include, you will need to use the is_page() condition to target real pages only. If you use the page_template filter (which is more desired here), you do not need this check.

I'm not really sure what the following line is suppose to do, and most probably why your filter never reach beyond this section

if (!isset( $this->templates[get_post_meta($post->ID, '_wp_page_template', true ) ] ) ) {
    return $template;
}

Because you are dealing with true pages, _wp_page_template should always have a value, so all we really need to do is to check if our template exists inside the template and then returning it

You can try the following:

public function view_project_template( $template ) {

    // Use get_queried_object_id() to get page id, much more reliable
    $current_page_id = get_queried_object_id();

    $page_template = get_post_meta( 
        $current_page_id, // Current page ID
        '_wp_page_template', // Meta key holding the page template value
        true // Return single value
    );

    /**
     * You can add extra protection and make sure $page_template has a value
     * although it should not be really necessary
     */
    // if ( !$page_template )
        // return $template;

    $file = plugin_dir_path(__FILE__) . $page_template;

    // Check if file exists, if not, return $template
    if ( !file_exists( $file ) ) 
        return $template;

    // If we reached this part, we can include our new template
    return $template = $file; // Or you can simply do return $file;

}

You should then hook your method as follow (as this is inside a class)

add_filter( 'page_template', [$this, 'view_project_template'] );

Just a small thought here, why not make the method private as you would not want it available outside of the class

0

You have no effect, because you haven't done anything with $template - not that you have to. It doesn't really affect the filter anyway, I would rather say, the filter gives you the possibility to intervene in the process. On the other hand, if $file exists and you return it, then you should see an effect - provided that $file is different from $template.

0

What the filter - apply_filters($tag, $value) do is passes the 'value' argument to each of the functions 'hooked' (using add_filter) into the specified filter 'tag'. Each function performs some processing on the value and returns a modified value to be passed to the next function in the sequence.

In your case, you are checking whether your template file exists and if it exists you are returning the file. In that case, you are telling WordPress that load your file instead of original template that WordPress is trying to load. WordPress by default loads the template that is outputted from the filter

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.