From 20f03677e3f6ae2016b3e5fb33a6cef5efd83150 Mon Sep 17 00:00:00 2001 From: Romain Date: Tue, 16 Mar 2021 13:55:56 +0100 Subject: [PATCH] [Serializer] Add a Custom End Of Line in CSV File --- src/Symfony/Component/Serializer/CHANGELOG.md | 5 +++-- src/Symfony/Component/Serializer/Encoder/CsvEncoder.php | 8 ++++++++ .../Component/Serializer/Tests/Encoder/CsvEncoderTest.php | 7 +++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index dde0f2cf21..07cfca2f9d 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -5,8 +5,9 @@ CHANGELOG --- * Add the ability to provide (de)normalization context using metadata (e.g. `@Symfony\Component\Serializer\Annotation\Context`) - * deprecated `ArrayDenormalizer::setSerializer()`, call `setDenormalizer()` instead. - * added normalization formats to `UidNormalizer` + * Deprecate `ArrayDenormalizer::setSerializer()`, call `setDenormalizer()` instead + * Add normalization formats to `UidNormalizer` + * Add `CsvEncoder::END_OF_LINE` context option 5.2.0 ----- diff --git a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php index 6018872e35..909e8fef0b 100644 --- a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php @@ -31,6 +31,7 @@ class CsvEncoder implements EncoderInterface, DecoderInterface public const ESCAPE_FORMULAS_KEY = 'csv_escape_formulas'; public const AS_COLLECTION_KEY = 'as_collection'; public const NO_HEADERS_KEY = 'no_headers'; + public const END_OF_LINE = 'csv_end_of_line'; public const OUTPUT_UTF8_BOM_KEY = 'output_utf8_bom'; private const UTF8_BOM = "\xEF\xBB\xBF"; @@ -40,6 +41,7 @@ class CsvEncoder implements EncoderInterface, DecoderInterface self::DELIMITER_KEY => ',', self::ENCLOSURE_KEY => '"', self::ESCAPE_CHAR_KEY => '', + self::END_OF_LINE => "\n", self::ESCAPE_FORMULAS_KEY => false, self::HEADERS_KEY => [], self::KEY_SEPARATOR_KEY => '.', @@ -94,11 +96,17 @@ class CsvEncoder implements EncoderInterface, DecoderInterface if (!($context[self::NO_HEADERS_KEY] ?? $this->defaultContext[self::NO_HEADERS_KEY])) { fputcsv($handle, $headers, $delimiter, $enclosure, $escapeChar); + if ("\n" !== ($context[self::END_OF_LINE] ?? $this->defaultContext[self::END_OF_LINE]) && 0 === fseek($handle, -1, \SEEK_CUR)) { + fwrite($handle, $context[self::END_OF_LINE]); + } } $headers = array_fill_keys($headers, ''); foreach ($data as $row) { fputcsv($handle, array_replace($headers, $row), $delimiter, $enclosure, $escapeChar); + if ("\n" !== ($context[self::END_OF_LINE] ?? $this->defaultContext[self::END_OF_LINE]) && 0 === fseek($handle, -1, \SEEK_CUR)) { + fwrite($handle, $context[self::END_OF_LINE]); + } } rewind($handle); diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php index 1b77704ef9..c71a173d42 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php @@ -621,4 +621,11 @@ CSV; $this->encoder->decode($csv, 'csv', [CsvEncoder::AS_COLLECTION_KEY => false]) ); } + + public function testEndOfLine() + { + $value = ['foo' => 'hello', 'bar' => 'test']; + + $this->assertSame("foo,bar\r\nhello,test\r\n", $this->encoder->encode($value, 'csv', [CsvEncoder::END_OF_LINE => "\r\n"])); + } }