smarty-php / smarty

Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.
Other
2.25k stars 709 forks source link

When an included template extends, a block is not not being rendered #776

Closed dealer-solutions-gene closed 2 years ago

dealer-solutions-gene commented 2 years ago

Hello,

I think I've got a bug with how included files that extend interact with blocks

Given this structure:

/tpl/document.tpl
/tpl/head.tpl
/tpl/theme/document.tpl
/tpl/theme/head.tpl

and with a template directory precedence order of:

$smarty->setTemplateDir([
    './tpl/theme/',
    './tpl'
]);
$smarty->display('document.tpl');

and with a very distilled reproducible example of block-bug.zip, I'm expecting to see the block with <div>My Theme Document Javascript</div> in the output

The file theme/head.tpl only contains {extends file="../head.tpl"} to reproduce this, normally it would have additional blocks appending to others, the idea would be my theme "head" injects additional blocks

if I remove theme/head.tpl then I at least get my block being included in the root level head.tpl as expected, which tells me blocks do pass into included templates, not just extended templates.


Desired Output:

Original Head
Original Javascript
My Theme Document Javascript
My Theme Content

Actual Output

Original Head
Original Javascript
My Theme Content
dealer-solutions-gene commented 2 years ago

I've found a much simpler way to demonstrate this.

Templates PHP 5.6 + Smarty 3.1 PHP 8.1 + Smarty 4.1
scenario-a.zip B Content A Content C Footer A Footer B Content A Content C Footer A Footer
scenario-b.zip B Content A Content D Footer A Footer B Content A Content D Footer
scenario-c.zip A Content B Content A Footer C Footer D Footer A Content B Content C Footer D Footer

These zips have multiple append blocks and an include block, but when the include has an extend, blocks go missing

template Smarty for Scenario C where A Footer goes missing
a.tpl {extends file="b.tpl"}
{block name="content" prepend} A Content {/block}
{block name="footer" prepend} A Footer {/block}
b.tpl {block name="content" append} B Content {/block}
{include file="c.tpl"}
c.tpl {extends file="d.tpl"}
{block name="footer" prepend} C Footer {/block}
d.tpl {block name="footer"} D Footer {/block}
wisskid commented 2 years ago

Seems like this behavior changed between v3.1.27 en v3.1.28 (dec 2015). The changelog contains a lot of entries, including "rework of template inheritance", "optimize subtemplate handling" en "update template inheritance processing" and more.

dealer-solutions-gene commented 2 years ago

@wisskid thank you for the response, I can see we currently are using a version before that at 3.1.21 and I've been tasked with making our website PHP 8.1 compliant, hence a well overdue upgrade of Smarty to make everything work. What do you think this means for this behavior? legitimate scenario? Our site has quite a heavy usage on replaceable theme components by directory structure that append/prepend to blocks in deeper includes. I've tried to simplify the example as much as I could, but the concept is extensive extends up-to a parent template then then recurses back down via the includes. "Scenario C" has the best example of this. With thanks

wisskid commented 2 years ago

@dealer-solutions-gene I'm not quite sure. The docs list a couple of notes regarding block content and includes. I suspect that these cannot be mixed liberally.

If you have a subtemplate which is included with {include} and it contains {block} areas it works only if the {include} itself is called from within a surrounding {block}. In the final parent template you may need a dummy {block} for it.

wisskid commented 2 years ago

@dealer-solutions-gene and

The content of {block} tags from child and parent templates can be merged by the append or prepend {block} tag option flags and {$smarty.block.parent} or {$smarty.block.child} placeholders.

I don't think you can prepend/append to blocks that are defined in included templates, since these are not compiled as one file:

Template inheritance is a compile time process which creates a single compiled template file.

dealer-solutions-gene commented 2 years ago

@wisskid Thanks again for the information, I've tried a combination of {block} wrappers and the {$smarty.block.*} tokens but I have been unable to get the older 3.x behavior replicated in the newer 4.x version, I may have to re-engineer my solution. Also managed to get a segfault by placing {$smarty.block.child} in the d.tpl block which was interesting.

Edit: ah, segfaults when I have a prepend in the child template and then {$smarty.block.child} in the parent template block.

dealer-solutions-gene commented 2 years ago

I've tried again for another few hours and I can't find a happy place between the extends and includes. As long as I don't have an included file that extends everything works, but that breaks my current implementation of smarty, so because of that, I'd like to think this is still some kind of behavior bug as "Scenario A" which has an include with blocks, but does not extend another template, does work as one would expect :(

wisskid commented 2 years ago

@dealer-solutions-gene isn't there another way of defining/using the blocks? We cannot revert a change that was also a fix for another problem and released 6 years ago without possibly breaking BC for everything built since dec 2015.

dealer-solutions-gene commented 2 years ago

@wisskid look that's a fair statement, I'm not sure how common having blocks in an extending include is, but what I have been able to do is to create a new block type to aggregates content together, in the same append/prepend/overwrite fashion to simply print them together.

I have discovered that whilst child template content outside of a {block} is ignored, other blocks are still processed, giving me the means to "capture" this output into a singleton style class.

{extends file='parent.tpl'}

this text is ignored, by design

{myblock name="foo"}still executes, allowing me to capture output{/myblock}

{block name="bar"}normal block{/block}

Thank you for your attention, it is appreciated.

wisskid commented 2 years ago

@dealer-solutions-gene great! Thank you for your kind words.