Passed
Push — master ( 25c805...999286 )
by Andy
02:56 queued 11s
created

CsvFileObject::escapeEnclosure()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 11
ccs 0
cts 6
cp 0
rs 10
cc 3
nc 2
nop 2
crap 12
1
<?php
2
3
namespace Palmtree\Csv;
4
5
use Palmtree\Csv\Util\StringUtil;
6
7
class CsvFileObject extends \SplFileObject
8
{
9
    /** @var int */
10
    private $bytesWritten = 0;
11
    /** @var string */
12
    private $lineEnding = "\r\n";
13
14 2
    public function fwriteCsv(array $row): int
15
    {
16 2
        $bytes = $this->fwrite($this->getCsvString($row));
17
18 2
        $this->bytesWritten += $bytes;
19
20 2
        return $bytes;
21
    }
22
23 4
    public function __destruct()
24
    {
25 4
        $this->trimFinalLineEnding();
26 4
    }
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 2
    public function getSize(): int
46
    {
47
        try {
48 2
            $size = parent::getSize();
49 2
        } catch (\RuntimeException $exception) {
50 2
            $size = $this->fstat()['size'];
51
        }
52
53 2
        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 4
    public function trimFinalLineEnding(): void
63
    {
64 4
        if ($this->bytesWritten > 0) {
65
            // Only trim the file if it ends with the line ending delimiter.
66 2
            $length = \strlen($this->lineEnding);
67
68 2
            $this->fseek(-$length, SEEK_END);
69
70 2
            if ($this->fread($length) === $this->lineEnding) {
71 2
                $this->ftruncate($this->bytesWritten - $length);
72
            }
73
        }
74 4
    }
75
76
    /**
77
     * Returns a string representation of a row to be written as a line in a CSV file.
78
     */
79 2
    private function getCsvString(array $row): string
80
    {
81 2
        list($delimiter, $enclosure) = $this->getCsvControl();
82
83
        return $enclosure .
84 2
               \implode($enclosure . $delimiter . $enclosure, StringUtil::escapeEnclosure($row, $enclosure)) .
85 2
               $enclosure .
86 2
               $this->lineEnding;
87
    }
88
}
89