Completed
Push — master ( 22d86c...c098c7 )
by ignace nyamagana
08:48 queued 06:57
created

Writer   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 229
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 23
lcom 1
cbo 3
dl 0
loc 229
c 4
b 0
f 0
ccs 54
cts 54
cp 1
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getNewline() 0 4 1
A getFlushThreshold() 0 4 1
A insertOne() 0 11 2
A formatRecord() 0 4 1
A validateRecord() 0 8 3
A consolidate() 0 20 4
A addFormatter() 0 6 1
A addValidator() 0 6 1
A setNewline() 0 6 1
A setFlushThreshold() 0 14 3
B insertAll() 0 16 5
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\Exception\InsertionException;
18
use League\Csv\Exception\InvalidArgumentException;
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
     * callable collection to validate the record before insertion
38
     *
39
     * @var callable[]
40
     */
41
    protected $validators = [];
42
43
    /**
44
     * callable collection to format the record before insertion
45
     *
46
     * @var callable[]
47
     */
48
    protected $formatters = [];
49
50
    /**
51
     * Insert records count for flushing
52
     *
53
     * @var int
54
     */
55
    protected $flush_counter = 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;
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
0 ignored issues
show
Bug introduced by
There is no parameter named $rows. 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...
97
     *
98
     * @throws InvalidArgumentException If the given rows format is invalid
99
     *
100
     * @return int
101
     */
102 6
    public function insertAll($records): int
103
    {
104 6
        if (!is_array($records) && !$records instanceof Traversable) {
105 2
            throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be iterable, %s given', __METHOD__, is_object($records) ? get_class($records) : gettype($records)));
106
        }
107
108 4
        $bytes = 0;
109 4
        foreach ($records as $record) {
110 4
            $bytes += $this->insertOne($record);
111
        }
112
113 4
        $this->flush_counter = 0;
114 4
        $this->document->fflush();
115
116 4
        return $bytes;
117
    }
118
119
    /**
120
     * Adds a single line to a CSV document
121
     *
122
     * @param string[] $record an array
123
     *
124
     * @throws InsertionException If the record can not be inserted
125
     *
126
     * @return int
127
     */
128 32
    public function insertOne(array $record): int
129
    {
130 32
        $record = array_reduce($this->formatters, [$this, 'formatRecord'], $record);
131 32
        $this->validateRecord($record);
132 28
        $bytes = $this->document->fputcsv($record, $this->delimiter, $this->enclosure, $this->escape);
133 28
        if (!$bytes) {
134 2
            throw InsertionException::createFromCsv($record);
135
        }
136
137 26
        return $bytes + $this->consolidate();
138
    }
139
140
    /**
141
     * Format the given row
142
     *
143
     * @param string[] $record
144
     * @param callable $formatter
145
     *
146
     * @return string[]
147
     */
148 4
    protected function formatRecord(array $record, callable $formatter): array
149
    {
150 4
        return $formatter($record);
151
    }
152
153
    /**
154
     * Validate a row
155
     *
156
     * @param string[] $record
157
     *
158
     * @throws InsertionException If the validation failed
159
     */
160 32
    protected function validateRecord(array $record)
161
    {
162 32
        foreach ($this->validators as $name => $validator) {
163 8
            if (true !== ($validator)($record)) {
164 8
                throw InsertionException::createFromValidator($name, $record);
165
            }
166
        }
167 28
    }
168
169
    /**
170
     * Apply post insertion actions
171
     *
172
     * @return int
173
     */
174 26
    protected function consolidate(): int
175
    {
176 26
        $bytes = 0;
177 26
        if ("\n" !== $this->newline) {
178 4
            $this->document->fseek(-1, SEEK_CUR);
179 4
            $bytes = $this->document->fwrite($this->newline, strlen($this->newline)) - 1;
180
        }
181
182 26
        if (null === $this->flush_threshold) {
183 24
            return $bytes;
184
        }
185
186 2
        ++$this->flush_counter;
187 2
        if (0 === $this->flush_counter % $this->flush_threshold) {
188 2
            $this->flush_counter = 0;
189 2
            $this->document->fflush();
190
        }
191
192 2
        return $bytes;
193
    }
194
195
    /**
196
     * add a formatter to the collection
197
     *
198
     * @param callable $formatter
199
     *
200
     * @return static
201
     */
202 4
    public function addFormatter(callable $formatter): self
203
    {
204 4
        $this->formatters[] = $formatter;
205
206 4
        return $this;
207
    }
208
209
    /**
210
     * add a Validator to the collection
211
     *
212
     * @param callable $validator
213
     * @param string   $name      the validator name
214
     *
215
     * @return static
216
     */
217 8
    public function addValidator(callable $validator, string $name): self
218
    {
219 8
        $this->validators[$name] = $validator;
220
221 8
        return $this;
222
    }
223
224
    /**
225
     * Sets the newline sequence characters
226
     *
227
     * @param string $newline
228
     *
229
     * @return static
230
     */
231 4
    public function setNewline(string $newline): self
232
    {
233 4
        $this->newline = $newline;
234
235 4
        return $this;
236
    }
237
238
    /**
239
     * Set the automatic flush threshold on write
240
     *
241
     * @param int|null $val
242
     */
243 4
    public function setFlushThreshold($val): self
244
    {
245 4
        if (null !== $val) {
246 4
            $val = $this->filterInteger($val, 1, __METHOD__.': The flush threshold must be a valid positive integer or null');
247
        }
248
249 4
        $this->flush_threshold = $val;
250 4
        if (0 < $this->flush_counter) {
251
            $this->flush_counter = 0;
252
            $this->document->fflush();
253
        }
254
255 4
        return $this;
256
    }
257
}
258