feature #29283 [Serializer] CsvEncoder no header option (encode / decode) (redecs)

This PR was squashed before being merged into the 4.3-dev branch (closes #29283).

Discussion
----------

[Serializer] CsvEncoder no header option (encode / decode)

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #27447
| License       | MIT
| Doc PR        | -

This PR wants to introduce a new context option for the CsvEncoder, `CsvEncoder::NO_HEADERS_KEY` (boolean), that allows CSV encoding/decoding when you don't have/need a header.

By default this is assumed to be false, so the headers are included in the CSV output or assumed to be present in the CSV input.

When the option is set to true, the following behaviour occurs.

Encoding
===
The following PHP input
```php
array(array('a','b'), array('c', 'd'))
```
will generate this CSV output
```csv
a,b
c,d
```

Decoding
===
Considering the CSV input to be
```csv
a,b
c,d
```
the following PHP array will be returned
```php
array (
  0 => array (
    0 => 'a',
    1 => 'b',
  ),
  1 => array (
    0 => 'c',
    1 => 'd',
  ),
)
```

Commits
-------

0e63c61190 [Serializer] CsvEncoder no header option (encode / decode)
This commit is contained in:
Fabien Potencier 2019-01-01 19:36:14 +01:00
commit 23cdc73a35
2 changed files with 42 additions and 7 deletions

View File

@ -29,6 +29,7 @@ class CsvEncoder implements EncoderInterface, DecoderInterface
const HEADERS_KEY = 'csv_headers';
const ESCAPE_FORMULAS_KEY = 'csv_escape_formulas';
const AS_COLLECTION_KEY = 'as_collection';
const NO_HEADERS_KEY = 'no_headers';
private $formulasStartCharacters = array('=', '-', '+', '@');
private $defaultContext = array(
@ -38,6 +39,7 @@ class CsvEncoder implements EncoderInterface, DecoderInterface
self::ESCAPE_FORMULAS_KEY => false,
self::HEADERS_KEY => array(),
self::KEY_SEPARATOR_KEY => '.',
self::NO_HEADERS_KEY => false,
);
/**
@ -95,7 +97,9 @@ class CsvEncoder implements EncoderInterface, DecoderInterface
$headers = array_merge(array_values($headers), array_diff($this->extractHeaders($data), $headers));
fputcsv($handle, $headers, $delimiter, $enclosure, $escapeChar);
if (!($context[self::NO_HEADERS_KEY] ?? false)) {
fputcsv($handle, $headers, $delimiter, $enclosure, $escapeChar);
}
$headers = array_fill_keys($headers, '');
foreach ($data as $row) {
@ -139,13 +143,20 @@ class CsvEncoder implements EncoderInterface, DecoderInterface
if (null === $headers) {
$nbHeaders = $nbCols;
foreach ($cols as $col) {
$header = explode($keySeparator, $col);
$headers[] = $header;
$headerCount[] = \count($header);
}
if ($context[self::NO_HEADERS_KEY] ?? false) {
for ($i = 0; $i < $nbCols; ++$i) {
$headers[] = array($i);
}
$headerCount = array_fill(0, $nbCols, 1);
} else {
foreach ($cols as $col) {
$header = explode($keySeparator, $col);
$headers[] = $header;
$headerCount[] = \count($header);
}
continue;
continue;
}
}
$item = array();

View File

@ -309,6 +309,18 @@ CSV
)));
}
public function testEncodeWithoutHeader()
{
$this->assertSame(<<<'CSV'
a,b
c,d
CSV
, $this->encoder->encode(array(array('a', 'b'), array('c', 'd')), 'csv', array(
CsvEncoder::NO_HEADERS_KEY => true,
)));
}
public function testSupportsDecoding()
{
$this->assertTrue($this->encoder->supportsDecoding('csv'));
@ -480,4 +492,16 @@ CSV
{
$this->assertEquals(array(), $this->encoder->decode('', 'csv'));
}
public function testDecodeWithoutHeader()
{
$this->assertEquals(array(array('a', 'b'), array('c', 'd')), $this->encoder->decode(<<<'CSV'
a,b
c,d
CSV
, 'csv', array(
CsvEncoder::NO_HEADERS_KEY => true,
)));
}
}