RangeError: Maximum call stack size exceeded in Twig - twig

I create twig template with structure
main.twig has block content with include 'card.twig'
card.twig extends 'main.twig' and realise block content with block secondContent include 'rec.twig
rec.twig extends 'card.twig' and realise block secondContent
But I have RangeError: Maximum call stack size exceeded. Why?

I create infinite loop. I solve it by below scheme
main.twig has block content with include 'card.twig'
card.twig realise block content with block secondContent include 'rec.twig'
rec.twig realise block secondContent

Related

Can we access twig inner property on construction?

Let's say I'm constructing a Twig object and I want to access an inner property defined previously:
{% set my_object =
default_width: 12,
default_height: default_width * 2
%}
This throws a Variable "default_width" does not exist error, which make sense since the object was not entirely declared yet but is there a way to make this work without two instructions?
This behavior isn't possible, the best way to do it is to declare a variable before the construction and reusing it here.

Using original function inside jest mock causes infinite loop

I have a chainable method from dynamoose where in testing I would like to add an additional method to the chain.
Essentially, in testing I would like to replace all instances of
Model.query(key).otherChainableMethods()
with
Model.query(key).limit(LIMIT).otherChainableMethods()
So I tried:
Model.query = jest.fn(key => Model.query(key).limit(LIMIT))
but this is clearly causing some sort of infinite loop, because I get RangeError: Maximum call stack size exceeded
How can use the original implementation of a function inside the mock implementation?
I found a simple solution. I can simply store the original method in another variable first.
const originalQuery = Profile.query
Profile.query = jest.fn(key => originalQuery(key).limit(LIMIT))

Rendering Twig template returns "cache is corrupted" and outputs PHP code

I'm attempting to render out a Twig template that has no layout, just a few variables and some loops.
When I call the render() function on Twig, it outputs a block of PHP code for the following class:
php
/** path/to/my/template.html.twig */
class __TwigTemplate_435244378aba3a3f94258b7d2af4d53eb7a41acb741dd3ad0efcac038b621c67 extends Twig_Template
{
// bunch of methods for Twig_Template,
// including the compiled version of my template
}
After this it gives me a stack trace with the following exception:
Failed to load Twig template "path/to/my/template.html.twig", index "": cache is corrupted in "path/to/my/template.html.twig".
I'm not even using a cache with this app currently, though adding a cache doesn't seem to make a different. I'm using Twig like this:
// Factory to return a new Twig environment
$loader = new \Twig_Loader_Filesystem(__DIR__ . '/../../views/');
return new \Twig_Environment($loader);
// My class has $this->twig set to the above object
$this->twig->render('path/to/my/template.html.twig', [
'report' => $report,
'file' => $file
]);
Twig seems to be able to read in my template, as the block of PHP code it outputs in the error has a properly compiled version of the template. Attempting to set a cache directory that is writable still results in the same error.
I'm using Twig 1.34.4 and PHP 5.6.29 under Apache.
EDIT
A bit of success, in a way. It seems that Twig is never evaling the code that it's generating.
I edited the vendor/twig/twig/lib/Twig/Environment.php file and on line 448 added the following:
eval("?><?" . $content);
After that my template renders just fine. That leads me to the conclusion something else in Twig is breaking, but this isn't a long-term solution since I shouldn't be editing the vendor files.
The block starting at line 456 seems to indicate that $content should have the opening <? but mine doesn't. So that could be screwing with the compilation.
Time for more digging.
I finally figured it out. It wasn't Twig's fault.
Our deployment process was leaving old files on the disk, so I was running with only part of 1.34.4 upgraded.
Fixed that and everything works.

how to define a default/fallback block in jade

I have a layout that looks like this:
body
header.l-header.l-site-width
block header
// include the block with the name body form whatever file that uses layout
.l-body.l-site-width
block body
footer.l-footer.l-site-width
block footer
now i don't specify a header block in the file that is using the layout, i would like to use a default include.
I tried:
block header || "something else"
in the best case:
block header || include ../partials/base/header
it does not work, but does not trow an error.
Any idea how to do this?
You can actually just write your default code in the header block.
block header
include ../partials/base/header
If you now extend your layout you can overwrite the contents of the block with a simple standalone block statement.
extends layout
block header
... your code ...
Alternatively you can use append or prepend to add to the block, in this case the old content persists.

global variables not parsing as parameters

I am having troubles with global variables not parsing when passed as parameters.
{exp:channel:entries
disable="categories|category_fields|member_data|pagination|trackbacks"
dynamic="no"
entry_id="{structure:child_ids_for:21}"
}
(0.012500 / 3.36MB) Tag: {exp:channel:entries disable="categories|category_fields|member_data|pagination|trackbacks" dynamic="no" entry_id="{structure:child_ids_for:21}" }
The same result is produced with and without parse="inward"
However this works fine and grabs the data I need
{exp:channel:entries
disable="categories|category_fields|member_data|pagination|trackbacks"
dynamic="no"
entry_id="{exp:query sql='SELECT exp_structure.entry_id,
exp_structure.parent_id,
exp_structure.lft
FROM exp_structure
WHERE parent_id = 21
ORDER BY exp_structure.lft ASC'}{entry_id}|{/exp:query}"
parse="inward"
}
But, then if I add in a global variable author_id="{logged_in_member_id}" it fails to work, if I hard code that value as 1 then it functions.
Any thoughts as to what could be happening here?
You can avoid the overhead of embeds by using Stash for this sort of thing. It has the insanely useful ability to let you explicitly state your preferred parse order for different chunks of code. In this case the first thing you'd do is store the two variables via {exp:stash:set}, then you can retrieve them in the second chunk of code via {exp:stash:get}. The magic bit is the parse priority tag; because the first item has a priority of 10 it will be executed first, which ensures the vars are available for use as channel entries parameters in the second {exp:stash:parse} tag.
{exp:stash:parse priority="10" process="end"}
{exp:stash:set}
{stash:structure_ids}{structure:sibling_ids}{/stash:structure_ids}
{stash:logged_in_member}{logged_in_member_id}{/stash:logged_in_member}
{/exp:stash:set}
{/exp:stash:parse}
{exp:stash:parse priority="20" process="end"}
{exp:channel:entries
disable="categories|category_fields|member_data|pagination|trackbacks"
dynamic="no"
entry_id="{exp:stash:get name='structure_ids'}"
author_id="{exp:stash:get name='logged_in_member'}"
parse="inward"
}
...
{/exp:channel:entries}
{/exp:stash:parse}
I can't speak for Structure's global variables, but {logged_in_member_id} is a late-parsed global variable, meaning you can't use it in a module tag parameter. I can only only assume that the same goes for the Structure variables.
You can use the CURRENT_USER constant in the author_id parameter though (docs).
Unfortunately, the solution for your {structure:child_ids_for:21} issue is to pass that as an embed variable, and put your Channel Entries loop in an embed. (I say unfortunately because embeds do incur some overhead.)
One note: parse="inward" has no effect on module tag pairs - they always parse inward. It only affects plugin tag pairs.

Resources