Completed
Push — master ( 9f41df...ade25d )
by Andy
01:52
created

Reader::getHeaderOffset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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