-
-
Notifications
You must be signed in to change notification settings - Fork 180
fix: layout snippet inside of snippet (#7567) #7571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop-patch
Are you sure you want to change the base?
fix: layout snippet inside of snippet (#7567) #7571
Conversation
src/Template/Template.php
Outdated
// let the snippet close and render natively | ||
return Snippet::$current->render($data); | ||
// handle any potentially open layout snippet | ||
return Snippet::endlayout($snippet, $template, $data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that any output from before opening the layout snippet gets discarded. This was already the case before. I think ideally, we should call Snippet::endlayout
before Tpl::load
calls ob_get_contents()
. However, I avoided to call Snippet::endlayout
from within Tpl::load
because I assumed dependencies from \Kirby\Toolkit
to \Kirby\Template
are to be avoided. Alternatively, it might make sense to trigger an exception if there is any output before opening a layout snippet.
@JojOatXGME Could you please provide the setup that this PR tries to solve. I have to admit I couldn't quite follow the description in the issue and therefore aren't sure if this is fixing an unwanted behavior or enabling an unwanted usage 😅 |
@distantnative I just created a fork of If you check out commit |
@JojOatXGME I've been trying to understand the PR for 15 minutes, but I don't get it, sorry 🙂 I just see that the Template::render method has been moved to Snippet::load. Am I missing something? Does this PR actually solve the problem? |
I think this might be the better/right direction, having the handling in The Template render call to snippet load reads a little weird - but might be full functional. Just semantically made me stumble. |
@afbora EDIT: I also now updated the description in the PR accordingly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will need very thorough testing. These nested snippets and slots pose a lot of edge cases that I am afraid our unit tests do not fully cover yet. Before we merge, we should be very certain this doesn't add a regression for other use cases.
We also need to update the DocBlock and comments of the Snippet::load()
method. It's misleading that we talk about templates win the context of snippets. I would also love if we could remove the term layout snippet (I know, not introduced but this PR but let's take the chance). Especially in this use case of nesting, the idea of layout doesn't make a lot of sense to me. I think in the end it's about snippets with slots where the closing endsnippet()
call has been omitted and Kirby should end it implicitly at the end of a snippet file.
array $data = [], | ||
array $layoutData = [], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question:
Where do you see the need to split this up into two parameters? Instead just having one $data
parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, Template::render
sets $layoutData
to the same value as $data
, but Snippet::render
keeps the parameter empty. I only set $layoutData
to the same value as $data
inside Template::render
for backward compatibility, but it looks to me like it actually might have been a bug. (At least the resulting deviation from normal snippets seems not to be documented.)
Within Snippet::render
, I cannot set $layoutData
to the same value as $data
because this would lead to a runtime exception. The array for $layoutData
currently must not contain 'slot'
nor 'slots'
. However, the $data
given by Snippet::render
does contain 'slot'
and 'slots'
.
I feel like the currently intended behavior is to always keep $layoutData
empty. In other words, I think forwarding $data
from the template to the snippet was actually another minor bug in the existing code, which I just preserved. If my understanding is correct, I could remove this parameter and always use an empty array instead.
However, if I look at the behavior not from the perspective of the bug fix, I would actually prefer if layout snippets would forward the data from the parent. I actually considered creating a feature request for that one or two weeks ago. This would match the behavior of “Template Inheritance” in other popular template engines like Twig, Laravel's Blade Templates, Jinja, and Django's template language. However, I would consider this a new feature and therefore did not implement this behavior. To make this feature work, I would always set $layoutData
to the same value as $data
, implement proper merging of slot
data, and tweak the precedence of data coming from this parameter vs the data explicitly provided from within the template. (The explicit content from the template should maybe take precedence for data, but not for slots.) While I would be happy to implement this behavior, I did not consider it part of this ticket. Also note that full “Template Inheritance” usually also includes a feature to call super()
or @@parent
to preserve the content from the extended template. This functionality would still not be covered by the implementation I have just described.
Description
Fixes #7567. Implement handling of layout snippets within snippets.
Extract implementation from
Template::render
intoSnippet::load
.Snippet::load
overridesTpl::load
. The calls tostatic::load
insideSnippet::render
andSnippet::factory
are now referencingSnippet::load
instead ofTpl::load
. As a result, these two methods are now correctly handling layout snippets.Changelog
🐛 Bug fixes
Docs
For review team