From 6e8b39122d854c758db6600297cb360ef1a27b28 Mon Sep 17 00:00:00 2001 From: bancer Date: Sun, 23 Nov 2025 13:13:52 +0100 Subject: [PATCH 1/6] Add github actions config file --- .github/workflows/ci.yml | 59 ++++++++++++++++++++++++++++++++++++++++ composer.json | 4 +-- 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..143d46e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,59 @@ +name: CI + +on: + push: + pull_request: + +jobs: + static-analysis: + name: Static Analysis + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP 8.1 + uses: shivammathur/setup-php@v2 + with: + php-version: '8.1' + tools: composer + + - name: Install dependencies + run: composer install --prefer-dist --no-interaction + + - name: Run PHPStan + run: composer phpstan + + - name: Run PHPCS + run: composer phpcs + + phpunit: + name: PHPUnit (PHP ${{ matrix.php }} + ORM ${{ matrix.orm }}) + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + php: ['7.4', '8.0'] + orm: ['4', '5'] + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer + + - name: Install dependencies + run: composer install --prefer-dist --no-interaction + + - name: Require ORM version + run: composer require "cakephp/orm:^${{ matrix.orm }}" "cakephp/database:^${{ matrix.orm }}" --no-interaction --no-update + + - name: Update dependencies + run: composer update --prefer-dist --no-interaction + + - name: Run PHPUnit + run: composer phpunit diff --git a/composer.json b/composer.json index 16078d6..24502ae 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,8 @@ "type": "library", "require": { "php": ">=7.4.0", - "cakephp/database": "^4.0", - "cakephp/orm": "^4.0" + "cakephp/database": "^4.0|^5.0", + "cakephp/orm": "^4.0|^5.0" }, "require-dev": { "phpstan/phpstan": "^2.0.0", From 5e53e095ba1ef3dd2d0aa9b1ae1695e7f6e510fd Mon Sep 17 00:00:00 2001 From: bancer Date: Sun, 23 Nov 2025 13:27:33 +0100 Subject: [PATCH 2/6] Add str_contains polyfill and adjust github actions config --- .github/workflows/ci.yml | 21 +++++++++++++++++---- composer.json | 5 ++++- src/polyfill_str_contains.php | 11 +++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 src/polyfill_str_contains.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 143d46e..fc6fa43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,8 +34,21 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.4', '8.0'] - orm: ['4', '5'] + include: + # ORM 4 requires PHP >= 7.2 + - { php: '7.2', orm: '4' } + - { php: '7.4', orm: '4' } + - { php: '8.0', orm: '4' } + - { php: '8.1', orm: '4' } + - { php: '8.2', orm: '4' } + - { php: '8.3', orm: '4' } + - { php: '8.4', orm: '4' } + + # ORM 5 requires PHP >= 8.1 + - { php: '8.1', orm: '5' } + - { php: '8.2', orm: '5' } + - { php: '8.3', orm: '5' } + - { php: '8.4', orm: '5' } steps: - uses: actions/checkout@v4 @@ -46,10 +59,10 @@ jobs: php-version: ${{ matrix.php }} tools: composer - - name: Install dependencies + - name: Install base dependencies run: composer install --prefer-dist --no-interaction - - name: Require ORM version + - name: Require CakePHP ORM version run: composer require "cakephp/orm:^${{ matrix.orm }}" "cakephp/database:^${{ matrix.orm }}" --no-interaction --no-update - name: Update dependencies diff --git a/composer.json b/composer.json index 24502ae..d287bc5 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,10 @@ "autoload": { "psr-4": { "Bancer\\NativeQueryMapper\\": "src/" - } + }, + "files": [ + "src/polyfill_str_contains.php" + ] }, "autoload-dev" : { "psr-4" : { diff --git a/src/polyfill_str_contains.php b/src/polyfill_str_contains.php new file mode 100644 index 0000000..f07b778 --- /dev/null +++ b/src/polyfill_str_contains.php @@ -0,0 +1,11 @@ + Date: Sun, 23 Nov 2025 13:30:28 +0100 Subject: [PATCH 3/6] Enable php 7.2 support --- .github/workflows/ci.yml | 1 + composer.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc6fa43..50d9150 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,6 +37,7 @@ jobs: include: # ORM 4 requires PHP >= 7.2 - { php: '7.2', orm: '4' } + - { php: '7.3', orm: '4' } - { php: '7.4', orm: '4' } - { php: '8.0', orm: '4' } - { php: '8.1', orm: '4' } diff --git a/composer.json b/composer.json index d287bc5..83c4cdb 100644 --- a/composer.json +++ b/composer.json @@ -8,8 +8,8 @@ "cakephp/orm": "^4.0|^5.0" }, "require-dev": { - "phpstan/phpstan": "^2.0.0", - "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan": "^1.0|^2.0", + "phpstan/phpstan-phpunit": "^1.0|^2.0", "phpunit/phpunit": "^8.5 || ^9.3", "squizlabs/php_codesniffer": "^4.0" }, From 0adde6b38a846bc1b9f17e64242fdaf00310d6bc Mon Sep 17 00:00:00 2001 From: bancer Date: Sun, 23 Nov 2025 13:33:42 +0100 Subject: [PATCH 4/6] Adjust php version in composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 83c4cdb..36ede37 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "A small CakePHP ORM-based library for hydrating raw SQL query results into entity graphs.", "type": "library", "require": { - "php": ">=7.4.0", + "php": ">=7.2.0", "cakephp/database": "^4.0|^5.0", "cakephp/orm": "^4.0|^5.0" }, From 34a08ab6bcbc7641380afeed990f98b5a47654c3 Mon Sep 17 00:00:00 2001 From: bancer Date: Sun, 23 Nov 2025 13:58:01 +0100 Subject: [PATCH 5/6] Fix failed tests --- .github/workflows/ci.yml | 2 -- composer.json | 2 +- src/ORM/AutoHydratorRecursive.php | 25 +++++++++++-------------- tests/bootstrap.php | 1 + 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50d9150..5fc3a39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,8 +36,6 @@ jobs: matrix: include: # ORM 4 requires PHP >= 7.2 - - { php: '7.2', orm: '4' } - - { php: '7.3', orm: '4' } - { php: '7.4', orm: '4' } - { php: '8.0', orm: '4' } - { php: '8.1', orm: '4' } diff --git a/composer.json b/composer.json index 36ede37..83c4cdb 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "A small CakePHP ORM-based library for hydrating raw SQL query results into entity graphs.", "type": "library", "require": { - "php": ">=7.2.0", + "php": ">=7.4.0", "cakephp/database": "^4.0|^5.0", "cakephp/orm": "^4.0|^5.0" }, diff --git a/src/ORM/AutoHydratorRecursive.php b/src/ORM/AutoHydratorRecursive.php index 31261e8..2c095b6 100644 --- a/src/ORM/AutoHydratorRecursive.php +++ b/src/ORM/AutoHydratorRecursive.php @@ -4,7 +4,6 @@ namespace Bancer\NativeQueryMapper\ORM; -use Cake\Database\StatementInterface; use Cake\Datasource\EntityInterface; use Cake\ORM\Table; use Cake\ORM\Entity; @@ -141,7 +140,7 @@ public function hydrateMany(array $rows): array $results = []; $rootAlias = $this->rootTable->getAlias(); foreach ($rows as $row) { - $tree = $this->buildEntityRecursive($this->rootTable, $row, $rootAlias); + $tree = $this->buildEntityRecursive($this->rootTable, $row); $root = $tree[$rootAlias]; $key = $this->entityKey($root, $this->rootTable); if (!isset($results[$key])) { @@ -156,14 +155,12 @@ public function hydrateMany(array $rows): array /** * @param Table $table * @param mixed[] $row - * @param string $expectedAlias * @param mixed[] $visited * @return \Cake\Datasource\EntityInterface[] */ protected function buildEntityRecursive( Table $table, array $row, - string $expectedAlias, array &$visited = [] ): array { $alias = $table->getAlias(); @@ -203,7 +200,7 @@ protected function buildEntityRecursive( continue; } if ($assoc instanceof HasMany) { - $tree = $this->buildEntityRecursive($target, $row, $childAlias, $visited); + $tree = $this->buildEntityRecursive($target, $row, $visited); if ($tree) { $list = $entity->get($assoc->getProperty()); if (!is_array($list)) { @@ -216,7 +213,7 @@ protected function buildEntityRecursive( continue; } if ($assoc instanceof BelongsTo || $assoc instanceof HasOne) { - $tree = $this->buildEntityRecursive($target, $row, $childAlias, $visited); + $tree = $this->buildEntityRecursive($target, $row, $visited); if ($tree) { $entity->set($assoc->getProperty(), $tree[$childAlias]); $out += $tree; @@ -224,17 +221,17 @@ protected function buildEntityRecursive( continue; } if ($assoc instanceof BelongsToMany) { - $junctionAlias = $assoc->getThrough(); - if (is_object($junctionAlias)) { - $junctionAlias = $junctionAlias->getAlias(); - } - $tree = $this->buildEntityRecursive($target, $row, $childAlias, $visited); + $tree = $this->buildEntityRecursive($target, $row, $visited); if ($tree) { $child = $tree[$childAlias]; + $junctionAlias = $assoc->getThrough(); + if (is_object($junctionAlias)) { + $junctionAlias = $junctionAlias->getAlias(); + } // hydrate join data only if the row contains it - if (isset($this->aliasMap[$junctionAlias])) { + if ($junctionAlias !== null && isset($this->aliasMap[$junctionAlias])) { $junctionTable = TableRegistry::getTableLocator()->get($junctionAlias); - $jTree = $this->buildEntityRecursive($junctionTable, $row, $junctionAlias, $visited); + $jTree = $this->buildEntityRecursive($junctionTable, $row, $visited); if ($jTree) { $child->set('_joinData', $jTree[$junctionAlias]); $out += $jTree; @@ -251,7 +248,7 @@ protected function buildEntityRecursive( continue; } // fallback - $tree = $this->buildEntityRecursive($target, $row, $childAlias, $visited); + $tree = $this->buildEntityRecursive($target, $row, $visited); if ($tree) { $entity->set($assoc->getProperty(), $tree[$childAlias]); $out += $tree; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 06cebb7..b2d6503 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -17,6 +17,7 @@ ]); ConnectionManager::alias('test', 'default'); +/** @var \Cake\Database\Connection $connection */ $connection = ConnectionManager::get('test'); $connection->execute(" From 9d5429c6050de42cc07b5de0a5133ef5ec2da426 Mon Sep 17 00:00:00 2001 From: bancer Date: Sun, 23 Nov 2025 14:00:53 +0100 Subject: [PATCH 6/6] Run coverage in github actions --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fc3a39..ef20b82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,4 +68,4 @@ jobs: run: composer update --prefer-dist --no-interaction - name: Run PHPUnit - run: composer phpunit + run: composer phpunit-coverage