Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
/LICENSE export-ignore
/Makefile export-ignore
/README.md export-ignore
/phpmd.xml export-ignore
/phpunit.xml export-ignore
/phpstan.neon.dist export-ignore
/infection.json.dist export-ignore
Expand Down
68 changes: 47 additions & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,42 @@ permissions:
contents: read

env:
PHP_VERSION: '8.3'
PHP_VERSION: '8.5'

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Configure PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
extensions: bcmath
tools: composer:2

- name: Validate composer.json
run: composer validate --no-interaction

- name: Install dependencies
run: composer install --no-progress --optimize-autoloader --prefer-dist --no-interaction

- name: Upload vendor and composer.lock as artifact
uses: actions/upload-artifact@v6
with:
name: vendor-artifact
path: |
vendor
composer.lock

auto-review:
name: Auto review
runs-on: ubuntu-latest
needs: build

steps:
- name: Checkout
Expand All @@ -22,16 +52,22 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
extensions: bcmath
tools: composer:2

- name: Install dependencies
run: composer update --no-progress --optimize-autoloader
- name: Download vendor artifact from build
uses: actions/download-artifact@v7
with:
name: vendor-artifact
path: .

- name: Run review
run: composer review

tests:
name: Tests
runs-on: ubuntu-latest
needs: auto-review

steps:
- name: Checkout
Expand All @@ -41,24 +77,14 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ env.PHP_VERSION }}
extensions: bcmath
tools: composer:2

- name: Install dependencies
run: composer update --no-progress --optimize-autoloader

- name: Clean up Docker
run: docker system prune -f

- name: Create Docker network
run: docker network create tiny-blocks

- name: Create Docker volume for migrations
run: docker volume create test-adm-migrations
- name: Download vendor artifact from build
uses: actions/download-artifact@v7
with:
name: vendor-artifact
path: .

- name: Run tests
run: |
docker run --network=tiny-blocks \
-v ${PWD}:/app \
-v ${PWD}/tests/Integration/Database/Migrations:/test-adm-migrations \
-v /var/run/docker.sock:/var/run/docker.sock \
-w /app \
gustavofreze/php:${{ env.PHP_VERSION }} bash -c "composer tests"
run: composer tests
60 changes: 45 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,38 +1,68 @@
ifeq ($(OS),Windows_NT)
PWD := $(shell cd)
else
PWD := $(shell pwd -L)
endif

PWD := $(CURDIR)
ARCH := $(shell uname -m)
PLATFORM :=

ifeq ($(ARCH),arm64)
PLATFORM := --platform=linux/amd64
endif

DOCKER_RUN = docker run ${PLATFORM} --rm -it --net=host -v ${PWD}:/app -w /app gustavofreze/php:8.3
DOCKER_RUN = docker run ${PLATFORM} --rm -it --net=host -v ${PWD}:/app -w /app gustavofreze/php:8.5-alpine

.PHONY: configure test test-file test-no-coverage review show-reports clean
RESET := \033[0m
GREEN := \033[0;32m
YELLOW := \033[0;33m

configure:
.DEFAULT_GOAL := help

.PHONY: configure
configure: ## Configure development environment
@${DOCKER_RUN} composer update --optimize-autoloader

test:
.PHONY: test
test: ## Run all tests with coverage
@${DOCKER_RUN} composer tests

test-file:
.PHONY: test-file
test-file: ## Run tests for a specific file (usage: make test-file FILE=path/to/file)
@${DOCKER_RUN} composer test-file ${FILE}

test-no-coverage:
.PHONY: test-no-coverage
test-no-coverage: ## Run all tests without coverage
@${DOCKER_RUN} composer tests-no-coverage

review:
.PHONY: review
review: ## Run static code analysis
@${DOCKER_RUN} composer review

show-reports:
.PHONY: show-reports
show-reports: ## Open static analysis reports (e.g., coverage, lints) in the browser
@sensible-browser report/coverage/coverage-html/index.html report/coverage/mutation-report.html

clean:
.PHONY: clean
clean: ## Remove dependencies and generated artifacts
@sudo chown -R ${USER}:${USER} ${PWD}
@rm -rf report vendor .phpunit.cache *.lock

.PHONY: help
help: ## Display this help message
@echo "Usage: make [target]"
@echo ""
@echo "$$(printf '$(GREEN)')Setup$$(printf '$(RESET)')"
@grep -E '^(configure):.*?## .*$$' $(MAKEFILE_LIST) \
| awk 'BEGIN {FS = ":.*? ## "}; {printf "$(YELLOW)%-25s$(RESET) %s\n", $$1, $$2}'
@echo ""
@echo "$$(printf '$(GREEN)')Testing$$(printf '$(RESET)')"
@grep -E '^(test|test-file|test-no-coverage):.*?## .*$$' $(MAKEFILE_LIST) \
| awk 'BEGIN {FS = ":.*?## "}; {printf "$(YELLOW)%-25s$(RESET) %s\n", $$1, $$2}'
@echo ""
@echo "$$(printf '$(GREEN)')Quality$$(printf '$(RESET)')"
@grep -E '^(review):.*?## .*$$' $(MAKEFILE_LIST) \
| awk 'BEGIN {FS = ":.*?## "}; {printf "$(YELLOW)%-25s$(RESET) %s\n", $$1, $$2}'
@echo ""
@echo "$$(printf '$(GREEN)')Reports$$(printf '$(RESET)')"
@grep -E '^(show-reports):.*?## .*$$' $(MAKEFILE_LIST) \
| awk 'BEGIN {FS = ":.*?## "}; {printf "$(YELLOW)%-25s$(RESET) %s\n", $$1, $$2}'
@echo ""
@echo "$$(printf '$(GREEN)')Cleanup$$(printf '$(RESET)')"
@grep -E '^(clean):.*?## .*$$' $(MAKEFILE_LIST) \
| awk 'BEGIN {FS = ":.*?## "}; {printf "$(YELLOW)%-25s$(RESET) %s\n", $$1, $$2}'
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ use TinyBlocks\Mapper\KeyPreservation;

$collection = Collection::createFrom(elements: [1, 2, 3, 4, 5])
->add(elements: [6, 7])
->filter(predicates: fn(int $value): bool => $value > 3)
->filter(predicates: static fn(int $value): bool => $value > 3)
->sort(order: Order::ASCENDING_VALUE)
->map(transformations: fn(int $value): int => $value * 2)
->map(transformations: static fn(int $value): int => $value * 2)
->toArray(keyPreservation: KeyPreservation::DISCARD);

# Output: [8, 10, 12, 14]
Expand Down Expand Up @@ -193,7 +193,7 @@ elements, or finding elements that match a specific condition.
- `findBy`: Finds the first element that matches one or more predicates.

```php
$collection->findBy(predicates: fn(CryptoCurrency $crypto): bool => $crypto->symbol === 'ETH');
$collection->findBy(predicates: static fn(CryptoCurrency $crypto): bool => $crypto->symbol === 'ETH');
```

<div id='comparing'></div>
Expand Down Expand Up @@ -261,7 +261,7 @@ combining elements.
This method is helpful for accumulating results, like summing or concatenating values.

```php
$collection->reduce(aggregator: fn(float $carry, float $amount): float => $carry + $amount, initial: 0.0)
$collection->reduce(aggregator: static fn(float $carry, float $amount): float => $carry + $amount, initial: 0.0)
```

<div id='transforming'></div>
Expand All @@ -276,15 +276,15 @@ These methods allow the Collection's elements to be transformed or converted int
The method is helpful for performing side effects, such as logging or adding elements to another collection.

```php
$collection->each(actions: fn(Invoice $invoice): void => $collectionB->add(elements: new InvoiceSummary(amount: $invoice->amount, customer: $invoice->customer)));
$collection->each(actions: static fn(Invoice $invoice): void => $collectionB->add(elements: new InvoiceSummary(amount: $invoice->amount, customer: $invoice->customer)));
```

#### Grouping elements

- `groupBy`: Groups the elements in the Collection based on the provided grouping criterion.

```php
$collection->groupBy(grouping: fn(Amount $amount): string => $amount->currency->name);
$collection->groupBy(grouping: static fn(Amount $amount): string => $amount->currency->name);
```

#### Mapping elements
Expand All @@ -293,7 +293,7 @@ These methods allow the Collection's elements to be transformed or converted int
elements.

```php
$collection->map(transformations: fn(int $value): int => $value * 2);
$collection->map(transformations: static fn(int $value): int => $value * 2);
```

#### Flattening elements
Expand Down
21 changes: 9 additions & 12 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,24 @@
}
},
"require": {
"php": "^8.3",
"tiny-blocks/mapper": "^1.2"
"php": "^8.5",
"tiny-blocks/mapper": "1.2.*"
},
"require-dev": {
"phpmd/phpmd": "^2.15",
"phpunit/phpunit": "^12.1",
"phpunit/phpunit": "^11.5",
"phpstan/phpstan": "^2.1",
"infection/infection": "^0.32",
"squizlabs/php_codesniffer": "^3.13"
},
"scripts": {
"test": "phpunit -d memory_limit=2G --configuration phpunit.xml tests",
"phpcs": "phpcs --standard=PSR12 --extensions=php ./src",
"phpmd": "phpmd ./src text phpmd.xml --suffixes php --ignore-violations-on-exit",
"phpstan": "phpstan analyse -c phpstan.neon.dist --quiet --no-progress",
"test-file": "phpunit --configuration phpunit.xml --no-coverage --filter",
"mutation-test": "infection --threads=max --logger-html=report/coverage/mutation-report.html --coverage=report/coverage",
"test-no-coverage": "phpunit --configuration phpunit.xml --no-coverage tests",
"test": "php -d memory_limit=2G ./vendor/bin/phpunit --configuration phpunit.xml tests",
"phpcs": "php ./vendor/bin/phpcs --standard=PSR12 --extensions=php ./src",
"phpstan": "php ./vendor/bin/phpstan analyse -c phpstan.neon.dist --quiet --no-progress",
"test-file": "php ./vendor/bin/phpunit --configuration phpunit.xml --no-coverage --filter",
"mutation-test": "php ./vendor/bin/infection --threads=max --logger-html=report/coverage/mutation-report.html --coverage=report/coverage",
"test-no-coverage": "php ./vendor/bin/phpunit --configuration phpunit.xml --no-coverage tests",
"review": [
"@phpcs",
"@phpmd",
"@phpstan"
],
"tests": [
Expand Down
59 changes: 0 additions & 59 deletions phpmd.xml

This file was deleted.

1 change: 1 addition & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ parameters:
- '#Unsafe usage of new static#'
- '#does not specify its types#'
- '#type specified in iterable type#'
- '#Generator expects key type#'
reportUnmatchedIgnoredErrors: false
26 changes: 16 additions & 10 deletions src/Internal/Operations/Filter/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,24 @@
{
private array $predicates;

private Closure $compiledPredicate;

private function __construct(?Closure ...$predicates)
{
$this->predicates = array_filter($predicates);

$buildCompositePredicate = static fn(array $predicates): Closure => static fn(
mixed $value,
mixed $key
): bool => array_all(
$predicates,
static fn(Closure $predicate): bool => $predicate($value, $key)
);

$this->compiledPredicate = match (count($this->predicates)) {
0 => static fn(mixed $value, mixed $key): bool => (bool)$value,
default => $buildCompositePredicate($this->predicates)
};
}

public static function from(?Closure ...$predicates): Filter
Expand All @@ -24,16 +39,7 @@ public static function from(?Closure ...$predicates): Filter

public function apply(iterable $elements): Generator
{
$predicate = $this->predicates
? function (mixed $value, mixed $key): bool {
foreach ($this->predicates as $predicate) {
if (!$predicate($value, $key)) {
return false;
}
}
return true;
}
: static fn(mixed $value): bool => (bool)$value;
$predicate = $this->compiledPredicate;

foreach ($elements as $key => $value) {
if ($predicate($value, $key)) {
Expand Down
Loading