Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d35fd52

Browse filesBrowse files
committed
bug #11906 [Intl] Fixed a few bugs in TextBundleWriter (webmozart)
This PR was merged into the 2.3 branch. Discussion ---------- [Intl] Fixed a few bugs in TextBundleWriter | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - See the included test cases for more information. This code was extracted from #9206. Commits ------- 7b4a35a [Intl] Fixed a few bugs in TextBundleWriter
2 parents 15aec88 + 7b4a35a commit d35fd52
Copy full SHA for d35fd52

File tree

6 files changed

+145
-16
lines changed
Filter options

6 files changed

+145
-16
lines changed
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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 Symfony\Component\Intl\Exception;
13+
14+
/**
15+
* Thrown when a method argument had an unexpected type.
16+
*
17+
* @author Bernhard Schussek <bschussek@gmail.com>
18+
*/
19+
class UnexpectedTypeException extends InvalidArgumentException
20+
{
21+
public function __construct($value, $expectedType)
22+
{
23+
parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
24+
}
25+
}

‎src/Symfony/Component/Intl/ResourceBundle/Writer/TextBundleWriter.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Intl/ResourceBundle/Writer/TextBundleWriter.php
+47-14Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111

1212
namespace Symfony\Component\Intl\ResourceBundle\Writer;
1313

14+
use Symfony\Component\Intl\Exception\UnexpectedTypeException;
15+
1416
/**
1517
* Writes .txt resource bundles.
1618
*
17-
* The resulting files can be converted to binary .res files using the
18-
* {@link \Symfony\Component\Intl\ResourceBundle\Transformer\BundleCompiler}.
19+
* The resulting files can be converted to binary .res files using a
20+
* {@link \Symfony\Component\Intl\ResourceBundle\Compiler\BundleCompilerInterface}
21+
* implementation.
1922
*
2023
* @author Bernhard Schussek <bschussek@gmail.com>
2124
*
@@ -28,11 +31,11 @@ class TextBundleWriter implements BundleWriterInterface
2831
/**
2932
* {@inheritdoc}
3033
*/
31-
public function write($path, $locale, $data)
34+
public function write($path, $locale, $data, $fallback = true)
3235
{
3336
$file = fopen($path.'/'.$locale.'.txt', 'w');
3437

35-
$this->writeResourceBundle($file, $locale, $data);
38+
$this->writeResourceBundle($file, $locale, $data, $fallback);
3639

3740
fclose($file);
3841
}
@@ -43,14 +46,16 @@ public function write($path, $locale, $data)
4346
* @param resource $file The file handle to write to.
4447
* @param string $bundleName The name of the bundle.
4548
* @param mixed $value The value of the node.
49+
* @param bool $fallback Whether the resource bundle should be merged
50+
* with the fallback locale.
4651
*
4752
* @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt
4853
*/
49-
private function writeResourceBundle($file, $bundleName, $value)
54+
private function writeResourceBundle($file, $bundleName, $value, $fallback)
5055
{
5156
fwrite($file, $bundleName);
5257

53-
$this->writeTable($file, $value, 0);
58+
$this->writeTable($file, $value, 0, $fallback);
5459

5560
fwrite($file, "\n");
5661
}
@@ -74,16 +79,25 @@ private function writeResource($file, $value, $indentation, $requireBraces = tru
7479
return;
7580
}
7681

82+
if ($value instanceof \Traversable) {
83+
$value = iterator_to_array($value);
84+
}
85+
7786
if (is_array($value)) {
78-
if (count($value) === count(array_filter($value, 'is_int'))) {
87+
$intValues = count($value) === count(array_filter($value, 'is_int'));
88+
89+
$keys = array_keys($value);
90+
91+
// check that the keys are 0-indexed and ascending
92+
$intKeys = $keys === range(0, count($keys) - 1);
93+
94+
if ($intValues && $intKeys) {
7995
$this->writeIntVector($file, $value, $indentation);
8096

8197
return;
8298
}
8399

84-
$keys = array_keys($value);
85-
86-
if (count($keys) === count(array_filter($keys, 'is_int'))) {
100+
if ($intKeys) {
87101
$this->writeArray($file, $value, $indentation);
88102

89103
return;
@@ -182,16 +196,35 @@ private function writeArray($file, array $value, $indentation)
182196
/**
183197
* Writes a "table" node.
184198
*
185-
* @param resource $file The file handle to write to.
186-
* @param array $value The value of the node.
187-
* @param int $indentation The number of levels to indent.
199+
* @param resource $file The file handle to write to.
200+
* @param array|\Traversable $value The value of the node.
201+
* @param int $indentation The number of levels to indent.
202+
* @param bool $fallback Whether the table should be merged
203+
* with the fallback locale.
204+
*
205+
* @throws UnexpectedTypeException When $value is not an array and not a
206+
* \Traversable instance.
188207
*/
189-
private function writeTable($file, array $value, $indentation)
208+
private function writeTable($file, $value, $indentation, $fallback = true)
190209
{
210+
if (!is_array($value) && !$value instanceof \Traversable) {
211+
throw new UnexpectedTypeException($value, 'array or \Traversable');
212+
}
213+
214+
if (!$fallback) {
215+
fwrite($file, ":table(nofallback)");
216+
}
217+
191218
fwrite($file, "{\n");
192219

193220
foreach ($value as $key => $entry) {
194221
fwrite($file, str_repeat(' ', $indentation + 1));
222+
223+
// escape colons, otherwise they are interpreted as resource types
224+
if (false !== strpos($key, ':') || false !== strpos($key, ' ')) {
225+
$key = '"'.$key.'"';
226+
}
227+
195228
fwrite($file, $key);
196229

197230
$this->writeResource($file, $entry, $indentation + 1);

‎src/Symfony/Component/Intl/Tests/ResourceBundle/Writer/Fixtures/en.txt

Copy file name to clipboardExpand all lines: src/Symfony/Component/Intl/Tests/ResourceBundle/Writer/Fixtures/en.txt
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ en{
1414
2,
1515
3,
1616
}
17+
NotAnIntVector{
18+
0:int{0}
19+
2:int{1}
20+
1:int{2}
21+
3:int{3}
22+
}
23+
IntVectorWithStringKeys{
24+
a:int{0}
25+
b:int{1}
26+
c:int{2}
27+
}
28+
TableWithIntKeys{
29+
0:int{0}
30+
1:int{1}
31+
3:int{3}
32+
}
1733
FalseBoolean{"false"}
1834
TrueBoolean{"true"}
1935
Null{""}
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
en_nofallback:table(nofallback){
2+
Entry{"Value"}
3+
}
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
escaped{
2+
"EntryWith:Colon"{"Value"}
3+
"Entry With Spaces"{"Value"}
4+
}

‎src/Symfony/Component/Intl/Tests/ResourceBundle/Writer/TextBundleWriterTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Intl/Tests/ResourceBundle/Writer/TextBundleWriterTest.php
+50-2Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class TextBundleWriterTest extends \PHPUnit_Framework_TestCase
3636
protected function setUp()
3737
{
3838
$this->writer = new TextBundleWriter();
39-
$this->directory = sys_get_temp_dir() . '/TextBundleWriterTest/' . rand(1000, 9999);
39+
$this->directory = sys_get_temp_dir().'/TextBundleWriterTest/'.rand(1000, 9999);
4040
$this->filesystem = new Filesystem();
4141

4242
$this->filesystem->mkdir($this->directory);
@@ -54,6 +54,9 @@ public function testWrite()
5454
'Array' => array('foo', 'bar', array('Key' => 'value')),
5555
'Integer' => 5,
5656
'IntVector' => array(0, 1, 2, 3),
57+
'NotAnIntVector' => array(0 => 0, 2 => 1, 1 => 2, 3 => 3),
58+
'IntVectorWithStringKeys' => array('a' => 0, 'b' => 1, 'c' => 2),
59+
'TableWithIntKeys' => array(0 => 0, 1 => 1, 3 => 3),
5760
'FalseBoolean' => false,
5861
'TrueBoolean' => true,
5962
'Null' => null,
@@ -62,6 +65,51 @@ public function testWrite()
6265
'Entry2' => 'String',
6366
));
6467

65-
$this->assertFileEquals(__DIR__ . '/Fixtures/en.txt', $this->directory . '/en.txt');
68+
$this->assertFileEquals(__DIR__.'/Fixtures/en.txt', $this->directory.'/en.txt');
69+
}
70+
71+
public function testWriteTraversable()
72+
{
73+
$this->writer->write($this->directory, 'en', new \ArrayIterator(array(
74+
'Entry1' => new \ArrayIterator(array(
75+
'Array' => array('foo', 'bar', array('Key' => 'value')),
76+
'Integer' => 5,
77+
'IntVector' => array(0, 1, 2, 3),
78+
'NotAnIntVector' => array(0 => 0, 2 => 1, 1 => 2, 3 => 3),
79+
'IntVectorWithStringKeys' => array('a' => 0, 'b' => 1, 'c' => 2),
80+
'TableWithIntKeys' => array(0 => 0, 1 => 1, 3 => 3),
81+
'FalseBoolean' => false,
82+
'TrueBoolean' => true,
83+
'Null' => null,
84+
'Float' => 1.23,
85+
)),
86+
'Entry2' => 'String',
87+
)));
88+
89+
$this->assertFileEquals(__DIR__.'/Fixtures/en.txt', $this->directory.'/en.txt');
90+
}
91+
92+
public function testWriteNoFallback()
93+
{
94+
$data = array(
95+
'Entry' => 'Value'
96+
);
97+
98+
$this->writer->write($this->directory, 'en_nofallback', $data, $fallback = false);
99+
100+
$this->assertFileEquals(__DIR__.'/Fixtures/en_nofallback.txt', $this->directory.'/en_nofallback.txt');
101+
}
102+
103+
public function testEscapeKeysIfNecessary()
104+
{
105+
$this->writer->write($this->directory, 'escaped', array(
106+
// Keys with colons must be escaped, otherwise the part after the
107+
// colon is interpreted as resource type
108+
'EntryWith:Colon' => 'Value',
109+
// Keys with spaces must be escaped
110+
'Entry With Spaces' => 'Value',
111+
));
112+
113+
$this->assertFileEquals(__DIR__.'/Fixtures/escaped.txt', $this->directory.'/escaped.txt');
66114
}
67115
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.