Skip to content

Commit 5269154

Browse files
authored
Merge pull request #26 from clue-labs/custom-eol
Support custom EOL character when encoding CSV
2 parents 073ca2a + 6f1c98a commit 5269154

File tree

4 files changed

+32
-11
lines changed

4 files changed

+32
-11
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ jobs:
1010
strategy:
1111
matrix:
1212
php:
13+
- 8.1
1314
- 8.0
1415
- 7.4
1516
- 7.3

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,10 @@ test,1,24
317317
```
318318

319319
The `Encoder` supports the same optional parameters as the underlying
320-
[`fputcsv()`](https://www.php.net/fputcsv) function.
320+
[`fputcsv()`](https://www.php.net/manual/en/function.fputcsv.php) function.
321321
This means that, by default, CSV fields will be delimited by a comma (`,`), will
322-
use a quote enclosure character (`"`) and a backslash escape character (`\`).
322+
use a quote enclosure character (`"`), a backslash escape character (`\`), and
323+
a Unix-style EOL (`\n` or `LF`).
323324
This behavior can be controlled through the optional constructor parameters:
324325

325326
```php
@@ -385,7 +386,7 @@ See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.
385386
This project aims to run on any platform and thus does not require any PHP
386387
extensions and supports running on legacy PHP 5.3 through current PHP 8+ and
387388
HHVM.
388-
It's *highly recommended to use PHP 7+* for this project.
389+
It's *highly recommended to use the latest supported PHP version PHP 7+* for this project.
389390

390391
## Tests
391392

src/Encoder.php

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,27 @@ class Encoder extends EventEmitter implements WritableStreamInterface
1717
private $delimiter;
1818
private $enclosure;
1919
private $escapeChar;
20+
private $eol;
2021

2122
/**
2223
* @param WritableStreamInterface $output
2324
* @param string $delimiter
2425
* @param string $enclosure
2526
* @param string $escapeChar
27+
* @param string $eol
2628
* @throws \BadMethodCallException
2729
*/
28-
public function __construct(WritableStreamInterface $output, $delimiter = ',', $enclosure = '"', $escapeChar = '\\')
30+
public function __construct(WritableStreamInterface $output, $delimiter = ',', $enclosure = '"', $escapeChar = '\\', $eol = "\n")
2931
{
30-
// @codeCoverageIgnoreStart
3132
if ($escapeChar !== '\\' && PHP_VERSION_ID < 50504) {
32-
throw new \BadMethodCallException('Custom escape character only supported on PHP 5.5.4+');
33+
throw new \BadMethodCallException('Custom escape character only supported on PHP 5.5.4+'); // @codeCoverageIgnore
3334
}
34-
// @codeCoverageIgnoreEnd
3535

3636
$this->output = $output;
3737
$this->delimiter = $delimiter;
3838
$this->enclosure = $enclosure;
3939
$this->escapeChar = $escapeChar;
40+
$this->eol = $eol;
4041

4142
if (!$output->isWritable()) {
4243
$this->close();
@@ -58,12 +59,14 @@ public function write($data)
5859

5960
$written = false;
6061
if (is_array($data)) {
61-
// custom escape character requires PHP 5.5.4+ (see constructor check)
62+
// custom EOL requires PHP 8.1+, custom escape character requires PHP 5.5.4+ (see constructor check)
6263
// @codeCoverageIgnoreStart
63-
if ($this->escapeChar === '\\') {
64-
$written = fputcsv($this->temp, $data, $this->delimiter, $this->enclosure);
65-
} else {
64+
if (\PHP_VERSION_ID >= 80100) {
65+
$written = fputcsv($this->temp, $data, $this->delimiter, $this->enclosure, $this->escapeChar, $this->eol);
66+
} elseif (\PHP_VERSION_ID >= 50504) {
6667
$written = fputcsv($this->temp, $data, $this->delimiter, $this->enclosure, $this->escapeChar);
68+
} else {
69+
$written = fputcsv($this->temp, $data, $this->delimiter, $this->enclosure);
6770
}
6871
// @codeCoverageIgnoreEnd
6972
}
@@ -77,6 +80,11 @@ public function write($data)
7780
$data = stream_get_contents($this->temp);
7881
ftruncate($this->temp, 0);
7982

83+
// manually replace custom EOL on PHP < 8.1
84+
if (\PHP_VERSION_ID < 80100 && $this->eol !== "\n") {
85+
$data = \substr($data, 0, -1) . $this->eol;
86+
}
87+
8088
return $this->output->write($data);
8189
}
8290

tests/EncoderTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ public function testWriteArrayWithCustomDelimiter()
4444
$this->encoder->write(array('hello', 'world'));
4545
}
4646

47+
public function testWriteArrayWithCustomEolForWindows()
48+
{
49+
$this->output = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock();
50+
$this->output->expects($this->once())->method('isWritable')->willReturn(true);
51+
$this->encoder = new Encoder($this->output, ',', '"', '\\', "\r\n");
52+
53+
$this->output->expects($this->once())->method('write')->with("hello,world\r\n");
54+
55+
$this->encoder->write(array('hello', 'world'));
56+
}
57+
4758
public function testWriteArrayTwiceWillSeparateWithNewlineAfterEachWrite()
4859
{
4960
$this->output = $this->getMockBuilder('React\Stream\WritableStreamInterface')->getMock();

0 commit comments

Comments
 (0)