WordPress.org

Make WordPress Core

Opened 6 years ago

Last modified 12 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 dev-feedback
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 6 years ago.
12877.2.patch (6.6 KB) - added by koopersmith 6 years ago.
12877.patch (4.0 KB) - added by scribu 6 years ago.
refresh
12877.4.patch (4.2 KB) - added by scribu 6 years ago.
use load_template()
12877.5.patch (4.2 KB) - added by scribu 6 years ago.
Don't include() directly in get_template_module()

Download all attachments as: .zip

Change History (54)

@koopersmith
6 years ago

#1 @jane
6 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.

#2 @koopersmith
6 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.

#3 @nacin
6 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.

#4 @scribu
6 years ago

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

I like the idea too.

@koopersmith
6 years ago

#5 @koopersmith
6 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.

#6 @filosofo
6 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.

#7 @rovo89
6 years ago

  • Cc wordpress@… added

#8 @mikeschinkel
6 years ago

  • Cc mikeschinkel@… added

#9 @aaroncampbell
6 years ago

  • Cc aaron@… added

#10 @sbressler
6 years ago

  • Cc sbressler@… added

#11 @F J Kaiser
6 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.

#12 @demetris
6 years ago

  • Cc dkikizas@… added

#13 @beaulebens
6 years ago

  • Cc beau@… added

#14 @willnorris
6 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.

#15 @rspindel
6 years ago

  • Cc rspindel added

#16 @F J Kaiser
6 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).

#17 @willnorris
6 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.

#18 @F J Kaiser
6 years ago

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

#19 @willnorris
6 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.

#20 @scribu
6 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.

#21 @scribu
6 years ago

And here it is: #14310

#22 @ramoonus
6 years ago

  • Cc ramoonus@… added

@scribu
6 years ago

refresh

#23 follow-up: @scribu
6 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(); ?>

#24 in reply to: ↑ 23 @nacin
6 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.

@scribu
6 years ago

use load_template()

#25 @scribu
6 years ago

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

@scribu
6 years ago

Don't include() directly in get_template_module()

#26 @willnorris
6 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.

#27 @azizur
6 years ago

  • Cc azizur added

#28 @svallory
6 years ago

  • Cc svallory added
  • Version changed from 3.0 to 3.1

#29 @scribu
6 years ago

  • Version 3.1 deleted

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

#30 follow-up: @scribu
5 years ago

FYI: this has been implemented as a plugin:

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

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

#31 @GreenDude
5 years ago

  • Cc GreenDude added

#32 @gruvii
5 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 5 years ago by gruvii (previous) (diff)

#33 in reply to: ↑ 30 @gruvii
5 years ago

Replying to scribu:

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

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

#34 @scribu
5 years ago

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

#35 @scribu
5 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.

#36 @ciobi
5 years ago

  • Cc alex.ciobica@… added

#37 @johnbillion
5 years ago

  • Cc johnbillion@… added

#38 @navjotjsingh
5 years ago

  • Cc navjotjsingh@… added

#39 @WraithKenny
5 years ago

  • Cc Ken@… added

#40 @bainternet
4 years ago

  • Cc admin@… added

#41 @emzo
4 years ago

  • Cc emzo added

#42 @retlehs
3 years ago

  • Cc retlehs added

#43 @aniketpant
3 years ago

  • Cc me@… added

#44 @mau
3 years ago

  • Cc ngomau@… added

#45 follow-up: @christianmagill
3 years 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.

#46 in reply to: ↑ 45 @willnorris
3 years 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.

#47 follow-up: @christianmagill
3 years 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?

#48 in reply to: ↑ 47 @willnorris
3 years 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.

#49 @chriscct7
12 months ago

  • Keywords dev-feedback added
Note: See TracTickets for help on using tickets.