Completed
Pull Request — master (#178)
by ignace nyamagana
02:52
created

RecordSet::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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 8.1.1
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
namespace League\Csv;
14
15
use CallbackFilterIterator;
16
use Countable;
17
use DOMDocument;
18
use DOMElement;
19
use Generator;
20
use InvalidArgumentException;
21
use Iterator;
22
use IteratorAggregate;
23
use JsonSerializable;
24
use League\Csv\Config\Validator;
25
use LimitIterator;
26
27
/**
28
 * A class to extract and convert data from a CSV
29
 *
30
 * @package League.csv
31
 * @since  3.0.0
32
 *
33
 */
34
class RecordSet implements Countable, IteratorAggregate, JsonSerializable
35
{
36
    use Validator;
37
38
    /**
39
     * @var array
40
     */
41
    protected $header;
42
43
    /**
44
     * @var array
45
     */
46
    protected $flip_header;
47
48
    /**
49
     * @var Iterator
50
     */
51
    protected $iterator;
52
53
    /**
54
     * New Instance
55
     *
56
     * @param Iterator $iterator
57
     * @param array    $header
58
     */
59
    public function __construct(Iterator $iterator, array $header)
60
    {
61
        $this->iterator = $iterator;
62
        $this->header = $header;
63
        $this->flip_header = array_flip($header);
64
    }
65
66
    /**
67
     * @inheritdoc
68
     */
69
    public function __destruct()
70
    {
71
        $this->iterator = null;
72
    }
73
74
    /**
75
     * Returns a HTML table representation of the CSV Table
76
     *
77
     * @param string $class_attr optional classname
78
     *
79
     * @return string
80
     */
81
    public function toHTML($class_attr = 'table-csv-data')
82
    {
83
        $doc = $this->toXML('table', 'tr', 'td');
84
        $doc->documentElement->setAttribute('class', $class_attr);
85
86
        return $doc->saveHTML($doc->documentElement);
87
    }
88
89
    /**
90
     * Transforms a CSV into a XML
91
     *
92
     * @param string $root_name XML root node name
93
     * @param string $row_name  XML row node name
94
     * @param string $cell_name XML cell node name
95
     *
96
     * @return DOMDocument
97
     */
98
    public function toXML($root_name = 'csv', $row_name = 'row', $cell_name = 'cell')
99
    {
100
        $doc = new DOMDocument('1.0', 'UTF-8');
101
        $root = $doc->createElement($root_name);
102
103
        if (!empty($this->header)) {
104
            $root->appendChild($this->convertRowToXML($this->header, $doc, $row_name, $cell_name));
105
        }
106
107
        foreach ($this->iterator as $row) {
108
            $root->appendChild($this->convertRowToXML($row, $doc, $row_name, $cell_name));
109
        }
110
        $doc->appendChild($root);
111
112
        return $doc;
113
    }
114
115
    /**
116
     * Convert a row into a DOMElement
117
     *
118
     * @param array       $row       Csv record
119
     * @param DOMDocument $doc
120
     * @param string      $row_name  XML row node name
121
     * @param string      $cell_name XML cell node name
122
     *
123
     * @return DOMElement
124
     */
125
    protected function convertRowToXML(array $row, DOMDocument $doc, $row_name, $cell_name)
126
    {
127
        $node = $doc->createElement($row_name);
128
        foreach ($row as $value) {
129
            $cell = $doc->createElement($cell_name);
130
            $cell->appendChild($doc->createTextNode($value));
131
            $node->appendChild($cell);
132
        }
133
134
        return $node;
135
    }
136
137
    /**
138
     * @inheritdoc
139
     */
140
    public function getIterator()
141
    {
142
        return $this->iterator;
143
    }
144
145
    /**
146
     * @inheritdoc
147
     */
148
    public function count()
149
    {
150
        return iterator_count($this);
151
    }
152
153
    /**
154
     * @inheritdoc
155
     */
156
    public function jsonSerialize()
157
    {
158
        return $this->fetchAll();
159
    }
160
161
    /**
162
     * Returns a sequential array of all founded RecordSet
163
     *
164
     * @return array
165
     */
166
    public function fetchAll()
167
    {
168
        return iterator_to_array($this, false);
169
    }
170
171
    /**
172
     * Returns a single record from the recordSet
173
     *
174
     * @param int $offset the record offset relative to the RecordSet
175
     *
176
     * @return array
177
     */
178
    public function fetchOne($offset = 0)
179
    {
180
        $offset = $this->validateInteger($offset, 0, 'the submitted offset is invalid');
181
        $it = new LimitIterator($this->iterator, $offset, 1);
182
        $it->rewind();
183
184
        return (array) $it->current();
185
    }
186
187
    /**
188
     * Returns the next value from a specific record column
189
     *
190
     * By default if no column index is provided the first column of the founded RecordSet is returned
191
     *
192
     * @param string|int $column_index CSV column index or header field name
193
     *
194
     * @return Iterator
195
     */
196
    public function fetchColumn($column_index = 0)
197
    {
198
        $column_index = $this->filterFieldName($column_index, 'the column index value is invalid');
199
        $filter = function ($row) use ($column_index) {
200
            return isset($row[$column_index]);
201
        };
202
        $select = function ($row) use ($column_index) {
203
            return $row[$column_index];
204
        };
205
206
        return new MapIterator(new CallbackFilterIterator($this->iterator, $filter), $select);
207
    }
208
209
    /**
210
     * Filter a field name against the CSV header if any
211
     *
212
     * @param string|int $field         the field name or the field index
213
     * @param string     $error_message the associated error message
214
     *
215
     * @throws InvalidArgumentException if the field is invalid
216
     *
217
     * @return string|int
218
     */
219
    protected function filterFieldName($field, $error_message)
220
    {
221
        if (false !== array_search($field, $this->header, true)) {
222
            return $field;
223
        }
224
225
        $index = $this->validateInteger($field, 0, $error_message);
226
        if (empty($this->header)) {
227
            return $index;
228
        }
229
230
        if (false !== ($index = array_search($index, $this->flip_header, true))) {
231
            return $index;
232
        }
233
234
        throw new InvalidArgumentException($error_message);
235
    }
236
237
    /**
238
     * Fetches the next key-value pairs from a result set (first
239
     * column is the key, second column is the value).
240
     *
241
     * By default if no column index is provided:
242
     * - the first CSV column is used to provide the keys
243
     * - the second CSV column is used to provide the value
244
     *
245
     * @param string|int $offset_index The field index or name to serve as offset
246
     * @param string|int $value_index  The field index or name to serve as value
247
     *
248
     * @return Generator
249
     */
250
    public function fetchPairs($offset_index = 0, $value_index = 1)
251
    {
252
        $offset_index = $this->filterFieldName($offset_index, 'the offset column index is invalid');
253
        $value_index = $this->filterFieldName($value_index, 'the value column index is invalid');
254
        $filter = function ($row) use ($offset_index) {
255
            return isset($row[$offset_index]);
256
        };
257
        $select = function ($row) use ($offset_index, $value_index) {
258
            return [$row[$offset_index], isset($row[$value_index]) ? $row[$value_index] : null];
259
        };
260
261
        $iterator = new MapIterator(new CallbackFilterIterator($this->iterator, $filter), $select);
262
        foreach ($iterator as $row) {
263
            yield $row[0] => $row[1];
264
        }
265
    }
266
}
267