Completed
Pull Request — master (#210)
by ignace nyamagana
04:10
created

Writer::getFputcsvParameters()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 9
ccs 0
cts 0
cp 0
rs 9.6666
c 1
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
crap 6
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 League\Csv\RecordFormatterInterface as RecordFormatter;
18
use League\Csv\RecordValidatorInterface as RecordValidator;
19
use Traversable;
20
21
/**
22
 * A class to manage data insertion into a CSV
23
 *
24
 * @package League.csv
25
 * @since   4.0.0
26
 * @author  Ignace Nyamagana Butera <[email protected]>
27
 *
28
 */
29
class Writer extends AbstractCsv
30
{
31
    /**
32
     * @inheritdoc
33
     */
34
    protected $stream_filter_mode = STREAM_FILTER_WRITE;
35
36
    /**
37
     * Callables to validate the record before insertion
38
     *
39
     * @var callable[]
40
     */
41
    protected $validators = [];
42
43
    /**
44
     * Callables to format the record before insertion
45
     *
46
     * @var callable[]
47
     */
48
    protected $formatters = [];
49
50
    /**
51
     * Insert Rows count
52
     *
53
     * @var int
54
     */
55
    protected $insert_count = 0;
56
57
    /**
58
     * newline character
59
     *
60
     * @var string
61
     */
62
    protected $newline = "\n";
63
64
    /**
65
     * Buffer flush threshold
66
     *
67
     * @var int
68
     */
69
    protected $flush_threshold = 500;
70
71
    /**
72
     * Returns the current newline sequence characters
73
     *
74
     * @return string
75
     */
76 4
    public function getNewline(): string
77
    {
78 4
        return $this->newline;
79
    }
80
81
    /**
82
     * Get the flush threshold
83
     *
84
     * @return int|null
85
     */
86 2
    public function getFlushThreshold()
87
    {
88 2
        return $this->flush_threshold;
89
    }
90
91
    /**
92
     * Adds multiple lines to the CSV document
93
     *
94
     * a simple wrapper method around insertOne
95
     *
96
     * @param Traversable|array $rows a multidimensional array or a Traversable object
97
     *
98
     * @throws Exception If the given rows format is invalid
99
     *
100
     * @return int
101
     */
102 6
    public function insertAll($rows): int
103
    {
104 6
        if (!is_array($rows) && !$rows instanceof Traversable) {
105 2
            throw new Exception('the provided data must be an array OR a `Traversable` object');
106
        }
107
108 4
        $bytes = 0;
109 4
        foreach ($rows as $row) {
110 4
            $bytes += $this->insertOne($row);
111
        }
112
113 4
        return $bytes;
114
    }
115
116
    /**
117
     * Adds a single line to a CSV document
118
     *
119
     * @param string[] $row an array
120
     *
121
     * @throws InsertionException If the row can not be inserted
122
     *
123
     * @return int
124
     */
125 32
    public function insertOne(array $row): int
126
    {
127 32
        $record = array_reduce($this->formatters, [$this, 'formatRecord'], $row);
128 32
        $this->validateRecord($record);
129 28
        $bytes = $this->document->fputcsv($record, $this->delimiter, $this->enclosure, $this->escape);
130 28
        if (!$bytes) {
131 2
            throw InsertionException::createFromCsv($record);
132
        }
133
134 26
        return $bytes + $this->consolidate();
135
    }
136
137
    /**
138
     * Format the given row
139
     *
140
     * @param string[]        $record
141
     * @param RecordFormatter $formatter
142
     *
143
     * @return string[]
144
     */
145 4
    protected function formatRecord(array $record, RecordFormatter $formatter): array
146
    {
147 4
        return $formatter->format($record);
148
    }
149
150
    /**
151
     * Validate a row
152
     *
153
     * @param string[] $row
0 ignored issues
show
Bug introduced by
There is no parameter named $row. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
154
     *
155
     * @throws InsertionException If the validation failed
156
     */
157 32
    protected function validateRecord(array $record)
158
    {
159 32
        foreach ($this->validators as $name => $validator) {
160 8
            if (true !== $validator->validate($record)) {
0 ignored issues
show
Bug introduced by
The method validate cannot be called on $validator (of type callable).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
161 8
                throw InsertionException::createFromValidator($name, $record);
162
            }
163
        }
164 28
    }
165
166
    /**
167
     * Apply post insertion actions
168
     *
169
     * @return int
170
     */
171 26
    protected function consolidate(): int
172
    {
173 26
        $bytes = 0;
174 26
        if ("\n" !== $this->newline) {
175 4
            $this->document->fseek(-1, SEEK_CUR);
176 4
            $bytes = $this->document->fwrite($this->newline, strlen($this->newline)) - 1;
177
        }
178
179 26
        $this->insert_count++;
180 26
        if (null !== $this->flush_threshold && 0 === $this->insert_count % $this->flush_threshold) {
181 2
            $this->document->fflush();
182
        }
183
184 26
        return $bytes;
185
    }
186
187
    /**
188
     * add a formatter to the collection
189
     *
190
     * @param RecordFormatter $formatter
191
     *
192
     * @return static
193
     */
194 4
    public function addFormatter(RecordFormatter $formatter): self
195
    {
196 4
        $this->formatters[] = $formatter;
197
198 4
        return $this;
199
    }
200
201
    /**
202
     * add a Validator to the collection
203
     *
204
     * @param RecordValidator $validator
205
     * @param string          $name      the validator name
206
     *
207
     * @return static
208
     */
209 8
    public function addValidator(RecordValidator $validator, string $name): self
210
    {
211 8
        $this->validators[$name] = $validator;
212
213 8
        return $this;
214
    }
215
216
    /**
217
     * Sets the newline sequence characters
218
     *
219
     * @param string $newline
220
     *
221
     * @return static
222
     */
223 4
    public function setNewline(string $newline): self
224
    {
225 4
        $this->newline = (string) $newline;
226
227 4
        return $this;
228
    }
229
230
    /**
231
     * Set the automatic flush threshold on write
232
     *
233
     * @param int|null $val
234
     */
235 4
    public function setFlushThreshold($val): self
236
    {
237 4
        if (null !== $val) {
238 4
            $val = $this->filterInteger($val, 1, 'The flush threshold must be a valid positive integer or null');
239
        }
240
241 4
        $this->flush_threshold = $val;
242
243 4
        return $this;
244
    }
245
}
246