Passed
Push — master ( 2046e5...3b7451 )
by Fabrice
02:23
created

CsvExtractor::getFirstRecord()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 4
nop 0
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of YaEtl.
5
 *     (c) Fabrice de Stefanis / https://github.com/fab2s/YaEtl
6
 * This source file is licensed under the MIT license which you will
7
 * find in the LICENSE file or at https://opensource.org/licenses/MIT
8
 */
9
10
namespace fab2s\YaEtl\Loaders\File;
11
12
use fab2s\NodalFlow\NodalFlowException;
13
use fab2s\NodalFlow\YaEtlException;
14
use fab2s\YaEtl\Extractors\File\FileExtractorAbstract;
15
use fab2s\YaEtl\Traits\CsvHandlerTrait;
16
17
/**
18
 * Class CsvExtractor
19
 */
20
class CsvExtractor extends FileExtractorAbstract
21
{
22
    use CsvHandlerTrait;
23
24
    /**
25
     * CsvLoader constructor.
26
     *
27
     * @param resource|string $input
28
     * @param string|null     $delimiter
29
     * @param string|null     $enclosure
30
     * @param string|null     $escape
31
     *
32
     * @throws NodalFlowException
33
     * @throws YaEtlException
34
     */
35
    public function __construct($input, $delimiter = null, $enclosure = null, $escape = null)
36
    {
37
        parent::__construct($input);
38
        $this->initCsvOptions($delimiter, $enclosure, $escape);
39
    }
40
41
    /**
42
     * @param mixed $param
43
     *
44
     * @return \Generator
45
     */
46
    public function getTraversable($param = null)
47
    {
48
        if (!$this->extract($param)) {
49
            return;
50
        }
51
52
        if (false !== ($firstRecord = $this->getFirstRecord())) {
53
            /* @var array $firstRecord */
54
            yield $this->bakeRecord($firstRecord);
55
        }
56
57
        while (false !== ($record = fgetcsv($this->handle, 0, $this->delimiter, $this->enclosure, $this->escape))) {
58
            /* @var array $record */
59
            if (isset($this->header)) {
60
                $record = array_combine($this->header, $record);
61
            }
62
63
            yield $this->bakeRecord($record);
64
        }
65
66
        $this->releaseHandle();
67
    }
68
69
    /**
70
     * @param array $record
71
     *
72
     * @return array
73
     */
74
    protected function bakeRecord(array $record)
75
    {
76
        return isset($this->header) ? array_combine($this->header, $record) : $record;
77
    }
78
79
    /**
80
     * @return string|bool
81
     */
82
    protected function getFirstRecord()
83
    {
84
        while (false !== ($line = fgets($this->handle))) {
85
            if ($line = trim($this->trimBom($line))) {
86
                $record = $this->handleHeader($line);
87
                if ($record === false) {
88
                    continue;
89
                }
90
91
                return $record;
92
            }
93
        }
94
95
        return false;
96
    }
97
98
    /**
99
     * @param string $line
100
     *
101
     * @return array|bool
102
     */
103
    protected function handleHeader($line)
104
    {
105
        // obey excel sep
106
        if (strpos($line, 'sep=') === 0) {
107
            $this->useSep    = true;
108
            $this->delimiter = $line[4];
109
110
            return false;
111
        }
112
113
        $record = str_getcsv($line, $this->delimiter, $this->enclosure, $this->escape);
114
        if ($this->useHeader && !isset($this->header)) {
115
            $this->header = array_map('trim', $record);
116
117
            return false;
118
        }
119
120
        return $record;
121
    }
122
123
    /**
124
     * @param array $record
125
     *
126
     * @return bool|int
127
     */
128
    protected function writeCsvLine(array $record)
129
    {
130
        return fputcsv($this->handle, $record, $this->delimiter, $this->enclosure, $this->escape);
131
    }
132
}
133