Completed
Pull Request — master (#210)
by ignace nyamagana
02:11
created

Writer::setNewline()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
/**
3
* This file is part of the League.csv library
4
*
5
* @license http://opensource.org/licenses/MIT
6
* @link https://github.com/thephpleague/csv/
7
* @version 9.0.0
8
* @package League.csv
9
*
10
* For the full copyright and license information, please view the LICENSE
11
* file that was distributed with this source code.
12
*/
13
declare(strict_types=1);
14
15
namespace League\Csv;
16
17
use Traversable;
18
19
/**
20
 *  A class to manage data insertion into a CSV
21
 *
22
 * @package League.csv
23
 * @since  4.0.0
24
 *
25
 */
26
class Writer extends AbstractCsv
27
{
28
    /**
29
     * Callables to validate the record before insertion
30
     *
31
     * @var callable[]
32
     */
33
    protected $validators = [];
34
35
    /**
36
     * Callables to format the record before insertion
37
     *
38
     * @var callable[]
39
     */
40
    protected $formatters = [];
41
42
    /**
43
     * @inheritdoc
44
     */
45
    protected $stream_filter_mode = STREAM_FILTER_WRITE;
46
47
    /**
48
     * Insert Rows count
49
     *
50
     * @var int
51
     */
52
    protected $insert_count = 0;
53
54
    /**
55
     * newline character
56
     *
57
     * @var string
58
     */
59
    protected $newline = "\n";
60
61
    /**
62
     * Buffer flush threshold
63
     *
64
     * @var int
65
     */
66
    protected $flush_threshold = 500;
67
68
    /**
69
     * Returns the current newline sequence characters
70
     *
71
     * @return string
72
     */
73 4
    public function getNewline(): string
74
    {
75 4
        return $this->newline;
76
    }
77
78
    /**
79
     * Get the flush threshold
80
     *
81
     * @return int|null
82
     */
83 2
    public function getFlushThreshold()
84
    {
85 2
        return $this->flush_threshold;
86
    }
87
88
    /**
89
     * Sets the newline sequence characters
90
     *
91
     * @param string $newline
92
     *
93
     * @return static
94
     */
95 4
    public function setNewline(string $newline): self
96
    {
97 4
        $this->newline = (string) $newline;
98
99 4
        return $this;
100
    }
101
102
    /**
103
     * Set the automatic flush threshold on write
104
     *
105
     * @param int|null $threshold
106
     */
107 4
    public function setFlushThreshold($threshold): self
108
    {
109 4
        if (null !== $threshold) {
110 4
            $threshold = $this->filterInteger(
111
                $threshold,
112 4
                0,
113 4
                'The flush threshold must be a valid positive integer or 0'
114
            );
115
        }
116 4
        $this->flush_threshold = $threshold;
117
118 4
        return $this;
119
    }
120
121
    /**
122
     * add a formatter to the collection
123
     *
124
     * @param callable $callable
125
     *
126
     * @return static
127
     */
128 4
    public function addFormatter(callable $callable): self
129
    {
130 4
        $this->formatters[] = $callable;
131
132 4
        return $this;
133
    }
134
135
    /**
136
     * add a Validator to the collection
137
     *
138
     * @param callable $callable
139
     * @param string   $name     the rule name
140
     *
141
     * @return static
142
     */
143 8
    public function addValidator(callable $callable, string $name): self
144
    {
145 8
        $this->validators[$name] = $callable;
146
147 8
        return $this;
148
    }
149
150
    /**
151
     * Adds multiple lines to the CSV document
152
     *
153
     * a simple wrapper method around insertOne
154
     *
155
     * @param Traversable|array $rows a multidimensional array or a Traversable object
156
     *
157
     * @throws Exception If the given rows format is invalid
158
     */
159 6
    public function insertAll($rows)
160
    {
161 6
        if (!is_array($rows) && !$rows instanceof Traversable) {
162 2
            throw new Exception('the provided data must be an array OR a `Traversable` object');
163
        }
164
165 4
        foreach ($rows as $row) {
166 4
            $this->insertOne($row);
167
        }
168 4
    }
169
170
    /**
171
     * Adds a single line to a CSV document
172
     *
173
     * @param string[] $row an array
174
     */
175 32
    public function insertOne(array $row)
176
    {
177 32
        $record = array_reduce($this->formatters, [$this, 'formatRecord'], $row);
178 32
        $this->validateRecord($record);
179 28
        if (!$this->document->fputcsv($record, $this->delimiter, $this->enclosure, $this->escape)) {
180 2
            throw new InvalidRowException(__METHOD__, $record, 'Unable to write data to the CSV document');
181
        }
182
183 26
        $this->postInsertionAction();
184 26
    }
185
186
    /**
187
     * Format the given row
188
     *
189
     * @param string[] $row
190
     * @param callable $formatter
191
     *
192
     * @return string[]
193
     */
194 4
    protected function formatRecord(array $row, callable $formatter): array
195
    {
196 4
        return $formatter($row);
197
    }
198
199
    /**
200
    * Validate a row
201
    *
202
    * @param string[] $row
203
    *
204
    * @throws InvalidRowException If the validation failed
205
    */
206 32
    protected function validateRecord(array $row)
207
    {
208 32
        foreach ($this->validators as $name => $validator) {
209 8
            if (true !== $validator($row)) {
210 8
                throw new InvalidRowException($name, $row, 'row validation failed');
211
            }
212
        }
213 28
    }
214
215
    /**
216
     * Post Insertion actions
217
     */
218 26
    protected function postInsertionAction()
219
    {
220 26
        if ("\n" !== $this->newline) {
221 4
            $this->document->fseek(-1, SEEK_CUR);
222 4
            $this->document->fwrite($this->newline, strlen($this->newline));
223
        }
224
225 26
        $this->insert_count++;
226 26
        if (null !== $this->flush_threshold && 0 === $this->insert_count % $this->flush_threshold) {
227 2
            $this->document->fflush();
228
        }
229 26
    }
230
}
231