PluginProbe
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder / 1.2.4
Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder v1.2.4
6.2.14 6.2.13 6.2.12 6.2.10 6.2.11 6.2.9 6.2.8 6.2.7 6.2.6 6.2.5 6.2.4 6.2.3 6.2.2 3.6.22 3.6.31 3.6.40 3.6.41 3.6.42 3.6.50 3.6.51 3.6.60 3.6.61 3.6.62 3.6.64 3.6.65 All 196 releases
fluentform / app / Services / csv / src / Reader.php

Reader.php in Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder 1.2.4, at app/Services/csv/src/Reader.php

340 lines 10.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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.2.2
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 Generator;
16 use InvalidArgumentException;
17 use Iterator;
18 use League\Csv\Modifier\MapIterator;
19 use LimitIterator;
20
21 /**
22 * A class to manage extracting and filtering a CSV
23 *
24 * @package League.csv
25 * @since 3.0.0
26 *
27 */
28 class Reader extends AbstractCsv
29 {
30 /**
31 * @inheritdoc
32 */
33 protected $stream_filter_mode = STREAM_FILTER_READ;
34
35 /**
36 * Returns a sequential array of all CSV lines
37 *
38 * The callable function will be applied to each Iterator item
39 *
40 * @param callable|null $callable a callable function
41 *
42 * @return array
43 */
44 public function fetchAll(callable $callable = null)
45 {
46 return iterator_to_array($this->applyCallable($this->getQueryIterator(), $callable), false);
47 }
48
49 /**
50 * Fetch the next row from a result set
51 *
52 * @param callable|null $callable a callable function to be applied to each Iterator item
53 *
54 * @return Iterator
55 */
56 public function fetch(callable $callable = null)
57 {
58 return $this->applyCallable($this->getQueryIterator(), $callable);
59 }
60
61 /**
62 * Apply The callable function
63 *
64 * @param Iterator $iterator
65 * @param callable|null $callable
66 *
67 * @return Iterator
68 */
69 protected function applyCallable(Iterator $iterator, callable $callable = null)
70 {
71 if (null !== $callable) {
72 return new MapIterator($iterator, $callable);
73 }
74
75 return $iterator;
76 }
77
78 /**
79 * Applies a callback function on the CSV
80 *
81 * The callback function must return TRUE in order to continue
82 * iterating over the iterator.
83 *
84 * @param callable $callable a callable function to apply to each selected CSV rows
85 *
86 * @return int the iteration count
87 */
88 public function each(callable $callable)
89 {
90 $index = 0;
91 $iterator = $this->getQueryIterator();
92 $iterator->rewind();
93 while ($iterator->valid() && true === call_user_func(
94 $callable,
95 $iterator->current(),
96 $iterator->key(),
97 $iterator
98 )) {
99 ++$index;
100 $iterator->next();
101 }
102
103 return $index;
104 }
105
106 /**
107 * Returns a single row from the CSV
108 *
109 * By default if no offset is provided the first row of the CSV is selected
110 *
111 * @param int $offset the CSV row offset
112 *
113 * @return array
114 */
115 public function fetchOne($offset = 0)
116 {
117 $this->setOffset($offset);
118 $this->setLimit(1);
119 $iterator = $this->getQueryIterator();
120 $iterator->rewind();
121
122 return (array) $iterator->current();
123 }
124
125 /**
126 * Returns the next value from a single CSV column
127 *
128 * The callable function will be applied to each value to be return
129 *
130 * By default if no column index is provided the first column of the CSV is selected
131 *
132 * @param int $column_index CSV column index
133 * @param callable|null $callable A callable to be applied to each of the value to be returned.
134 *
135 * @return Iterator
136 */
137 public function fetchColumn($column_index = 0, callable $callable = null)
138 {
139 $column_index = $this->validateInteger($column_index, 0, 'the column index must be a positive integer or 0');
140
141 $filter_column = function ($row) use ($column_index) {
142 return isset($row[$column_index]);
143 };
144
145 $select_column = function ($row) use ($column_index) {
146 return $row[$column_index];
147 };
148
149 $this->addFilter($filter_column);
150
151 return $this->applyCallable(new MapIterator($this->getQueryIterator(), $select_column), $callable);
152 }
153
154 /**
155 * Retrieve CSV data as pairs
156 *
157 * DEPRECATION WARNING! This method will be removed in the next major point release
158 *
159 * @deprecated deprecated since version 8.2
160 * @see Reader::fetchPairs
161 *
162 * Fetches an associative array of all rows as key-value pairs (first
163 * column is the key, second column is the value).
164 *
165 * By default if no column index is provided:
166 * - the first CSV column is used to provide the keys
167 * - the second CSV column is used to provide the value
168 *
169 * If the value from the column key index is duplicated its corresponding value will
170 * be overwritten
171 *
172 * @param int $offset_index The column index to serve as offset
173 * @param int $value_index The column index to serve as value
174 * @param callable|null $callable A callable to be applied to each of the rows to be returned.
175 *
176 * @return array
177 */
178 public function fetchPairsWithoutDuplicates($offset_index = 0, $value_index = 1, callable $callable = null)
179 {
180 return iterator_to_array($this->fetchPairs($offset_index, $value_index, $callable), true);
181 }
182
183 /**
184 * Fetches the next key-value pairs from a result set (first
185 * column is the key, second column is the value).
186 *
187 * By default if no column index is provided:
188 * - the first CSV column is used to provide the keys
189 * - the second CSV column is used to provide the value
190 *
191 * @param int $offset_index The column index to serve as offset
192 * @param int $value_index The column index to serve as value
193 * @param callable|null $callable A callable to be applied to each of the rows to be returned.
194 *
195 * @return Generator
196 */
197 public function fetchPairs($offset_index = 0, $value_index = 1, callable $callable = null)
198 {
199 $offset_index = $this->validateInteger($offset_index, 0, 'the offset column index must be a positive integer or 0');
200 $value_index = $this->validateInteger($value_index, 0, 'the value column index must be a positive integer or 0');
201 $filter_pairs = function ($row) use ($offset_index) {
202 return isset($row[$offset_index]);
203 };
204 $select_pairs = function ($row) use ($offset_index, $value_index) {
205 return [
206 $row[$offset_index],
207 isset($row[$value_index]) ? $row[$value_index] : null,
208 ];
209 };
210
211 $this->addFilter($filter_pairs);
212 $iterator = $this->applyCallable(new MapIterator($this->getQueryIterator(), $select_pairs), $callable);
213 foreach ($iterator as $row) {
214 yield $row[0] => $row[1];
215 }
216 }
217
218 /**
219 * Fetch the next row from a result set
220 *
221 * The rows are presented as associated arrays
222 * The callable function will be applied to each row
223 *
224 * @param int|array $offset_or_keys the name for each key member OR the row Index to be
225 * used as the associated named keys
226 *
227 * @param callable $callable A callable to be applied to each of the rows to be returned.
228 *
229 * @throws InvalidArgumentException If the submitted keys are invalid
230 *
231 * @return Iterator
232 */
233 public function fetchAssoc($offset_or_keys = 0, callable $callable = null)
234 {
235 $keys = $this->getAssocKeys($offset_or_keys);
236 $keys_count = count($keys);
237 $combine_array = function (array $row) use ($keys, $keys_count) {
238 if ($keys_count != count($row)) {
239 $row = array_slice(array_pad($row, $keys_count, null), 0, $keys_count);
240 }
241
242 return array_combine($keys, $row);
243 };
244
245 return $this->applyCallable(new MapIterator($this->getQueryIterator(), $combine_array), $callable);
246 }
247
248 /**
249 * Selects the array to be used as key for the fetchAssoc method
250 *
251 * @param int|array $offset_or_keys the assoc key OR the row Index to be used
252 * as the key index
253 *
254 * @throws InvalidArgumentException If the row index and/or the resulting array is invalid
255 *
256 * @return array
257 */
258 protected function getAssocKeys($offset_or_keys)
259 {
260 if (is_array($offset_or_keys)) {
261 return $this->validateKeys($offset_or_keys);
262 }
263
264 $offset_or_keys = $this->validateInteger(
265 $offset_or_keys,
266 0,
267 'the row index must be a positive integer, 0 or a non empty array'
268 );
269 $keys = $this->validateKeys($this->getRow($offset_or_keys));
270 $filterOutRow = function ($row, $rowIndex) use ($offset_or_keys) {
271 return $rowIndex != $offset_or_keys;
272 };
273 $this->addFilter($filterOutRow);
274
275 return $keys;
276 }
277
278 /**
279 * Validates the array to be used by the fetchAssoc method
280 *
281 * @param array $keys
282 *
283 * @throws InvalidArgumentException If the submitted array fails the assertion
284 *
285 * @return array
286 */
287 protected function validateKeys(array $keys)
288 {
289 if (empty($keys) || $keys !== array_unique(array_filter($keys, [$this, 'isValidKey']))) {
290 throw new InvalidArgumentException('Use a flat array with unique string values');
291 }
292
293 return $keys;
294 }
295
296 /**
297 * Returns whether the submitted value can be used as string
298 *
299 * @param mixed $value
300 *
301 * @return bool
302 */
303 protected function isValidKey($value)
304 {
305 return is_scalar($value) || (is_object($value) && method_exists($value, '__toString'));
306 }
307
308 /**
309 * Returns a single row from the CSV without filtering
310 *
311 * @param int $offset
312 *
313 * @throws InvalidArgumentException If the $offset is not valid or the row does not exist
314 *
315 * @return array
316 */
317 protected function getRow($offset)
318 {
319 $fileObj = $this->getIterator();
320 $iterator = new LimitIterator($fileObj, $offset, 1);
321 $iterator->rewind();
322 $row = $iterator->current();
323 if (empty($row)) {
324 throw new InvalidArgumentException('the specified row does not exist or is empty');
325 }
326
327 if (0 !== $offset || !$this->isBomStrippable()) {
328 return $row;
329 }
330
331 $bom_length = mb_strlen($this->getInputBOM());
332 $row[0] = mb_substr($row[0], $bom_length);
333 if ($this->enclosure == mb_substr($row[0], 0, 1) && $this->enclosure == mb_substr($row[0], -1, 1)) {
334 $row[0] = mb_substr($row[0], 1, -1);
335 }
336
337 return $row;
338 }
339 }
340