-
Notifications
You must be signed in to change notification settings - Fork 93
/
Copy pathDefaultApplyingNodeVisitor.php
162 lines (138 loc) · 5.28 KB
/
DefaultApplyingNodeVisitor.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<?php
/*
* This file is part of the PHP Translation package.
*
* (c) PHP Translation team <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Translation\Bundle\Twig\Visitor;
use Translation\Bundle\Twig\Node\Transchoice;
use Twig\Environment;
use Twig\Node\Expression\ArrayExpression;
use Twig\Node\Expression\Binary\EqualBinary;
use Twig\Node\Expression\ConditionalExpression;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\FilterExpression;
use Twig\Node\Expression\Ternary\ConditionalTernary;
use Twig\Node\Node;
use Twig\Node\Nodes;
use Twig\TwigFilter;
/**
* Applies the value of the "desc" filter if the "trans" filter has no
* translations.
*
* This is only active in your development environment.
*
* @author Johannes M. Schmitt <[email protected]>
*/
final class DefaultApplyingNodeVisitor extends AbstractNodeVisitor
{
/**
* @var bool
*/
private $enabled = true;
public function setEnabled(bool $bool): void
{
$this->enabled = $bool;
}
public function doEnterNode(Node $node, Environment $env): Node
{
if (!$this->enabled) {
return $node;
}
if (!($node instanceof FilterExpression && 'desc' === $this->getValueFromNode($node))) {
return $node;
}
$transNode = $node->getNode('node');
while ($transNode instanceof FilterExpression
&& 'trans' !== $this->getValueFromNode($transNode)
&& 'transchoice' !== $this->getValueFromNode($transNode)) {
$transNode = $transNode->getNode('node');
}
if (!$transNode instanceof FilterExpression) {
throw new \RuntimeException('The "desc" filter must be applied after a "trans", or "transchoice" filter.');
}
$wrappingNode = $node->getNode('node');
$testNode = clone $wrappingNode;
$defaultNode = $node->getNode('arguments')->getNode(0);
// if the |transchoice filter is used, delegate the call to the TranslationExtension
// so that we can catch a possible exception when the default translation has not yet
// been extracted
if ('transchoice' === $this->getValueFromNode($transNode)) {
$transchoiceArguments = new ArrayExpression([], $transNode->getTemplateLine());
$transchoiceArguments->addElement($wrappingNode->getNode('node'));
$transchoiceArguments->addElement($defaultNode);
foreach ($wrappingNode->getNode('arguments') as $arg) {
$transchoiceArguments->addElement($arg);
}
$transchoiceNode = new Transchoice($transchoiceArguments, $transNode->getTemplateLine());
$node->setNode('node', $transchoiceNode);
return $node;
}
// if the |trans filter has replacements parameters
// (e.g. |trans({'%foo%': 'bar'}))
if ($wrappingNode->getNode('arguments')->hasNode(0)) {
$lineno = $wrappingNode->getTemplateLine();
// remove the replacements from the test node
$testNode->setNode('arguments', clone $testNode->getNode('arguments'));
$testNode->getNode('arguments')->setNode(0, new ArrayExpression([], $lineno));
// wrap the default node in a |replace filter
if (Environment::VERSION_ID >= 31500) {
$defaultNode = new FilterExpression(
clone $node->getNode('arguments')->getNode(0),
new TwigFilter('replace'),
new Nodes([
clone $wrappingNode->getNode('arguments')->getNode(0),
]),
$lineno
);
} else {
$defaultNode = new FilterExpression(
clone $node->getNode('arguments')->getNode(0),
new ConstantExpression('replace', $lineno),
new Node([
clone $wrappingNode->getNode('arguments')->getNode(0),
]),
$lineno
);
}
}
$expr = new EqualBinary($testNode, $transNode->getNode('node'), $wrappingNode->getTemplateLine());
if (Environment::VERSION_ID >= 31700) {
$expr->setAttribute('operator', 'binary_==');
$condition = new ConditionalTernary(
$expr,
$defaultNode,
clone $wrappingNode,
$wrappingNode->getTemplateLine()
);
} else {
$condition = new ConditionalExpression(
$expr,
$defaultNode,
clone $wrappingNode,
$wrappingNode->getTemplateLine()
);
}
$node->setNode('node', $condition);
return $node;
}
public function doLeaveNode(Node $node, Environment $env): Node
{
return $node;
}
public function getPriority(): int
{
return -2;
}
public function enterNode(Node $node, Environment $env): Node
{
return $this->doEnterNode($node, $env);
}
public function leaveNode(Node $node, Environment $env): ?Node
{
return $this->doLeaveNode($node, $env);
}
}