Skip to content

Instantly share code, notes, and snippets.

@emnsen
Last active May 17, 2022 13:43
Show Gist options
  • Save emnsen/f9c65c6ba5ceee8e0424fe5828994201 to your computer and use it in GitHub Desktop.
Save emnsen/f9c65c6ba5ceee8e0424fe5828994201 to your computer and use it in GitHub Desktop.
twig variable extractor #symfony #twig
<?php declare(strict_types=1);
namespace App\Twig;
use Twig\Environment;
use Twig\Node\Expression\ConditionalExpression;
use Twig\Node\Expression\Filter\DefaultFilter;
use Twig\Node\Expression\FilterExpression;
use Twig\Node\Expression\FunctionExpression;
use Twig\Node\Expression\NameExpression;
use Twig\Node\PrintNode;
use function iter\filter;
use function iter\flatten;
use function iter\func\operator;
use function iter\map;
use function iter\toArray;
final class VariableExtractor
{
public function __construct(
private Environment $twig,
) {
}
public function extract(string $path): ?array
{
$template = $this->twig->load($path);
$source = $template->getSourceContext();
$stream = $this->twig->tokenize($source);
$mainNode = $this->twig->parse($stream);
if (!$mainNode->hasNode('body')) {
return null;
}
$cb = static function ($node) use (&$cb) {
if ($node instanceof NameExpression) {
return $node->getAttribute('name');
}
if ($node instanceof ConditionalExpression) {
return $cb($node->getNode('expr1')->getNode('node'));
}
if ($node instanceof FilterExpression) {
$node = $node->getNode('node');
if ($node instanceof ConditionalExpression) {
return $cb($node->getNode('expr1'));
}
if ($node instanceof DefaultFilter) {
return $cb($node->getNode('node'));
}
return $node->getAttribute('name');
}
if ($node instanceof FunctionExpression) {
return map($cb, toArray($node->getNode('arguments')->getIterator()));
}
if ($node instanceof PrintNode) {
return $cb($node->getNode('expr'));
}
throw new \Exception('Something wrong with this node.');
};
return toArray(
flatten(
map(
$cb,
filter(
operator('instanceof', PrintNode::class),
$mainNode->getNode('body')->getNode('0')->getIterator(),
),
),
)
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment