Deep in the guts of the theme system, the 'base' template file for a theme function is used to check what directories should be scanned at runtime. For example, if a theme contains node.tpl.php, it will be checked for template files matching any of its suggested variations (node-blog.tpl.php, node-story.tpl.php, node.tpl.php) whenever a node is themed. Unfortunately, if the theme ONLY contains template files that match suggested variations -- and not the underlying 'base' theme function -- all the variations are ignored.

The most obvious way to trigger this is to rename garland's node.tpl.php file to node-story.tpl.php, and rebuild the theme registry. NO nodes -- not even story nodes -- will use that template. If both node.tpl.php AND node-story.tpl.php exist, both will be recognized and used properly. This issue is similar to #258089: Themes cannot have a preprocess function without a corresponding .tpl.php file but has a couple of additional wrinkles.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yched’s picture

Yep, I just noticed that as well when writing theming instructions for CCK field template overrides.

eaton’s picture

Status: Active » Needs review
FileSize
827 bytes

This may not be the cleanest solution -- I'm looking closer to see if there's a way to avoid checking the $theme global -- but it seems to work for the 'node-story.tpl.php' case.

In a nutshell, *if there are suggestions* the theme system always checks the current theme directory for matching templates.

The downside is that it only fixes the problem for *the currently active theme* -- if a theme only has node-story.tpl.php and its CHILD theme is currently active, the problem pops up again. template inheritance for child themes is a bit sticky anyhow, though; I tend towards thinking that should be solved separately.

merlinofchaos’s picture

IMO the proper solution is that during registration, 'theme paths' for every hook is always updated with the theme being processed, that way suggestions will be looked for in the right place. This can be done in the theme's hook_theme(), much like we have functions to auto-find templates and theme functions. If this doesn't make sense I can try to elaborate.

eaton’s picture

IMO the proper solution is that during registration, 'theme paths' for every hook is always updated with the theme being processed, that way suggestions will be looked for in the right place. This can be done in the theme's hook_theme(), much like we have functions to auto-find templates and theme functions. If this doesn't make sense I can try to elaborate.

That seems a little bit odd. it would mean that themes with node.tpl.php would work fine, but themes with node-story.tpl.php would have to implement hook_theme(). Or rather, hook_theme_registry_alter(), to add the entry to 'theme paths' for each template they handle.

Since we already scan various directories when 'suggestions' is set, is there a problem with always checking the theme's directory? I'm not saying there isn't -- it just seems like this is a fairly obvious bug, and punting the work of fixing it to themes just makes things trickier. I would rather we remove the ability to automatically find node.tpl.php in a theme's directory than have auto-discovery work for some template and not for others...

mfer’s picture

@eaton I agree that this seems like a bug. If anything it's an issue that theme system does not do what it used to do (or what people expect), it's not intuitive to figure out, and I have not read an migration information for this topic. This just doesn't seem intuitive and isn't documented. It would be great to have this fixed or documented well before 6.3 goes out.

For theme inheritance shouldn't we check the theme and any parent themes for suggestions?

dvessel’s picture

Priority: Critical » Normal

mfer, it is documented (see bottom of page). There's also a note where the suggestions are listed.

Suggestions work on any level as long as that "base" template is there but this problem gets tricky since templates can exist in any sub-directory. It would be difficult to track down any derivatives without that base.

One possibility is to have some sort of naming convention so the base hook is clearly differentiated from the rest of the name. For example, say we have "node.tpl.php" and it doesn't exist in the theme. We could modify the template scanning function so it can determine that "node[story].tpl.php" belongs to a node hook. –If those are legal characters. I mean, whatever makes the most sense.

Every single suggestion doesn't have to be stored in the registry, just the path's that lead to the detected hook. This would keep the flexibility of allowing any template to be organized in any way the themer pleases. Think this would work?

eaton’s picture

mfer, it is documented (see bottom of page). There's also a note where the suggestions are listed.

Man, I feel dumb now. I tend to think that checking the theme's directory whenever there are suggestions is a good idea -- it's a quick check and it covers the majority of the cases. In the 'olden days' it wasn't that much of a problem, because there just weren't that many items that had suggestions. Now, though, modules are providing lots of potential suggestion candidates and explaining that we need to copy the original template over, DUPLICATE it, and then modify the more-specific duplicate might make it more explicit if we can't bring ourselves to get rid of the blind-spot...

mfer’s picture

Well, if this isn't going to be a bug fix for drupal 6, it would be a great enhancement for drupal 7! This would be a nice step up in the developer experience realm making drupal more intuitive and easier to theme on.

dvessel’s picture

Version: 6.x-dev » 7.x-dev
Status: Needs review » Needs work

Eaton, the only problem I can see with defaulting to the base level of the themes directory is exactly what you stated. There can be many templates so IMO, it should be flexible about how it can be managed. Limiting it to that one directory can get out of control and can lead to a pattern of overloading the base directory even for base templates.

What do you guys think of the approach I mentioned. On first glance, it should be relatively simple. We just have to agree on the naming convention. Or if there are any other ideas, lets hear it.

eaton’s picture

What do you guys think of the approach I mentioned. On first glance, it should be relatively simple. We just have to agree on the naming convention. Or if there are any other ideas, lets hear it.

I'm very very hesitant about that change in the naming convention; between wildcards, suggestions, and other pieces we have so many utterly confusing ways to do things in the theme system that introducing a new file naming convention to work around this bug will only make things worse. I'd rather see this problem remain than introduce a new 'magic' naming scheme on top of all of our other magic.

dvessel’s picture

Yeah, I see your point but being able to differentiate I think would be helpful too. A naming convention can help spot what is what at a glance. One pattern, one purpose. Having that clarity would be nice but as you stated, it's another thing to learn.

eaton’s picture

Eaton, the only problem I can see with defaulting to the base level of the themes directory is exactly what you stated. There can be many templates so IMO, it should be flexible about how it can be managed. Limiting it to that one directory can get out of control and can lead to a pattern of overloading the base directory even for base templates

I'm not quite sure what you mean by 'more flexibility' in this context. you mean a naming convention that would make it easier for us to determine what base theme element a given template corresponds to?

dvessel’s picture

I meant just the placement of the template. Not restricting it to the base level. That's all.

I tend to manage templates into sub-folders now. Even in Drupal 5, I figured out a way and I found it very useful for complex themes.

moshe weitzman’s picture

So, any resolution here?

dvessel’s picture

I guess not.. What do you think about defaulting to the base level of the theme? I don't agree with it but I won't argue if everyone else thinks it is acceptable.

moshe weitzman’s picture

I don't really know the right answer. In general, I have no problem with fie naming conventions. D6 introduced a nice convention for include files, for example. So if we can solve this with some convention like node.story.tpl.php (for example), thats looks pretty clean to me.

sila80’s picture

moshe weitzman
+1

-----------------------
Wrinkles treatment - free info!

dvessel’s picture

Assigned: Unassigned » dvessel

I'll work on this over the weekend.

Robin Monks’s picture

Subscribing

dvessel’s picture

I apologize for the delay. I've been running into a few hiccups. I also discovered a bug where the global $theme_path will not always point to the right place. Due to the current implementation, it rarely encountered.

Specifically, $theme_path is always supposed to point to the location where the theming implementation is located whether it's in a module, theme or sub-theme. $theme_path informs path_to_theme() so it always points to the right place. So, for example, this bug would be exposed if a template suggestion located in a module folder is used while the base template from the theme exists. path_to_theme() would point to the theme and not the module where the template is located.

Very unlikely this would happen in core since there are about 2-3 template suggestions in core but it can crop up in contrib if suggestions are provided.

Now, if I can manage to get this patch up, the bug would be encountered a lot more often. Even with Eatons suggestion's it would be a problem. Lets say the base template is in a module and the themer copied only the suggestion into their theme. path_to_theme() would point to the module and not the theme.

It's impossible to work around unless we rework how paths are determined for a themed implementation.

What I'm trying to do now is feed the theme registry with all the theme paths. There's a key of 'theme paths' for each hook done as templates. As long as the path to the suggestion is there, it will use it. See drupal_discover_template() where the 'theme paths' would be pushed as $paths. I'll keep working on that. It's not as easy as I thought it would be. :/ The chain of functions is complex and I haven't managed to get it in there cleanly.

merlinofchaos’s picture

Hey dvessel -- using 'theme paths' is what I was suggesting all along, wasn't it?

dvessel’s picture

Hi Merlin, you definitely suggested that but I thought you meant that it can be left to themers taking care of it. What I'm trying to do now is pushing those paths without it interfering with anything. I'm was trying from drupal_find_theme_templates but getting all the hooks to accept those 'theme paths' screws with what's already there while being processed in _theme_preprocess_registry.

For the global $theme_path, do you have any ideas? Because it's so dependent on the default template, I can't see any way around it.

thanks!

dvessel’s picture

Status: Needs work » Needs review
FileSize
14.92 KB

Here's what I have. Suggestions for normal hooks work as well as wild card hooks. When setting up the suggestions from preprocessors, the base hook doesn't have to be added. It's automatically prepended. I thought it was odd to define that "." between the HOOK.SUGGESTION.

I know this won't fly as it is. Theme paths as I mentioned above would have to be reworked to allow the base and suggested template from being in different locations.

It works as long as path_to_theme isn't invoked at the wrong location.

dvessel’s picture

And again..

arhak’s picture

subscribing

dvessel’s picture

Assigned: dvessel » Unassigned
Status: Needs review » Postponed

Postponed till we figure out a better way to determine theming paths.

meba’s picture

Somebody noticed but in order to be more google-searchable, please note that this also affects content-field.tpl.php - content-field-field_name.tpl.php won't work without the former file.

TravisCarden’s picture

Subscribing.

geerlingguy’s picture

Subscribe...

And to meba / #27 - this applies to pretty much any kind of .tpl.php - you can't use any children of a main template file without the main one being in your theme folder.

SeanBannister’s picture

Sub

Chris Charlton’s picture

Subscribed.

webchick’s picture

Status: Postponed » Needs work

Reverting from "postponed" status so other people know it's ok to work on this. This is always a total WTF for themers new and old alike, so I'd love to see this fixed.

mattyoung’s picture

.

forngren’s picture

Issue tags: +DrupalWTF

Submarine.

Aren Cambre’s picture

blitux’s picture

So, is there a Q&D workaround for this? Using Drupal 6.14, Zen 6.x-1.1

Subscribing.

izmeez’s picture

subscribing

I encountered this with Zen 6.x-1.1 and posted an issue http://drupal.org/node/649216 before being directed to this issue. The work around for me was to copy the default node.tpl.php file from the zen directory to the subtheme.

blitux’s picture

izmeez, thank you. It works.

mattyoung’s picture

I wrote an article about this a while back.

Jon Nunan’s picture

sub

Jon Nunan’s picture

FileSize
1.89 KB

Only done some real basic testing with this, giving the patch to the bot while I try and create a weird combination of template files in the base theme and the sub theme to make sure it works as expected. Only tested on node templates at the moment, will probably need to add template suggestions for other hooks.

Jon Nunan’s picture

Status: Needs work » Needs review
FileSize
2.21 KB

Found the first bug, templates in the base theme weren't getting used. patch attached.

Status: Needs review » Needs work

The last submitted patch failed testing.

Jon Nunan’s picture

Status: Needs work » Closed (duplicate)

If I read the issue correctly this should be fixed by #678714: Unify use of theme hook / template suggestions, fix clobbering problems, and improve suggestion discovery performance, feel free to update the status if I've got it wrong.

Stol’s picture

Title: Themes can't use node-story.tpl.php without node.tpl.php » Is there any D6 fix for this issue ?

Running on Drupal 6.15 I still have to copy node.tpl.php into my theme folder to activate my node-my_content_type.tpl.php

Is there any solution of fix for Drupal 6 ?

Stol’s picture

Title: Is there any D6 fix for this issue ? » Themes can't use node-story.tpl.php without node.tpl.php
JohnAlbin’s picture

Status: Closed (duplicate) » Active

No, they are confusing template suggestions and named theme implementations in that other issue. They are separate things and this bug is still active.

JohnAlbin’s picture

Version: 7.x-dev » 6.x-dev
Status: Active » Closed (won't fix)

Woah, I totally misread #678714: Unify use of theme hook / template suggestions, fix clobbering problems, and improve suggestion discovery performance. template suggestions have been completely removed from D7. Given the intractableness of this issue, I really like that solution. :-D

So this issue only affects D6 now.

However, I've been thinking about how to fix this for 2 years now and the only solution I ever came up with was to remove the feature altogether. The auto-discovery theme registry build cannot discover template suggestions because there's no pattern to the template naming it can latch onto. For example, user-profile-category.tpl.php: is it a template suggestion for user-profile.tpl.php, for the user theme hook, or its own theme hook? You can't tell just by looking at the name.

Given that you can only fix this problem by re-writing the API, I'm calling this "won't fix" for D6. Sorry, guys! You'll just have to keep copying the base template over to your sub-theme when you want to use a template suggestion.

Aren Cambre’s picture

I'm totally OK with this and would rather available time go into D7 upgrade effort anyway. Seems like D7 is going to have a lot of modules/themes ready for it out of the gate.

Garrett Albright’s picture

Just thought I'd chime in and say that I ran into a related (I think) issue when I wanted to add a region-sidebar-first.tpl.php to a Zen 6.x-2.x-dev subtheme I'm working on at the moment. The region-sidebar-first.tpl.php template file isn't "picked up" unless there's a region.tpl.php in the "templates" directory as well (the intermediate region-sidebar.tpl.php is not necessary). Hope this saves someone some time and head-scratching…

kaanon’s picture

I had a similar issue with regards to a module not looking in my theme directory for a candidate theme file. I remedied it with a core hack to the d6 theme.inc (lame, i know)

In case you need it, i added this after line 325 "// Check for sub-directories."

##-- HACK --##
$result[$hook]['theme paths'][] = path_to_theme();

Seems to work so far.

pukku’s picture

I'm not sure if I should make this un-closed, but this is a potential security issue. In order to provide an override for just one type of node (or block, in my case), I need to copy the default .tpl.php file into my theme folder. This means that if there are any updates to the default .tpl.php file (bug fixes or security fixes) my theme won't use them. If I were modifying node.tpl.php (or block.tpl.php) anyway, it would be a different matter, as any bugs or security issues could rightly be said to be my fault, but since in my case I'm not touching the file, it really shouldn't need to be there.

Jon Nunan’s picture

node.tpl.php only prints out theme variables. If there was any security problem with the output of theme variables it'd be a problem with the theme function that generated that variable not the tpl.php file that printed it out.

Well thats my understanding at least.

joshuajabbour’s picture

@pukka True, since you have to create the base template file in order to use overrides, it can be a problem if you want to keep that file in sync with any changes made by the providing module or theme.

In order to get around this, I simple include the contents of the original file. Here's an example using views. If I want to create a more specific template override for "views-view-list" but don't want to override the default output, I simply create a "views-view-list.tpl.php" in my theme with the following contents (instead of copying the code from the original file):

/**
 * @file
 * This template must exist for more specific suggestions to be discovered.
 *
 * In order to reduce duplication of code, this file simply includes
 * the actual file from the providing module or theme.
 */
include drupal_get_path('module', 'views') . '/theme/views-view-list.tpl.php';
saurabh.dhariwal’s picture

Issue summary: View changes