Issue #1975462 by thedavidmeister, alexpott, alexrayu, chx, joelpittet: Fixed Allow and test for NULL and integer 0 values in Twig templates.
Problem description
NULL variables being passed to Twig templates lead to exceptions - eg. #1961872: Convert html.tpl.php to Twig, #1843746: Convert views/templates/views-view-field.tpl.php to Twig . NULL variables can simply be the result of calling drupal_render() on a renderable array with '#access' => FALSE within a preprocess/process function - #1975442: drupal_render() should always return a string., so it's very likely that this will turn up more in contrib than we're currently seeing in core.
Additionally, Drupal's Twig implementation does not print anything for the following: {% set var = 0 %}{{ var }}
. This should print '0'.
Solution
Fix Drupal's twig implementation to
- not produce exceptions when passed a null value
- print 0 when passed an integer 0
- add tests for PHP's scalar variables.
Commit message
git commit -m "Issue #1975462 by thedavidmeister, alexrayu, alexpott, chx, joelpittet: Fixed Allow and test for NULL and integer 0 values in Twig templates."
Comment | File | Size | Author |
---|---|---|---|
#40 | 37-40-interdiff.txt | 1.08 KB | alexpott |
#40 | 1975462-twig-php-variables-40.patch | 7.57 KB | alexpott |
#37 | 34-37-interdiff.txt | 4.05 KB | alexpott |
#37 | 1975462-twig-php-variables-37.patch | 7.56 KB | alexpott |
#34 | 33-34-interdiff.txt | 434 bytes | alexpott |
Comments
Comment #1
star-szrtagging.
Comment #2
thedavidmeister CreditAttribution: thedavidmeister commentedFirst, a test to demonstrate the exceptions. Setting needs review just to get the testbots running.
Comment #3
thedavidmeister CreditAttribution: thedavidmeister commentedHere's the proposed fix + test.
Comment #4
Fabianx CreditAttribution: Fabianx commentedI was about to RTBC this, then I noticed that is_null also gives back TRUE if the array index does not exist. Therefore this fix is not right as the following script proves:
Expected result: 3 error messages; Actual result: 2 error messages.
Proposed Fix
I checked what Twig uses and they use a much slower:
So as a compromise and because isset() is really fast, I suggest we do:
The new tests should still pass.
Comment #5
thedavidmeister CreditAttribution: thedavidmeister commentedwhat about
!isset($context[$item]) && $context[$item] !== NULL
?Comment #6
thedavidmeister CreditAttribution: thedavidmeister commentedI actually don't know how to write an "assert exception" test in SimpleTest, otherwise I would.
Comment #7
thedavidmeister CreditAttribution: thedavidmeister commentedbah, !== NULL throws a notice when used on an undefined variable but then again, so are we so that might actually be ok? I dunno. I'll have a look at the array_key_exists() thing too.
Comment #9
thedavidmeister CreditAttribution: thedavidmeister commentedI just did some simple benchmarking like this:
The numbers in comments next to each line represent the timer values for each of those lines. The notice errors thrown by ($undefined === NULL) are crazy slow (the testbots hate it anyway)! Even with @ they're still about 20x slower than the next closest example.
The thing is though, that if we're optimising for the case that there are no errors (production sites) rather than when there are errors (dev sites), @($var !== NULL) is about 20% faster than array_key_exists().
(also, this is all silly micro-optimisation and @Fabianx told me in IRC this class is getting deleted soon and replaced with something else.)
Patch attached.
Comment #10
thedavidmeister CreditAttribution: thedavidmeister commentedComment #11
thedavidmeister CreditAttribution: thedavidmeister commentedeeexcept that
print $undefined === NULL;
prints 1.isset() scores 0.5 on the benchmarking for #9 btw. I forgot to put it in there.
Here's something that actually works. Thanks @Fabianx, I got there eventually ;)
Comment #13
thedavidmeister CreditAttribution: thedavidmeister commentedFailed because I forgot to include the preprocess in that patch. oops.
Comment #14
joelpittetGave this a run through and it worked great. Thanks @thedavidmeister
Also thanks for adding the test in there too.
There was a new line whitespace issue in the patch, I think it is in "core/modules/system/tests/themes/test_theme_twig/theme_test.template_test.html.twig" but it got corrected when I applied it the patch or my editor autofixed it because it wasn't there on opening it... :S
Comment #15
chx CreditAttribution: chx commentedWhitespace fix.
Comment #16
joelpittetI think the one I am seeing is line 65 of the patch, EOF whitespace. Maybe it's a patch format discrepancy but thanks @chx for finding a real whitespace issue:)
I'll post the patch file, that git diff is providing me. No interdiff because the extra line ending is fixed automatically when the patch is applied.
Comment #17
star-szrI think this should be 'various PHP data types', right?
Comment #18
alexpottAlso... is this really various types... is not just testing whether or not twig handles nulls in the expected fashion?
Comment #19
thedavidmeister CreditAttribution: thedavidmeister commented+ // @todo: Coverage for all PHP data types.
;)I'll fix up the docs.
Comment #20
thedavidmeister CreditAttribution: thedavidmeister commentedComment #21
thedavidmeister CreditAttribution: thedavidmeister commentedHopefully these docs are better.
Comment #22
thedavidmeister CreditAttribution: thedavidmeister commentedComment #23
Fabianx CreditAttribution: Fabianx commentedRTBC per #14.
I second this RTBC also:
* Fixes a bug
* Has tests to show the bug
* Is performance optimized
=> RTBC (plus #14 RTBC)
Comment #24
alexpottI don't think we should be adding @todo's at this stage. Let's test all the php scalar variable types.
This will fail because at the moment...
Will result in
<li>twig_int_0: </li>
whereas I think we should expect<li>twig_int_0: 0</li>
Comment #25
Fabianx CreditAttribution: Fabianx commentedThis is fixed here: #1970960: Twig implementation does not print int(0)
So maybe wait till that is committed, then commit this here?
Comment #26
thedavidmeister CreditAttribution: thedavidmeister commented#24 - I don't see any reason not to add the @todo. I was planning on making a followup issue to flesh that test out if this lands, but didn't want to make the issue straight away in case this patch doesn't get committed.
In this issue I'd really like to focus just on NULL because a bunch of conversion patches ran into it. Tests for the variables making it through Twig are important in general though, so I wanted to make something that will be easy to extend beyond NULL.
Comment #27
alexpott@thedavidmeister since we're now in code slush each commit should make us closer to release and therefore we should avoid adding @todo especially if the patch is small and well contained. I see no reason not to merge #1970960: Twig implementation does not print int(0) and press on with your good idea to test all scalar variable types.
The commit message should additionally attribute
alexrayu
.Comment #28
thedavidmeister CreditAttribution: thedavidmeister commentedI guess I'll close the other issue as a duplicate then..
Comment #28.0
alexpottUpdated issue summary.
Comment #29
alexpottAnd now removing the @todo :) doh!
Comment #30
Fabianx CreditAttribution: Fabianx commentedStill RTBC per #14.
I second this RTBC also:
* Fixes two bugs
* Unblocks some twig conversions
* Has tests to show the bugs, adds extensive coverage for rendering via twig template.
* Is performance optimized
=> RTBC
Comment #31
Fabianx CreditAttribution: Fabianx commentedRTBC per #30 - ahem ...
Comment #32
star-szrSomething to consider: it might be worth creating a new template/callback for these additional tests. Maybe it's just me but it feels a bit like we are commandeering theme_test.template_test.html.twig which was previously a simple template override test:
Comment #33
alexpott@Cottser yep I agree... let's not do that... added a new twig_theme_test module so we don't add any twigness to the theme_test module.
Comment #34
alexpottRemove unnecessary use...
Comment #35
star-szrAh, that looks much better. Thanks @alexpott! :)
Does this need a routing.yml now if we're adding a new page callback? Does the page callback need to be a controller? Not sure what the policy is around this now :)
Nitpickery:
End this comment in a period per http://drupal.org/node/1354#drupal.
All caps for PHP.
Twig should be capitalized (not the "twig_" one of course).
Comment #36
Fabianx CreditAttribution: Fabianx commentedAdding quick fix tag once this is RTBC again :).
Comment #37
alexpottMoved to new routing system and fixed everything in #35 plus a few other coding standards related things.
Comment #38
star-szrThanks @alexpott, looks good. I went over the whole patch again and this is all I could find:
Docblock needs updating :)
All caps PHP please.
Comment #39
star-szrAh I think there's some discrepancies with newlines too:
http://drupal.org/node/1918356 shows a blank line before the @file, http://drupal.org/node/1353118 doesn't. I'm guessing the former is accurate.
Extra blank line after use statements can be removed.
Comment #40
alexpottDamn c&p from Drupal\book\Controller\BookController ... at least I didn't commit it :)
Comment #41
star-szrLooks great. Thanks everyone!
Comment #41.0
star-szrUpdated issue summary.
Comment #41.1
star-szrAdd commit message
Comment #42
catchCommitted/pushed to 8.x, thanks!
Comment #43.0
(not verified) CreditAttribution: commentedWhitespace