Skip to content

Commit ff3ed89

Browse files
committed
Merge branch '2.5'
* 2.5: (23 commits) [HttpKernel] fixed some unit tests for 2.4 (signature now uses SHA256 instead of MD5) [HttpKernel] simplified code [HttpKernel] fixed internal fragment handling fixing yaml indentation Unexpexted ));" [WebProfiler] replaced the import/export feature from the web interface to a CLI tool Forced all fragment uris to be signed, even for ESI Add tests and more assertions [FrameworkBundle][Translator] Validate locales. [HttpFoundation] added some missing tests [HttpFoundation] Improve string values in test codes [Security] Add more tests for StringUtils::equals fix comment: not fourth but sixth argument fixing typo in a comment [FrameworkBundle] fixed CS [FrameworkBundle] PhpExtractor bugfix and improvements [Finder] Fix findertest readability [Filesystem] Add FTP stream wrapper context option to enable overwrite (override) fix parsing of Authorization header Test examples from Drupal SA-CORE-2014-003 ... Conflicts: src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/admin.html.twig src/Symfony/Component/Filesystem/Filesystem.php src/Symfony/Component/HttpKernel/Fragment/EsiFragmentRenderer.php
2 parents 048f5da + 46fd9ec commit ff3ed89

File tree

7 files changed

+324
-21
lines changed

7 files changed

+324
-21
lines changed

Resources/config/fragment_renderer.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
<tag name="kernel.fragment_renderer" />
4141
<argument type="service" id="esi" on-invalid="null" />
4242
<argument type="service" id="fragment.renderer.inline" />
43+
<argument type="service" id="uri_signer" />
4344
<call method="setFragmentPath"><argument>%fragment.path%</argument></call>
4445
</service>
4546

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,33 @@
11
This template is used for translation message extraction tests
22
<?php echo $view['translator']->trans('single-quoted key') ?>
33
<?php echo $view['translator']->trans("double-quoted key") ?>
4+
<?php echo $view['translator']->trans(<<<EOF
5+
heredoc key
6+
EOF
7+
) ?>
8+
<?php echo $view['translator']->trans(<<<'EOF'
9+
nowdoc key
10+
EOF
11+
) ?>
12+
<?php echo $view['translator']->trans(
13+
"double-quoted key with whitespace and escaped \$\n\" sequences"
14+
) ?>
15+
<?php echo $view['translator']->trans(
16+
'single-quoted key with whitespace and nonescaped \$\n\' sequences'
17+
) ?>
18+
<?php echo $view['translator']->trans( <<<EOF
19+
heredoc key with whitespace and escaped \$\n sequences
20+
EOF
21+
) ?>
22+
<?php echo $view['translator']->trans( <<<'EOF'
23+
nowdoc key with whitespace and nonescaped \$\n sequences
24+
EOF
25+
) ?>
26+
27+
<?php echo $view['translator']->trans('single-quoted key with "quote mark at the end"') ?>
28+
29+
<?php echo $view['translator']->transChoice(
30+
'{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples',
31+
10,
32+
array('%count%' => 10)
33+
) ?>

Tests/Translation/PhpExtractorTest.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,27 @@ public function testExtraction()
2727
// Act
2828
$extractor->extract(__DIR__.'/../Fixtures/Resources/views/', $catalogue);
2929

30+
$expectedHeredoc = <<<EOF
31+
heredoc key with whitespace and escaped \$\n sequences
32+
EOF;
33+
$expectedNowdoc = <<<'EOF'
34+
nowdoc key with whitespace and nonescaped \$\n sequences
35+
EOF;
3036
// Assert
31-
$this->assertCount(2, $catalogue->all('messages'), '->extract() should find 1 translation');
32-
$this->assertTrue($catalogue->has('single-quoted key'), '->extract() should find the "single-quoted key" message');
33-
$this->assertTrue($catalogue->has('double-quoted key'), '->extract() should find the "double-quoted key" message');
34-
$this->assertEquals('prefixsingle-quoted key', $catalogue->get('single-quoted key'), '->extract() should apply "prefix" as prefix');
37+
$expectedCatalogue = array('messages' => array(
38+
'single-quoted key' => 'prefixsingle-quoted key',
39+
'double-quoted key' => 'prefixdouble-quoted key',
40+
'heredoc key' => 'prefixheredoc key',
41+
'nowdoc key' => 'prefixnowdoc key',
42+
"double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixdouble-quoted key with whitespace and escaped \$\n\" sequences",
43+
'single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixsingle-quoted key with whitespace and nonescaped \$\n\' sequences',
44+
'single-quoted key with "quote mark at the end"' => 'prefixsingle-quoted key with "quote mark at the end"',
45+
$expectedHeredoc => "prefix".$expectedHeredoc,
46+
$expectedNowdoc => "prefix".$expectedNowdoc,
47+
'{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples' => 'prefix{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples',
48+
));
49+
$actualCatalogue = $catalogue->all();
50+
51+
$this->assertEquals($expectedCatalogue, $actualCatalogue);
3552
}
3653
}

Tests/Translation/TranslatorTest.php

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@ public function testTransWithCaching()
9393
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
9494
}
9595

96+
public function testTransWithCachingWithInvalidLocale()
97+
{
98+
$loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
99+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), '\Symfony\Bundle\FrameworkBundle\Tests\Translation\TranslatorWithInvalidLocale');
100+
$translator->setLocale('invalid locale');
101+
102+
$this->setExpectedException('\InvalidArgumentException');
103+
$translator->trans('foo');
104+
}
105+
96106
/**
97107
* @dataProvider getGetLocaleData
98108
*/
@@ -102,7 +112,7 @@ public function testGetLocale($inRequestScope)
102112
if ($inRequestScope) {
103113
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
104114
$request
105-
->expects($this->once())
115+
->expects($this->any())
106116
->method('getLocale')
107117
->will($this->returnValue('en'))
108118
;
@@ -135,6 +145,37 @@ public function getGetLocaleData()
135145
);
136146
}
137147

148+
public function testGetLocaleWithInvalidLocale()
149+
{
150+
$request = $this->getMock('Symfony\Component\HttpFoundation\Request');
151+
152+
$request
153+
->expects($this->any())
154+
->method('getLocale')
155+
->will($this->returnValue('foo bar'))
156+
;
157+
$request
158+
->expects($this->once())
159+
->method('getDefaultLocale')
160+
->will($this->returnValue('en-US'))
161+
;
162+
163+
$requestStack = new RequestStack();
164+
$requestStack->push($request);
165+
166+
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
167+
$container
168+
->expects($this->once())
169+
->method('get')
170+
->with('request_stack')
171+
->will($this->returnValue($requestStack))
172+
;
173+
174+
$translator = new Translator($container, new MessageSelector());
175+
$this->assertSame('en-US', $translator->getLocale());
176+
}
177+
178+
138179
protected function getCatalogue($locale, $messages)
139180
{
140181
$catalogue = new MessageCatalogue($locale);
@@ -215,9 +256,9 @@ protected function getContainer($loader)
215256
return $container;
216257
}
217258

218-
public function getTranslator($loader, $options = array())
259+
public function getTranslator($loader, $options = array(), $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator')
219260
{
220-
$translator = new Translator(
261+
$translator = new $translatorClass(
221262
$this->getContainer($loader),
222263
new MessageSelector(),
223264
array('loader' => array('loader')),
@@ -235,3 +276,14 @@ public function getTranslator($loader, $options = array())
235276
return $translator;
236277
}
237278
}
279+
280+
class TranslatorWithInvalidLocale extends Translator
281+
{
282+
/**
283+
* {@inheritdoc}
284+
*/
285+
public function setLocale($locale)
286+
{
287+
$this->locale = $locale;
288+
}
289+
}

Translation/PhpExtractor.php

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
class PhpExtractor implements ExtractorInterface
2424
{
2525
const MESSAGE_TOKEN = 300;
26-
const IGNORE_TOKEN = 400;
2726

2827
/**
2928
* Prefix for new found message.
@@ -39,15 +38,16 @@ class PhpExtractor implements ExtractorInterface
3938
*/
4039
protected $sequences = array(
4140
array(
42-
'$view',
43-
'[',
44-
'\'translator\'',
45-
']',
4641
'->',
4742
'trans',
4843
'(',
4944
self::MESSAGE_TOKEN,
50-
')',
45+
),
46+
array(
47+
'->',
48+
'transChoice',
49+
'(',
50+
self::MESSAGE_TOKEN,
5151
),
5252
);
5353

@@ -76,6 +76,7 @@ public function setPrefix($prefix)
7676
* Normalizes a token.
7777
*
7878
* @param mixed $token
79+
*
7980
* @return string
8081
*/
8182
protected function normalizeToken($token)
@@ -87,6 +88,56 @@ protected function normalizeToken($token)
8788
return $token;
8889
}
8990

91+
/**
92+
* Seeks to a non-whitespace token.
93+
*/
94+
private function seekToNextReleventToken(\Iterator $tokenIterator)
95+
{
96+
for (; $tokenIterator->valid(); $tokenIterator->next()) {
97+
$t = $tokenIterator->current();
98+
if (!is_array($t) || ($t[0] !== T_WHITESPACE)) {
99+
break;
100+
}
101+
}
102+
}
103+
104+
/**
105+
* Extracts the message from the iterator while the tokens
106+
* match allowed message tokens
107+
*/
108+
private function getMessage(\Iterator $tokenIterator)
109+
{
110+
$message = '';
111+
$docToken = '';
112+
113+
for (; $tokenIterator->valid(); $tokenIterator->next()) {
114+
$t = $tokenIterator->current();
115+
if (!is_array($t)) {
116+
break;
117+
}
118+
119+
switch ($t[0]) {
120+
case T_START_HEREDOC:
121+
$docToken = $t[1];
122+
break;
123+
case T_ENCAPSED_AND_WHITESPACE:
124+
case T_CONSTANT_ENCAPSED_STRING:
125+
$message .= $t[1];
126+
break;
127+
case T_END_HEREDOC:
128+
return PhpStringTokenParser::parseDocString($docToken, $message);
129+
default:
130+
break 2;
131+
}
132+
}
133+
134+
if ($message) {
135+
$message = PhpStringTokenParser::parse($message);
136+
}
137+
138+
return $message;
139+
}
140+
90141
/**
91142
* Extracts trans message from PHP tokens.
92143
*
@@ -95,24 +146,27 @@ protected function normalizeToken($token)
95146
*/
96147
protected function parseTokens($tokens, MessageCatalogue $catalog)
97148
{
98-
foreach ($tokens as $key => $token) {
149+
$tokenIterator = new \ArrayIterator($tokens);
150+
151+
for ($key = 0; $key < $tokenIterator->count(); $key++) {
99152
foreach ($this->sequences as $sequence) {
100153
$message = '';
154+
$tokenIterator->seek($key);
101155

102-
foreach ($sequence as $id => $item) {
103-
if ($this->normalizeToken($tokens[$key + $id]) == $item) {
156+
foreach ($sequence as $item) {
157+
$this->seekToNextReleventToken($tokenIterator);
158+
159+
if ($this->normalizeToken($tokenIterator->current()) == $item) {
160+
$tokenIterator->next();
104161
continue;
105162
} elseif (self::MESSAGE_TOKEN == $item) {
106-
$message = $this->normalizeToken($tokens[$key + $id]);
107-
} elseif (self::IGNORE_TOKEN == $item) {
108-
continue;
163+
$message = $this->getMessage($tokenIterator);
164+
break;
109165
} else {
110166
break;
111167
}
112168
}
113169

114-
$message = trim($message, '\'"');
115-
116170
if ($message) {
117171
$catalog->set($message, $this->prefix.$message);
118172
break;

0 commit comments

Comments
 (0)