PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.2.2
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.2.2
2.4.0 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 All 67 releases
better-payment / vendor / league / csv / src / ResultSet.php

ResultSet.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.2.2, at vendor/league/csv/src/ResultSet.php

262 lines 7.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * League.Csv (https://csv.thephpleague.com)
5 *
6 * (c) Ignace Nyamagana Butera <[email protected]>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 declare(strict_types=1);
13
14 namespace League\Csv;
15
16 use CallbackFilterIterator;
17 use Generator;
18 use Iterator;
19 use JsonSerializable;
20 use LimitIterator;
21 use function array_flip;
22 use function array_search;
23 use function is_string;
24 use function iterator_count;
25 use function iterator_to_array;
26
27 /**
28 * Represents the result set of a {@link Reader} processed by a {@link Statement}.
29 */
30 class ResultSet implements TabularDataReader, JsonSerializable
31 {
32 /** The CSV records collection. */
33 protected Iterator $records;
34 /** @var array<string> The CSV records collection header. */
35 protected array $header = [];
36
37 public function __construct(Iterator $records, array $header)
38 {
39 $this->validateHeader($header);
40
41 $this->records = $records;
42 $this->header = $header;
43 }
44
45 /**
46 * @throws SyntaxError if the header syntax is invalid
47 */
48 protected function validateHeader(array $header): void
49 {
50 if ($header !== ($filtered_header = array_filter($header, 'is_string'))) {
51 throw SyntaxError::dueToInvalidHeaderColumnNames();
52 }
53
54 if ($header !== array_unique($filtered_header)) {
55 throw SyntaxError::dueToDuplicateHeaderColumnNames($header);
56 }
57 }
58
59 public function __destruct()
60 {
61 unset($this->records);
62 }
63
64 /**
65 * Returns a new instance from an object implementing the TabularDataReader interface.
66 */
67 public static function createFromTabularDataReader(TabularDataReader $reader): self
68 {
69 return new self($reader->getRecords(), $reader->getHeader());
70 }
71
72 /**
73 * Returns the header associated with the result set.
74 *
75 * @return array<string>
76 */
77 public function getHeader(): array
78 {
79 return $this->header;
80 }
81
82 public function getIterator(): Iterator
83 {
84 return $this->getRecords();
85 }
86
87 public function getRecords(array $header = []): Iterator
88 {
89 $this->validateHeader($header);
90 $records = $this->combineHeader($header);
91 foreach ($records as $offset => $value) {
92 yield $offset => $value;
93 }
94 }
95
96 /**
97 * Combine the header to each record if present.
98 */
99 protected function combineHeader(array $header): Iterator
100 {
101 if ($header === $this->header || [] === $header) {
102 return $this->records;
103 }
104
105 $field_count = count($header);
106 $mapper = static function (array $record) use ($header, $field_count): array {
107 if (count($record) != $field_count) {
108 $record = array_slice(array_pad($record, $field_count, null), 0, $field_count);
109 }
110
111 /** @var array<string|null> $assocRecord */
112 $assocRecord = array_combine($header, $record);
113
114 return $assocRecord;
115 };
116
117 return new MapIterator($this->records, $mapper);
118 }
119
120 public function count(): int
121 {
122 return iterator_count($this->records);
123 }
124
125 public function jsonSerialize(): array
126 {
127 return iterator_to_array($this->records, false);
128 }
129
130 public function fetchOne(int $nth_record = 0): array
131 {
132 if ($nth_record < 0) {
133 throw InvalidArgument::dueToInvalidRecordOffset($nth_record, __METHOD__);
134 }
135
136 $iterator = new LimitIterator($this->records, $nth_record, 1);
137 $iterator->rewind();
138
139 $result = $iterator->current();
140 if (!is_array($result)) {
141 return [];
142 }
143
144 return $result;
145 }
146
147 /**
148 * @throws Exception
149 */
150 public function fetchColumnByName(string $name): Iterator
151 {
152 return $this->yieldColumn(
153 $this->getColumnIndexByValue($name, 'name', __METHOD__)
154 );
155 }
156
157 /**
158 * @throws Exception
159 */
160 public function fetchColumnByOffset(int $offset): Iterator
161 {
162 return $this->yieldColumn(
163 $this->getColumnIndexByKey($offset, 'offset', __METHOD__)
164 );
165 }
166
167 public function fetchColumn($index = 0): Iterator
168 {
169 return $this->yieldColumn(
170 $this->getColumnIndex($index, 'offset', __METHOD__)
171 );
172 }
173
174 /**
175 * @param string|int $offset
176 */
177 protected function yieldColumn($offset): Generator
178 {
179 $iterator = new MapIterator(
180 new CallbackFilterIterator($this->records, fn (array $record): bool => isset($record[$offset])),
181 fn (array $record): string => $record[$offset]
182 );
183
184 foreach ($iterator as $key => $value) {
185 yield $key => $value;
186 }
187 }
188
189 /**
190 * Filter a column name against the header if any.
191 *
192 * @param string|int $field the field name or the field index
193 *
194 * @throws InvalidArgument if the field is invalid or not found
195 *
196 * @return string|int
197 */
198 protected function getColumnIndex($field, string $type, string $method)
199 {
200 if (is_string($field)) {
201 return $this->getColumnIndexByValue($field, $type, $method);
202 }
203
204 return $this->getColumnIndexByKey($field, $type, $method);
205 }
206
207 /**
208 * Returns the selected column name.
209 *
210 * @throws InvalidArgument if the column is not found
211 */
212 protected function getColumnIndexByValue(string $value, string $type, string $method): string
213 {
214 if (false === array_search($value, $this->header, true)) {
215 throw InvalidArgument::dueToInvalidColumnIndex($value, $type, $method);
216 }
217
218 return $value;
219 }
220
221 /**
222 * Returns the selected column name according to its offset.
223 *
224 * @throws InvalidArgument if the field is invalid or not found
225 *
226 * @return int|string
227 */
228 protected function getColumnIndexByKey(int $index, string $type, string $method)
229 {
230 if ($index < 0) {
231 throw InvalidArgument::dueToInvalidColumnIndex($index, $type, $method);
232 }
233
234 if ([] === $this->header) {
235 return $index;
236 }
237
238 $value = array_search($index, array_flip($this->header), true);
239 if (false === $value) {
240 throw InvalidArgument::dueToInvalidColumnIndex($index, $type, $method);
241 }
242
243 return $value;
244 }
245
246 public function fetchPairs($offset_index = 0, $value_index = 1): Iterator
247 {
248 $offset = $this->getColumnIndex($offset_index, 'offset', __METHOD__);
249 $value = $this->getColumnIndex($value_index, 'value', __METHOD__);
250
251 $iterator = new MapIterator(
252 new CallbackFilterIterator($this->records, fn (array $record): bool => isset($record[$offset])),
253 fn (array $record): array => [$record[$offset], $record[$value] ?? null]
254 );
255
256 /** @var array{0:int|string, 1:string|null} $pair */
257 foreach ($iterator as $pair) {
258 yield $pair[0] => $pair[1];
259 }
260 }
261 }
262