Skip to content

Commit e87d408

Browse files
authored
Add support for a SourceLocation container (#22)
* Add support for a SourceLocation container * style fix
1 parent e82f42a commit e87d408

File tree

4 files changed

+174
-0
lines changed

4 files changed

+174
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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;
13+
14+
use Translation\Extractor\Model\SourceLocation;
15+
16+
/**
17+
* This interface is recognized by the extractors. Use this on your Form classes
18+
* or anywhere where you have dynamic translation strings.
19+
*
20+
* @author Tobias Nyholm <[email protected]>
21+
*/
22+
interface TranslationSourceLocationContainer
23+
{
24+
/**
25+
* Return an array of source locations.
26+
*
27+
* @return SourceLocation[]
28+
*/
29+
public static function getTranslationSourceLocations();
30+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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\Php;
13+
14+
use PhpParser\Node;
15+
use PhpParser\NodeVisitor;
16+
use Translation\Extractor\Model\SourceLocation;
17+
18+
/**
19+
* Extract translations from classes implementing
20+
* Translation\Extractor\Model\SourceLocation\TranslationSourceLocationContainer.
21+
*
22+
* @author Tobias Nyholm <[email protected]>
23+
*/
24+
class SourceLocationContainerExtractor extends BasePHPVisitor implements NodeVisitor
25+
{
26+
/**
27+
* @var string
28+
*/
29+
private $namespace = '';
30+
31+
/**
32+
* @var array
33+
*/
34+
private $useStatements = [];
35+
36+
public function beforeTraverse(array $nodes)
37+
{
38+
}
39+
40+
public function enterNode(Node $node)
41+
{
42+
if ($node instanceof Node\Stmt\Namespace_) {
43+
if (isset($node->name)) {
44+
// Save namespace of this class for later.
45+
$this->namespace = implode('\\', $node->name->parts);
46+
}
47+
$this->useStatements = [];
48+
49+
return;
50+
}
51+
52+
if ($node instanceof Node\Stmt\UseUse) {
53+
$this->useStatements[$node->alias] = implode('\\', $node->name->parts);
54+
55+
return;
56+
}
57+
58+
if (!$node instanceof Node\Stmt\Class_) {
59+
return;
60+
}
61+
62+
$isContainer = false;
63+
foreach ($node->implements as $interface) {
64+
$name = implode('\\', $interface->parts);
65+
if (isset($this->useStatements[$name])) {
66+
$name = $this->useStatements[$name];
67+
}
68+
69+
if ('Translation\Extractor\TranslationSourceLocationContainer' === $name) {
70+
$isContainer = true;
71+
break;
72+
}
73+
}
74+
75+
if (!$isContainer) {
76+
return;
77+
}
78+
79+
$sourceLocations = call_user_func([$this->namespace.'\\'.$node->name, 'getTranslationSourceLocations']);
80+
if (!is_array($sourceLocations)) {
81+
throw new \RuntimeException(sprintf('%s::getTranslationSourceLocations() was expected to return an array of SourceLocations, but got %s.', $this->namespace.'\\'.$node->name, gettype($sourceLocations)));
82+
}
83+
84+
foreach ($sourceLocations as $sourceLocation) {
85+
if (!$sourceLocation instanceof SourceLocation) {
86+
throw new \RuntimeException(sprintf('%s::getTranslationSourceLocations() was expected to return an array of SourceLocations, but got an array which contains an item of type %s.', $this->namespace.'\\'.$node->name, gettype($sourceLocation)));
87+
}
88+
89+
$this->collection->addLocation($sourceLocation);
90+
}
91+
}
92+
93+
public function leaveNode(Node $node)
94+
{
95+
}
96+
97+
public function afterTraverse(array $nodes)
98+
{
99+
}
100+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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\Tests\Functional\Visitor\Php;
13+
14+
use Translation\Extractor\Visitor\Php\SourceLocationContainerExtractor;
15+
use Translation\Extractor\Tests\Resources;
16+
17+
class SourceLocationContainerExtractorTest extends BasePHPVisitorTest
18+
{
19+
public function testExtract()
20+
{
21+
$collection = $this->getSourceLocations(new SourceLocationContainerExtractor(), Resources\Php\SourceLocationContainer::class);
22+
23+
$this->assertCount(2, $collection);
24+
$source = $collection->first();
25+
$this->assertEquals('foo', $source->getMessage());
26+
}
27+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Translation\Extractor\Tests\Resources\Php;
4+
5+
use Translation\Extractor\Model\SourceLocation;
6+
use Translation\Extractor\TranslationSourceLocationContainer;
7+
8+
class SourceLocationContainer implements TranslationSourceLocationContainer
9+
{
10+
public static function getTranslationSourceLocations()
11+
{
12+
return [
13+
SourceLocation::createHere('foo'),
14+
SourceLocation::createHere('bar'),
15+
];
16+
}
17+
}

0 commit comments

Comments
 (0)