Passed
Push — master ( 2a5d2e...e3462d )
by Andy
02:12
created

Reader::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 5
crap 1
1
<?php
2
3
namespace Palmtree\Csv;
4
5
use Palmtree\Csv\Normalizer\NormalizerInterface;
6
use Palmtree\Csv\Normalizer\NullNormalizer;
7
use Palmtree\Csv\Row\Row;
8
use Palmtree\Csv\Util\StringUtil;
9
10
/**
11
 * Reads a CSV file by loading each line into memory
12
 * one at a time.
13
 */
14
class Reader extends AbstractCsv implements \Iterator
15
{
16
    /** @var string */
17
    protected $defaultNormalizer = NullNormalizer::class;
18
    /** @var NormalizerInterface */
19
    protected $headerNormalizer;
20
    /** @var string */
21
    protected $openMode = 'r';
22
    /** @var NormalizerInterface[] */
23
    protected $normalizers = [];
24
    /** @var Row */
25
    protected $headers;
26
    /** @var Row */
27
    protected $row;
28
    /** @var bool */
29
    protected $bom = false;
30
    /** @var int */
31
    protected $offset = 0;
32
33 8
    public function __construct($file, $hasHeaders = true, $delimiter = ',', $enclosure = '"', $escape = "\0")
34
    {
35 8
        $this->headerNormalizer = new NullNormalizer();
36 8
        parent::__construct($file, $hasHeaders, $delimiter, $enclosure, $escape);
37 8
    }
38
39
    /**
40
     * @param string $file
41
     *
42
     * @return Reader
43
     */
44
    public static function read($file)
45
    {
46
        $csv = new static($file);
47
48
        return $csv;
49
    }
50
51
    /**
52
     * @return Row
53
     */
54 2
    public function getHeaders()
55
    {
56 2
        if (is_null($this->headers) && $this->hasHeaders()) {
57 2
            $this->rewind();
58
        }
59
60 2
        return $this->headers;
61
    }
62
63
    /**
64
     * @param $key
65
     *
66
     * @return mixed
67
     */
68 7
    public function getHeader($key)
69
    {
70 7
        if (!isset($this->headers[$key])) {
71 7
            return $key;
72
        }
73
74 2
        return $this->headers[$key];
75
    }
76
77
    /**
78
     * @param NormalizerInterface $headerNormalizer
79
     */
80
    public function setHeaderNormalizer(NormalizerInterface $headerNormalizer)
81
    {
82
        $this->headerNormalizer = $headerNormalizer;
83
84
        return $this;
85
    }
86
87
    /**
88
     * @param mixed               $key
89
     * @param NormalizerInterface $normalizer Normalizer instance.
90
     *
91
     * @return $this
92
     */
93
    public function addNormalizer($key, NormalizerInterface $normalizer)
94
    {
95
        $this->normalizers[$key] = $normalizer;
96
97
        return $this;
98
    }
99
100
    /**
101
     * @param array|\Traversable $normalizers
102
     *
103
     * @return $this
104
     */
105
    public function addNormalizers($normalizers)
106
    {
107
        foreach ($normalizers as $key => $normalizer) {
108
            $this->addNormalizer($key, $normalizer);
109
        }
110
111
        return $this;
112
    }
113
114
    /**
115
     * @param mixed $key
116
     *
117
     * @return NormalizerInterface
118
     */
119 7
    public function getNormalizer($key)
120
    {
121 7
        if ($this->hasHeaders && is_int($key)) {
122 4
            $this->normalizers[$key] = $this->headerNormalizer;
123
        }
124
125 7
        if (!isset($this->normalizers[$key])) {
126 5
            $class = $this->getDefaultNormalizer();
127
128 5
            $this->normalizers[$key] = new $class();
129
        }
130
131 7
        return $this->normalizers[$key];
132
    }
133
134
    /**
135
     * Reads the next line in the CSV file
136
     * and returns a Row object from it.
137
     *
138
     * @return Row|null
139
     */
140 4
    protected function getCurrentRow()
141
    {
142 4
        $cells = $this->getDocument()->current();
143
144 4
        if (!is_array($cells)) {
145 2
            return null;
146
        }
147
148 4
        if ($this->key() === 0 && $this->hasBom()) {
149 1
            $stripped = StringUtil::stripBom($cells[0], StringUtil::BOM_UTF8);
150
151 1
            if ($stripped !== $cells[0]) {
152 1
                $cells[0] = trim($stripped, $this->getEnclosure());
153
            }
154
        }
155
156 4
        $row = new Row($cells, $this);
157
158 4
        return $row;
159
    }
160
161
    /**
162
     * @inheritDoc
163
     */
164 2
    public function current()
165
    {
166 2
        return $this->row;
167
    }
168
169
    /**
170
     * @inheritDoc
171
     */
172 4
    public function next()
173
    {
174 4
        $this->getDocument()->next();
175 4
    }
176
177
    /**
178
     * @inheritDoc
179
     */
180 4
    public function key()
181
    {
182 4
        return $this->getDocument()->key();
183
    }
184
185
    /**
186
     * @inheritDoc
187
     */
188 2
    public function valid()
189
    {
190 2
        $this->row = $this->getCurrentRow();
191
192 2
        return $this->row instanceof Row;
193
    }
194
195
    /**
196
     * @inheritDoc
197
     */
198 4
    public function rewind()
199
    {
200 4
        $this->getDocument()->rewind();
201 4
        $this->getDocument()->seek($this->offset);
202
203 4
        if ($this->hasHeaders()) {
204
            // Set headers to null first so the header row is a zero-based array and can be used
205
            // to set the array keys of all other rows.
206 4
            $this->headers = null;
207 4
            $this->headers = $this->getCurrentRow();
208 4
            $this->next();
209
        }
210 4
    }
211
212
    /**
213
     * @param string $defaultNormalizer
214
     *
215
     * @return Reader
216
     */
217
    public function setDefaultNormalizer($defaultNormalizer)
218
    {
219
        $this->defaultNormalizer = $defaultNormalizer;
220
221
        return $this;
222
    }
223
224
    /**
225
     * @return string
226
     */
227 5
    public function getDefaultNormalizer()
228
    {
229 5
        return $this->defaultNormalizer;
230
    }
231
232
    /**
233
     * @param bool $bom
234
     *
235
     * @return Reader
236
     */
237 2
    public function setBom($bom)
238
    {
239 2
        $this->bom = $bom;
240
241 2
        return $this;
242
    }
243
244
    /**
245
     * @return bool
246
     */
247 3
    public function hasBom()
248
    {
249 3
        return $this->bom;
250
    }
251
252
    /**
253
     * @param int $offset
254
     */
255 1
    public function setOffset($offset)
256
    {
257 1
        $this->offset = $offset;
258 1
    }
259
260
    /**
261
     * @return int
262
     */
263
    public function getOffset()
264
    {
265
        return $this->offset;
266
    }
267
268
    /**
269
     * @return array
270
     */
271
    public function toArray()
272
    {
273
        $result = [];
274
        foreach ($this as $rowKey => $row) {
275
            $result[$rowKey] = $row->toArray();
276
        }
277
278
        return $result;
279
    }
280
}
281