forked from clue/reactphp-csv
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEncoder.php
More file actions
135 lines (111 loc) · 3.71 KB
/
Encoder.php
File metadata and controls
135 lines (111 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
namespace Clue\React\Csv;
use Evenement\EventEmitter;
use React\Stream\WritableStreamInterface;
/**
* The Encoder / Serializer can be used to write any array, encode it as a CSV record and forward it to an output stream
*/
class Encoder extends EventEmitter implements WritableStreamInterface
{
private $output;
private $temp = false;
private $closed = false;
private $delimiter;
private $enclosure;
private $escapeChar;
private $eol;
/**
* @param WritableStreamInterface $output
* @param string $delimiter
* @param string $enclosure
* @param string $escapeChar
* @param string $eol
* @throws \BadMethodCallException
*/
public function __construct(WritableStreamInterface $output, $delimiter = ',', $enclosure = '"', $escapeChar = '\\', $eol = "\n")
{
if ($escapeChar !== '\\' && PHP_VERSION_ID < 50504) {
throw new \BadMethodCallException('Custom escape character only supported on PHP 5.5.4+'); // @codeCoverageIgnore
}
$this->output = $output;
$this->delimiter = $delimiter;
$this->enclosure = $enclosure;
$this->escapeChar = $escapeChar;
$this->eol = $eol;
if (!$output->isWritable()) {
$this->close();
return;
}
$this->temp = fopen('php://memory', 'r+');
$this->output->on('drain', array($this, 'handleDrain'));
$this->output->on('error', array($this, 'handleError'));
$this->output->on('close', array($this, 'close'));
}
public function write($data)
{
if ($this->closed) {
return false;
}
$written = false;
if (is_array($data)) {
// custom EOL requires PHP 8.1+, custom escape character requires PHP 5.5.4+ (see constructor check)
// @codeCoverageIgnoreStart
if (\PHP_VERSION_ID >= 80100) {
$written = fputcsv($this->temp, $data, $this->delimiter, $this->enclosure, $this->escapeChar, $this->eol);
} elseif (\PHP_VERSION_ID >= 50504) {
$written = fputcsv($this->temp, $data, $this->delimiter, $this->enclosure, $this->escapeChar);
} else {
$written = fputcsv($this->temp, $data, $this->delimiter, $this->enclosure);
}
// @codeCoverageIgnoreEnd
}
if ($written === false) {
$this->handleError(new \RuntimeException('Unable to encode CSV'));
return false;
}
rewind($this->temp);
$data = stream_get_contents($this->temp);
ftruncate($this->temp, 0);
// manually replace custom EOL on PHP < 8.1
if (\PHP_VERSION_ID < 80100 && $this->eol !== "\n") {
$data = \substr($data, 0, -1) . $this->eol; // @codeCoverageIgnore
}
return $this->output->write($data);
}
public function end($data = null)
{
if ($data !== null) {
$this->write($data);
}
$this->output->end();
}
public function isWritable()
{
return !$this->closed;
}
public function close()
{
if ($this->closed) {
return;
}
$this->closed = true;
$this->output->close();
if ($this->temp !== false) {
fclose($this->temp);
$this->temp = false;
}
$this->emit('close');
$this->removeAllListeners();
}
/** @internal */
public function handleDrain()
{
$this->emit('drain');
}
/** @internal */
public function handleError(\Exception $error)
{
$this->emit('error', array($error));
$this->close();
}
}