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

CsvFileObject   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Test Coverage

Coverage 77.42%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 11
eloc 26
dl 0
loc 80
ccs 24
cts 31
cp 0.7742
rs 10
c 2
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __destruct() 0 3 1
A getLineEnding() 0 3 1
A getBytesWritten() 0 3 1
A fwriteCsv() 0 7 1
A getCsvString() 0 8 1
A setLineEnding() 0 5 1
A getSize() 0 9 2
A trimFinalLineEnding() 0 10 3
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