Completed
Pull Request — master (#210)
by ignace nyamagana
02:41
created

Reader::getHeaderOffset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
* This file is part of the League.csv library
4
*
5
* @license http://opensource.org/licenses/MIT
6
* @link https://github.com/thephpleague/csv/
7
* @version 9.0.0
8
* @package League.csv
9
*
10
* For the full copyright and license information, please view the LICENSE
11
* file that was distributed with this source code.
12
*/
13
declare(strict_types=1);
14
15
namespace League\Csv;
16
17
use CallbackFilterIterator;
18
use Countable;
19
use DomDocument;
20
use Generator;
21
use Iterator;
22
use IteratorAggregate;
23
use JsonSerializable;
24
use LimitIterator;
25
use SplFileObject;
26
27
/**
28
 *  A class to manage extracting and filtering a CSV
29
 *
30
 * @package League.csv
31
 * @since  3.0.0
32
 *
33
 */
34
class Reader extends AbstractCsv implements JsonSerializable, Countable, IteratorAggregate
35
{
36
    /**
37
     * @inheritdoc
38
     */
39
    protected $stream_filter_mode = STREAM_FILTER_READ;
40
41
    /**
42
     * CSV Document header offset
43
     *
44
     * @var int|null
45
     */
46
    protected $header_offset;
47
48
    /**
49
     * Returns the record offset used as header
50
     *
51
     * If no CSV record is used this method MUST return null
52
     *
53
     * @return int|null
54
     */
55 106
    public function getHeaderOffset()
56
    {
57 106
        return $this->header_offset;
58
    }
59
60
    /**
61
     * Selects the record to be used as the CSV header
62
     *
63
     * Because of the header is represented as an array, to be valid
64
     * a header MUST contain only unique string value.
65
     *
66
     * @param int|null $offset the header row offset
67
     *
68
     * @return $this
69
     */
70 22
    public function setHeaderOffset($offset): self
71
    {
72 22
        $this->header_offset = null;
73 22
        if (null !== $offset) {
74 18
            $this->header_offset = $this->filterInteger(
75
                $offset,
76 18
                0,
77 18
                'the header offset index must be a positive integer or 0'
78
            );
79
        }
80
81 20
        return $this;
82
    }
83
84
    /**
85
     * Detect Delimiters occurences in the CSV
86
     *
87
     * Returns a associative array where each key represents
88
     * a valid delimiter and each value the number of occurences
89
     *
90
     * @param string[] $delimiters the delimiters to consider
91
     * @param int      $nb_rows    Detection is made using $nb_rows of the CSV
92
     *
93
     * @return array
94
     */
95 8
    public function fetchDelimitersOccurrence(array $delimiters, int $nb_rows = 1): array
96
    {
97 8
        $nb_rows = $this->filterInteger($nb_rows, 1, 'The number of rows to consider must be a valid positive integer');
98
        $filter_row = function ($row) {
99 6
            return is_array($row) && count($row) > 1;
100 6
        };
101 6
        $delimiters = array_unique(array_filter($delimiters, function ($value) {
102 6
            return 1 == strlen($value);
103 6
        }));
104 6
        $csv = $this->getDocument();
105 6
        $csv->setFlags(SplFileObject::READ_CSV);
106 6
        $res = [];
107 6
        foreach ($delimiters as $delim) {
108 6
            $csv->setCsvControl($delim, $this->enclosure, $this->escape);
109 6
            $iterator = new CallbackFilterIterator(new LimitIterator($csv, 0, $nb_rows), $filter_row);
110 6
            $res[$delim] = count(iterator_to_array($iterator, false), COUNT_RECURSIVE);
111
        }
112 6
        arsort($res, SORT_NUMERIC);
113
114 6
        return $res;
115
    }
116
117
    /**
118
     * Returns a collection of selected records
119
     *
120
     * @param Statement|null $stmt
121
     *
122
     * @return RecordSet
123
     */
124 92
    public function select(Statement $stmt = null): RecordSet
125
    {
126 92
        $stmt = $stmt ?: new Statement();
127
128 92
        return $stmt->process($this);
129
    }
130
131
    /**
132
     * @inheritdoc
133
     */
134 2
    public function count(): int
135
    {
136 2
        return count($this->select());
137
    }
138
139
    /**
140
     * @inheritdoc
141
     */
142 4
    public function getIterator(): Iterator
143
    {
144 4
        return $this->select()->getIterator();
145
    }
146
147
    /**
148
     * @inheritdoc
149
     */
150 2
    public function jsonSerialize()
151
    {
152 2
        return $this->select()->jsonSerialize();
153
    }
154
155
    /**
156
     * Returns the column header associate with the RecordSet
157
     *
158
     * @return string[]
159
     */
160 2
    public function getHeader()
161
    {
162 2
        return $this->select()->getHeader();
163
    }
164
165
    /**
166
     * Returns a HTML table representation of the CSV Table
167
     *
168
     * @param string $class_attr optional classname
169
     *
170
     * @return string
171
     */
172 2
    public function toHTML(string $class_attr = 'table-csv-data'): string
173
    {
174 2
        return $this->select()->toHTML($class_attr);
175
    }
176
177
    /**
178
     * Transforms a CSV into a XML
179
     *
180
     * @param string $root_name XML root node name
181
     * @param string $row_name  XML row node name
182
     * @param string $cell_name XML cell node name
183
     *
184
     * @return DomDocument
185
     */
186 2
    public function toXML(string $root_name = 'csv', string $row_name = 'row', string $cell_name = 'cell'): DomDocument
187
    {
188 2
        return $this->select()->toXML($root_name, $row_name, $cell_name);
189
    }
190
191
    /**
192
     * Returns a sequential array of all CSV lines
193
     *
194
     * @return array
195
     */
196 42
    public function fetchAll(): array
197
    {
198 42
        return $this->select()->fetchAll();
199
    }
200
201
    /**
202
     * Returns a single row from the CSV
203
     *
204
     * By default if no offset is provided the first row of the CSV is selected
205
     *
206
     * @param int $offset the CSV row offset
207
     *
208
     * @return array
209
     */
210 6
    public function fetchOne(int $offset = 0): array
211
    {
212 6
        return $this->select()->fetchOne($offset);
213
    }
214
215
    /**
216
     * Returns the next value from a single CSV column
217
     *
218
     * By default if no column index is provided the first column of the CSV is selected
219
     *
220
     * @param string|int $column_index CSV column index
221
     *
222
     * @return Iterator
223
     */
224 10
    public function fetchColumn($column_index = 0): Iterator
225
    {
226 10
        return $this->select()->fetchColumn($column_index);
227
    }
228
229
    /**
230
     * Fetches the next key-value pairs from a result set (first
231
     * column is the key, second column is the value).
232
     *
233
     * By default if no column index is provided:
234
     * - the first CSV column is used to provide the keys
235
     * - the second CSV column is used to provide the value
236
     *
237
     * @param string|int $offset_index The column index to serve as offset
238
     * @param string|int $value_index  The column index to serve as value
239
     *
240
     * @return Generator
241
     */
242 8
    public function fetchPairs($offset_index = 0, $value_index = 1)
243
    {
244 8
        return $this->select()->fetchPairs($offset_index, $value_index);
245
    }
246
}
247