From 4be6e6943b54af5e22ea7dbfb62a774b491e1e5d Mon Sep 17 00:00:00 2001 From: craig410 Date: Wed, 12 Mar 2025 16:23:11 +0000 Subject: [PATCH] Option to customise CSV EOL characters --- CHANGELOG.md | 4 ++++ src/CSV/CSVWriter.php | 7 +++--- test/unit/CSV/CSVWriterTest.php | 42 +++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e889090..058f33a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ### Unreleased +### v2.3.1 (2025-03-12) + +* Support option to customize EOL character in CSVWriter + ### v2.3.0 (2025-03-10) * Support option to write CSV column headers unquoted diff --git a/src/CSV/CSVWriter.php b/src/CSV/CSVWriter.php index 85282e8..6e49ad8 100644 --- a/src/CSV/CSVWriter.php +++ b/src/CSV/CSVWriter.php @@ -35,6 +35,7 @@ class CSVWriter protected $options = [ 'write_utf8_bom' => FALSE, 'quote_headers' => TRUE, + 'eol' => "\n", ]; /** @@ -79,7 +80,7 @@ public function write(array $row) throw MismatchedSchemaException::forSchema($this->expect_schema, $row_schema); } - \fputcsv($this->resource, $row); + \fputcsv($this->resource, $row, eol: $this->options['eol']); } protected function isResourceOpen() @@ -103,7 +104,7 @@ public function close() private function writeHeaders(array $keys): void { if ($this->options['quote_headers']) { - \fputcsv($this->resource, $keys); + \fputcsv($this->resource, $keys, eol: $this->options['eol']); } else { array_walk( $keys, @@ -112,7 +113,7 @@ private function writeHeaders(array $keys): void "Column header `$str` cannot contain comma if headers are not quoted" ) ); - fwrite($this->resource, implode(',', $keys).PHP_EOL); + fwrite($this->resource, implode(',', $keys).$this->options['eol']); } } } diff --git a/test/unit/CSV/CSVWriterTest.php b/test/unit/CSV/CSVWriterTest.php index 76f0b3c..899f1ef 100644 --- a/test/unit/CSV/CSVWriterTest.php +++ b/test/unit/CSV/CSVWriterTest.php @@ -194,6 +194,48 @@ public function test_it_throws_if_column_headers_contain_comma_when_unquoted(): fclose($file); } + public static function providerLineEndings(): array + { + return [ + 'default' => [ + [], + "\"our big\",is\ndata,here\n", + ], + 'default, with unquoted headers' => [ + ['quote_headers' => false], + "our big,is\ndata,here\n", + ], + 'unix' => [ + ['eol' => "\n"], + "\"our big\",is\ndata,here\n", + ], + 'mac' => [ + ['eol' => "\r"], + "\"our big\",is\rdata,here\r", + ], + 'windows' => [ + ['eol' => "\r\n"], + "\"our big\",is\r\ndata,here\r\n", + ], + 'windows, with unquoted headers' => [ + ['eol' => "\r\n", 'quote_headers' => false], + "our big,is\r\ndata,here\r\n", + ], + ]; + } + + #[DataProvider('providerLineEndings')] + public function test_its_line_endings_can_be_configured(array $options, string $expect): void + { + $file = fopen('php://memory', 'w'); + $subj = $this->newSubject(); + $subj->open($file, $options); + $subj->write(['our big' => 'data', 'is' => 'here']); + rewind($file); + $this->assertSame($expect, stream_get_contents($file)); + fclose($file); + } + #[TestWith([true])] #[TestWith([false])] public function test_it_optionally_writes_byte_order_mark_at_start_of_file($write_bom)