Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2d26645

Browse files
committed
add context transformer to support closures
1 parent 8f854fa commit 2d26645

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

core-bundle/src/Resources/contao/library/Contao/TemplateInheritance.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
namespace Contao;
1212

1313
use Contao\CoreBundle\Monolog\ContaoContext;
14+
use Contao\CoreBundle\Twig\Interop\ContextHelper;
1415
use Psr\Log\LogLevel;
1516
use Symfony\Component\DependencyInjection\ContainerInterface;
1617

@@ -338,6 +339,11 @@ protected function getTemplatePath($strTemplate, $strFormat='html5', $blnDefault
338339

339340
private function renderTwigSurrogateIfExists(): ?string
340341
{
342+
if (!$this instanceof Template)
343+
{
344+
return null;
345+
}
346+
341347
$container = System::getContainer();
342348

343349
if (null === ($twig = $container->get('twig', ContainerInterface::NULL_ON_INVALID_REFERENCE)))
@@ -349,7 +355,7 @@ private function renderTwigSurrogateIfExists(): ?string
349355

350356
if ($twig->getLoader()->exists($templateCandidate))
351357
{
352-
return $twig->render($templateCandidate, $this->arrData);
358+
return $twig->render($templateCandidate, ContextHelper::fromContaoTemplate($this));
353359
}
354360

355361
return null;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of Contao.
7+
*
8+
* (c) Leo Feyer
9+
*
10+
* @license LGPL-3.0-or-later
11+
*/
12+
13+
namespace Contao\CoreBundle\Twig\Interop;
14+
15+
use Contao\Template;
16+
17+
class ContextHelper
18+
{
19+
/**
20+
* Adjust Contao template data to seamlessly work as a Twig context.
21+
*/
22+
public static function fromContaoTemplate(Template $template): array
23+
{
24+
$context = $template->getData();
25+
26+
array_walk_recursive(
27+
$context,
28+
static function (&$value, $key): void {
29+
if (\is_callable($value)) {
30+
$value = self::getCallableWrapper($value, (string) $key);
31+
}
32+
}
33+
);
34+
35+
return $context;
36+
}
37+
38+
private static function getCallableWrapper(callable $callable, string $name): object
39+
{
40+
return new class($callable, $name) {
41+
/**
42+
* @var callable
43+
*/
44+
private $callable;
45+
46+
/**
47+
* @var string
48+
*/
49+
private $name;
50+
51+
public function __construct(callable $callable, string $name)
52+
{
53+
$this->callable = $callable;
54+
$this->name = $name;
55+
}
56+
57+
/**
58+
* Delegate call to callable, e.g. when in a Contao template context.
59+
*/
60+
public function __invoke(...$args)
61+
{
62+
return ($this->callable)(...$args);
63+
}
64+
65+
/**
66+
* Called when evaluating `{{ var }}` in a Twig template.
67+
*/
68+
public function __toString(): string
69+
{
70+
try {
71+
return (string) $this();
72+
} catch (\Throwable $e) {
73+
// Enhance exception message
74+
throw new \RuntimeException("There was an error evaluating '{$this->name}': {$e->getMessage()}");
75+
}
76+
}
77+
78+
/**
79+
* Called when evaluating `{{ var.invoke(…) }}` in a Twig template.
80+
* We do not cast to string here, so that other types (like arrays)
81+
* are supported as well.
82+
*/
83+
public function invoke(...$args)
84+
{
85+
return $this(...$args);
86+
}
87+
};
88+
}
89+
}

0 commit comments

Comments
 (0)