Skip to content

Commit

Permalink
Drop support for PHP 8.0 and make 8.1 the minimum version (#28)
Browse files Browse the repository at this point in the history
Change CI/CD pipelines to test with PHP 8.1, 8.2 and 8.3

Bump PHPUnit to 10.5

Refactor code to make all properties read-only where possible

Add `FilterOperatorXor`

Remove getters from `MapperCallers` and use public read-only properties instead

`AbstractItem::getBuilders` is now an abstract method that should always be implemented in subclasses

Remove useless `catch` blocks in `CollectionTrait`

Refactor some code to use more PHP 8.1 features

Update tests to PHPUnit 10.5

Update documentation
  • Loading branch information
hugo-goncalves-kununu authored Mar 13, 2024
1 parent c601ee3 commit 131f069
Show file tree
Hide file tree
Showing 32 changed files with 254 additions and 178 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ jobs:
strategy:
matrix:
php-version:
- 8.0
- 8.1
- 8.2
- 8.3
dependencies:
- lowest
- highest
Expand Down Expand Up @@ -58,7 +60,7 @@ jobs:

- uses: actions/download-artifact@v4
with:
name: build-8-highest-coverage
name: build-8.1-highest-coverage
path: tests/.results/

- name: Fix Code Coverage Paths
Expand Down
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.idea
.phpunit.cache
.phpunit.result.cache
composer.lock
phpunit.log
tests/.results
vendor
composer.lock
.php_cs.cache
.phpunit.result.cache
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
}
],
"require": {
"php": ">=8.0"
"php": ">=8.1"
},
"require-dev": {
"kununu/scripts": ">=4.0",
"phpunit/phpunit": "^9.6"
"phpunit/phpunit": "^10.5"
},
"autoload": {
"psr-4": {
Expand All @@ -31,8 +31,8 @@
}
},
"scripts": {
"test": "phpunit --no-coverage tests",
"test-coverage": "XDEBUG_MODE=coverage phpunit --coverage-clover tests/.results/coverage.xml --coverage-html tests/.results/html/ tests"
"test": "phpunit --log-events-text phpunit.log --no-coverage --no-logging --no-progress --testsuite Full",
"test-coverage": "XDEBUG_MODE=coverage phpunit --log-events-text phpunit.log --no-progress --testsuite Full"
},
"scripts-descriptions": {
"test": "Run all tests",
Expand Down
6 changes: 6 additions & 0 deletions docs/abstract-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
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.

```php
<?php
declare(strict_types=1);

use Kununu\Collection\AbstractCollection;

final class MyCollection extends AbstractCollection
Expand All @@ -19,6 +22,9 @@ $collection = MyCollection::fromIterable($myData);
Using the same concept as `AbstractCollection` this class extends `ArrayIterator` and add the `FilterableCollectionTrait` to it.

```php
<?php
declare(strict_types=1);

use Kununu\Collection\AbstractFilterableCollection;

final class MyCollection extends AbstractFilterableCollection
Expand Down
41 changes: 29 additions & 12 deletions docs/abstract-item.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ Since many of the times we are building those objects based on data collected fr
The basic structure of a class extending this is the following:

```php
<?php
declare(strict_types=1);

final class MyItem extends AbstractItem
{
protected const PROPERTIES = [
'id',
'name',
'createdAt'
'simpleName',
'verified',
'industryId',
];

public function __construct()
Expand All @@ -26,9 +32,9 @@ final class MyItem extends AbstractItem
protected static function getBuilders(): array
{
return [
'id' => fn(array $data) => $data['id'] ?? null,
'name' => fn(array $data) => $data['name'] ?? null,
'createdAt' => fn(array $data) => $data['createdAt'] ?? null,
'id' => static fn(array $data): ?int => $data['id'] ?? null,
'name' => static fn(array $data): ?string => $data['name'] ?? null,
'createdAt' => static fn(array $data)? DateTime => $data['createdAt'] ?? null,
'simpleName' => self::buildStringGetter('simpleName'),
'verified' => self::buildBoolGetter('verified'),
'industryId' => self::buildIntGetter('industryId'),
Expand Down Expand Up @@ -56,6 +62,9 @@ If you want to use different prefixes for setters/getters you can! Just override
Example:

```php
<?php
declare(strict_types=1);

final class MyItem extends AbstractItem
{
protected const PROPERTIES = [
Expand Down Expand Up @@ -86,6 +95,9 @@ Since all the setters/getters are "magic" we might feel the need to have code hi
Example:

```php
<?php
declare(strict_types=1);

/**
* @method int|null getId()
* @method string|null getName()
Expand All @@ -95,7 +107,7 @@ Example:
* @method MyItem setName(?string $name)
* @method MyItem setCreatedAt(?DateTime $createdAt)
*/
class MyItem extends AbstractItem
final class MyItem extends AbstractItem
{
protected const PROPERTIES = [
'id',
Expand All @@ -110,21 +122,24 @@ class MyItem extends AbstractItem
As said above the class can help you to build your instances from data stored in arrays. Every subclass will have the method `build`.

```php
/**
* @param array $data
*
* @return static
*/
public static function build(array $data): self;
<?php
declare(strict_types=1);

/**
* @param array $data
*
* @return static
*/
public static function build(array $data): self;
```

But in order for it to work your subclass must override the `getBuilders` static method.
But in order for it to work your subclass must implement the `getBuilders` static method.

This method will basically return a map of `'property'` => `callable` to get data for the property:

```php
[
'itemProperty' => fn(array $data) => $valueForTheProperty,
'itemProperty' => static fn(array $data): mixed => $valueForTheProperty,
]
```

Expand Down Expand Up @@ -326,6 +341,8 @@ If `$useSnakeCase` is `true` the `$sourceField` will be converted to snake case

Example:
```php
<?php
declare(strict_types=1);

final class MyItem extends AbstractItem
{
Expand Down
16 changes: 7 additions & 9 deletions docs/autosortable-offsetset-trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ By doing a proper implementation of the `append` method you can auto-sort your c
When appending to an instance of this collection it will automatically sort it (and in this example also only allow one entry per key).

```php
<?php
declare(strict_types=1);

use Kununu\Collection\AbstractCollection;
use Kununu\Collection\AutoSortableOffsetSetTrait;
Expand All @@ -17,16 +19,12 @@ final class MyCollection extends AbstractCollection
{
use AutoSortableOffsetSetTrait;

public function append($value)
public function append($value): void
{
switch (true) {
case is_string($value):
case is_int($value):
$this->offsetSet($value, $value);
break;
default:
parent::append($value);
}
match (true) {
is_int($value) => $this->offsetSet($value, $value),
default => parent::append($value)
};
}
}

Expand Down
7 changes: 5 additions & 2 deletions docs/collection-trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ This applies also to collections that are defined inside a class that is an item
Example:

```php
<?php
declare(strict_types=1);

final class MyTopCollection implements ToArray
{
use CollectionTrait;
Expand All @@ -126,8 +129,8 @@ final class MySubCollection implements ToArray

final class MyTopItem implements ToArray
{
public $name;
public $subCollection;
public string $name;
public MySubCollection $subCollection;

public function toArray(): array
{
Expand Down
12 changes: 9 additions & 3 deletions docs/filterable-collection-trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,13 @@ The `initialValue` is the value to use if you want to perform several operations

The `exitConditionValue` is the value to use if you want to exit the calculation when performing several calculations (like a short circuit evaluation).

By default, the library provides two implementations of this interface: `FilterOperatorAnd` and `FilterOperatorOr`.
By default, the library provides three implementations of this interface: `FilterOperatorAnd`, `FilterOperatorOr` and `FilterOperatorXOr`.

A quick example:
```php
<?php
declare(strict_types=1);

$filter = CompositeFilter(
new FilterOperatorAnd(),
new MyFilter1(),
Expand All @@ -124,6 +127,9 @@ $myFilter1->isSatisfiedBy(...) && $myFilter2->isSatisfiedBy(...) && $myFilter3->
So to wrap it up, on how to filter/group a collection:

```php
<?php
declare(strict_types=1);

$filteredCollection = $collection->filter(
// Filter1 AND Filter2 AND Filter3
new CompositeFilter(
Expand All @@ -145,12 +151,12 @@ $groupByResults = $collection->groupBy(
),
// Second group
new CompositeFilter(
// Filter1 AND Filter3 AND (Filter2 OR Filter4)
// Filter1 AND Filter3 AND (Filter2 XOR Filter4)
new FilterOperatorAnd(),
new MyFilter1(),
new MyFilter3(),
new CompositeFilter(
new FilterOperatorOr(),
new FilterOperatorXor(),
new MyFilter2(),
new MyFilter4()
)
Expand Down
18 changes: 8 additions & 10 deletions docs/mapper.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,17 @@ The `$fnGetValue` closure should receive an instance of your collection item and
### Example

```php
<?php
declare(strict_types=1);

use Kununu\Collection\AbstractCollection;
use Kununu\Collection\Mapper\DefaultMapper;
use Kununu\Collection\Mapper\MapperCallers;

final class MyCollectionItem
{
public $key;
public $value;

public function __construct(int $key, string $value)
public function __construct(public readonly int $key, public readonly string $value)
{
$this->key = $key;
$this->value = $value;
}
}

Expand All @@ -71,8 +69,8 @@ final class MyMapper extends DefaultMapper
{
if (MyCollection::class === $collectionClass) {
return new MapperCallers(
fn(MyCollectionItem $item): int => $item->key,
fn(MyCollectionItem $item): string => $item->value()
fn(MyCollectionItem $item): string => sprintf('ID %s', $item->key),
fn(MyCollectionItem $item): string => $item->value
);
}

Expand All @@ -91,8 +89,8 @@ $map = $mapper->map(
/*
Value of $map:
[
1 => 'Item 1',
2 => 'Item 2'
'ID 1' => 'Item 1',
'ID 2' => 'Item 2'
]
*/

Expand Down
18 changes: 10 additions & 8 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.readthedocs.io/en/9.6/ -->
<!-- https://phpunit.readthedocs.io/en/10.5/ -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.6/phpunit.xsd" bootstrap="vendor/autoload.php"
colors="true" beStrictAboutChangesToGlobalState="true" testdox="true">
<coverage processUncoveredFiles="true">
<include>
<directory>src</directory>
</include>
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" bootstrap="vendor/autoload.php"
colors="true" beStrictAboutChangesToGlobalState="true" testdox="true" cacheDirectory=".phpunit.cache">
<coverage>
<report>
<clover outputFile="tests/.results/tests-clover.xml"/>
<html outputDirectory="tests/.results/html/"/>
</report>
</coverage>
<testsuites>
<testsuite name="Collections Test Suite">
<testsuite name="Full">
<directory>tests</directory>
</testsuite>
</testsuites>
<logging>
<junit outputFile="tests/.results/tests-junit.xml"/>
</logging>
<source>
<include>
<directory suffix=".php">src</directory>
</include>
</source>
</phpunit>
Loading

0 comments on commit 131f069

Please sign in to comment.