Skip to content

Commit

Permalink
Define interfaces for collections
Browse files Browse the repository at this point in the history
Create FromIterable interface

Change AbstractCollection and AbstractFilterableCollection to implement the interfaces

Allow `duplicates` to remove only unique values

Add `keys` and `values` method to collections

Fix tests

Add tests for new code

Update documentation
  • Loading branch information
hugo-goncalves-kununu committed Jul 15, 2024
1 parent 1f54323 commit c868efe
Show file tree
Hide file tree
Showing 23 changed files with 763 additions and 361 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,17 @@ composer test-coverage

## Usage

The library provide three traits that you can add to your custom class extending `ArrayIterator`.
The library defines interfaces to deal with collections and also boilerplate code with default implementations.

It defines interfaces to convert collection items to `array`, `string` and `int` and to compare items.
You can either use the provided traits to your custom class extending `ArrayIterator` or simply expand the abstract collection classes using them.

It has a default implementation for a "basic" collection and also one to filter and group data on your collections (a "filterable" collection).

It also provides some interfaces to filter and group data on your collections and base classes with default implementations.
It defines interfaces to convert collection items to `array`, `string` and `int` and to compare items.

More details:

- [Collection Interfaces](docs/collection-interfaces.md)
- [Collection Trait](docs/collection-trait.md)
- [Filterable Collection Trait](docs/filterable-collection-trait.md)
- [Auto Sortable OffsetSet Trait](docs/autosortable-offsetset-trait.md)
Expand Down
4 changes: 2 additions & 2 deletions docs/abstract-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## AbstractCollection

This is an abstract base class that you can use for your collections. It extends `ArrayIterator` (and already uses the `CollectionTrait`) so you just need to extend it to have a proper collection class.
This is an abstract base class that you can use for your collections. It extends `ArrayIterator` and implements the `Collection` interface (and already uses the `CollectionTrait`) so you just need to extend it to have a proper collection class.

```php
<?php
Expand All @@ -19,7 +19,7 @@ $collection = MyCollection::fromIterable($myData);

## AbstractFilterableCollection

Using the same concept as `AbstractCollection` this class extends `ArrayIterator` and add the `FilterableCollectionTrait` to it.
Using the same concept as `AbstractCollection` this class extends `ArrayIterator` and implements the `FilterableCollection` (and already uses the `FilterableCollectionTrait`).

```php
<?php
Expand Down
194 changes: 194 additions & 0 deletions docs/collection-interfaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Collection Interfaces

The library defines two interfaces for collections.

The first one ([`Collection`](../src/Collection.php)) is a basic "bare-bones" collection.

The second one ([`FilterableCollection`](../src/FilterableCollection.php)) is a "filterable" collection, which allows you to filter and group elements on your collection.

`FilterableCollection` extends `Collection`, so all methods should also be implemented in a `FilterableCollection` (plus the specific methods).

Every collection interface is also extending from `FromIterable` and `ToArray` interfaces.

So they should also implement the following methods:

## fromIterable

```php
public static function fromIterable(iterable $data): self|static;
```

This method should try to create an instance of your collection class with data from a source that is an `iterable` (e.g. an array).

## toArray

```php
public function toArray(): array;
```

This method will convert your collection to a representation of it as an array.

## Collection

The `Collection` interface defines the methods your collection should provide.

### add

```php
public function add(mixed $value): self|static;
```

This method is defined to be a fluent version of `ArrayIterator::append`. To do stuff like:

```php
$collection->add($item1)->add($item2);
```

### diff

```php
public function diff(self $other): self|static;
```

This method will produce a collection with the difference between your collection and another instance.

### duplicates

```php
public function duplicates(bool $strict = true, bool $uniques = false): self|static;
```

This method produces a collection which contains items which occur multiple times in the collection.

- `$strict` parameter allows you to use strict comparison (e.g. if your implementation uses PHP `in_array`).
- `$uniques` parameter allows you to specify if you want to return unique duplicates values instead of all duplicates entries.

### each

```php
public function each(callable $function, bool $rewind = true): self|static;
```

This method will iterate through each item of a collection, optionally rewind it at the end of the iteration, calling an anonymous function where you can do whatever you need with each item.

Callable signature:

```php
function(mixed $element, string|float|int|bool|null $elementKey): void;
```

### empty

```php
public function empty(): bool;
```

Just a shortcut to see if your collection has a count of elements greater than zero.

### has

```php
public function has(mixed $value, bool $strict = true): bool;
```

This method will tell you if your collection contains the given value.

- `$strict` parameter allows you to use strict comparison (e.g. if your implementation uses PHP `in_array`).

### keys

```php
public function keys(): array;
```

This method will return the keys of the collection.

### map

```php
public function map(callable $function, bool $rewind = true): array;
```

This method will map your collection to an array, optionally rewind it at the end of the iteration, calling an anonymous function where you can do whatever you need with each item.

Callable signature:

```php
function(mixed $element, string|float|int|bool|null $elementKey): mixed;
```

### reduce

```php
public function reduce(callable $function, mixed $initial = null, bool $rewind = true): mixed;
```

This method will reduce your collection to a single value, optionally rewind it at the end of the iteration, calling an anonymous function where you can do whatever you need with each item.

Callable signature:

```php
function(mixed $carry, mixed $element, string|float|int|bool|null $elementKey): mixed;
```

### reverse

```php
public function reverse(): self|static;
```

This method will produce a collection with elements of your collection in the reverse order.

### unique

```php
public function unique(): self|static;
```

This method will produce a collection with distinct elements of your collection.

### values

```php
public function values(): array;
```

This method will return the values of the collection.

## FilterableCollection

The `FilterableCollection` interface defines additional methods that your collection should provide in order to filter and/or group elements in it.

### filter

```php
public function filter(CollectionFilter $filter): self|static
```

This will accept a `CollectionFilter` instance (with the definitions of the filter being applied to the collection), and returns a new collection with only the elements that have met the criteria defined in `$filter`.

### groupBy

```php
public function groupBy(bool $removeEmptyGroups, CollectionFilter ...$filters): array
```

This method allows you to apply a series of filters to a collection and group the result by each filter. The `$removeEmptyGroups` flag means if we will remove or keep groups in the result without items.

The result should be returned as an array with the following structure:

```php
[
'filter_1_key' => [
'item_key_1' => item object 1
...
'item_key_N' => item object X
],
'filter_2_key' => [
'item_key_1' => item object 1
...
'item_key_N' => item object Y
],
...
]
```
Loading

0 comments on commit c868efe

Please sign in to comment.