Completed
Push — master ( 4b5c92...896769 )
by Adrien
16:06 queued 09:43
created

Csv::writeLine()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 28
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 3
nop 2
dl 0
loc 28
ccs 11
cts 11
cp 1
crap 3
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6
use PhpOffice\PhpSpreadsheet\Spreadsheet;
7
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
8
9
class Csv extends BaseWriter
10
{
11
    /**
12
     * PhpSpreadsheet object.
13
     *
14
     * @var Spreadsheet
15
     */
16
    private $spreadsheet;
17
18
    /**
19
     * Delimiter.
20
     *
21
     * @var string
22
     */
23
    private $delimiter = ',';
24
25
    /**
26
     * Enclosure.
27
     *
28
     * @var string
29
     */
30
    private $enclosure = '"';
31
32
    /**
33
     * Line ending.
34
     *
35
     * @var string
36
     */
37
    private $lineEnding = PHP_EOL;
38
39
    /**
40
     * Sheet index to write.
41
     *
42
     * @var int
43
     */
44
    private $sheetIndex = 0;
45
46
    /**
47
     * Whether to write a BOM (for UTF8).
48
     *
49
     * @var bool
50
     */
51
    private $useBOM = false;
52
53
    /**
54
     * Whether to write a Separator line as the first line of the file
55
     *     sep=x.
56
     *
57
     * @var bool
58
     */
59
    private $includeSeparatorLine = false;
60
61
    /**
62
     * Whether to write a fully Excel compatible CSV file.
63
     *
64
     * @var bool
65
     */
66
    private $excelCompatibility = false;
67
68
    /**
69
     * Create a new CSV.
70
     *
71
     * @param Spreadsheet $spreadsheet Spreadsheet object
72
     */
73 5
    public function __construct(Spreadsheet $spreadsheet)
74
    {
75 5
        $this->spreadsheet = $spreadsheet;
76 5
    }
77
78
    /**
79
     * Save PhpSpreadsheet to file.
80
     *
81
     * @param resource|string $pFilename
82
     *
83
     * @throws Exception
84
     */
85 4
    public function save($pFilename)
86
    {
87
        // Fetch sheet
88 4
        $sheet = $this->spreadsheet->getSheet($this->sheetIndex);
89
90 4
        $saveDebugLog = Calculation::getInstance($this->spreadsheet)->getDebugLog()->getWriteDebugLog();
91 4
        Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog(false);
92 4
        $saveArrayReturnType = Calculation::getArrayReturnType();
93 4
        Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_VALUE);
94
95
        // Open file
96 4
        if (is_resource($pFilename)) {
97 1
            $fileHandle = $pFilename;
98
        } else {
99 3
            $fileHandle = fopen($pFilename, 'wb+');
100
        }
101
102 4
        if ($fileHandle === false) {
103
            throw new WriterException("Could not open file $pFilename for writing.");
104
        }
105
106 4
        if ($this->excelCompatibility) {
107 1
            $this->setUseBOM(true); //  Enforce UTF-8 BOM Header
108 1
            $this->setIncludeSeparatorLine(true); //  Set separator line
109 1
            $this->setEnclosure('"'); //  Set enclosure to "
110 1
            $this->setDelimiter(';'); //  Set delimiter to a semi-colon
111 1
            $this->setLineEnding("\r\n");
112
        }
113 4
        if ($this->useBOM) {
114
            // Write the UTF-8 BOM code if required
115 2
            fwrite($fileHandle, "\xEF\xBB\xBF");
116
        }
117 4
        if ($this->includeSeparatorLine) {
118
            // Write the separator line if required
119 1
            fwrite($fileHandle, 'sep=' . $this->getDelimiter() . $this->lineEnding);
120
        }
121
122
        //    Identify the range that we need to extract from the worksheet
123 4
        $maxCol = $sheet->getHighestDataColumn();
124 4
        $maxRow = $sheet->getHighestDataRow();
125
126
        // Write rows to file
127 4
        for ($row = 1; $row <= $maxRow; ++$row) {
128
            // Convert the row to an array...
129 4
            $cellsArray = $sheet->rangeToArray('A' . $row . ':' . $maxCol . $row, '', $this->preCalculateFormulas);
130
            // ... and write to the file
131 4
            $this->writeLine($fileHandle, $cellsArray[0]);
132
        }
133
134 4
        Calculation::setArrayReturnType($saveArrayReturnType);
135 4
        Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
136 4
    }
137
138
    /**
139
     * Get delimiter.
140
     *
141
     * @return string
142
     */
143 1
    public function getDelimiter()
144
    {
145 1
        return $this->delimiter;
146
    }
147
148
    /**
149
     * Set delimiter.
150
     *
151
     * @param string $pValue Delimiter, defaults to ','
152
     *
153
     * @return $this
154
     */
155 1
    public function setDelimiter($pValue)
156
    {
157 1
        $this->delimiter = $pValue;
158
159 1
        return $this;
160
    }
161
162
    /**
163
     * Get enclosure.
164
     *
165
     * @return string
166
     */
167
    public function getEnclosure()
168
    {
169
        return $this->enclosure;
170
    }
171
172
    /**
173
     * Set enclosure.
174
     *
175
     * @param string $pValue Enclosure, defaults to "
176
     *
177
     * @return $this
178
     */
179 1
    public function setEnclosure($pValue)
180
    {
181 1
        if ($pValue == '') {
182
            $pValue = null;
183
        }
184 1
        $this->enclosure = $pValue;
185
186 1
        return $this;
187
    }
188
189
    /**
190
     * Get line ending.
191
     *
192
     * @return string
193
     */
194
    public function getLineEnding()
195
    {
196
        return $this->lineEnding;
197
    }
198
199
    /**
200
     * Set line ending.
201
     *
202
     * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL)
203
     *
204
     * @return $this
205
     */
206 1
    public function setLineEnding($pValue)
207
    {
208 1
        $this->lineEnding = $pValue;
209
210 1
        return $this;
211
    }
212
213
    /**
214
     * Get whether BOM should be used.
215
     *
216
     * @return bool
217
     */
218
    public function getUseBOM()
219
    {
220
        return $this->useBOM;
221
    }
222
223
    /**
224
     * Set whether BOM should be used.
225
     *
226
     * @param bool $pValue Use UTF-8 byte-order mark? Defaults to false
227
     *
228
     * @return $this
229
     */
230 2
    public function setUseBOM($pValue)
231
    {
232 2
        $this->useBOM = $pValue;
233
234 2
        return $this;
235
    }
236
237
    /**
238
     * Get whether a separator line should be included.
239
     *
240
     * @return bool
241
     */
242
    public function getIncludeSeparatorLine()
243
    {
244
        return $this->includeSeparatorLine;
245
    }
246
247
    /**
248
     * Set whether a separator line should be included as the first line of the file.
249
     *
250
     * @param bool $pValue Use separator line? Defaults to false
251
     *
252
     * @return $this
253
     */
254 1
    public function setIncludeSeparatorLine($pValue)
255
    {
256 1
        $this->includeSeparatorLine = $pValue;
257
258 1
        return $this;
259
    }
260
261
    /**
262
     * Get whether the file should be saved with full Excel Compatibility.
263
     *
264
     * @return bool
265
     */
266
    public function getExcelCompatibility()
267
    {
268
        return $this->excelCompatibility;
269
    }
270
271
    /**
272
     * Set whether the file should be saved with full Excel Compatibility.
273
     *
274
     * @param bool $pValue Set the file to be written as a fully Excel compatible csv file
275
     *                                Note that this overrides other settings such as useBOM, enclosure and delimiter
276
     *
277
     * @return $this
278
     */
279 1
    public function setExcelCompatibility($pValue)
280
    {
281 1
        $this->excelCompatibility = $pValue;
282
283 1
        return $this;
284
    }
285
286
    /**
287
     * Get sheet index.
288
     *
289
     * @return int
290
     */
291
    public function getSheetIndex()
292
    {
293
        return $this->sheetIndex;
294
    }
295
296
    /**
297
     * Set sheet index.
298
     *
299
     * @param int $pValue Sheet index
300
     *
301
     * @return $this
302
     */
303 1
    public function setSheetIndex($pValue)
304
    {
305 1
        $this->sheetIndex = $pValue;
306
307 1
        return $this;
308
    }
309
310
    /**
311
     * Write line to CSV file.
312
     *
313
     * @param resource $pFileHandle PHP filehandle
314
     * @param array $pValues Array containing values in a row
315
     */
316 4
    private function writeLine($pFileHandle, array $pValues)
317
    {
318
        // No leading delimiter
319 4
        $writeDelimiter = false;
320
321
        // Build the line
322 4
        $line = '';
323
324 4
        foreach ($pValues as $element) {
325
            // Escape enclosures
326 4
            $element = str_replace($this->enclosure, $this->enclosure . $this->enclosure, $element);
327
328
            // Add delimiter
329 4
            if ($writeDelimiter) {
330 2
                $line .= $this->delimiter;
331
            } else {
332 4
                $writeDelimiter = true;
333
            }
334
335
            // Add enclosed string
336 4
            $line .= $this->enclosure . $element . $this->enclosure;
337
        }
338
339
        // Add line ending
340 4
        $line .= $this->lineEnding;
341
342
        // Write to file
343 4
        fwrite($pFileHandle, $line);
344 4
    }
345
}
346