Lines n/a 0 / 0
Functions and Methods n/a 0 / 0
Classes and Traits n/a 0 / 0
Name Lines Functions and Methods CRAP Classes and Traits
1<?php
2
3declare(strict_types=1);
4
5namespace BlueprintAU\Collections;
6
7/**
8 * The contract shared by eager (Collection) and lazy (LazyCollection)
9 * implementations. Any collection is foreach-able and JSON-serializable.
10 *
11 * Only methods that behave identically whether the data is eagerly in memory
12 * or lazily streamed belong here. Anything that forces materialization
13 * (count, sort, unique, toArray) is intentionally excluded.
14 *
15 * @template  TKey of array-key
16 * @template  TValue
17 *
18 * @extends  \IteratorAggregate<TKey, TValue>
19 */
20interface Enumerable extends \IteratorAggregate, \JsonSerializable
21{
22    // ---- Transforms (lazy-compatible) ----
23
24    /**
25     * Map each item through a callback, producing a new collection.
26     *
27     * @template  TNewValue
28     * @param  callable(TValue, TKey): TNewValue $callback
29     * @return  static<TKey, TNewValue>
30     */
31    public function map(callable $callback): static;
32
33    /**
34     * Filter the collection to items that pass the given callback.
35     *
36     * @param  (callable(TValue, TKey): bool)|null $callback
37     * @return  static
38     */
39    public function filter(?callable $callback = null): static;
40
41    /**
42     * Pluck a single column's value from each item.
43     *
44     * @param  (TValue is array ? key-of<TValue> : string) $value
45     * @param  ((TValue is array ? key-of<TValue> : string)|null) $key
46     * @return  static<($key is null ? int : int|string), (TValue is array ? value-of<TValue> : mixed)>
47     */
48    public function pluck(int|string $value, int|string|null $key = null): static;
49
50    /**
51     * Re-key the collection by a given column's value.
52     *
53     * @param  (TValue is array ? key-of<TValue> : string) $key
54     * @return  static<int|string, TValue>
55     */
56    public function keyBy(int|string $key): static;
57
58    /**
59     * Group the collection's items by a column or callback.
60     *
61     * @param  ((TValue is array ? key-of<TValue> : string)|callable(TValue, TKey): mixed) $groupBy
62     * @return  static
63     */
64    public function groupBy(int|string|callable $groupBy): static;
65
66    /**
67     * Map each item to an associative array and merge the results.
68     *
69     * @template  TMapKey of array-key
70     * @template  TMapValue
71     * @param  callable(TValue, TKey): array<TMapKey, TMapValue> $callback
72     * @return  static<TMapKey, TMapValue>
73     */
74    public function mapWithKeys(callable $callback): static;
75
76    /**
77     * Map each item through a callback, collapsing one level.
78     *
79     * The callback may return any array; string keys survive the collapse and
80     * integer keys are renumbered, so the resulting key type is int|string.
81     *
82     * @param  callable(TValue, TKey): mixed $callback
83     * @return  static<int|string, mixed>
84     */
85    public function flatMap(callable $callback): static;
86
87    /**
88     * Map each item through a callback, dropping null results.
89     *
90     * Keys are preserved — call `values()` to renumber to a 0-based list.
91     *
92     * @template  TNewValue
93     * @param  callable(TValue, TKey): (TNewValue|null) $callback
94     * @return  static<TKey, TNewValue>
95     */
96    public function filterMap(callable $callback): static;
97
98    /**
99     * Filter the collection to items that fail the given callback.
100     *
101     * When no callback is given, truthy items are dropped. Keys are preserved.
102     *
103     * @param  (callable(TValue, TKey): bool)|null $callback
104     * @return  static
105     */
106    public function reject(?callable $callback = null): static;
107
108    // ---- Reductions (lazy-compatible) ----
109
110    /**
111     * Reduce the collection to a single value using a callback.
112     *
113     * @template  TCarry
114     * @param  callable(TCarry, TValue, TKey): TCarry $callback
115     * @param  TCarry $initial
116     * @return  TCarry
117     */
118    public function reduce(callable $callback, mixed $initial = null): mixed;
119
120    /**
121     * Sum the collection's values, or a single column of each item.
122     *
123     * @param  (TValue is array ? key-of<TValue> : string)|(callable(TValue): (int|float))|null $column
124     * @return  int|float
125     */
126    public function sum(int|string|callable|null $column = null): int|float;
127
128    /**
129     * Average the collection's values, or a single column of each item.
130     *
131     * @param  (TValue is array ? key-of<TValue> : string)|(callable(TValue): (int|float))|null $column
132     * @return  int|float
133     */
134    public function avg(int|string|callable|null $column = null): int|float;
135
136    /**
137     * Get the minimum value, or the minimum of a single column.
138     *
139     * Returns null for an empty collection.
140     *
141     * @template  TColumn
142     * @param  (callable(TValue): TColumn)|(TValue is array ? key-of<TValue> : string)|null $column
143     * @return  ($column is null ? (TValue is array ? value-of<TValue> : mixed)|null : ($column is callable ? TColumn : (TValue is array ? value-of<TValue> : mixed)))
144     */
145    public function min(int|string|callable|null $column = null): mixed;
146
147    /**
148     * Get the maximum value, or the maximum of a single column.
149     *
150     * Returns null for an empty collection.
151     *
152     * @template  TColumn
153     * @param  (callable(TValue): TColumn)|(TValue is array ? key-of<TValue> : string)|null $column
154     * @return  ($column is null ? (TValue is array ? value-of<TValue> : mixed)|null : ($column is callable ? TColumn : (TValue is array ? value-of<TValue> : mixed)))
155     */
156    public function max(int|string|callable|null $column = null): mixed;
157
158    /**
159     * Determine whether the collection contains a given item.
160     *
161     * With one argument, membership is strict value equality — a callable
162     * value is checked as a value, never invoked as a predicate. With a
163     * column and value, the column is compared using the given operator.
164     *
165     * @param  mixed  $key  A value to find, or a column name for the comparison form.
166     * @param  mixed  $value  The value the column is compared against.
167     * @param  ComparisonOperator  $operator
168     * @return  bool
169     */
170    public function contains(mixed $key, mixed $value = null, ComparisonOperator $operator = ComparisonOperator::Equals): bool;
171
172    /**
173     * Filter the collection to items whose column matches a value.
174     *
175     * @param  (TValue is array ? key-of<TValue> : string) $key
176     * @param  mixed $value
177     * @param  ComparisonOperator $operator
178     * @return  static
179     */
180    public function where(mixed $key, mixed $value = null, ComparisonOperator $operator = ComparisonOperator::Equals): static;
181
182    /**
183     * Determine whether every item passes the given callback.
184     *
185     * @param  callable(TValue, TKey): bool $callback
186     * @return  bool
187     */
188    public function every(callable $callback): bool;
189
190    /**
191     * Determine whether any item passes the given callback.
192     *
193     * @param  callable(TValue, TKey): bool $callback
194     * @return  bool
195     */
196    public function some(callable $callback): bool;
197
198    /**
199     * Determine whether the collection is empty.
200     *
201     * @return  bool
202     */
203    public function isEmpty(): bool;
204
205    /**
206     * Determine whether the collection is not empty.
207     *
208     * @return  bool
209     */
210    public function isNotEmpty(): bool;
211
212    /**
213     * Get the single item matching the given criteria.
214     *
215     * With no arguments the collection must hold exactly one item. With one
216     * argument, matching is strict value equality — a callable value is
217     * checked as a value, never invoked as a predicate. With a column and
218     * value, the column is compared using the given operator.
219     *
220     * @param  mixed  $key  A value to find, or a column name for the comparison form.
221     * @param  mixed  $value  The value the column is compared against.
222     * @param  ComparisonOperator  $operator
223     * @return  TValue
224     *
225     * @throws \LogicException When no item, two items, or three or more items match.
226     */
227    public function sole(mixed $key = null, mixed $value = null, ComparisonOperator $operator = ComparisonOperator::Equals): mixed;
228
229    /**
230     * Get the first item whose column matches a value.
231     *
232     * Returns null when nothing matches — chain `first()` for a custom default.
233     *
234     * @param  (TValue is array ? key-of<TValue> : string) $key
235     * @param  mixed $value
236     * @param  ComparisonOperator $operator
237     * @return  TValue|null
238     */
239    public function firstWhere(int|string $key, mixed $value = null, ComparisonOperator $operator = ComparisonOperator::Equals): mixed;
240
241    /**
242     * Filter the collection to items that are null.
243     *
244     * With no column, the item itself is checked; otherwise the column's
245     * value is checked. Keys are preserved.
246     *
247     * @param  ((TValue is array ? key-of<TValue> : string)|null) $key
248     * @return  static
249     */
250    public function whereNull(int|string|null $key = null): static;
251
252    /**
253     * Filter the collection to items that are not null.
254     *
255     * With no column, the item itself is checked; otherwise the column's
256     * value is checked. Keys are preserved.
257     *
258     * @param  ((TValue is array ? key-of<TValue> : string)|null) $key
259     * @return  static
260     */
261    public function whereNotNull(int|string|null $key = null): static;
262
263    /**
264     * Join the collection's values, or a single column of each item.
265     *
266     * @param  string $glue
267     * @param  ((TValue is array ? key-of<TValue> : string)|null) $column
268     * @return  string
269     */
270    public function implode(string $glue, int|string|null $column = null): string;
271
272    // ---- Iteration (lazy-compatible) ----
273
274    /**
275     * Execute a callback over each item.
276     *
277     * @param  callable(TValue, TKey): mixed $callback
278     * @return  static
279     */
280    public function each(callable $callback): static;
281
282    /**
283     * Get the first item, optionally the first matching a callback.
284     *
285     * @template  TDefault
286     * @param  (callable(TValue, TKey): bool)|null $callback
287     * @param  TDefault $default
288     * @return  TValue|TDefault
289     */
290    public function first(?callable $callback = null, mixed $default = null): mixed;
291
292    /**
293     * Get the last item, optionally the last matching a callback.
294     *
295     * @template  TDefault
296     * @param  (callable(TValue, TKey): bool)|null $callback
297     * @param  TDefault $default
298     * @return  TValue|TDefault
299     */
300    public function last(?callable $callback = null, mixed $default = null): mixed;
301
302    /**
303     * Reset the collection's keys to a sequential 0-based list.
304     *
305     * @return  static<int, TValue>
306     */
307    public function values(): static;
308
309    /**
310     * Get the collection's keys as a new collection.
311     *
312     * @return  static<int, TKey>
313     */
314    public function keys(): static;
315
316    // ---- Selection (lazy-compatible) ----
317
318    /**
319     * Take the first N items.
320     *
321     * @param  int $limit
322     * @return  static
323     */
324    public function take(int $limit): static;
325
326    /**
327     * Skip the first N items.
328     *
329     * @param  int $count
330     * @return  static
331     */
332    public function skip(int $count): static;
333
334    /**
335     * Take a slice of the collection starting at the given offset.
336     *
337     * @param  int $offset
338     * @param  int|null $length
339     * @return  static
340     */
341    public function slice(int $offset, ?int $length = null): static;
342
343    /**
344     * Take items while the callback passes, stopping at the first failure.
345     *
346     * Keys are preserved.
347     *
348     * @param  callable(TValue, TKey): bool $callback
349     * @return  static
350     */
351    public function takeWhile(callable $callback): static;
352
353    /**
354     * Skip items while the callback passes, keeping the rest.
355     *
356     * Only the initial run of passing items is skipped — after the first
357     * failure, every remaining item is kept even if the callback passes
358     * again. Keys are preserved.
359     *
360     * @param  callable(TValue, TKey): bool $callback
361     * @return  static
362     */
363    public function skipWhile(callable $callback): static;
364
365    /**
366     * Take items until the callback passes, stopping at the first success.
367     *
368     * Keys are preserved.
369     *
370     * @param  callable(TValue, TKey): bool $callback
371     * @return  static
372     */
373    public function takeUntil(callable $callback): static;
374
375    /**
376     * Skip items until the callback passes, keeping the rest.
377     *
378     * The item on which the callback first passes is the first kept item.
379     * Keys are preserved.
380     *
381     * @param  callable(TValue, TKey): bool $callback
382     * @return  static
383     */
384    public function skipUntil(callable $callback): static;
385
386    /**
387     * Convert the collection to a plain array.
388     *
389     * Nested collections are recursively converted to arrays. This is a
390     * terminal operation — a lazy collection materializes on call.
391     *
392     * @return  array<TKey, mixed>
393     */
394    public function toArray(): array;
395}