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

Writer::__destruct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 5
ccs 0
cts 0
cp 0
rs 9.4285
c 1
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
crap 2
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 InvalidArgumentException;
18
use ReflectionMethod;
19
use SplFileObject;
20
use Traversable;
21
22
/**
23
 *  A class to manage data insertion into a CSV
24
 *
25
 * @package League.csv
26
 * @since  4.0.0
27
 *
28
 */
29
class Writer extends AbstractCsv
30
{
31
    /**
32
     * Callables to validate the row before insertion
33
     *
34
     * @var callable[]
35
     */
36
    protected $validators = [];
37
38
    /**
39
     * Callables to format the row before insertion
40
     *
41
     * @var callable[]
42
     */
43
    protected $formatters = [];
44
45
    /**
46
     * @inheritdoc
47
     */
48
    protected $stream_filter_mode = STREAM_FILTER_WRITE;
49
50
    /**
51
     * fputcsv method from SplFileObject or StreamIterator
52
     *
53
     * @var ReflectionMethod
54
     */
55
    protected $fputcsv;
56
57
    /**
58
     * Nb parameters for SplFileObject::fputcsv method
59
     *
60
     * @var integer
61 69
     */
62
    protected $fputcsv_param_count;
63 69
64 69
    /**
65 69
     * add a formatter to the collection
66
     *
67
     * @param callable $callable
68
     *
69
     * @return $this
70 69
     */
71
    public function addFormatter(callable $callable): self
72 69
    {
73 3
        $this->formatters[] = $callable;
74 3
75 2
        return $this;
76 69
    }
77
78
    /**
79
     * add a Validator to the collection
80
     *
81
     * @param callable $callable
82
     * @param string   $name     the rule name
83
     *
84
     * @return $this
85
     */
86
    public function addValidator(callable $callable, string $name): self
87
    {
88
        $this->validators[$name] = $callable;
89 12
90
        return $this;
91 12
    }
92 3
93 1
    /**
94 2
     * Adds multiple lines to the CSV document
95
     *
96
     * a simple wrapper method around insertOne
97 9
     *
98 9
     * @param Traversable|array $rows a multidimensional array or a Traversable object
99 6
     *
100
     * @throws InvalidArgumentException If the given rows format is invalid
101 9
     *
102
     * @return static
103
     */
104
    public function insertAll($rows): self
105
    {
106
        if (!is_array($rows) && !$rows instanceof Traversable) {
107
            throw new InvalidArgumentException(
108
                'the provided data must be an array OR a `Traversable` object'
109
            );
110
        }
111 39
112
        foreach ($rows as $row) {
113 39
            $this->insertOne($row);
114 15
        }
115 10
116 39
        return $this;
117 39
    }
118
119 36
    /**
120 36
     * Adds a single line to a CSV document
121 24
     *
122
     * @param string[]|string $row a string, an array or an object implementing to '__toString' method
123 36
     *
124 36
     * @return static
125 3
     */
126 3
    public function insertOne(array $row): self
127 2
    {
128
        $row = $this->formatRow($row);
129 36
        $this->validateRow($row);
130
        $this->addRow($row);
131
132
        return $this;
133
    }
134
135
    /**
136
     * Format the given row
137
     *
138
     * @param array $row
139 36
     *
140
     * @return array
141 36
     */
142 36
    protected function formatRow(array $row): array
143 36
    {
144 24
        foreach ($this->formatters as $formatter) {
145
            $row = ($formatter)($row);
146 36
        }
147
148
        return $row;
149
    }
150
151
    /**
152 6
    * Validate a row
153
    *
154 6
    * @param array $row
155
    *
156
    * @throws InvalidRowException If the validation failed
157
    */
158
    protected function validateRow(array $row)
159
    {
160 69
        foreach ($this->validators as $name => $validator) {
161
            if (true !== ($validator)($row)) {
162 69
                throw new InvalidRowException($name, $row, 'row validation failed');
163 69
            }
164 69
        }
165
    }
166
167
    /**
168
     * Add new record to the CSV document
169
     *
170
     * @param array $row record to add
171
     */
172
    protected function addRow(array $row)
173
    {
174
        $this->initCsv();
175
        $this->fputcsv->invokeArgs($this->document, $this->getFputcsvParameters($row));
176
        if ("\n" !== $this->newline) {
177
            $this->document->fseek(-1, SEEK_CUR);
178
            $this->document->fwrite($this->newline, strlen($this->newline));
179
        }
180
    }
181
182
    /**
183
     * Initialize the CSV object and settings
184
     */
185
    protected function initCsv()
186
    {
187
        if (null !== $this->fputcsv) {
188
            return;
189
        }
190
191
        $this->fputcsv = new ReflectionMethod(get_class($this->document), 'fputcsv');
192
        $this->fputcsv_param_count = $this->fputcsv->getNumberOfParameters();
193
    }
194
195
    /**
196
     * returns the parameters for SplFileObject::fputcsv
197
     *
198
     * @param array $fields The fields to be add
199
     *
200
     * @return array
201
     */
202
    protected function getFputcsvParameters(array $fields): array
203
    {
204
        $parameters = [$fields, $this->delimiter, $this->enclosure];
205
        if (4 == $this->fputcsv_param_count) {
206
            $parameters[] = $this->escape;
207
        }
208
209
        return $parameters;
210
    }
211
}
212