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.
Comment | File | Size | Author |
---|---|---|---|
#42 | theme.patch | 2.21 KB | Jon Nunan |
#41 | theme.patch | 1.89 KB | Jon Nunan |
#24 | template_flex_suggest.b.patch | 14.85 KB | dvessel |
#23 | template_flex_suggest.patch | 14.92 KB | dvessel |
#2 | template-suggestions.patch | 827 bytes | eaton |
Comments
Comment #1
yched CreditAttribution: yched commentedYep, I just noticed that as well when writing theming instructions for CCK field template overrides.
Comment #2
eaton CreditAttribution: eaton commentedThis 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.
Comment #3
merlinofchaos CreditAttribution: merlinofchaos commentedIMO 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.
Comment #4
eaton CreditAttribution: eaton commentedThat 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...
Comment #5
mfer CreditAttribution: mfer commented@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?
Comment #6
dvessel CreditAttribution: dvessel commentedmfer, 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?
Comment #7
eaton CreditAttribution: eaton commentedMan, 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...
Comment #8
mfer CreditAttribution: mfer commentedWell, 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.
Comment #9
dvessel CreditAttribution: dvessel commentedEaton, 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.
Comment #10
eaton CreditAttribution: eaton commentedI'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.
Comment #11
dvessel CreditAttribution: dvessel commentedYeah, 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.
Comment #12
eaton CreditAttribution: eaton commentedI'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?
Comment #13
dvessel CreditAttribution: dvessel commentedI 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.
Comment #14
moshe weitzman CreditAttribution: moshe weitzman commentedSo, any resolution here?
Comment #15
dvessel CreditAttribution: dvessel commentedI 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.
Comment #16
moshe weitzman CreditAttribution: moshe weitzman commentedI 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.
Comment #17
sila80 CreditAttribution: sila80 commentedmoshe weitzman
+1
-----------------------
Wrinkles treatment - free info!
Comment #18
dvessel CreditAttribution: dvessel commentedI'll work on this over the weekend.
Comment #19
Robin Monks CreditAttribution: Robin Monks commentedSubscribing
Comment #20
dvessel CreditAttribution: dvessel commentedI 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.
Comment #21
merlinofchaos CreditAttribution: merlinofchaos commentedHey dvessel -- using 'theme paths' is what I was suggesting all along, wasn't it?
Comment #22
dvessel CreditAttribution: dvessel commentedHi 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!
Comment #23
dvessel CreditAttribution: dvessel commentedHere'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.
Comment #24
dvessel CreditAttribution: dvessel commentedAnd again..
Comment #25
arhak CreditAttribution: arhak commentedsubscribing
Comment #26
dvessel CreditAttribution: dvessel commentedPostponed till we figure out a better way to determine theming paths.
Comment #27
meba CreditAttribution: meba commentedSomebody 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.
Comment #28
TravisCarden CreditAttribution: TravisCarden commentedSubscribing.
Comment #29
geerlingguy CreditAttribution: geerlingguy commentedSubscribe...
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.
Comment #30
SeanBannister CreditAttribution: SeanBannister commentedSub
Comment #31
Chris CharltonSubscribed.
Comment #32
webchickReverting 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.
Comment #33
mattyoung CreditAttribution: mattyoung commented.
Comment #34
forngren CreditAttribution: forngren commentedSubmarine.
Comment #35
Aren Cambre CreditAttribution: Aren Cambre commentedsubscribe. #311201: template suggestions (like node-[type].tpl.php) do not work in subtheme folder depends on this. Major WTF for Zen themers.
Comment #36
blitux CreditAttribution: blitux commentedSo, is there a Q&D workaround for this? Using Drupal 6.14, Zen 6.x-1.1
Subscribing.
Comment #37
izmeez CreditAttribution: izmeez commentedsubscribing
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.
Comment #38
blitux CreditAttribution: blitux commentedizmeez, thank you. It works.
Comment #39
mattyoung CreditAttribution: mattyoung commentedI wrote an article about this a while back.
Comment #40
Jon Nunan CreditAttribution: Jon Nunan commentedsub
Comment #41
Jon Nunan CreditAttribution: Jon Nunan commentedOnly 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.
Comment #42
Jon Nunan CreditAttribution: Jon Nunan commentedFound the first bug, templates in the base theme weren't getting used. patch attached.
Comment #44
Jon Nunan CreditAttribution: Jon Nunan commentedIf 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.
Comment #45
Stol CreditAttribution: Stol commentedRunning 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 ?
Comment #46
Stol CreditAttribution: Stol commentedComment #47
JohnAlbinNo, they are confusing template suggestions and named theme implementations in that other issue. They are separate things and this bug is still active.
Comment #48
JohnAlbinWoah, 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.
Comment #49
Aren Cambre CreditAttribution: Aren Cambre commentedI'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.
Comment #50
Garrett Albright CreditAttribution: Garrett Albright commentedJust 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…
Comment #51
kaanon CreditAttribution: kaanon commentedI 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."
Seems to work so far.
Comment #52
pukku CreditAttribution: pukku commentedI'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.
Comment #53
Jon Nunan CreditAttribution: Jon Nunan commentednode.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.
Comment #54
joshuajabbour CreditAttribution: joshuajabbour commented@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):
Comment #55
saurabh.dhariwal CreditAttribution: saurabh.dhariwal at AddWeb Solution Pvt. Ltd. commented