Skip to content

Commit a423a52

Browse files
authored
Using better visitors for twig (#35)
* Using better extractor * Adding new Twig visitors and workers * Reverted some changes * cs * Removed class not used * Updated docs
1 parent c953860 commit a423a52

14 files changed

+271
-19
lines changed

src/FileExtractor/TwigFileExtractor.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
/**
1919
* @author Tobias Nyholm <[email protected]>
2020
*/
21-
final class TwigFileExtractor implements FileExtractor
21+
final class TwigFileExtractor extends \Twig_Extension implements FileExtractor
2222
{
2323
/**
2424
* @var Visitor[]|\Twig_NodeVisitorInterface[]
@@ -36,6 +36,7 @@ final class TwigFileExtractor implements FileExtractor
3636
public function __construct(\Twig_Environment $twig)
3737
{
3838
$this->twig = $twig;
39+
$twig->addExtension($this);
3940
}
4041

4142
public function getSourceLocations(SplFileInfo $file, SourceCollection $collection)
@@ -52,9 +53,7 @@ public function getSourceLocations(SplFileInfo $file, SourceCollection $collecti
5253
} else {
5354
$stream = $this->twig->tokenize($file->getContents(), $path);
5455
}
55-
$tokens = $this->twig->parse($stream);
56-
$traverser = new \Twig_NodeTraverser($this->twig, $this->visitors);
57-
$traverser->traverse($tokens);
56+
$this->twig->parse($stream);
5857
}
5958

6059
public function getType()
@@ -69,4 +68,12 @@ public function addVisitor(\Twig_NodeVisitorInterface $visitor)
6968
{
7069
$this->visitors[] = $visitor;
7170
}
71+
72+
/**
73+
* {@inheritdoc}
74+
*/
75+
public function getNodeVisitors()
76+
{
77+
return $this->visitors;
78+
}
7279
}

src/Visitor/Twig/TranslationBlock.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
/**
1919
* @author Tobias Nyholm <[email protected]>
20+
*
21+
* @deprecated Use Twig1Visitor. Will be removed in 2.0.
2022
*/
2123
final class TranslationBlock extends BaseVisitor implements \Twig_NodeVisitorInterface
2224
{

src/Visitor/Twig/TranslationFilter.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
/**
1919
* @author Tobias Nyholm <[email protected]>
20+
*
21+
* @deprecated Use Twig1Visitor. Will be removed in 2.0.
2022
*/
2123
final class TranslationFilter extends BaseVisitor implements \Twig_NodeVisitorInterface
2224
{

src/Visitor/Twig/Twig1Visitor.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the PHP Translation package.
5+
*
6+
* (c) PHP Translation team <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Translation\Extractor\Visitor\Twig;
13+
14+
use Translation\Extractor\Visitor\BaseVisitor;
15+
use Twig_Environment;
16+
use Twig_NodeInterface;
17+
18+
/**
19+
* @author Tobias Nyholm <[email protected]>
20+
*/
21+
final class Twig1Visitor extends BaseVisitor implements \Twig_NodeVisitorInterface
22+
{
23+
/**
24+
* @var WorkerTranslationFilter
25+
*/
26+
private $worker;
27+
28+
public function __construct()
29+
{
30+
$this->worker = new Worker();
31+
}
32+
33+
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
34+
{
35+
return $this->worker->work($node, $this->collection, function () {
36+
return $this->getAbsoluteFilePath();
37+
});
38+
}
39+
40+
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
41+
{
42+
return $node;
43+
}
44+
45+
public function getPriority()
46+
{
47+
return 0;
48+
}
49+
}

src/Visitor/Twig/Twig2TranslationBlock.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
/**
1919
* @author Tobias Nyholm <[email protected]>
20+
*
21+
* @deprecated Use Twig2Visitor. Will be removed in 2.0.
2022
*/
2123
final class Twig2TranslationBlock extends BaseVisitor implements \Twig_NodeVisitorInterface
2224
{

src/Visitor/Twig/Twig2TranslationFilter.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
/**
1919
* @author Tobias Nyholm <[email protected]>
20+
*
21+
* @deprecated Use Twig2Visitor. Will be removed in 2.0.
2022
*/
2123
final class Twig2TranslationFilter extends BaseVisitor implements \Twig_NodeVisitorInterface
2224
{

src/Visitor/Twig/Twig2Visitor.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the PHP Translation package.
5+
*
6+
* (c) PHP Translation team <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Translation\Extractor\Visitor\Twig;
13+
14+
use Translation\Extractor\Visitor\BaseVisitor;
15+
use Twig_Environment;
16+
use Twig_Node;
17+
18+
/**
19+
* @author Tobias Nyholm <[email protected]>
20+
*/
21+
final class Twig2Visitor extends BaseVisitor implements \Twig_NodeVisitorInterface
22+
{
23+
/**
24+
* @var WorkerTranslationFilter
25+
*/
26+
private $worker;
27+
28+
public function __construct()
29+
{
30+
$this->worker = new Worker();
31+
}
32+
33+
public function enterNode(Twig_Node $node, Twig_Environment $env)
34+
{
35+
return $this->worker->work($node, $this->collection, function () {
36+
return $this->getAbsoluteFilePath();
37+
});
38+
}
39+
40+
public function leaveNode(Twig_Node $node, Twig_Environment $env)
41+
{
42+
return $node;
43+
}
44+
45+
public function getPriority()
46+
{
47+
return 0;
48+
}
49+
}

src/Visitor/Twig/Worker.php

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the PHP Translation package.
5+
*
6+
* (c) PHP Translation team <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Translation\Extractor\Visitor\Twig;
13+
14+
use Symfony\Bridge\Twig\Node\TransNode;
15+
use Translation\Extractor\Model\SourceCollection;
16+
use Translation\Extractor\Model\SourceLocation;
17+
18+
/**
19+
* The Worker tha actually extract the translations.
20+
*
21+
* @author Tobias Nyholm <[email protected]>
22+
* @author Fabien Potencier <[email protected]>
23+
*/
24+
final class Worker
25+
{
26+
const UNDEFINED_DOMAIN = 'messages';
27+
28+
/**
29+
* @param \Twig_Node|\Twig_NodeInterface $node
30+
* @param SourceCollection $collection
31+
* @param callable $getAbsoluteFilePath
32+
*
33+
* @return \Twig_Node|\Twig_NodeInterface
34+
*/
35+
public function work($node, SourceCollection $collection, callable $getAbsoluteFilePath)
36+
{
37+
if (
38+
$node instanceof \Twig_Node_Expression_Filter &&
39+
'trans' === $node->getNode('filter')->getAttribute('value') &&
40+
$node->getNode('node') instanceof \Twig_Node_Expression_Constant
41+
) {
42+
// extract constant nodes with a trans filter
43+
$collection->addLocation(new SourceLocation(
44+
$node->getNode('node')->getAttribute('value'),
45+
$getAbsoluteFilePath(),
46+
$node->getTemplateLine(),
47+
['domain' => $this->getReadDomainFromArguments($node->getNode('arguments'), 1)]
48+
));
49+
} elseif (
50+
$node instanceof \Twig_Node_Expression_Filter &&
51+
'transchoice' === $node->getNode('filter')->getAttribute('value') &&
52+
$node->getNode('node') instanceof \Twig_Node_Expression_Constant
53+
) {
54+
// extract constant nodes with a trans filter
55+
$collection->addLocation(new SourceLocation(
56+
$node->getNode('node')->getAttribute('value'),
57+
$getAbsoluteFilePath(),
58+
$node->getTemplateLine(),
59+
['domain' => $this->getReadDomainFromArguments($node->getNode('arguments'), 2)]
60+
));
61+
} elseif ($node instanceof TransNode) {
62+
// extract trans nodes
63+
$collection->addLocation(new SourceLocation(
64+
$node->getNode('body')->getAttribute('data'),
65+
$getAbsoluteFilePath(),
66+
$node->getTemplateLine(),
67+
['domain' => $node->hasNode('domain') ? $this->getReadDomainFromNode($node->getNode('domain')) : self::UNDEFINED_DOMAIN]
68+
));
69+
}
70+
71+
return $node;
72+
}
73+
74+
/**
75+
* @param \Twig_Node $arguments
76+
* @param int $index
77+
*
78+
* @return string|null
79+
*/
80+
private function getReadDomainFromArguments(\Twig_Node $arguments, $index)
81+
{
82+
if ($arguments->hasNode('domain')) {
83+
$argument = $arguments->getNode('domain');
84+
} elseif ($arguments->hasNode($index)) {
85+
$argument = $arguments->getNode($index);
86+
} else {
87+
return self::UNDEFINED_DOMAIN;
88+
}
89+
90+
return $this->getReadDomainFromNode($argument);
91+
}
92+
93+
/**
94+
* @param \Twig_Node $node
95+
*
96+
* @return string|null
97+
*/
98+
private function getReadDomainFromNode(\Twig_Node $node)
99+
{
100+
if ($node instanceof \Twig_Node_Expression_Constant) {
101+
return $node->getAttribute('value');
102+
}
103+
104+
return self::UNDEFINED_DOMAIN;
105+
}
106+
}

src/Visitor/Twig/WorkerTranslationBlock.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
/**
1919
* @author Tobias Nyholm <[email protected]>
20+
*
21+
* @deprecated Use Worker. Will be removed in 2.0.
2022
*/
2123
final class WorkerTranslationBlock
2224
{

src/Visitor/Twig/WorkerTranslationFilter.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
/**
1818
* @author Tobias Nyholm <[email protected]>
19+
*
20+
* @deprecated Use Worker. Will be removed in 2.0.
1921
*/
2022
final class WorkerTranslationFilter
2123
{

0 commit comments

Comments
 (0)