CsvFileObject::__destruct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Palmtree\Csv;
6
7
use Palmtree\Csv\Util\StringUtil;
8
9
class CsvFileObject extends \SplFileObject
10
{
11
    private int $bytesWritten = 0;
12
    private string $lineEnding = "\r\n";
13
14 3
    public function fwriteCsv(array $row): int
15
    {
16 3
        $bytes = $this->fwrite($this->getCsvString($row));
17
18 3
        $this->bytesWritten += $bytes;
19
20 3
        return $bytes;
21
    }
22
23 6
    public function __destruct()
24
    {
25 6
        $this->trimFinalLineEnding();
26 6
    }
27
28
    public function getBytesWritten(): int
29
    {
30
        return $this->bytesWritten;
31
    }
32
33
    public function getLineEnding(): string
34
    {
35
        return $this->lineEnding;
36
    }
37
38
    public function setLineEnding(string $lineEnding): self
39
    {
40
        $this->lineEnding = $lineEnding;
41
42
        return $this;
43
    }
44
45 4
    public function getSize(): int
46
    {
47
        try {
48 4
            $size = parent::getSize();
49 4
        } catch (\RuntimeException $exception) {
50 4
            $size = $this->fstat()['size'];
51
        }
52
53 4
        return $size;
54
    }
55
56
    /**
57
     * Trims the line ending delimiter from the end of the CSV file.
58
     * RFC-4180 states CSV files should not contain a trailing new line.
59
     *
60
     * @see https://tools.ietf.org/html/rfc4180#section-2
61
     */
62 6
    public function trimFinalLineEnding(): void
63
    {
64 6
        if ($this->bytesWritten > 0) {
65
            // Only trim the file if it ends with the line ending delimiter.
66 3
            $length = \strlen($this->lineEnding);
67
68 3
            $this->fseek(-$length, \SEEK_END);
69
70 3
            if ($this->fread($length) === $this->lineEnding) {
71 3
                $this->ftruncate($this->bytesWritten - $length);
72
            }
73
        }
74 6
    }
75
76
    /**
77
     * Returns a string representation of a row to be written as a line in a CSV file.
78
     */
79 3
    private function getCsvString(array $row): string
80
    {
81 3
        list($delimiter, $enclosure) = $this->getCsvControl();
82
83
        return $enclosure .
84 3
               implode($enclosure . $delimiter . $enclosure, StringUtil::escapeEnclosure($row, $enclosure)) .
85 3
               $enclosure .
86 3
               $this->lineEnding;
87
    }
88
}
89