Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1cef186

Browse files
committed
feature #22537 [Serializer] Allow to pass csv encoder options in context (ogizanagi)
This PR was merged into the 3.3-dev branch. Discussion ---------- [Serializer] Allow to pass csv encoder options in context | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | N/A | License | MIT | Doc PR | N/A CSV contents typically are provided by one or many third-parties, not always allowing you to get control over the provided format. In case you need to import csv files with different formats, either you have to instantiate a decoder yourself/inject it instead of the main serializer instance, either you need another serializer instance with a differently configured csv encoder registered within. This PR allows to configure any encoder option through the context, so you can keep injecting and using the same serializer instance. Commits ------- 10a76aa [Serializer] Allow to pass csv encoder options in context
2 parents 460fcbf + 10a76aa commit 1cef186

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed

src/Symfony/Component/Serializer/Encoder/CsvEncoder.php

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
class CsvEncoder implements EncoderInterface, DecoderInterface
2222
{
2323
const FORMAT = 'csv';
24+
const DELIMITER_KEY = 'csv_delimiter';
25+
const ENCLOSURE_KEY = 'csv_enclosure';
26+
const ESCAPE_CHAR_KEY = 'csv_escape_char';
27+
const KEY_SEPARATOR_KEY = 'csv_key_separator';
2428

2529
private $delimiter;
2630
private $enclosure;
@@ -65,19 +69,21 @@ public function encode($data, $format, array $context = array())
6569
}
6670
}
6771

72+
list($delimiter, $enclosure, $escapeChar, $keySeparator) = $this->getCsvOptions($context);
73+
6874
$headers = null;
6975
foreach ($data as $value) {
7076
$result = array();
71-
$this->flatten($value, $result);
77+
$this->flatten($value, $result, $keySeparator);
7278

7379
if (null === $headers) {
7480
$headers = array_keys($result);
75-
fputcsv($handle, $headers, $this->delimiter, $this->enclosure, $this->escapeChar);
81+
fputcsv($handle, $headers, $delimiter, $enclosure, $escapeChar);
7682
} elseif (array_keys($result) !== $headers) {
7783
throw new InvalidArgumentException('To use the CSV encoder, each line in the data array must have the same structure. You may want to use a custom normalizer class to normalize the data format before passing it to the CSV encoder.');
7884
}
7985

80-
fputcsv($handle, $result, $this->delimiter, $this->enclosure, $this->escapeChar);
86+
fputcsv($handle, $result, $delimiter, $enclosure, $escapeChar);
8187
}
8288

8389
rewind($handle);
@@ -108,14 +114,16 @@ public function decode($data, $format, array $context = array())
108114
$nbHeaders = 0;
109115
$result = array();
110116

111-
while (false !== ($cols = fgetcsv($handle, 0, $this->delimiter, $this->enclosure, $this->escapeChar))) {
117+
list($delimiter, $enclosure, $escapeChar, $keySeparator) = $this->getCsvOptions($context);
118+
119+
while (false !== ($cols = fgetcsv($handle, 0, $delimiter, $enclosure, $escapeChar))) {
112120
$nbCols = count($cols);
113121

114122
if (null === $headers) {
115123
$nbHeaders = $nbCols;
116124

117125
foreach ($cols as $col) {
118-
$headers[] = explode($this->keySeparator, $col);
126+
$headers[] = explode($keySeparator, $col);
119127
}
120128

121129
continue;
@@ -166,16 +174,27 @@ public function supportsDecoding($format)
166174
*
167175
* @param array $array
168176
* @param array $result
177+
* @param string $keySeparator
169178
* @param string $parentKey
170179
*/
171-
private function flatten(array $array, array &$result, $parentKey = '')
180+
private function flatten(array $array, array &$result, $keySeparator, $parentKey = '')
172181
{
173182
foreach ($array as $key => $value) {
174183
if (is_array($value)) {
175-
$this->flatten($value, $result, $parentKey.$key.$this->keySeparator);
184+
$this->flatten($value, $result, $keySeparator, $parentKey.$key.$keySeparator);
176185
} else {
177186
$result[$parentKey.$key] = $value;
178187
}
179188
}
180189
}
190+
191+
private function getCsvOptions(array $context)
192+
{
193+
$delimiter = isset($context[self::DELIMITER_KEY]) ? $context[self::DELIMITER_KEY] : $this->delimiter;
194+
$enclosure = isset($context[self::ENCLOSURE_KEY]) ? $context[self::ENCLOSURE_KEY] : $this->enclosure;
195+
$escapeChar = isset($context[self::ESCAPE_CHAR_KEY]) ? $context[self::ESCAPE_CHAR_KEY] : $this->escapeChar;
196+
$keySeparator = isset($context[self::KEY_SEPARATOR_KEY]) ? $context[self::KEY_SEPARATOR_KEY] : $this->keySeparator;
197+
198+
return array($delimiter, $enclosure, $escapeChar, $keySeparator);
199+
}
181200
}

src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,23 @@ public function testEncodeCustomSettings()
112112
, $this->encoder->encode($value, 'csv'));
113113
}
114114

115+
public function testEncodeCustomSettingsPassedInContext()
116+
{
117+
$value = array('a' => 'he\'llo', 'c' => array('d' => 'foo'));
118+
119+
$this->assertSame(<<<'CSV'
120+
a;c-d
121+
'he''llo';foo
122+
123+
CSV
124+
, $this->encoder->encode($value, 'csv', array(
125+
CsvEncoder::DELIMITER_KEY => ';',
126+
CsvEncoder::ENCLOSURE_KEY => "'",
127+
CsvEncoder::ESCAPE_CHAR_KEY => '|',
128+
CsvEncoder::KEY_SEPARATOR_KEY => '-',
129+
)));
130+
}
131+
115132
public function testEncodeEmptyArray()
116133
{
117134
$this->assertEquals("\n\n", $this->encoder->encode(array(), 'csv'));
@@ -207,6 +224,21 @@ public function testDecodeCustomSettings()
207224
, 'csv'));
208225
}
209226

227+
public function testDecodeCustomSettingsPassedInContext()
228+
{
229+
$expected = array('a' => 'hell\'o', 'bar' => array('baz' => 'b'));
230+
$this->assertEquals($expected, $this->encoder->decode(<<<'CSV'
231+
a;bar-baz
232+
'hell''o';b;c
233+
CSV
234+
, 'csv', array(
235+
CsvEncoder::DELIMITER_KEY => ';',
236+
CsvEncoder::ENCLOSURE_KEY => "'",
237+
CsvEncoder::ESCAPE_CHAR_KEY => '|',
238+
CsvEncoder::KEY_SEPARATOR_KEY => '-',
239+
)));
240+
}
241+
210242
public function testDecodeMalformedCollection()
211243
{
212244
$expected = array(

0 commit comments

Comments
 (0)