WordPress.org

Make WordPress Core

Opened 4 years ago

Last modified 4 months ago

#12877 new feature request

Modular themes: Apply template hierarchy to folders within a theme

Reported by: koopersmith Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Themes Keywords: has-patch
Focuses: Cc:

Description

Applying template heirarchy to folders within a theme will allow themes to be broken into modules, allowing theme developers to substantially reduce repeated code. This is an automated, complete version of the use of get_template_part() in Twenty Ten.

I've written posts on the justification for modular themes and their potential to transform theme organization.

Based on my tests, these functions should cause no noticeable difference in performance.

The patch has the added benefit of creating an accurate global $wp_template_hierarchy object (and a getter method), so any plugin/theme can access the template hierarchy for $wp_query.

The patch introduces several new functions: get_template_module($folder), get_template_hierarchy(), update_template_hierarchy(), and 2 private functions.

Finally, the patch also add a 'locate_template' filter on $template_names at the beginning of locate_template(), and turns the large conditional in template-loader.php into a function: template_loader().

Attachments (5)

12877.1.patch (6.9 KB) - added by koopersmith 4 years ago.
12877.2.patch (6.6 KB) - added by koopersmith 4 years ago.
12877.patch (4.0 KB) - added by scribu 4 years ago.
refresh
12877.4.patch (4.2 KB) - added by scribu 4 years ago.
use load_template()
12877.5.patch (4.2 KB) - added by scribu 4 years ago.
Don't include() directly in get_template_module()

Download all attachments as: .zip

Change History (53)

koopersmith4 years ago

comment:1 jane4 years ago

  • Component changed from Template to Themes
  • Type changed from enhancement to feature request
  • Version set to 3.0

I think this is a big enough change to be labeled feature request. Have also added Themes as component.

comment:2 koopersmith4 years ago

  • Summary changed from Modular themes: Apply template heirarchy to folders within a theme to Modular themes: Apply template hierarchy to folders within a theme

Hah, the one time I spell hierarchy wrong, it's in the title and the first line.

comment:3 nacin4 years ago

Interesting concept. This is something that should be brought up when 3.0 is out the door.

Related on a much smaller scale: #11216.

Also, _prevent_template_include can become __return_false.

comment:4 scribu4 years ago

  • Keywords has-patch added
  • Milestone changed from Unassigned to Future Release

I like the idea too.

koopersmith4 years ago

comment:5 koopersmith4 years ago

nacin: Didn't know about __return_false, thanks. Added.

Also, #11216 would be a nice addition. Currently, if using modules, you'd have to declare a page template in the root dir and redirect it to index.php (assuming you didn't want custom structure for the page template).

I expected this to be a 3.1 discussion (as per the @since blocks), but I figured I might as well bring it up now.

comment:6 filosofo4 years ago

I think this is a promising idea. Since it can be implemented via plugin, why don't you create the plugin and get a few theme developers to use it? Getting their feedback while it's still relatively malleable (in other words, as a plugin rather than in core) and seeing it used in practice would be among the best ways to demonstrate its worth as a core feature.

comment:7 rovo894 years ago

  • Cc wordpress@… added

comment:8 mikeschinkel4 years ago

  • Cc mikeschinkel@… added

comment:9 aaroncampbell4 years ago

  • Cc aaron@… added

comment:10 sbressler4 years ago

  • Cc sbressler@… added

comment:11 F J Kaiser4 years ago

  • Cc 24-7@… added

+1
I would def. test it as a plugin at my themes. As far as i read your thoughts on your blog, i agree in most parts. My thoughts about it here (you got no comments on your blog):

  • Ptha Dunbars idea of get_template_file sounds better to me, because it's more flexible and better explains the idea of "get a module-file" to a not-pro-wp-user.

Just to describe another (not perfect) approach on this:
My custom version of a folder-module_file-approach differs in 3 basic folders in the root: /js/, /lib/ and /ui/. That makes it more easy to separate between script, styles&images and content.
Subfolders of /lib/ are /head/ (doctype and wp_enqueue_* script/style), /func/ (hooks, shortcodes, module-calling-file) and /mod/ (all different modules)
Everything just hooks into page-templates
As i sayed: not perfect and doesn't fit straight into template-hierarchy.

comment:12 demetris4 years ago

  • Cc dkikizas@… added

comment:13 beaulebens4 years ago

  • Cc beau@… added

comment:14 willnorris4 years ago

  • Cc willnorris added

really curious whatever happened to this idea. I'm sorry I stumbled upon it so late after it was proposed, since it now looks like it clearly won't be in 3.0. While it does make the theme structure *slightly* more complicated by adding a couple of folders, it makes everything significantly cleaner. Feels somewhat similar to how Carrington operates, but in a much more manageable (and easier to grok) fashion.

comment:15 rspindel4 years ago

  • Cc rspindel added

comment:16 F J Kaiser4 years ago

If i understood the patch right: The only draw back (of this first version) i can currently see is that the file($template_name) get_template_module($folder) searches for must be an exact match. That would only allow one file per template. If this would be a little extended with something like ex. a preg_match that works with some sort of hierarchical order (for ex. page-xy.php) this would be a nice addition that could make a lot of people pretty happy (looking at a lot of frameworks or theme-bases that work that way - see the list promoted by wordpress.org themself: all use something to get out of the flat scheme).

comment:17 willnorris4 years ago

@FJKaiser: I'm not sure I follow. get_template_module() supports all the same template file names that the normal template system supports. So if I call get_template_module('foo') during a request for an author page, then it will try to load the following template files, stopping at the first one it finds:

  • STYLESHEETPATH . "/foo/author-{$author}.php"
  • TEMPLATEPATH . "/foo/author-{$author}.php"
  • STYLESHEETPATH . "/foo/author-{$author_id}.php"
  • TEMPLATEPATH . "/foo/author-{$author_id}.php"
  • STYLESHEETPATH . "/foo/author.php"
  • TEMPLATEPATH . "/foo/author.php"

And if a plugin implements the author_template filter to provide an alternate template name, that will be applied to get_template_module() as well.

comment:18 F J Kaiser4 years ago

As i said "If i understood the patch right" ... thanks for explaining :)

comment:19 willnorris4 years ago

oops... the last part I mentioned about the 'author_template' filter is not correct. that would not actually effect the template files that get_template_module() looks for.

comment:20 scribu4 years ago

With the current patch, trying to alter the top-level hierarchy causes problems:

Say I want to add an 'author-{role}.php' top-level template. So, I hook into 'author_template':

function author_role_template( $old_template ) {
  // get current author's role

  $new_template = locate_template( array( "author-$role.php" ) );

  if( $new_template )
    return $new_template;

  return $old_template;
}

update_template_hierarchy(); will miss that, so you won't have access to "/module/author-editor.php" etc.

What would be needed is a filter applied to the array before it's passed to locate_template():

$templates = apply_filters( 'author_template_pre', $templates );

$template = locate_template( $templates );

Actually, I think that would be useful independent of the current proposal. I'll oepn a separate ticket.

comment:21 scribu4 years ago

And here it is: #14310

comment:22 ramoonus4 years ago

  • Cc ramoonus@… added

scribu4 years ago

refresh

comment:23 follow-up: scribu4 years ago

With the current patch, the template files are not loaded in the global scope anymore, causing all sorts of trouble.

Noticed this with the tag.php file in P2:

http://svn.automattic.com/wpcom-themes/p2/tag.php

Specifically, this line: <?php $tag_obj = $wp_query->get_queried_object(); ?>

comment:24 in reply to: ↑ 23 nacin4 years ago

Replying to scribu:

With the current patch, the template files are not loaded in the global scope anymore, causing all sorts of trouble.

I believe you're referring to the fact that core currently uses load_template() which extracts a ton of query variables into the global namespace. Yes, it would make sense for this to leverage that function.

scribu4 years ago

use load_template()

comment:25 scribu4 years ago

Indeed, using load_template() fixes the problem. See 12877.4.patch.

scribu4 years ago

Don't include() directly in get_template_module()

comment:26 willnorris4 years ago

One minor thing I added in my implementation was to include: $template_namess[] = $module . '.php' in get_template_module(), so that it behaves a little more similarly to get_template_part(). Because of this, I also renamed $folder to $module since it isn't strictly looking in a folder. So you end up with:

function get_template_module( $module ) { 
    $template_hierarchy = get_template_hierarchy(); 
    $template_names = array();
    foreach( $template_hierarchy as $template_name ) {
        $template_names[] = $module . '/' . $template_name;
    }
    $template_names[] = $module . '.php';
 
     return locate_template($template_names, true);
} 

This also makes a secondary use case of get_template_module() a lot cleaner. I break up my entry markup so that it is easier to override them in a child theme. (see: https://github.com/willnorris/pdx-theme/blob/master/loop/index.php). With this extra template name, I can simply have entry/title.php template files instead of needing entry/title/index.php.

comment:27 azizur3 years ago

  • Cc azizur added

comment:28 svallory3 years ago

  • Cc svallory added
  • Version changed from 3.0 to 3.1

comment:29 scribu3 years ago

  • Version 3.1 deleted

Since this isn't a bug, the version field isn't really useful.

comment:30 follow-up: scribu3 years ago

FYI: this has been implemented as a plugin:

https://github.com/willnorris/template-modules

Version 0, edited 3 years ago by scribu (next)

comment:31 GreenDude3 years ago

  • Cc GreenDude added

comment:32 gruvii3 years ago

  • Cc gruvii added

You might want to look at some of the ways Carrington implemented a system like this that is now in version 3.1. I used it very extensively for a while and it has a great hierarchical template matching system.

http://carringtontheme.com/2010/11/carrington-core-3-1/

Last edited 3 years ago by gruvii (previous) (diff)

comment:33 in reply to: ↑ 30 gruvii3 years ago

Replying to scribu:

Scribu, will this or Will Norris's plugin work if I apply your #14310 patch?

Last edited 3 years ago by gruvii (previous) (diff)

comment:34 scribu3 years ago

Will Norris's plugin will work with the patch on #14310, yes. I'm currently using it on a live site.

comment:35 scribu3 years ago

Just wanted to throw in an alternative way of removing duplicate code:

http://scribu.net/wordpress/theme-wrappers.html

It's more restricted than template modules, in the sense that the template hierarchy isn't traversed again for each part.

comment:36 ciobi3 years ago

  • Cc alex.ciobica@… added

comment:37 johnbillion3 years ago

  • Cc johnbillion@… added

comment:38 navjotjsingh3 years ago

  • Cc navjotjsingh@… added

comment:39 WraithKenny3 years ago

  • Cc Ken@… added

comment:40 bainternet2 years ago

  • Cc admin@… added

comment:41 emzo2 years ago

  • Cc emzo added

comment:42 retlehs15 months ago

  • Cc retlehs added

comment:43 aniketpant15 months ago

  • Cc me@… added

comment:44 mau12 months ago

  • Cc ngomau@… added

comment:45 follow-up: christianmagill4 months ago

Is the mentioned plugin still current, and what needs to happen for this feature to be included in a future release. It seems really useful for ridding themes of duplicate code, but looks like it has been forgotten.

comment:46 in reply to: ↑ 45 willnorris4 months ago

Replying to christianmagill:

Is the mentioned plugin still current, and what needs to happen for this feature to be included in a future release. It seems really useful for ridding themes of duplicate code, but looks like it has been forgotten.

Obviously I haven't touched the plugin in several years, and don't actually use it myself anymore (I've moved to Genesis-based themes, which has its own way of doing things which I've really come to like). Though I'm not sure that much has changed in that time with regard to how theme templates work, so I suspect it's still "current" in the sense that it should still work. There certainly doesn't seem to be anyone strongly advocating for getting this into core anymore though.

comment:47 follow-up: christianmagill4 months ago

Thanks,

It's a shame, seems like a really great idea.

Would something like the ticket mentioned above,

https://core.trac.wordpress.org/ticket/14310

, allow the functionality to be added in a more future-proof way without duplicating the template selection logic?

comment:48 in reply to: ↑ 47 willnorris4 months ago

Replying to christianmagill:

Thanks,

It's a shame, seems like a really great idea.

Would something like the ticket mentioned above,

https://core.trac.wordpress.org/ticket/14310

, allow the functionality to be added in a more future-proof way without duplicating the template selection logic?

actually, it looks like I was already relying on the {$type}_template_hierarchy filter from #14310 which I believe was later reverted. So maybe my template-modules plugin doesn't work anymore after all.

Note: See TracTickets for help on using tickets.