Skip to content

Commit

Permalink
test: test ORM 2.x and 3.x (#264)
Browse files Browse the repository at this point in the history
* test: test ORM 2.x and 3.x

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* fix: compatibility with ORM 3.0, 3.1 and 3.2
  • Loading branch information
priyadi authored Jan 18, 2025
1 parent 12fcf75 commit 186147f
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 10 deletions.
14 changes: 9 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ jobs:
operating-system: [ubuntu-latest]
php: [ '8.2', '8.3', '8.4' ]
symfony: [ '6.*', '7.*' ]
orm: ['^2.19', '^3.0']
dep: [highest,lowest]

name: Symfony ${{ matrix.symfony }}, ${{ matrix.dep }} deps, PHP ${{ matrix.php }}, ${{ matrix.operating-system }}
name: SF ${{ matrix.symfony }}, ${{ matrix.dep }} deps, ORM ${{ matrix.orm }}, PHP ${{ matrix.php }}, ${{ matrix.operating-system }}

steps:
- uses: actions/checkout@v4
Expand All @@ -34,6 +35,9 @@ jobs:
- name: Validate composer.json and composer.lock
run: composer validate --strict

- name: Change ORM version
run: jq '.require["doctrine/orm"] = "${{ matrix.orm }}"' composer.json > composer.json.tmp && mv composer.json.tmp composer.json

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v4
Expand All @@ -56,19 +60,19 @@ jobs:

- name: Run psalm
run: vendor/bin/psalm
if: matrix.dep == 'highest' && matrix.symfony == '7.*'
if: matrix.dep == 'highest' && matrix.symfony == '7.*' && matrix.orm == '^3.0'

- name: Run phpstan
run: vendor/bin/phpstan analyse
if: matrix.dep == 'highest' && matrix.symfony == '7.*'
if: matrix.dep == 'highest' && matrix.symfony == '7.*' && matrix.orm == '^3.0'

# - name: Lint container
# run: tests/bin/console lint:container

- name: Validate monorepo
run: vendor/bin/monorepo-builder validate
run: git reset --hard ; vendor/bin/monorepo-builder validate

# - name: Rector
# - name: Rector
# run: vendor/bin/rector process --no-progress-bar --no-diffs --dry-run --no-ansi

- name: Validate php-cs-fixer
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

# 0.22.3

* test: test ORM 2.x and 3.x
* fix: compatibility with ORM 3.0, 3.1 and 3.2

# 0.22.2

* fix: fix compatibility problem with ORM 2.20
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/rekapager package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

namespace Rekalogika\Rekapager\Doctrine\ORM\Internal;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\AST\SelectStatement;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\ORM\Query\SqlWalker;

/**
* Borrowed from the class of the same name in Doctrine ORM.
*
* @phpstan-import-type QueryComponent from Parser
*/
class CountOutputWalker30 extends SqlWalker
{
private readonly AbstractPlatform $platform;
private readonly ResultSetMapping $rsm;

/**
* {@inheritDoc}
*/
public function __construct($query, $parserResult, array $queryComponents)
{
$this->platform = $query->getEntityManager()->getConnection()->getDatabasePlatform();
$this->rsm = $parserResult->getResultSetMapping();

parent::__construct($query, $parserResult, $queryComponents);
}

public function walkSelectStatement(SelectStatement $AST): string
{
if ($this->platform instanceof SQLServerPlatform) {
$AST->orderByClause = null;
}

$sql = parent::walkSelectStatement($AST);

// modification start
$maxResults = $this->getQuery()->getHint('maxResults');
\assert(\is_int($maxResults));
$firstResult = $this->getQuery()->getHint('firstResult');
\assert(\is_int($firstResult));
$sql = $this->platform->modifyLimitQuery($sql, $maxResults, $firstResult);
// modification end

if ($AST->groupByClause) {
return \sprintf(
'SELECT COUNT(*) AS dctrn_count FROM (%s) dctrn_table',
$sql,
);
}

// Find out the SQL alias of the identifier column of the root entity
// It may be possible to make this work with multiple root entities but that
// would probably require issuing multiple queries or doing a UNION SELECT
// so for now, It's not supported.

// Get the root entity and alias from the AST fromClause
$from = $AST->fromClause->identificationVariableDeclarations;
if (\count($from) > 1) {
throw new RuntimeException('Cannot count query which selects two FROM components, cannot make distinction');
}

$fromRoot = reset($from);
$rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable;
$rootClass = $this->getMetadataForDqlAlias($rootAlias);
$rootIdentifier = $rootClass->identifier;

// For every identifier, find out the SQL alias by combing through the ResultSetMapping
$sqlIdentifier = [];
foreach ($rootIdentifier as $property) {
if (isset($rootClass->fieldMappings[$property])) {
foreach (array_keys($this->rsm->fieldMappings, $property, true) as $alias) {
if ($this->rsm->columnOwnerMap[$alias] === $rootAlias) {
$sqlIdentifier[$property] = $alias;
}
}
}

if (isset($rootClass->associationMappings[$property])) {
$joinColumn = $rootClass->associationMappings[$property]['joinColumns'][0]['name'];

foreach (array_keys($this->rsm->metaMappings, $joinColumn, true) as $alias) {
if ($this->rsm->columnOwnerMap[$alias] === $rootAlias) {
$sqlIdentifier[$property] = $alias;
}
}
}
}

if (\count($rootIdentifier) !== \count($sqlIdentifier)) {
throw new RuntimeException(\sprintf(
'Not all identifier properties can be found in the ResultSetMapping: %s',
implode(', ', array_diff($rootIdentifier, array_keys($sqlIdentifier))),
));
}

// Build the counter query
return \sprintf(
'SELECT COUNT(*) AS dctrn_count FROM (SELECT DISTINCT %s FROM (%s) dctrn_result) dctrn_table',
implode(', ', $sqlIdentifier),
$sql,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*
* @phpstan-import-type QueryComponent from Parser
*/
class CountOutputWalker extends SqlOutputWalker
class CountOutputWalker33 extends SqlOutputWalker
{
private readonly AbstractPlatform $platform;
private readonly ResultSetMapping $rsm;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ private function getCountQuery(): Query
throw new RuntimeException('Could not determine the installed version of doctrine/orm');
}

if (version_compare($version, '3.0.0', '>=')) {
$outputWalker = CountOutputWalker::class;
if (version_compare($version, '3.3.0', '>=')) {
$outputWalker = CountOutputWalker33::class;
} elseif (version_compare($version, '3.0.0', '>=')) {
$outputWalker = CountOutputWalker30::class;
} else {
$outputWalker = CountOutputWalker2::class;
}
Expand Down
3 changes: 2 additions & 1 deletion phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ parameters:
excludePaths:
- tests/var
- tests/src/App/Factory
- packages/rekapager-doctrine-orm-adapter/src/Internal/CountOutputWalker.php
- packages/rekapager-doctrine-orm-adapter/src/Internal/CountOutputWalker33.php
- packages/rekapager-doctrine-orm-adapter/src/Internal/CountOutputWalker30.php
- packages/rekapager-doctrine-orm-adapter/src/Internal/CountOutputWalker2.php
ignoreErrors:
- '#Rekalogika\\Rekapager\\Tests\\App\\Entity\\Post> given.#'
Expand Down
3 changes: 2 additions & 1 deletion psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
<ignoreFiles>
<directory name="vendor" />
<directory name="tests/src/App/Factory" />
<file name="packages/rekapager-doctrine-orm-adapter/src/Internal/CountOutputWalker.php" />
<file name="packages/rekapager-doctrine-orm-adapter/src/Internal/CountOutputWalker30.php" />
<file name="packages/rekapager-doctrine-orm-adapter/src/Internal/CountOutputWalker33.php" />
<file name="packages/rekapager-doctrine-orm-adapter/src/Internal/CountOutputWalker2.php" />
</ignoreFiles>
</projectFiles>
Expand Down

0 comments on commit 186147f

Please sign in to comment.