diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1744b75..3633fe5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,17 +7,17 @@ on: branches: [ master ] jobs: - build: + ci: runs-on: ubuntu-latest strategy: matrix: - php-versions: [ '8.1', '8.2', '8.3' ] + php-versions: [ '8.3', '8.4' ] steps: - uses: actions/checkout@v4 with: - fetch-depth: 0 # To avoid "Shallow clone detected" error in SonarCloud report + fetch-depth: 0 #~ PHP Setup - name: Setup PHP ${{ matrix.php-versions }} @@ -48,29 +48,18 @@ jobs: #~ CI part - name: Dependencies - run: make deps + run: make php/deps - name: Check Code Style - run: make phpcs + run: make php/check - name: Units Tests - run: make tests + run: make php/tests - name: Fix unit tests report path run: | sed -i 's+'$GITHUB_WORKSPACE'+/github/workspace+g' build/reports/phpunit/clover.xml sed -i 's+'$GITHUB_WORKSPACE'+/github/workspace+g' build/reports/phpunit/unit.xml - - name: PHP 8.1 Compatibility - run: make php81compatibility - - - name: PHP 8.3 Compatibility - run: make php83compatibility - - name: PHP Static Analyze - run: make analyze - - - name: SonarCloud Scan - uses: SonarSource/sonarqube-scan-action@v5.1.0 - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: make php/analyze diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..8aca7aa --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,46 @@ +name: CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + sonarcloud: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # To avoid "Shallow clone detected" error in SonarCloud report + + #~ PHP Setup + - name: Setup PHP 8.3 # Minimum version + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + + #~ Composer Cache + - name: Get Composer Cache Directory + id: composer-cache + run: | + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - uses: actions/cache@v3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install dependencies + if: steps.composer-cache.outputs.cache-hit != 'true' + run: make install + + - name: Units Tests + run: make php/tests # To generate the coverage report + + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@v5.2.0 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.gitignore b/.gitignore index 29d6d41..583f3bb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,6 @@ composer.lock #~ Tests /build/* -.phpunit.result.cache -.phpunit.cache /tests/unit/Generated/* !/tests/unit/Generated/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e97cdd..c34a23b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,26 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ``` ## [template] -[template]: https://github.com/eureka-framework/component-orm/compare/6.0.0...master +[template]: https://github.com/eureka-framework/component-orm/compare/7.0.0...master ### Changed ### Added ### Removed ``` +## [7.0.0] - 2025-08-25 +[7.0.0]: https://github.com/eureka-framework/component-orm/compare/6.1.0...7.0.0 +### Added +- PHP 8.4 support +### Removed +- Drop support for PHP 8.1, 8.2 +### Changed +- Improve some phpdoc typing +- Fix some CS issues in generated classes +- Fix some php 8.4 deprecations +- Dependencies updates + +--- + ## [6.1.0] - 2025-05-14 [6.1.0]: https://github.com/eureka-framework/component-orm/compare/6.0.3...6.1.0 ### Added diff --git a/Makefile b/Makefile index b3857ec..02253cb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,7 @@ -.PHONY: validate install update deps phpcs phpcsf php81compatibility php83compatibility phpstan analyze tests testdox ci clean build/reports/phpunit build/reports/phpcs build/reports/phpstan +.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 define header = @if [ -t 1 ]; then printf "\n\e[37m\e[100m \e[104m $(1) \e[0m\n"; else printf "\n### $(1)\n"; fi @@ -29,56 +32,50 @@ vendor/bin/phpunit: build/reports/phpunit: @mkdir -p build/reports/phpunit -build/reports/phpcs: - @mkdir -p build/reports/cs - build/reports/phpstan: @mkdir -p build/reports/phpstan #~ main commands -deps: composer.json +php/deps: composer.json $(call header,Checking Dependencies) - @XDEBUG_MODE=off ./vendor/bin/composer-require-checker check + @XDEBUG_MODE=off ./vendor/bin/composer-dependency-analyser --config ./ci/composer-dependency-analyser.php # for shadow, unused required dependencies and ext-* missing dependencies -phpcs: vendor/bin/php-cs-fixer build/reports/phpcs +php/check: vendor/bin/php-cs-fixer $(call header,Checking Code Style) - @./vendor/bin/php-cs-fixer check + @./vendor/bin/php-cs-fixer check -v --diff -phpcsf: vendor/bin/php-cs-fixer +php/fix: vendor/bin/php-cs-fixer $(call header,Fixing Code Style) @./vendor/bin/php-cs-fixer fix -v -php81compatibility: vendor/bin/phpstan build/reports/phpstan - $(call header,Checking PHP 8.1 compatibility) - @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/php81-compatibility.neon --error-format=table +php/min-compatibility: vendor/bin/phpstan build/reports/phpstan + $(call header,Checking PHP ${PHP_VERSION_MIN} compatibility) + @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/phpmin-compatibility.neon --error-format=table -php83compatibility: vendor/bin/phpstan build/reports/phpstan - $(call header,Checking PHP 8.3 compatibility) - @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/php83-compatibility.neon --error-format=table +php/max-compatibility: vendor/bin/phpstan build/reports/phpstan #ci + $(call header,Checking PHP ${PHP_VERSION_MAX} compatibility) + @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --configuration=./ci/phpmax-compatibility.neon --error-format=table -phpstan: vendor/bin/phpstan build/reports/phpstan - $(call header,Running Static Analyze) - @XDEBUG_MODE=off ./vendor/bin/phpstan analyse --error-format=checkstyle > ./build/reports/phpstan/phpstan.xml - -analyze: vendor/bin/phpstan build/reports/phpstan +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 -tests: vendor/bin/phpunit build/reports/phpunit #ci +php/tests: vendor/bin/phpunit build/reports/phpunit #ci $(call header,Running Unit Tests) - @rm -rf ./tests/unit/Generated/Entity ./tests/unit/Generated/Infrastructure ./tests/unit/Generated/Repository - @XDEBUG_MODE=coverage php -dzend_extension=xdebug.so ./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 + @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 + +php/test: php/tests -integration: vendor/bin/phpunit build/reports/phpunit #manual +php/integration: vendor/bin/phpunit build/reports/phpunit #manual $(call header,Running Integration Tests) - @XDEBUG_MODE=coverage php -dzend_extension=xdebug.so ./vendor/bin/phpunit --testsuite=integration --fail-on-warning + @XDEBUG_MODE=coverage php ./vendor/bin/phpunit --testsuite=integration --fail-on-warning -testdox: vendor/bin/phpunit #manual +php/testdox: vendor/bin/phpunit #manual $(call header,Running Unit Tests (Pretty format)) - @XDEBUG_MODE=coverage php -dzend_extension=xdebug.so ./vendor/bin/phpunit --testsuite=unit --fail-on-warning --testdox + @XDEBUG_MODE=coverage php ./vendor/bin/phpunit --testsuite=unit --fail-on-warning --testdox clean: - $(call header,Cleaning previous build) + $(call header,Cleaning previous build) #manual @if [ "$(shell ls -A ./build)" ]; then rm -rf ./build/*; fi; echo " done" -ci: clean validate deps install phpcs tests integration php81compatibility php83compatibility analyze +ci: clean 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 1888039..cc74fd4 100644 --- a/README.md +++ b/README.md @@ -329,27 +329,27 @@ interface PostRepositoryInterface extends RepositoryInterface You can run tests on your side with following commands: ```bash -make tests # run tests with coverage -make testdox # run tests without coverage reports but with prettified output +make php/tests # run tests with coverage +make php/test # run tests with coverage +make php/testdox # run tests without coverage reports but with prettified output ``` You also can run code style check or code style fixes with following commands: ```bash -make phpcs # run checks on check style -make phpcbf # run check style auto fix +make php/check # run checks on check style +make php/fix # run check style auto fix ``` To perform a static analyze of your code (with phpstan, lvl 9 at default), you can use the following command: ```bash -make phpstan -make analyze # Same as phpstan but with CLI output as table +make php/analyze # Same as phpstan but with CLI output as table ``` To ensure you code still compatible with current supported version and futures versions of php, you need to run the following commands (both are required for full support): ```bash -make php74compatibility # run compatibility check on current minimal version of php we support -make php81compatibility # run compatibility check on last version of php we will support in future +make php/min-compatibility # run compatibility check on current minimal version of php we support +make php/max-compatibility # run compatibility check on last version of php we will support in future ``` And the last "helper" commands, you can run before commit and push is: diff --git a/ci/composer-dependency-analyser.php b/ci/composer-dependency-analyser.php new file mode 100644 index 0000000..79b92af --- /dev/null +++ b/ci/composer-dependency-analyser.php @@ -0,0 +1,14 @@ +addPathToScan(__DIR__ . '/../src', isDev: false) + ->addPathToScan(__DIR__ . '/../tests', isDev: true) + ->ignoreUnknownClassesRegex('`Eureka\\\\Component\\\\Orm\\\\Tests\\\\Unit\\\\Generated.+`') +; + + +return $config; diff --git a/ci/php81-compatibility.neon b/ci/phpmax-compatibility.neon similarity index 85% rename from ci/php81-compatibility.neon rename to ci/phpmax-compatibility.neon index e523201..2c7cc0b 100644 --- a/ci/php81-compatibility.neon +++ b/ci/phpmax-compatibility.neon @@ -3,11 +3,10 @@ includes: - ./../vendor/phpstan/phpstan-phpunit/rules.neon parameters: - phpVersion: 80100 + phpVersion: 80400 level: 0 paths: - ./../src - - ./../scripts - ./../tests bootstrapFiles: diff --git a/ci/php83-compatibility.neon b/ci/phpmin-compatibility.neon similarity index 92% rename from ci/php83-compatibility.neon rename to ci/phpmin-compatibility.neon index 375595f..ac7cd7b 100644 --- a/ci/php83-compatibility.neon +++ b/ci/phpmin-compatibility.neon @@ -7,7 +7,6 @@ parameters: level: 0 paths: - ./../src - - ./../scripts - ./../tests bootstrapFiles: diff --git a/composer.json b/composer.json index 3b69a63..0c3f840 100644 --- a/composer.json +++ b/composer.json @@ -31,25 +31,24 @@ }, "require": { - "php": "8.1.*||8.2.*||8.3.*", + "php": "8.3.*||8.4.*", "ext-pdo": "*", - "eureka/component-database": "^3.2", - "eureka/component-validation": "^5.2", - "eureka/component-console": "^6.1.0", + "eureka/component-database": "^3.4", + "eureka/component-validation": "^6.0", + "eureka/component-console": "^6.3", - "psr/cache": "^1.0||^2.0||^3.0", - "psr/log": "^1.1||^2.0||^3.0" + "psr/cache": "^1.0||^2.0||^3.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.75.0", - "maglnet/composer-require-checker": "^3.8||^4.7.1", - "phpstan/phpstan": "^1.12.23", - "phpstan/phpstan-phpunit": "^1.4.2", - "phpstan/phpstan-strict-rules": "^1.6.2", - "phpunit/phpcov": "^9.0.2", - "phpunit/phpunit": "^10.5.45", - "symfony/cache": "^5.4.0||^6.4.20" + "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" } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 8f503da..4eaa195 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,9 +1,10 @@ includes: - ./vendor/phpstan/phpstan-phpunit/extension.neon - ./vendor/phpstan/phpstan-phpunit/rules.neon + #- ./vendor/phpstan/phpstan-strict-rules/rules.neon # For next major release parameters: - phpVersion: 80100 # PHP 8.1 - Current minimal version supported + phpVersion: 80300 level: max paths: - ./src @@ -15,3 +16,18 @@ parameters: ignoreErrors: - identifier: missingType.generics + - + path: 'src/Traits/EntityAwareTrait.php' + identifier: argument.type + count: 8 + - + path: 'src/Traits/MapperTrait.php' + identifier: argument.type + count: 8 + - + path: 'src/Generator/Compiler/MapperCompiler.php' + identifier: instanceof.alwaysTrue + count: 2 + - + path: 'tests/unit/' + identifier: staticMethod.alreadyNarrowedType diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 0662af6..49e04d0 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,28 +2,22 @@ - - - ./tests/unit - - + cacheDirectory="build/.phpunit.cache" +> ./src + + + + ./tests/unit + + + ./tests/integration + + + diff --git a/src/EntityAwareInterface.php b/src/EntityAwareInterface.php index 21c146b..9e32945 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 $row = null, bool $exists = false): object; + public function newEntity(\stdClass|null $row = null, bool $exists = false): object; /** * Create new entity from array. diff --git a/src/EntityInterface.php b/src/EntityInterface.php index 6305e83..d26f960 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 $property = null): bool; + public function isUpdated(string|null $property = null): bool; /** * Reset updated list of properties diff --git a/src/Generator/Compiler/AbstractClassCompiler.php b/src/Generator/Compiler/AbstractClassCompiler.php index ed36dec..3d930d4 100644 --- a/src/Generator/Compiler/AbstractClassCompiler.php +++ b/src/Generator/Compiler/AbstractClassCompiler.php @@ -18,15 +18,13 @@ use Eureka\Component\Orm\Generator\Compiler\Field\FieldValidatorService; /** - * Class AbstractClassCompiler - * - * @author Romain Cottard + * @phpstan-import-type FieldType from Field */ class AbstractClassCompiler extends AbstractCompiler { - protected const TYPE_REPOSITORY = 'repository'; - protected const TYPE_MAPPER = 'mapper'; - protected const TYPE_ENTITY = 'entity'; + protected const string TYPE_REPOSITORY = 'repository'; + protected const string TYPE_MAPPER = 'mapper'; + protected const string TYPE_ENTITY = 'entity'; /** @var string $type */ private string $type; @@ -70,7 +68,7 @@ public function initFields(): self $this->fields = []; while (false !== ($column = $statement->fetch(\PDO::FETCH_OBJ))) { - /** @var \stdClass $column */ + /** @var FieldType $column */ $this->fields[] = new Field($column, $this->config->getDbPrefix(), $this->config->getValidation()); } diff --git a/src/Generator/Compiler/AbstractCompiler.php b/src/Generator/Compiler/AbstractCompiler.php index bb52a36..c192e7d 100644 --- a/src/Generator/Compiler/AbstractCompiler.php +++ b/src/Generator/Compiler/AbstractCompiler.php @@ -55,7 +55,7 @@ public function __construct(array $templates) */ public function setVerbose(bool $verbose): self { - $this->verbose = (bool) $verbose; + $this->verbose = $verbose; return $this; } @@ -85,7 +85,12 @@ protected function renderTemplate(string $template, Context $context): string $content = $this->readTemplate($template); //~ Replace template vars - $content = str_replace($context->getKeys(), $context->getValues(), $content); + $content = str_replace( + $context->getKeys(), + \array_map(fn($value) => is_scalar($value) ? (string) $value : '', $context->getValues()), + $content, + ); + return str_replace(["\n\n\n", " }\n\n}"], ["\n\n", " }\n}"], $content); // clean double empty lines } diff --git a/src/Generator/Compiler/Context.php b/src/Generator/Compiler/Context.php index db4156e..caf389a 100644 --- a/src/Generator/Compiler/Context.php +++ b/src/Generator/Compiler/Context.php @@ -70,7 +70,7 @@ public function merge(Context $context): self */ public function getKeys(): array { - return array_keys($this->context); + return \array_keys($this->context); } /** @@ -78,7 +78,7 @@ public function getKeys(): array */ public function getValues(): array { - return array_values($this->context); + return \array_values($this->context); } /** diff --git a/src/Generator/Compiler/EntityCompiler.php b/src/Generator/Compiler/EntityCompiler.php index 39ccec9..1d27ee5 100644 --- a/src/Generator/Compiler/EntityCompiler.php +++ b/src/Generator/Compiler/EntityCompiler.php @@ -60,7 +60,7 @@ protected function updateContext(Context $context, bool $isAbstract = false): Co /** @var string $repositoryName */ $repositoryName = $context->get('class.repository'); $context->add('entity.uses', [ - "use {$this->config->getBaseNamespaceForRepository()}\\{$repositoryName};", + "{$this->config->getBaseNamespaceForRepository()}\\{$repositoryName}" => "use {$this->config->getBaseNamespaceForRepository()}\\{$repositoryName};", ]); $compiledTemplate = [ diff --git a/src/Generator/Compiler/Field/Field.php b/src/Generator/Compiler/Field/Field.php index f2dc400..72e30ff 100644 --- a/src/Generator/Compiler/Field/Field.php +++ b/src/Generator/Compiler/Field/Field.php @@ -14,6 +14,17 @@ use Eureka\Component\Orm\Exception\GeneratorException; use Eureka\Component\Orm\Generator\Type; +/** + * @phpstan-type FieldType object{ + * Field: string, + * Key: string, + * Type: string, + * Comment: string, + * Null: string, + * Default: string, + * Extra: string, + * }&\stdClass + */ class Field { protected string $name = ''; @@ -35,7 +46,7 @@ class Field /** * Field constructor. * - * @param \stdClass $field + * @param FieldType $field * @param string[] $dbPrefixes * @param array{ * extended_validation?: array}>, @@ -121,6 +132,7 @@ public function isAutoIncrement(): bool } /** + * @param FieldType $field * @throws GeneratorException */ protected function setData(\stdClass $field): static diff --git a/src/Generator/Compiler/MapperCompiler.php b/src/Generator/Compiler/MapperCompiler.php index c8a9e74..1da9af3 100644 --- a/src/Generator/Compiler/MapperCompiler.php +++ b/src/Generator/Compiler/MapperCompiler.php @@ -75,10 +75,10 @@ private function buildFields(bool $onlyKey = false): string if ($onlyKey && !$field->isPrimaryKey()) { continue; } - $names[] = "'" . $field->getName() . "'"; + $names[] = "'" . $field->getName() . "',"; } - return implode(",\n ", $names); + return implode("\n ", $names); } /** diff --git a/src/Generator/Templates/AbstractEntity.template b/src/Generator/Templates/AbstractEntity.template index aa45417..5fe9012 100644 --- a/src/Generator/Templates/AbstractEntity.template +++ b/src/Generator/Templates/AbstractEntity.template @@ -43,7 +43,7 @@ abstract class Abstract{{ class.name }} implements EntityInterface public function __construct( {{ class.repository }} $repository, ?ValidatorFactoryInterface $validatorFactory = null, - ?ValidatorEntityFactoryInterface $validatorEntityFactory = null + ?ValidatorEntityFactoryInterface $validatorEntityFactory = null, ) { $this->setRepository($repository); $this->setValidatorFactories($validatorFactory, $validatorEntityFactory); diff --git a/src/Generator/Templates/AbstractMapper.template b/src/Generator/Templates/AbstractMapper.template index 4884c15..149ae14 100644 --- a/src/Generator/Templates/AbstractMapper.template +++ b/src/Generator/Templates/AbstractMapper.template @@ -51,7 +51,7 @@ abstract class Abstract{{ class.mapper }} ValidatorEntityFactory|null $validatorEntityFactory = null, array $mappers = [], CacheItemPoolInterface|null $cache = null, - bool $enableCacheOnRead = false + bool $enableCacheOnRead = false, ) { $this->setConnectionName($connectionName); $this->setConnectionFactory($connectionFactory); diff --git a/src/Generator/Templates/Mapper.template b/src/Generator/Templates/Mapper.template index caef0f9..a045a69 100644 --- a/src/Generator/Templates/Mapper.template +++ b/src/Generator/Templates/Mapper.template @@ -24,4 +24,6 @@ class {{ class.mapper }} extends Abstracts\Abstract{{ class.mapper }} implements { /** @use Traits\RepositoryTrait<{{ class.repository }}, {{ class.entity }}> */ use Traits\RepositoryTrait; + /** @use Traits\MapperTrait<{{ class.repository }}, {{ class.entity }}> */ + use Traits\MapperTrait; } diff --git a/src/Traits/CacheAwareTrait.php b/src/Traits/CacheAwareTrait.php index e6a6779..d8fb7c3 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 $cache = null): static + protected function setCache(CacheItemPoolInterface|null $cache = null): static { $this->cache = $cache; diff --git a/src/Traits/EntityAwareTrait.php b/src/Traits/EntityAwareTrait.php index 5791aab..c3aafde 100644 --- a/src/Traits/EntityAwareTrait.php +++ b/src/Traits/EntityAwareTrait.php @@ -61,9 +61,8 @@ public function setEntityClass(string $entityClass): static * * @phpstan-return TEntity */ - public function newEntity(\stdClass $row = null, bool $exists = false): object + public function newEntity(\stdClass|null $row = null, bool $exists = false): object { - /** @var TEntity $entity */ $entity = new $this->entityClass($this, $this->getValidatorFactory(), $this->getValidatorEntityFactory()); if ($row instanceof \stdClass) { @@ -138,10 +137,6 @@ public function newEntitySuffixAware(\stdClass $row, string $suffix, string $typ /** @var TEntity $entity */ $entity = new $this->entityClass($this, $this->getValidatorFactory(), $this->getValidatorEntityFactory()); - if (!($entity instanceof EntityInterface)) { - throw new \LogicException('Entity object is not an instance of AbstractData class!'); // @codeCoverageIgnore - } - $data = []; $hasSomeJoinValues = ($type !== JoinType::LEFT); @@ -179,7 +174,7 @@ public function newEntitySuffixAware(\stdClass $row, string $suffix, string $typ /** - * @phpstan-param TEntity $entity + * @phpstan-param TEntity $entity */ public function isEntityUpdated(EntityInterface $entity, string $field): bool { @@ -197,10 +192,9 @@ public function isEntityUpdated(EntityInterface $entity, string $field): bool } /** - * @phpstan-param TEntity $entity - * @return string|int|float|bool|null + * @phpstan-param TEntity $entity */ - public function getEntityValue(EntityInterface $entity, string $field): mixed + public function getEntityValue(EntityInterface $entity, string $field): string|int|float|bool|null { if (!isset($this->entityNamesMap[$field]['get'])) { throw new \DomainException( @@ -208,15 +202,18 @@ public function getEntityValue(EntityInterface $entity, string $field): mixed ); } - $method = $this->entityNamesMap[$field]['get']; + $getter = $this->entityNamesMap[$field]['get']; + + /** @var string|int|float|bool|null $value */ + $value = $entity->{$getter}(); - return $entity->{$method}(); + return $value; } /** * Get array "key" => "value" for primaries keys. * - * @phpstan-param TEntity $entity + * @phpstan-param TEntity $entity * @return array */ public function getEntityPrimaryKeysValues(EntityInterface $entity): array @@ -225,7 +222,10 @@ public function getEntityPrimaryKeysValues(EntityInterface $entity): array foreach ($this->getPrimaryKeys() as $key) { $getter = $this->getGetterForField($key); - $values[$key] = $entity->{$getter}(); + + /** @var string|int|float|bool|null $value */ + $value = $entity->{$getter}(); + $values[$key] = $value; } return $values; diff --git a/src/Traits/MapperTrait.php b/src/Traits/MapperTrait.php index 6018e9a..53ce3f3 100644 --- a/src/Traits/MapperTrait.php +++ b/src/Traits/MapperTrait.php @@ -105,7 +105,10 @@ public function getMaxId(): int $statement = $this->execute($query); - return $statement->fetch(PDO::FETCH_OBJ)->{$field}; + /** @var int $value */ + $value = $statement->fetch(PDO::FETCH_OBJ)->{$field}; + + return $value; } /** @@ -249,7 +252,6 @@ public function select(Query\SelectBuilder $queryBuilder): array $listIndexedByField = $queryBuilder->getListIndexedByField(); if ($this->isCacheEnabledOnRead) { - /** @var TRepository $repository */ $repository = $this; $collection = $this->selectFromCache($repository, $queryBuilder); } @@ -377,7 +379,6 @@ private function getJoinsConfig(array $filters = []): array */ private function getRawResultsWithJoin(Query\SelectBuilder $queryBuilder, array $joinConfigs): array { - /** @var TRepository $repository */ $repository = $this; //~ Add main fields to query builder @@ -450,7 +451,9 @@ private function getCollectionAndRelations(array $list, array $joinConfigs): arr //~ Resolve one-many relations $ids = []; foreach ($getters as $getterPrimaryKey) { - $ids[] = '|' . $data->$getterPrimaryKey(); + /** @var int|string $primaryValue */ + $primaryValue = $data->$getterPrimaryKey(); + $ids[] = '|' . $primaryValue; } $hash = md5(implode('|', $ids)); @@ -467,7 +470,7 @@ private function getCollectionAndRelations(array $list, array $joinConfigs): arr $mapper->enableIgnoreNotMappedFields(); - /** @var TEntity $dataJoin */ + /** @var TEntity|null $dataJoin */ $dataJoin = $mapper->newEntitySuffixAware($row, $aliasSuffix, $join['type']); if (!isset($relations[$name][$hash])) { diff --git a/src/Traits/RepositoryTrait.php b/src/Traits/RepositoryTrait.php index 57f881a..d34ed44 100644 --- a/src/Traits/RepositoryTrait.php +++ b/src/Traits/RepositoryTrait.php @@ -60,7 +60,6 @@ public function findById(int $id): EntityInterface */ public function findByKeys(array $keys): object { - /** @var TRepository $this */ $queryBuilder = new Query\SelectBuilder($this); foreach ($keys as $field => $value) { $queryBuilder->addWhere($field, $value); @@ -76,7 +75,6 @@ public function findByKeys(array $keys): object */ public function findAllByKeys(array $keys): array { - /** @var TRepository $this */ $queryBuilder = new Query\SelectBuilder($this); foreach ($keys as $field => $value) { $queryBuilder->addWhere($field, $value); diff --git a/src/Traits/ValidatorAwareTrait.php b/src/Traits/ValidatorAwareTrait.php index 3e98dd0..2c29c19 100644 --- a/src/Traits/ValidatorAwareTrait.php +++ b/src/Traits/ValidatorAwareTrait.php @@ -34,7 +34,7 @@ trait ValidatorAwareTrait private array $validationConfig = []; /** - * @param array $data + * @param array $data * @param array}> $config * @return GenericEntity */ @@ -48,7 +48,7 @@ public function newGenericEntity(array $data = [], array $config = []): GenericE // @codeCoverageIgnoreEnd } - $config = !empty($config) ? $config : $this->getValidatorConfig(); + $config = $config !== [] ? $config : $this->getValidatorConfig(); return $this->getValidatorEntityFactory()->createGeneric($config, $data); } diff --git a/tests/integration/.gitkeep b/tests/integration/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/Generator/GeneratorTest.php b/tests/unit/Generator/GeneratorTest.php index eaeddbb..caa9c13 100644 --- a/tests/unit/Generator/GeneratorTest.php +++ b/tests/unit/Generator/GeneratorTest.php @@ -33,7 +33,7 @@ class GeneratorTest extends TestCase public function testICanInstantiateGenerator(): void { $generator = new Generator(); - $this->assertInstanceOf(Generator::class, $generator); + self::assertInstanceOf(Generator::class, $generator); } /** @@ -45,7 +45,7 @@ public function testICanGenerateMappersAndEntityClassesAccordingToConfigAndMocke $generator = new Generator(); $generator->generate($this->getConnectionMock(), $this->getConfig(), '', false); - $this->assertInstanceOf(Generator::class, $generator); + self::assertInstanceOf(Generator::class, $generator); } /** @@ -57,7 +57,7 @@ public function testICanGenerateMappersAndEntityClassesAccordingToConfigAndMocke $generator = new Generator(); $generator->generate($this->getConnectionMock(), $this->getConfig(), 'user', false); - $this->assertInstanceOf(Generator::class, $generator); + self::assertInstanceOf(Generator::class, $generator); } /** @@ -69,7 +69,7 @@ public function testICanGenerateMappersAndEntityClassesAccordingToConfigAndMocke $generator = new Generator(); $generator->generate($this->getConnectionMock(), $this->getConfig(), 'user.*', false); - $this->assertInstanceOf(Generator::class, $generator); + self::assertInstanceOf(Generator::class, $generator); } /** @@ -83,7 +83,7 @@ public function testIHaveAnExceptionWhenITryToGenerateCodeWithEmptyConfig(): voi $this->expectExceptionMessage('Invalid config. Empty information about orm!'); $generator->generate($this->getConnectionMock(), [], '', false); - $this->assertInstanceOf(Generator::class, $generator); + self::assertInstanceOf(Generator::class, $generator); } /** @@ -97,7 +97,7 @@ public function testIHaveAnExceptionWhenITryToGenerateCodeWithNotDefinedJoinedCo $this->expectExceptionMessage('Invalid orm config file for "user_invalid"'); $generator->generate($this->getConnectionMock(), $this->getInvalidJoinConfig(), '', false); - $this->assertInstanceOf(Generator::class, $generator); + self::assertInstanceOf(Generator::class, $generator); } /** @@ -111,7 +111,7 @@ public function testIHaveAnExceptionWhenITryToGenerateCodeWithNonExistingJoinedC $this->expectExceptionMessage('Invalid config. Joined config "not_exist" does not exist!'); $generator->generate($this->getConnectionMock(), $this->getConfigWithMissingJoinedConfig(), '', false); - $this->assertInstanceOf(Generator::class, $generator); + self::assertInstanceOf(Generator::class, $generator); } private function getConnectionMock(): Connection&MockObject @@ -227,9 +227,7 @@ private function getConnectionMock(): Connection&MockObject } } - $connection->method('query')->will( - $this->returnValueMap($map), - ); + $connection->method('query')->willReturnMap($map); return $connection; } @@ -243,7 +241,7 @@ private function getPDOStatementMock(array $mockedData = []): \PDOStatement $mockBuilder = $this->getMockBuilder(\PDOStatement::class); /** @var \PDOStatement&MockObject $statement */ $statement = $mockBuilder->getMock(); - $statement->method('fetch')->with(\PDO::FETCH_OBJ)->willReturnOnConsecutiveCalls(...$mockedData); + $statement->method('fetch')->with(\PDO::FETCH_OBJ)->willReturnOnConsecutiveCalls(...\array_values($mockedData)); return $statement; } diff --git a/tests/unit/Generator/TypeTest.php b/tests/unit/Generator/TypeTest.php index 29bccdc..2f7a2c3 100644 --- a/tests/unit/Generator/TypeTest.php +++ b/tests/unit/Generator/TypeTest.php @@ -13,6 +13,7 @@ use Eureka\Component\Orm\Exception\GeneratorException; use Eureka\Component\Orm\Generator\Type; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; /** @@ -23,18 +24,17 @@ class TypeTest extends TestCase { /** - * @dataProvider typeProvider - * * @param string $sqlType * @param class-string $classType * @return void * @throws GeneratorException */ + #[DataProvider('typeProvider')] public function testICanCreateTypeWithFactory(string $sqlType, string $classType) { $type = Type\Factory::create($sqlType, ''); - $this->assertInstanceOf($classType, $type); + self::assertInstanceOf($classType, $type); } /** @@ -52,9 +52,8 @@ public function testIHaveAnExceptionWhenITryToGetTypeWithUnknownType() * @param string $sqlType * @return void * @throws GeneratorException - * - * @dataProvider invalidTypeProvider */ + #[DataProvider('invalidTypeProvider')] public function testIHaveAnExceptionWhenITryToGetTypeWithInvalidSqlType(string $sqlType) { $this->expectException(GeneratorException::class); diff --git a/tests/unit/Mapper/EntityTest.php b/tests/unit/Mapper/EntityTest.php index cc1051d..9b2ba1e 100644 --- a/tests/unit/Mapper/EntityTest.php +++ b/tests/unit/Mapper/EntityTest.php @@ -66,7 +66,7 @@ public function testICanCreateNewEmptyUserEntityFromEmptyContent(): void $repository = $this->getUserRepository(); $user = $repository->newEntity(); - $this->assertInstanceOf(User::class, $user); + self::assertInstanceOf(User::class, $user); } /** @@ -87,8 +87,8 @@ public function testICanCreateNewUserEntityFromNonEmptyContent(): void ], ); - $this->assertInstanceOf(User::class, $user); - $this->assertInstanceOf(UserRepositoryInterface::class, $user->getRepository()); + self::assertInstanceOf(User::class, $user); + self::assertInstanceOf(UserRepositoryInterface::class, $user->getRepository()); } /** @@ -113,17 +113,17 @@ public function testICanUpdateAnEntity(): void $user->setAutoIncrementId(2); $user->setDateUpdate('2020-01-02 10:00:00'); - $this->assertTrue($user->isUpdated()); - $this->assertTrue($user->isUpdated('id')); - $this->assertTrue($user->isUpdated('dateUpdate')); + self::assertTrue($user->isUpdated()); + self::assertTrue($user->isUpdated('id')); + self::assertTrue($user->isUpdated('dateUpdate')); - $this->assertTrue($repository->isEntityUpdated($user, 'user_id')); - $this->assertTrue($repository->isEntityUpdated($user, 'user_date_update')); + self::assertTrue($repository->isEntityUpdated($user, 'user_id')); + self::assertTrue($repository->isEntityUpdated($user, 'user_date_update')); $user->resetUpdated(); - $this->assertFalse($user->isUpdated()); - $this->assertFalse($user->isUpdated('id')); - $this->assertFalse($user->isUpdated('dateUpdate')); + self::assertFalse($user->isUpdated()); + self::assertFalse($user->isUpdated('id')); + self::assertFalse($user->isUpdated('dateUpdate')); } /** @@ -155,7 +155,7 @@ public function testICanCreateNewEntityFromArray(): void $a = $expected->getId(); - $this->assertEquals($expected, $user); + self::assertEquals($expected, $user); } @@ -178,7 +178,7 @@ public function testICanCreateNewEntityWithUnknownFieldWhenIEnableIgnoreNotMappe ], ); $repository->disableIgnoreNotMappedFields(); - $this->assertInstanceOf(User::class, $user); + self::assertInstanceOf(User::class, $user); } /** @@ -259,7 +259,7 @@ public function testICanCreateNewGenericEntityFromUserEntity(): void $generic = $user->getGenericEntity(); - $this->assertEquals($expected, $generic); + self::assertEquals($expected, $generic); } /** @@ -293,7 +293,7 @@ public function testICanCreateNewEntityFromGenericEntity(): void ], ); - $this->assertEquals($expected, $user); + self::assertEquals($expected, $user); } /** @@ -307,7 +307,7 @@ public function testICanResetLazyLoadedData(): void $user->setUserParent($this->getUserParentRepository()->newEntity()); - $this->assertInstanceOf(UserParent::class, $user->getUserParent()); + self::assertInstanceOf(UserParent::class, $user->getUserParent()); $user->resetLazyLoadedData(); } diff --git a/tests/unit/Mapper/MapperJoinTest.php b/tests/unit/Mapper/MapperJoinTest.php index 078533b..c8e57af 100644 --- a/tests/unit/Mapper/MapperJoinTest.php +++ b/tests/unit/Mapper/MapperJoinTest.php @@ -78,7 +78,7 @@ public function testICanRetrieveUserWithJoinedData(): void ], ); - $this->assertEquals([$expectedUser], $users); + self::assertEquals([$expectedUser], $users); } /** @@ -105,7 +105,7 @@ public function testICanRetrieveUserWithoutJoinedLeftData(): void true, ); - $this->assertEquals([$expectedUser], $users); + self::assertEquals([$expectedUser], $users); } /** @@ -117,9 +117,7 @@ public function testICanRetrieveUserWithJoinedLeftData(): void { $userRepository = $this->getUserRepository($this->getMockEntityFindOne(true)); - /** @var User $user */ $user = $userRepository->selectJoin(new SelectBuilder($userRepository), ['UserComment']); - /** @var User $expectedUser */ $expectedUser = $userRepository->newEntity( (object) [ 'user_id' => 1, @@ -144,7 +142,7 @@ public function testICanRetrieveUserWithJoinedLeftData(): void ); $expectedUser->setUserComment($expectedComment); - $this->assertEquals([$expectedUser], $user); + self::assertEquals([$expectedUser], $user); } /** @@ -162,7 +160,7 @@ private function getConnectionFactoryMock(array $entityMock = []): ConnectionFac $statementMock = $this->getMockBuilder(\PDOStatement::class)->getMock(); $statementMock->method('execute')->willReturn(true); $statementMock->method('rowCount')->willReturn($count); - $statementMock->method('fetch')->willReturnOnConsecutiveCalls(...$entityMock); + $statementMock->method('fetch')->willReturnOnConsecutiveCalls(...\array_values($entityMock)); $statementMock->method('fetchColumn')->willReturn($count); $mockBuilder = $this->getMockBuilder(Connection::class)->disableOriginalConstructor(); diff --git a/tests/unit/Mapper/MapperTest.php b/tests/unit/Mapper/MapperTest.php index 53ddf44..e346371 100644 --- a/tests/unit/Mapper/MapperTest.php +++ b/tests/unit/Mapper/MapperTest.php @@ -30,6 +30,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\Stub\Exception; use PHPUnit\Framework\TestCase; +use Random\Engine\Mt19937; use Symfony\Component\Cache\Adapter\ArrayAdapter; /** @@ -48,9 +49,9 @@ public function testICanInstantiateUserMapper(): void $repository->disableCacheOnRead(); $repository->enableCacheOnRead(); - $this->assertInstanceOf(UserMapper::class, $repository); - $this->assertInstanceOf(UserRepositoryInterface::class, $repository); - $this->assertInstanceOf(MapperInterface::class, $repository); + self::assertInstanceOf(UserMapper::class, $repository); + self::assertInstanceOf(UserRepositoryInterface::class, $repository); + self::assertInstanceOf(MapperInterface::class, $repository); } /** @@ -73,9 +74,9 @@ public function testICanInsertEntity(): void ], ); - $this->assertFalse($user->exists(), 'User should not exists'); + self::assertFalse($user->exists(), 'User should not exists'); $repository->persist($user); - $this->assertTrue($user->exists(), 'User should exists'); + self::assertTrue($user->exists(), 'User should exists'); $repository->insert($user); } @@ -103,9 +104,9 @@ public function testICanInsertUpdateEntity(): void $repository->persist($user); // nothing happen, entity is not updated $user->setDateUpdate('2020-01-01 10:00:00'); - $this->assertTrue($user->isUpdated()); + self::assertTrue($user->isUpdated()); $repository->persist($user); - $this->assertFalse($user->isUpdated()); + self::assertFalse($user->isUpdated()); } /** @@ -129,9 +130,9 @@ public function testICanDeleteEntity(): void true, ); - $this->assertTrue($user->exists(), 'User should always exists'); + self::assertTrue($user->exists(), 'User should always exists'); $repository->delete($user); - $this->assertFalse($user->exists(), 'User should not exists anymore'); + self::assertFalse($user->exists(), 'User should not exists anymore'); } /** @@ -157,14 +158,14 @@ public function testICanFindEntityById(): void ], true, ); - $this->assertEquals($expected, $user); + self::assertEquals($expected, $user); //~ Then retrieve from cache /** @var User $user */ $user = $repository->findById(1); - $this->assertEquals($expected, $user); - $this->assertSame(1, $repository->rowCount()); - $this->assertSame(1, $repository->rowCountOnSelect()); + self::assertEquals($expected, $user); + self::assertSame(1, $repository->rowCount()); + self::assertSame(1, $repository->rowCountOnSelect()); } /** @@ -190,10 +191,10 @@ public function testICanFindEntityByIdWithoutCacheEnabledNorCache(): void ], true, ); - $this->assertEquals($expected, $user); + self::assertEquals($expected, $user); $repository->delete($user); - $this->assertFalse($user->exists()); + self::assertFalse($user->exists()); } /** @@ -218,7 +219,7 @@ public function testICanFindEntitiesByKeys(): void $users = $repository->findAllByKeys(['user_id' => 1]); - $this->assertCount(2, $users); + self::assertCount(2, $users); } /** @@ -255,7 +256,7 @@ public function testICanGetListOfEntityIndexedByGivenFieldWhenExecuteQuery(): vo ), ]; - $this->assertEquals($expected, $collection); + self::assertEquals($expected, $collection); } /** @@ -271,9 +272,9 @@ public function testICanGetListOfEntityIndexedByGivenFieldWhenExecuteSelect(): v $users = $repository->select($builder); $ids = array_keys($users); - $this->assertCount(2, $users); - $this->assertSame($ids[0], $users[$ids[0]]->getId()); - $this->assertSame($ids[1], $users[$ids[1]]->getId()); + self::assertCount(2, $users); + self::assertSame($ids[0], $users[$ids[0]]->getId()); + self::assertSame($ids[1], $users[$ids[1]]->getId()); //~ Also test when retrieve all entities from cache $builder = new SelectBuilder($repository); @@ -282,9 +283,9 @@ public function testICanGetListOfEntityIndexedByGivenFieldWhenExecuteSelect(): v /** @var User[] $users */ $users = $repository->select($builder); - $this->assertCount(2, $users); - $this->assertSame($ids[0], $users[$ids[0]]->getId()); - $this->assertSame($ids[1], $users[$ids[1]]->getId()); + self::assertCount(2, $users); + self::assertSame($ids[0], $users[$ids[0]]->getId()); + self::assertSame($ids[1], $users[$ids[1]]->getId()); } /** @@ -308,7 +309,7 @@ public function testICanCheckIfRowExists(): void { $repository = $this->getUserRepository($this->getMockEntityFindId1()); - $this->assertTrue($repository->rowExists((new SelectBuilder($repository))->addWhere('user_id', 1))); + self::assertTrue($repository->rowExists((new SelectBuilder($repository))->addWhere('user_id', 1))); } /** @@ -318,7 +319,7 @@ public function testICanCountRows(): void { $repository = $this->getUserRepository($this->getMockEntityFindAll()); - $this->assertSame(2, $repository->count(new QueryBuilder($repository))); + self::assertSame(2, $repository->count(new QueryBuilder($repository))); } /** @@ -329,7 +330,7 @@ public function testICanCheckIfRowDoesNotExists(): void { $repository = $this->getUserRepository($this->getMockEntityNone()); - $this->assertFalse($repository->rowExists((new SelectBuilder($repository))->addWhere('user_id', 1))); + self::assertFalse($repository->rowExists((new SelectBuilder($repository))->addWhere('user_id', 1))); } /** @@ -339,7 +340,7 @@ public function testICanGetMaxPrimaryKeyIdForARepository(): void { $repository = $this->getUserRepository($this->getMockEntityFindId1()); - $this->assertSame(1, $repository->getMaxId()); + self::assertSame(1, $repository->getMaxId()); } /** @@ -349,7 +350,7 @@ public function testAReconnectionIsMadeAutomaticallyWhenConnectionIsLostAndITryT { $repository = $this->getUserRepository($this->getMockEntityFindId1(), true, 2006); - $this->assertSame(1, $repository->getMaxId()); + self::assertSame(1, $repository->getMaxId()); } /** @@ -367,7 +368,7 @@ public function testAReconnectionIsMadeAutomaticallyWhenConnectionIsLostAndITryT $entity->setExists(true); $entity->setEmail('new@email.com'); - $this->assertTrue($repository->persist($entity)); + self::assertTrue($repository->persist($entity)); } /** @@ -403,10 +404,9 @@ public function testIHaveAnExceptionWhenITryToGetNonExistingMapper(): void $repository = $this->getUserRepository($this->getMockEntityNone()); $this->expectException(UndefinedMapperException::class); - $this->expectExceptionMessage('Mapper does not exist! (mapper: \Unknown\Mapper\ClassName)'); + $this->expectExceptionMessage('Mapper does not exist! (mapper: ' . Mt19937::class . ')'); - /** @var class-string $mapperClass */ - $mapperClass = '\Unknown\Mapper\ClassName'; + $mapperClass = Mt19937::class; // Not a mapper class $repository->getMapper($mapperClass); } @@ -476,7 +476,7 @@ private function getConnectionFactoryMock( $statementMock = $this->getMockBuilder(\PDOStatement::class)->getMock(); $statementMock->method('rowCount')->willReturn($count); - $statementMock->method('fetch')->willReturnOnConsecutiveCalls(...$entityMock); + $statementMock->method('fetch')->willReturnOnConsecutiveCalls(...\array_values($entityMock)); $statementMock->method('fetchColumn')->willReturn($count); if ($exceptionCode > 0) { diff --git a/tests/unit/QueryBuilder/QueryBuilderTest.php b/tests/unit/QueryBuilder/QueryBuilderTest.php index 8078a00..624dfc2 100644 --- a/tests/unit/QueryBuilder/QueryBuilderTest.php +++ b/tests/unit/QueryBuilder/QueryBuilderTest.php @@ -50,8 +50,8 @@ public function testICanInstantiateQueryBuilderWithFactory(): void $queryBuilder->setListIndexedByField('user_id'); $queryBuilder->bindAll([':user_id' => 1]); - $this->assertSame('user_id', $queryBuilder->getListIndexedByField()); - $this->assertSame([':user_id' => 1], $queryBuilder->getAllBind()); + self::assertSame('user_id', $queryBuilder->getListIndexedByField()); + self::assertSame([':user_id' => 1], $queryBuilder->getAllBind()); } /** * @return void @@ -61,11 +61,11 @@ public function testICanInstantiateAnyQueryBuilderWithFactory(): void $repository = $this->getUserRepository($this->getMockEntityFindAll()); $factory = new QueryBuilderFactory(); - $this->assertInstanceOf(QueryBuilder::class, $factory->newQueryBuilder($repository)); - $this->assertInstanceOf(SelectBuilder::class, $factory->newSelectBuilder($repository)); - $this->assertInstanceOf(DeleteBuilder::class, $factory->newDeleteBuilder($repository)); - $this->assertInstanceOf(InsertBuilder::class, $factory->newInsertBuilder($repository)); - $this->assertInstanceOf(UpdateBuilder::class, $factory->newUpdateBuilder($repository)); + self::assertInstanceOf(QueryBuilder::class, $factory->newQueryBuilder($repository)); + self::assertInstanceOf(SelectBuilder::class, $factory->newSelectBuilder($repository)); + self::assertInstanceOf(DeleteBuilder::class, $factory->newDeleteBuilder($repository)); + self::assertInstanceOf(InsertBuilder::class, $factory->newInsertBuilder($repository)); + self::assertInstanceOf(UpdateBuilder::class, $factory->newUpdateBuilder($repository)); } /** @@ -84,18 +84,18 @@ public function testICanGetWellFormattedInsertQueryFromInsertQueryBuilder(): voi $suffix = '\_[a-z0-9]{13}'; $insertQuery = $queryBuilder->getQuery(); $patternQuery = "/INSERT INTO user SET `user_id` = :user_id$suffix, `user_name` = :user_name$suffix/"; - $this->assertMatchesRegularExpression($patternQuery, $insertQuery); + self::assertMatchesRegularExpression($patternQuery, $insertQuery); //~ Query with IGNORE for duplicate $insertQuery = $queryBuilder->getQuery(false, true); $patternQuery = "/INSERT IGNORE INTO user SET `user_id` = :user_id$suffix, `user_name` = :user_name$suffix/"; - $this->assertMatchesRegularExpression($patternQuery, $insertQuery); + self::assertMatchesRegularExpression($patternQuery, $insertQuery); //~ Query with IGNORE for duplicate $queryBuilder->addUpdate('user_name', 'test'); $insertQuery = $queryBuilder->getQuery(true); $patternQuery = "/INSERT INTO user SET `user_id` = :user_id$suffix, `user_name` = :user_name$suffix ON DUPLICATE KEY UPDATE `user_name` = :user_name$suffix/"; - $this->assertMatchesRegularExpression($patternQuery, $insertQuery); + self::assertMatchesRegularExpression($patternQuery, $insertQuery); } /** @@ -119,7 +119,7 @@ public function testICanGetWellFormattedInsertQueryFromInsertQueryBuilderWithEnt $queryBuilder = (new QueryBuilderFactory())->newInsertBuilder($repository, $user); $query = $queryBuilder->getQuery(true); - $this->assertIsString($query); + self::assertIsString($query); } /** @@ -135,7 +135,7 @@ public function testICanGetQueryFromQueryBuilder(): void $query = $queryBuilder->getQuery(); $expected = 'SELECT `user_id` FROM `user`'; - $this->assertSame($expected, $query); + self::assertSame($expected, $query); } /** @@ -147,7 +147,7 @@ public function testICanUseQueryFieldsPersonalizedParameters(): void $queryBuilder = (new QueryBuilderFactory())->newQueryBuilder($repository); $queryField = $queryBuilder->getQueryFieldsPersonalized(['user_id' => 'usr_id', 'user_name' => '']); - $this->assertSame('`user_id` AS `usr_id`, `user_name`', $queryField); + self::assertSame('`user_id` AS `usr_id`, `user_name`', $queryField); } /** @@ -160,7 +160,7 @@ public function testICanGetQueryFields(): void $queryBuilder->addField('user_id'); $queryField = $queryBuilder->getQueryFields($repository); - $this->assertSame('`user_id`', $queryField); + self::assertSame('`user_id`', $queryField); } /** @@ -172,7 +172,7 @@ public function testICanGetQueryFieldsWithOnlyPrefixedPrimaryKeys(): void $queryBuilder = (new QueryBuilderFactory())->newQueryBuilder($repository); $queryField = $queryBuilder->getQueryFields($repository, true, true); - $this->assertSame('user.user_id', $queryField); + self::assertSame('user.user_id', $queryField); } /** @@ -184,7 +184,7 @@ public function testICanGetQueryFieldsWithOnlyCustomPrefixedPrimaryKeys(): void $queryBuilder = (new QueryBuilderFactory())->newQueryBuilder($repository); $queryField = $queryBuilder->getQueryFieldsList($repository, true, true, 'usr_alias', '_suffix'); - $this->assertSame('usr_alias.user_id AS user_id_suffix', $queryField[0]); + self::assertSame('usr_alias.user_id AS user_id_suffix', $queryField[0]); } /** @@ -197,12 +197,12 @@ public function testICanEnableAndDisableRowFoundCalculationForQuery(): void $queryBuilder->enableCalculateFoundRows(); $queryField = $queryBuilder->getQueryFieldsPersonalized(['user_id' => 'usr_id', 'user_name' => '']); - $this->assertSame('SQL_CALC_FOUND_ROWS `user_id` AS `usr_id`, `user_name`', $queryField); + self::assertSame('SQL_CALC_FOUND_ROWS `user_id` AS `usr_id`, `user_name`', $queryField); $queryBuilder->clear(); $queryBuilder->disableCalculateFoundRows(); $queryField = $queryBuilder->getQueryFieldsPersonalized(['user_id' => 'usr_id', 'user_name' => '']); - $this->assertSame('`user_id` AS `usr_id`, `user_name`', $queryField); + self::assertSame('`user_id` AS `usr_id`, `user_name`', $queryField); } /** @@ -214,7 +214,7 @@ public function testICanAddOrderToQueryBuilder(): void $queryBuilder = (new QueryBuilderFactory())->newQueryBuilder($repository); $queryBuilder->addOrder('user_id'); - $this->assertSame(' ORDER BY user_id ASC', $queryBuilder->getQueryOrderBy()); + self::assertSame(' ORDER BY user_id ASC', $queryBuilder->getQueryOrderBy()); } /** @@ -226,7 +226,7 @@ public function testICanAddGroupByToQueryBuilder(): void $queryBuilder = (new QueryBuilderFactory())->newQueryBuilder($repository); $queryBuilder->addGroupBy('user_id'); - $this->assertSame(' GROUP BY user_id ', $queryBuilder->getQueryGroupBy()); + self::assertSame(' GROUP BY user_id ', $queryBuilder->getQueryGroupBy()); } /** @@ -240,7 +240,7 @@ public function testICanAddHavingClauseToQueryBuilder(): void $suffix = '\_[a-z0-9]{13}'; $patternQuery = "/ HAVING user_id > :user_id$suffix /"; - $this->assertMatchesRegularExpression($patternQuery, $queryBuilder->getQueryHaving()); + self::assertMatchesRegularExpression($patternQuery, $queryBuilder->getQueryHaving()); } /** @@ -253,7 +253,7 @@ public function testICanAddJoinToQueryBuilder(): void $queryBuilder->addJoin(JoinType::INNER, 'address', 'user_id', 'user', 'user_id', 'address'); $expected = ' INNER JOIN address AS address ON user.user_id = address.user_id '; - $this->assertSame($expected, $queryBuilder->getQueryJoin()); + self::assertSame($expected, $queryBuilder->getQueryJoin()); } /** @@ -266,7 +266,7 @@ public function testICanAddWhereWithRegexpTypeToQueryBuilder(): void $queryBuilder = new QueryBuilder($repository); $queryBuilder->addWhere('user_name', 'test[a-z]', Operator::Regexp); - $this->assertSame(' WHERE user_name REGEXP \'test[a-z]\' ', $queryBuilder->getQueryWhere()); + self::assertSame(' WHERE user_name REGEXP \'test[a-z]\' ', $queryBuilder->getQueryWhere()); } /** @@ -283,7 +283,7 @@ public function testICanAddMultipleWhereWithRegexpTypeToQueryBuilder(): void $queryBuilder->addWhere('user_name', 'any'); $pattern = "` WHERE user_id = :user_id_$suffix AND user_name = :user_name_$suffix `"; - $this->assertMatchesRegularExpression($pattern, $queryBuilder->getQueryWhere()); + self::assertMatchesRegularExpression($pattern, $queryBuilder->getQueryWhere()); } /** @@ -297,7 +297,7 @@ public function testICanAddWhereRawToQueryBuilder(): void $queryBuilder->addWhereRaw('user_id IS NULL'); $queryBuilder->addWhereRaw('user_name LIKE "test"'); - $this->assertSame(' WHERE user_id IS NULL AND user_name LIKE "test" ', $queryBuilder->getQueryWhere()); + self::assertSame(' WHERE user_id IS NULL AND user_name LIKE "test" ', $queryBuilder->getQueryWhere()); } /** @@ -313,7 +313,7 @@ public function testICanAddWhereKeysOrToQueryBuilder(): void $suffix = '\_[a-z0-9]{13}'; $patternQuery = "/ WHERE \(primary_key_1 = :primary_key_1$suffix AND primary_key_2 = :primary_key_2$suffix\) OR \(primary_key_1 = :primary_key_1$suffix AND primary_key_2 = :primary_key_2$suffix\) /"; - $this->assertMatchesRegularExpression($patternQuery, $queryBuilder->getQueryWhere()); + self::assertMatchesRegularExpression($patternQuery, $queryBuilder->getQueryWhere()); } /** @@ -383,7 +383,7 @@ private function getConnectionFactoryMock(array $entityMock = []): ConnectionFac $statementMock = $this->getMockBuilder(\PDOStatement::class)->getMock(); $statementMock->method('execute')->willReturn(true); $statementMock->method('rowCount')->willReturn($count); - $statementMock->method('fetch')->willReturnOnConsecutiveCalls(...$entityMock); + $statementMock->method('fetch')->willReturnOnConsecutiveCalls(...\array_values($entityMock)); $statementMock->method('fetchColumn')->willReturn($count); $mockBuilder = $this->getMockBuilder(Connection::class)->disableOriginalConstructor();