From 147c39e30f0503e9c22b42c9c1e62702368f7416 Mon Sep 17 00:00:00 2001 From: velkuns Date: Mon, 5 Jan 2026 14:11:10 +0100 Subject: [PATCH] Component ORM: PHP 8.5 support - PHP 8.5 support - Fix phpstan error - PHP code style fixes - Update CI - Update Makefile --- .github/workflows/ci.yml | 2 +- .github/workflows/sonarcloud.yml | 4 +- .php-cs-fixer.dist.php | 4 +- CHANGELOG.md | 10 +++++ Makefile | 40 +++++++++++-------- README.md | 2 +- ci/phpmax-compatibility.neon | 2 +- composer.json | 22 +++++----- src/EntityAwareInterface.php | 2 +- src/EntityInterface.php | 2 +- .../Compiler/Field/FieldValidatorService.php | 30 +++++++------- src/Query/InsertBuilder.php | 8 ++-- src/Query/QueryBuilder.php | 22 +++++----- src/Query/SelectBuilder.php | 16 ++++---- src/Traits/CacheAwareTrait.php | 2 +- src/Traits/EntityAwareTrait.php | 2 +- src/Traits/MapperTrait.php | 10 ++++- 17 files changed, 102 insertions(+), 78 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3633fe5..10b872c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.3', '8.4' ] + php-versions: [ '8.3', '8.4', '8.5' ] steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 8aca7aa..9130fbb 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -1,4 +1,4 @@ -name: CI +name: SonarQube on: push: @@ -41,6 +41,6 @@ jobs: run: make php/tests # To generate the coverage report - name: SonarQube Scan - uses: SonarSource/sonarqube-scan-action@v5.2.0 + uses: SonarSource/sonarqube-scan-action@v7 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 87d2ce9..c36d041 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -4,8 +4,8 @@ //~ Rules ->setRules( [ - '@PER-CS2.0' => true, - ] + '@PER-CS3x0' => true, + ], ) //~ Format diff --git a/CHANGELOG.md b/CHANGELOG.md index c34a23b..9460732 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Removed ``` +## [7.1.0] - 2026-01-05 +[7.1.0]: https://github.com/eureka-framework/component-orm/compare/7.0.0...7.1.0 +### Added +- PHP 8.5 support +### Changed +- Fix phpstan error +- PHP code style fixes +- Update CI +- Update Makefile + ## [7.0.0] - 2025-08-25 [7.0.0]: https://github.com/eureka-framework/component-orm/compare/6.1.0...7.0.0 ### Added diff --git a/Makefile b/Makefile index 02253cb..5932d3f 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ .PHONY: validate install update php/deps php/check php/fix php/min-compatibility php/max-compatibility php/phpstan php/analyze php/tests php/test php/testdox ci clean -PHP_VERSION_MIN := 8.3 -PHP_VERSION_MAX := 8.4 - +PHP_MIN_VERSION := "8.3" +PHP_MAX_VERSION := "8.5" +COMPOSER_BIN := composer define header = @if [ -t 1 ]; then printf "\n\e[37m\e[100m \e[104m $(1) \e[0m\n"; else printf "\n### $(1)\n"; fi endef @@ -10,23 +10,23 @@ endef #~ Composer dependency validate: $(call header,Composer Validation) - @composer validate + @${COMPOSER_BIN} validate install: $(call header,Composer Install) - @composer install + @${COMPOSER_BIN} install update: $(call header,Composer Update) - @composer update - @composer bump --dev-only + @${COMPOSER_BIN} update + @${COMPOSER_BIN} bump --dev-only composer.lock: install #~ Vendor binaries dependencies -vendor/bin/php-cs-fixer: -vendor/bin/phpstan: -vendor/bin/phpunit: +vendor/bin/php-cs-fixer: composer.lock +vendor/bin/phpstan: composer.lock +vendor/bin/phpunit: composer.lock #~ Report directories dependencies build/reports/phpunit: @@ -42,24 +42,26 @@ php/deps: composer.json php/check: vendor/bin/php-cs-fixer $(call header,Checking Code Style) - @./vendor/bin/php-cs-fixer check -v --diff - + @XDEBUG_MODE=off ./vendor/bin/php-cs-fixer check php/fix: vendor/bin/php-cs-fixer $(call header,Fixing Code Style) - @./vendor/bin/php-cs-fixer fix -v + @XDEBUG_MODE=off ./vendor/bin/php-cs-fixer fix -v php/min-compatibility: vendor/bin/phpstan build/reports/phpstan - $(call header,Checking PHP ${PHP_VERSION_MIN} compatibility) + $(call header,Checking PHP ${PHP_MIN_VERSION} compatibility) @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/phpmin-compatibility.neon --error-format=table php/max-compatibility: vendor/bin/phpstan build/reports/phpstan #ci - $(call header,Checking PHP ${PHP_VERSION_MAX} compatibility) + $(call header,Checking PHP ${PHP_MAX_VERSION} compatibility) @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/phpmax-compatibility.neon --error-format=table php/analyze: vendor/bin/phpstan build/reports/phpstan #manual & ci $(call header,Running Static Analyze - Pretty tty format) @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --error-format=table +php/clean-tests: + $(call header,Clean previous generated classes from tests) + php/tests: vendor/bin/phpunit build/reports/phpunit #ci $(call header,Running Unit Tests) @XDEBUG_MODE=coverage php ./vendor/bin/phpunit --testsuite=unit --coverage-clover=./build/reports/phpunit/clover.xml --log-junit=./build/reports/phpunit/unit.xml --coverage-php=./build/reports/phpunit/unit.cov --coverage-html=./build/reports/coverage/ --fail-on-warning @@ -78,4 +80,10 @@ clean: $(call header,Cleaning previous build) #manual @if [ "$(shell ls -A ./build)" ]; then rm -rf ./build/*; fi; echo " done" -ci: clean validate install php/deps php/check php/tests php/integration php/min-compatibility php/max-compatibility php/analyze +clean-tests: + $(call header,Cleaning generated classes from tests) #manual + @if [ "$(shell ls -A ./tests/unit/Generated/Entity)" ]; then rm -rf ./tests/unit/Generated/Entity; fi; echo " . Removing entities: done" + @if [ "$(shell ls -A ./tests/unit/Generated/Infrastructure)" ]; then rm -rf ./tests/unit/Generated/Infrastructure; fi; echo " . Removing infrastructure: done" + @if [ "$(shell ls -A ./tests/unit/Generated/Repository)" ]; then rm -rf ./tests/unit/Generated/Repository; fi; echo " . Removing repositories: done" + +ci: clean clean-tests validate install php/deps php/check php/tests php/integration php/min-compatibility php/max-compatibility php/analyze diff --git a/README.md b/README.md index 8aca89c..e8d9070 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # component-orm [![Current version](https://img.shields.io/packagist/v/eureka/component-orm.svg?logo=composer)](https://packagist.org/packages/eureka/component-orm) -[![Supported PHP version](https://img.shields.io/static/v1?logo=php&label=PHP&message=8.3%20-%208.4&color=777bb4)](https://packagist.org/packages/eureka/component-orm) +[![Supported PHP version](https://img.shields.io/static/v1?logo=php&label=PHP&message=>%3D8.3&color=777bb4)](https://packagist.org/packages/eureka/component-orm) ![CI](https://github.com/eureka-framework/component-orm/workflows/CI/badge.svg) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=eureka-framework_component-orm&metric=alert_status)](https://sonarcloud.io/dashboard?id=eureka-framework_component-orm) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=eureka-framework_component-orm&metric=coverage)](https://sonarcloud.io/dashboard?id=eureka-framework_component-orm) diff --git a/ci/phpmax-compatibility.neon b/ci/phpmax-compatibility.neon index 2c7cc0b..085b5a0 100644 --- a/ci/phpmax-compatibility.neon +++ b/ci/phpmax-compatibility.neon @@ -3,7 +3,7 @@ includes: - ./../vendor/phpstan/phpstan-phpunit/rules.neon parameters: - phpVersion: 80400 + phpVersion: 80500 level: 0 paths: - ./../src diff --git a/composer.json b/composer.json index 0c3f840..a902cca 100644 --- a/composer.json +++ b/composer.json @@ -31,24 +31,24 @@ }, "require": { - "php": "8.3.*||8.4.*", + "php": ">=8.3", "ext-pdo": "*", - "eureka/component-database": "^3.4", + "eureka/component-database": "^4.0", "eureka/component-validation": "^6.0", - "eureka/component-console": "^6.3", + "eureka/component-console": "^7.0", "psr/cache": "^1.0||^2.0||^3.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.86.0", - "phpstan/phpstan": "^2.1.22", - "phpstan/phpstan-phpunit": "^2.0.7", - "phpstan/phpstan-strict-rules": "^2.0.6", - "phpunit/phpcov": "^11.0.1", - "phpunit/phpunit": "^12.3.6", - "symfony/cache": "^7.3.2", - "shipmonk/composer-dependency-analyser": "^1.8.3" + "friendsofphp/php-cs-fixer": "^3.92.4", + "phpstan/phpstan": "^2.1.33", + "phpstan/phpstan-phpunit": "^2.0.11", + "phpstan/phpstan-strict-rules": "^2.0.7", + "phpunit/phpcov": "^11.0.3", + "phpunit/phpunit": "^12.5.4", + "symfony/cache": "^7.4.3", + "shipmonk/composer-dependency-analyser": "^1.8.4" } } diff --git a/src/EntityAwareInterface.php b/src/EntityAwareInterface.php index 9e32945..2653a55 100644 --- a/src/EntityAwareInterface.php +++ b/src/EntityAwareInterface.php @@ -35,7 +35,7 @@ public function disableIgnoreNotMappedFields(): static; * @param bool $exists * @return TEntity */ - public function newEntity(\stdClass|null $row = null, bool $exists = false): object; + public function newEntity(?\stdClass $row = null, bool $exists = false): object; /** * Create new entity from array. diff --git a/src/EntityInterface.php b/src/EntityInterface.php index d26f960..826ed4f 100644 --- a/src/EntityInterface.php +++ b/src/EntityInterface.php @@ -78,7 +78,7 @@ public function setExists(bool $exists): static; * @param string|null $property * @return bool */ - public function isUpdated(string|null $property = null): bool; + public function isUpdated(?string $property = null): bool; /** * Reset updated list of properties diff --git a/src/Generator/Compiler/Field/FieldValidatorService.php b/src/Generator/Compiler/Field/FieldValidatorService.php index 5cc2714..99ac28a 100644 --- a/src/Generator/Compiler/Field/FieldValidatorService.php +++ b/src/Generator/Compiler/Field/FieldValidatorService.php @@ -112,21 +112,21 @@ private function getValidatorOptionsFromType(Field $field, Type\TypeInterface $t private function getIntegerOptions(string $typeClass, bool $isUnsigned): array { return match ($typeClass) { - Type\TypeBigint::class => $isUnsigned ? - IntegerValidator::BIGINT_UNSIGNED : - IntegerValidator::BIGINT_SIGNED, - Type\TypeInt::class => $isUnsigned ? - IntegerValidator::INT_UNSIGNED : - IntegerValidator::INT_SIGNED, - Type\TypeMediumint::class => $isUnsigned ? - IntegerValidator::MEDIUMINT_UNSIGNED : - IntegerValidator::MEDIUMINT_SIGNED, - Type\TypeSmallint::class => $isUnsigned ? - IntegerValidator::SMALLINT_UNSIGNED : - IntegerValidator::SMALLINT_SIGNED, - Type\TypeTinyint::class => $isUnsigned ? - IntegerValidator::TINYINT_UNSIGNED : - IntegerValidator::TINYINT_SIGNED, + Type\TypeBigint::class => $isUnsigned + ? IntegerValidator::BIGINT_UNSIGNED + : IntegerValidator::BIGINT_SIGNED, + Type\TypeInt::class => $isUnsigned + ? IntegerValidator::INT_UNSIGNED + : IntegerValidator::INT_SIGNED, + Type\TypeMediumint::class => $isUnsigned + ? IntegerValidator::MEDIUMINT_UNSIGNED + : IntegerValidator::MEDIUMINT_SIGNED, + Type\TypeSmallint::class => $isUnsigned + ? IntegerValidator::SMALLINT_UNSIGNED + : IntegerValidator::SMALLINT_SIGNED, + Type\TypeTinyint::class => $isUnsigned + ? IntegerValidator::TINYINT_UNSIGNED + : IntegerValidator::TINYINT_SIGNED, default => [], }; } diff --git a/src/Query/InsertBuilder.php b/src/Query/InsertBuilder.php index 83a6b21..d6eeb77 100644 --- a/src/Query/InsertBuilder.php +++ b/src/Query/InsertBuilder.php @@ -56,10 +56,10 @@ public function getQuery(bool $onDuplicateUpdate = false, bool $onDuplicateIgnor $this->appendUpdateValues(); } - return 'INSERT ' . $onDuplicateIgnoreClause . - 'INTO ' . $this->repository->getTable() . - $this->getQuerySet() . - $this->getQueryDuplicateUpdate() + return 'INSERT ' . $onDuplicateIgnoreClause + . 'INTO ' . $this->repository->getTable() + . $this->getQuerySet() + . $this->getQueryDuplicateUpdate() ; } diff --git a/src/Query/QueryBuilder.php b/src/Query/QueryBuilder.php index 13c4466..725e23c 100644 --- a/src/Query/QueryBuilder.php +++ b/src/Query/QueryBuilder.php @@ -24,13 +24,13 @@ class QueryBuilder extends SelectBuilder */ public function getQuery(bool $usePrefix = false, string $prefix = '', bool $onlyPrimaryKey = false): string { - return 'SELECT ' . $this->getQueryFieldsPersonalized() . - $this->getQueryFromPersonalized() . - $this->getQueryWhere() . - $this->getQueryGroupBy() . - $this->getQueryHaving() . - $this->getQueryOrderBy() . - $this->getQueryLimit() + return 'SELECT ' . $this->getQueryFieldsPersonalized() + . $this->getQueryFromPersonalized() + . $this->getQueryWhere() + . $this->getQueryGroupBy() + . $this->getQueryHaving() + . $this->getQueryOrderBy() + . $this->getQueryLimit() ; } @@ -43,10 +43,10 @@ public function getQuery(bool $usePrefix = false, string $prefix = '', bool $onl */ public function getQueryCount(string $field = '*'): string { - return 'SELECT COUNT(' . $field . ') AS nb_results' . - $this->getQueryFrom($this->repository) . - $this->getQueryWhere() . - $this->getQueryGroupBy() + return 'SELECT COUNT(' . $field . ') AS nb_results' + . $this->getQueryFrom($this->repository) + . $this->getQueryWhere() + . $this->getQueryGroupBy() ; } } diff --git a/src/Query/SelectBuilder.php b/src/Query/SelectBuilder.php index 9e14885..ffd11be 100644 --- a/src/Query/SelectBuilder.php +++ b/src/Query/SelectBuilder.php @@ -59,13 +59,13 @@ public function clear(bool $forNotCached = false): static */ public function getQuery(bool $usePrefix = false, string $prefix = '', bool $onlyPrimaryKey = false): string { - return 'SELECT ' . $this->getQueryFields($this->repository, $usePrefix, $onlyPrimaryKey) . - $this->getQueryFrom($this->repository) . - $this->getQueryJoin() . - $this->getQueryWhere() . - $this->getQueryGroupBy() . - $this->getQueryHaving() . - $this->getQueryOrderBy() . - $this->getQueryLimit(); + return 'SELECT ' . $this->getQueryFields($this->repository, $usePrefix, $onlyPrimaryKey) + . $this->getQueryFrom($this->repository) + . $this->getQueryJoin() + . $this->getQueryWhere() + . $this->getQueryGroupBy() + . $this->getQueryHaving() + . $this->getQueryOrderBy() + . $this->getQueryLimit(); } } diff --git a/src/Traits/CacheAwareTrait.php b/src/Traits/CacheAwareTrait.php index d8fb7c3..ae57d7a 100644 --- a/src/Traits/CacheAwareTrait.php +++ b/src/Traits/CacheAwareTrait.php @@ -72,7 +72,7 @@ public function disableCacheOnRead(): static * @param CacheItemPoolInterface|null $cache * @return static */ - protected function setCache(CacheItemPoolInterface|null $cache = null): static + protected function setCache(?CacheItemPoolInterface $cache = null): static { $this->cache = $cache; diff --git a/src/Traits/EntityAwareTrait.php b/src/Traits/EntityAwareTrait.php index c3aafde..45e9785 100644 --- a/src/Traits/EntityAwareTrait.php +++ b/src/Traits/EntityAwareTrait.php @@ -61,7 +61,7 @@ public function setEntityClass(string $entityClass): static * * @phpstan-return TEntity */ - public function newEntity(\stdClass|null $row = null, bool $exists = false): object + public function newEntity(?\stdClass $row = null, bool $exists = false): object { $entity = new $this->entityClass($this, $this->getValidatorFactory(), $this->getValidatorEntityFactory()); diff --git a/src/Traits/MapperTrait.php b/src/Traits/MapperTrait.php index 53ce3f3..0f3a5d7 100644 --- a/src/Traits/MapperTrait.php +++ b/src/Traits/MapperTrait.php @@ -191,7 +191,11 @@ public function query(QueryBuilderInterface $queryBuilder): array ); } - $index = !empty($indexedBy) ? $row->{$indexedBy} : $id++; + $index = $indexedBy !== '' ? $row->{$indexedBy} : $id++; + if (!\is_string($index) && !\is_int($index)) { + $index = $id++; + } + $entity = $this->newEntity($row, true); $collection[$index] = $entity; } @@ -501,7 +505,9 @@ private function setIndexFieldsOnCollection(string $listIndexedBy, array $rawCol $nameMap = $this->getNamesMap($listIndexedBy); $getter = $nameMap['get']; foreach ($rawCollection as $item) { - $collection[$item->$getter()] = $item; + /** @var string|int $index */ + $index = $item->$getter(); + $collection[$index] = $item; } return $collection;