Passed
Push — master ( 3c9123...ff0da8 )
by Andy
01:28
created

CsvFileObject   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 129
Duplicated Lines 0 %

Test Coverage

Coverage 18.6%

Importance

Changes 0
Metric Value
wmc 17
eloc 37
dl 0
loc 129
ccs 8
cts 43
cp 0.186
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getLineEnding() 0 3 1
A fwriteCsv() 0 11 2
A getCsvString() 0 14 3
A setLineEnding() 0 5 1
A getSize() 0 9 2
A escapeEnclosure() 0 11 3
A getBytesWritten() 0 3 1
A __destruct() 0 3 1
A trimFinalLineEnding() 0 10 3
1
<?php
2
3
namespace Palmtree\Csv;
4
5
class CsvFileObject extends \SplFileObject
6
{
7
    protected $bytesWritten = 0;
8
    protected $lineEnding = "\r\n";
9
10
    public function fwriteCsv(array $row, $delimiter = null, $enclosure = null)
11
    {
12
        $bytes = $this->fwrite($this->getCsvString($row, $delimiter, $enclosure));
13
14
        if ($bytes === false) {
15
            return false;
16
        }
17
18
        $this->bytesWritten += $bytes;
19
20
        return $bytes;
21
    }
22
23 1
    public function __destruct()
24
    {
25 1
        $this->trimFinalLineEnding();
26 1
    }
27
28
    /**
29
     * Returns a string representation of a row to be written
30
     * as a line in a CSV file.
31
     *
32
     * @param array $row
33
     *
34
     * @param       $delimiter
35
     * @param       $enclosure
36
     *
37
     * @return string
38
     */
39
    protected function getCsvString(array $row, $delimiter, $enclosure)
40
    {
41
        $csvControl = $this->getCsvControl();
42
43
        $delimiter = $delimiter ? : $csvControl[0];
44
        $enclosure = $enclosure ? : $csvControl[1];
45
46
        $result = $enclosure;
47
        $result .= implode($enclosure . $delimiter . $enclosure, self::escapeEnclosure($row, $enclosure));
48
        $result .= $enclosure;
49
50
        $result .= $this->getLineEnding();
51
52
        return $result;
53
    }
54
55
    /**
56
     * @return int
57
     */
58 1
    public function getBytesWritten()
59
    {
60 1
        return (int)$this->bytesWritten;
61
    }
62
63
    /**
64
     * @return string
65
     */
66
    public function getLineEnding()
67
    {
68
        return $this->lineEnding;
69
    }
70
71
    /**
72
     * @param string $lineEnding
73
     *
74
     * @return CsvFileObject
75
     */
76
    public function setLineEnding($lineEnding)
77
    {
78
        $this->lineEnding = $lineEnding;
79
80
        return $this;
81
    }
82
83
    public function getSize()
84
    {
85
        try {
86
            $size = parent::getSize();
87
        } catch (\RuntimeException $exception) {
88
            $size = $this->fstat()['size'];
89
        }
90
91
        return $size;
92
    }
93
94
    /**
95
     * Trims the line ending delimiter from the end of the CSV file.
96
     * RFC-4180 states CSV files should not contain a trailing new line.
97
     */
98 1
    public function trimFinalLineEnding()
99
    {
100 1
        if ($this->getBytesWritten() > 0) {
101
            // Only trim the file if it ends with the line ending delimiter.
102
            $length = strlen($this->getLineEnding());
103
104
            $this->fseek(-$length, SEEK_END);
105
106
            if ($this->fread($length) === $this->getLineEnding()) {
107
                $this->ftruncate($this->getBytesWritten() - $length);
108
            }
109
        }
110 1
    }
111
112
    /**
113
     * Escapes the enclosure character recursively.
114
     * RFC-4180 states the enclosure character (usually double quotes) should be
115
     * escaped by itself, so " becomes "".
116
     *
117
     * @param mixed $data Array or string of data to escape.
118
     *
119
     * @param       $enclosure
120
     *
121
     * @return mixed Escaped data
122
     */
123
    protected static function escapeEnclosure($data, $enclosure)
124
    {
125
        if (is_array($data)) {
126
            foreach ($data as $key => $value) {
127
                $data[$key] = self::escapeEnclosure($value, $enclosure);
128
            }
129
        } else {
130
            $data = str_replace($enclosure, str_repeat($enclosure, 2), $data);
131
        }
132
133
        return $data;
134
    }
135
}
136