From b513f7c935c6f6b560d4e4337cc300373da0e31c Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 27 Dec 2021 13:05:20 +0100 Subject: [PATCH 1/6] Bump reusable workflows --- .github/workflows/coding-standard.yml | 2 +- .github/workflows/release-on-milestone-closed.yml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/coding-standard.yml b/.github/workflows/coding-standard.yml index 8e9b6a40c68..a02f52cfe2d 100644 --- a/.github/workflows/coding-standard.yml +++ b/.github/workflows/coding-standard.yml @@ -10,6 +10,6 @@ on: jobs: coding-standards: - uses: "doctrine/.github/.github/workflows/coding-standards.yml@1.1.1" + uses: "doctrine/.github/.github/workflows/coding-standards.yml@1.4.1" with: php-version: "7.4" diff --git a/.github/workflows/release-on-milestone-closed.yml b/.github/workflows/release-on-milestone-closed.yml index ea567791392..b8645ec65cd 100644 --- a/.github/workflows/release-on-milestone-closed.yml +++ b/.github/workflows/release-on-milestone-closed.yml @@ -7,9 +7,8 @@ on: jobs: release: - uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@1.1.1" + uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@1.4.1" secrets: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }} GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }} ORGANIZATION_ADMIN_TOKEN: ${{ secrets.ORGANIZATION_ADMIN_TOKEN }} From 92ff9c91083f4f23160d780a8c5d354b294e7e52 Mon Sep 17 00:00:00 2001 From: David ALLIX Date: Mon, 27 Dec 2021 19:03:47 +0100 Subject: [PATCH 2/6] Allow arithmetic expressions within IN operator (#9242) * allow arithmetic expressions within IN operator Co-authored-by: Artem Stepin --- .../reference/dql-doctrine-query-language.rst | 2 +- lib/Doctrine/ORM/Query/Parser.php | 6 ++-- lib/Doctrine/ORM/Query/SqlWalker.php | 2 +- .../ORM/Functional/QueryDqlFunctionTest.php | 33 +++++++++++++++++++ .../ORM/Query/SelectSqlGenerationTest.php | 14 ++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/docs/en/reference/dql-doctrine-query-language.rst b/docs/en/reference/dql-doctrine-query-language.rst index 632d729ffb8..24488dec264 100644 --- a/docs/en/reference/dql-doctrine-query-language.rst +++ b/docs/en/reference/dql-doctrine-query-language.rst @@ -1724,7 +1724,7 @@ Literal Values .. code-block:: php Literal ::= string | char | integer | float | boolean - InParameter ::= Literal | InputParameter + InParameter ::= ArithmeticExpression | InputParameter Input Parameter ~~~~~~~~~~~~~~~ diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index 3e5bcf4d1b5..baab67c0800 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -2758,9 +2758,9 @@ public function Literal() } /** - * InParameter ::= Literal | InputParameter + * InParameter ::= ArithmeticExpression | InputParameter * - * @return AST\InputParameter|AST\Literal + * @return AST\InputParameter|AST\ArithmeticExpression */ public function InParameter() { @@ -2768,7 +2768,7 @@ public function InParameter() return $this->InputParameter(); } - return $this->Literal(); + return $this->ArithmeticExpression(); } /** diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 2a1139181cb..d896f857285 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -2106,7 +2106,7 @@ public function walkInParameter($inParam) { return $inParam instanceof AST\InputParameter ? $this->walkInputParameter($inParam) - : $this->walkLiteral($inParam); + : $this->walkArithmeticExpression($inParam); } /** diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php index 316d47d8656..745cec914bf 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryDqlFunctionTest.php @@ -420,6 +420,39 @@ public function testBitAndComparison(): void self::assertEquals($result[3][0]['salary'] / 100000 & 2, $result[3]['salary_bit_and']); } + public function testInArithmeticExpression1(): void + { + $dql = <<<'SQL' + SELECT m, m.name AS m_name + FROM Doctrine\Tests\Models\Company\CompanyManager m + WHERE m.salary IN (800000 / 8, 100000 * 2) +SQL; + + $result = $this->_em->createQuery($dql)->getArrayResult(); + + self::assertCount(2, $result); + self::assertEquals('Roman B.', $result[0]['m_name']); + self::assertEquals('Benjamin E.', $result[1]['m_name']); + } + + public function testInArithmeticExpression2(): void + { + $this->_em->getConfiguration()->addCustomStringFunction('FOO', static function ($funcName) { + return new NoOp($funcName); // See Doctrine/Tests/ORM/Functional/CustomFunctionsTest + }); + + $dql = <<<'SQL' + SELECT m, m.name AS m_name + FROM Doctrine\Tests\Models\Company\CompanyManager m + WHERE m.department IN (FOO('Administration')) +SQL; + + $result = $this->_em->createQuery($dql)->getArrayResult(); + + self::assertCount(1, $result); + self::assertEquals('Jonathan W.', $result[0]['m_name']); + } + protected function generateFixture(): void { $manager1 = new CompanyManager(); diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 710a03accbf..efc1cd94c18 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -643,6 +643,20 @@ public function testInvalidInExpressionWithSingleValuedAssociationPathExpression ); } + public function testInExpressionWithArithmeticExpression(): void + { + $this->entityManager->getConfiguration()->addCustomStringFunction('FOO', MyAbsFunction::class); + + $this->assertSqlGeneration( + "SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.username IN (FOO('Lo'), 'Lo', :name)", + "SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.username IN (ABS('Lo'), 'Lo', ?)" + ); + $this->assertSqlGeneration( + 'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u WHERE u.id IN (1 + 1)', + 'SELECT f0_.id AS id_0, f0_.username AS username_1 FROM forum_users f0_ WHERE f0_.id IN (1 + 1)' + ); + } + public function testSupportsConcatFunctionForMysqlAndPostgresql(): void { $connMock = $this->entityManager->getConnection(); From 2ddeb79431eb92cd6db66fa52f63e17a21ddd911 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 27 Dec 2021 23:43:09 +0100 Subject: [PATCH 3/6] Fix union type on QueryExpressionVisitorTest::testWalkComparison() (#9294) --- .../Tests/ORM/Query/QueryExpressionVisitorTest.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Query/QueryExpressionVisitorTest.php b/tests/Doctrine/Tests/ORM/Query/QueryExpressionVisitorTest.php index c06586fff20..054adcacede 100644 --- a/tests/Doctrine/Tests/ORM/Query/QueryExpressionVisitorTest.php +++ b/tests/Doctrine/Tests/ORM/Query/QueryExpressionVisitorTest.php @@ -27,7 +27,7 @@ protected function setUp(): void } /** - * @param QueryBuilder\Comparison|string $queryExpr + * @param QueryBuilder\Comparison|QueryBuilder\Func|string $queryExpr * * @dataProvider comparisonData */ @@ -39,7 +39,13 @@ public function testWalkComparison(CriteriaComparison $criteriaExpr, $queryExpr, } } - /** @psalm-return list + */ public function comparisonData(): array { $cb = new CriteriaBuilder(); From ab98d0ffc6d7538aa43ad4f57fac2e5722505f22 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 28 Dec 2021 00:49:32 +0100 Subject: [PATCH 4/6] Synchronize Psalm baseline (#9296) --- psalm-baseline.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index b691d93cae5..f97d08514de 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -3760,11 +3760,6 @@ $indexName - - - isAbstract - - new ClassLoader('Doctrine', $directory) From 6a9393e8edafab29ca5cad18f6eee7139800d7fc Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 28 Dec 2021 00:49:50 +0100 Subject: [PATCH 5/6] Fix return type (#9295) --- tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php b/tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php index 02e9e6dd966..d687a82041a 100644 --- a/tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php +++ b/tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php @@ -30,7 +30,7 @@ public function testInvalidEntityName($value, string $expectedMessage): void } /** - * @return string[][] + * @psalm-return list */ public function invalidEntityNames(): array { From 70dcffa0259161495c136fed9cfcbbd1441687a1 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 28 Dec 2021 08:02:16 +0100 Subject: [PATCH 6/6] Leverage get_debug_type() (#9297) --- .../MetadataCacheUsesNonPersistentCache.php | 4 ++-- .../QueryCacheUsesNonPersistentCache.php | 4 ++-- .../ORM/Decorator/EntityManagerDecorator.php | 4 ++-- lib/Doctrine/ORM/EntityManager.php | 4 ++-- lib/Doctrine/ORM/EntityNotFoundException.php | 2 -- lib/Doctrine/ORM/Event/PreUpdateEventArgs.php | 4 ++-- .../ORM/Exception/EntityMissingAssignedId.php | 4 ++-- .../ORM/Mapping/Exception/CannotGenerateIds.php | 4 ++-- lib/Doctrine/ORM/ORMException.php | 6 +++--- lib/Doctrine/ORM/ORMInvalidArgumentException.php | 9 ++++----- lib/Doctrine/ORM/Query/AST/ASTException.php | 4 ++-- lib/Doctrine/ORM/Query/AST/Node.php | 6 +++--- lib/Doctrine/ORM/Query/Expr/Base.php | 15 ++++++--------- .../ClearCache/CollectionRegionCommand.php | 6 ++---- .../Command/ClearCache/EntityRegionCommand.php | 6 ++---- .../Console/Command/ClearCache/QueryCommand.php | 6 +++--- .../Command/ClearCache/QueryRegionCommand.php | 6 ++---- .../Console/Command/ClearCache/ResultCommand.php | 6 +++--- .../Console/Command/MappingDescribeCommand.php | 4 ++-- lib/Doctrine/ORM/UnitOfWork.php | 7 ++++--- phpstan-baseline.neon | 7 +------ psalm-baseline.xml | 15 ++------------- tests/Doctrine/Tests/ORM/EntityManagerTest.php | 2 +- .../ORM/Functional/ClassTableInheritanceTest.php | 3 ++- .../Tests/ORM/Functional/Ticket/DDC1383Test.php | 6 +++--- .../Tests/ORM/Functional/Ticket/DDC1655Test.php | 3 ++- .../ORM/Mapping/AbstractMappingDriverTest.php | 4 ++-- .../Tests/ORM/ORMInvalidArgumentExceptionTest.php | 10 +++++----- tests/Doctrine/Tests/OrmFunctionalTestCase.php | 6 +++--- tests/Doctrine/Tests/TestUtil.php | 4 ++-- 30 files changed, 73 insertions(+), 98 deletions(-) diff --git a/lib/Doctrine/ORM/Cache/Exception/MetadataCacheUsesNonPersistentCache.php b/lib/Doctrine/ORM/Cache/Exception/MetadataCacheUsesNonPersistentCache.php index 60f01eb5a51..1073b98bacd 100644 --- a/lib/Doctrine/ORM/Cache/Exception/MetadataCacheUsesNonPersistentCache.php +++ b/lib/Doctrine/ORM/Cache/Exception/MetadataCacheUsesNonPersistentCache.php @@ -6,14 +6,14 @@ use Doctrine\Common\Cache\Cache; -use function get_class; +use function get_debug_type; final class MetadataCacheUsesNonPersistentCache extends CacheException { public static function fromDriver(Cache $cache): self { return new self( - 'Metadata Cache uses a non-persistent cache driver, ' . get_class($cache) . '.' + 'Metadata Cache uses a non-persistent cache driver, ' . get_debug_type($cache) . '.' ); } } diff --git a/lib/Doctrine/ORM/Cache/Exception/QueryCacheUsesNonPersistentCache.php b/lib/Doctrine/ORM/Cache/Exception/QueryCacheUsesNonPersistentCache.php index 393591d759b..e5aa76491cb 100644 --- a/lib/Doctrine/ORM/Cache/Exception/QueryCacheUsesNonPersistentCache.php +++ b/lib/Doctrine/ORM/Cache/Exception/QueryCacheUsesNonPersistentCache.php @@ -6,14 +6,14 @@ use Doctrine\Common\Cache\Cache; -use function get_class; +use function get_debug_type; final class QueryCacheUsesNonPersistentCache extends CacheException { public static function fromDriver(Cache $cache): self { return new self( - 'Query Cache uses a non-persistent cache driver, ' . get_class($cache) . '.' + 'Query Cache uses a non-persistent cache driver, ' . get_debug_type($cache) . '.' ); } } diff --git a/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php b/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php index f7a3bf55d50..fd60b164cb0 100644 --- a/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php +++ b/lib/Doctrine/ORM/Decorator/EntityManagerDecorator.php @@ -8,7 +8,7 @@ use Doctrine\ORM\Query\ResultSetMapping; use Doctrine\Persistence\ObjectManagerDecorator; -use function get_class; +use function get_debug_type; use function method_exists; use function sprintf; use function trigger_error; @@ -67,7 +67,7 @@ public function wrapInTransaction(callable $func) { if (! method_exists($this->wrapped, 'wrapInTransaction')) { trigger_error( - sprintf('Calling `transactional()` instead of `wrapInTransaction()` which is not implemented on %s', get_class($this->wrapped)), + sprintf('Calling `transactional()` instead of `wrapInTransaction()` which is not implemented on %s', get_debug_type($this->wrapped)), E_USER_NOTICE ); diff --git a/lib/Doctrine/ORM/EntityManager.php b/lib/Doctrine/ORM/EntityManager.php index 5b861f4dc21..fe3888a0db4 100644 --- a/lib/Doctrine/ORM/EntityManager.php +++ b/lib/Doctrine/ORM/EntityManager.php @@ -32,7 +32,7 @@ use function array_keys; use function call_user_func; -use function get_class; +use function get_debug_type; use function gettype; use function is_array; use function is_callable; @@ -948,7 +948,7 @@ protected static function createConnection($connection, Configuration $config, ? throw new InvalidArgumentException( sprintf( 'Invalid $connection argument of type %s given%s.', - is_object($connection) ? get_class($connection) : gettype($connection), + get_debug_type($connection), is_object($connection) ? '' : ': "' . $connection . '"' ) ); diff --git a/lib/Doctrine/ORM/EntityNotFoundException.php b/lib/Doctrine/ORM/EntityNotFoundException.php index ff59a3be7c0..76abf4dbc91 100644 --- a/lib/Doctrine/ORM/EntityNotFoundException.php +++ b/lib/Doctrine/ORM/EntityNotFoundException.php @@ -37,8 +37,6 @@ public static function fromClassNameAndIdentifier($className, array $id) /** * Instance for which no identifier can be found - * - * @psalm-param class-string $className */ public static function noIdentifierFound(string $className): self { diff --git a/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php b/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php index 4ac4bbd15b0..ba578fdad10 100644 --- a/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php +++ b/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php @@ -8,7 +8,7 @@ use Doctrine\ORM\PersistentCollection; use InvalidArgumentException; -use function get_class; +use function get_debug_type; use function sprintf; /** @@ -108,7 +108,7 @@ private function assertValidField(string $field): void throw new InvalidArgumentException(sprintf( 'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.', $field, - get_class($this->getEntity()) + get_debug_type($this->getEntity()) )); } } diff --git a/lib/Doctrine/ORM/Exception/EntityMissingAssignedId.php b/lib/Doctrine/ORM/Exception/EntityMissingAssignedId.php index 194c76cabe5..2cda5b6a966 100644 --- a/lib/Doctrine/ORM/Exception/EntityMissingAssignedId.php +++ b/lib/Doctrine/ORM/Exception/EntityMissingAssignedId.php @@ -4,7 +4,7 @@ namespace Doctrine\ORM\Exception; -use function get_class; +use function get_debug_type; final class EntityMissingAssignedId extends ORMException { @@ -13,7 +13,7 @@ final class EntityMissingAssignedId extends ORMException */ public static function forField($entity, string $field): self { - return new self('Entity of type ' . get_class($entity) . " is missing an assigned ID for field '" . $field . "'. " . + return new self('Entity of type ' . get_debug_type($entity) . " is missing an assigned ID for field '" . $field . "'. " . 'The identifier generation strategy for this entity requires the ID field to be populated before ' . 'EntityManager#persist() is called. If you want automatically generated identifiers instead ' . 'you need to adjust the metadata mapping accordingly.'); diff --git a/lib/Doctrine/ORM/Mapping/Exception/CannotGenerateIds.php b/lib/Doctrine/ORM/Mapping/Exception/CannotGenerateIds.php index 408b45b5da3..e244e449d3c 100644 --- a/lib/Doctrine/ORM/Mapping/Exception/CannotGenerateIds.php +++ b/lib/Doctrine/ORM/Mapping/Exception/CannotGenerateIds.php @@ -7,7 +7,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\ORM\Exception\ORMException; -use function get_class; +use function get_debug_type; use function sprintf; final class CannotGenerateIds extends ORMException @@ -16,7 +16,7 @@ public static function withPlatform(AbstractPlatform $platform): self { return new self(sprintf( 'Platform %s does not support generating identifiers', - get_class($platform) + get_debug_type($platform) )); } } diff --git a/lib/Doctrine/ORM/ORMException.php b/lib/Doctrine/ORM/ORMException.php index a5232b03b96..eb5aa6c7b40 100644 --- a/lib/Doctrine/ORM/ORMException.php +++ b/lib/Doctrine/ORM/ORMException.php @@ -8,7 +8,7 @@ use Doctrine\Persistence\ObjectRepository; use Exception; -use function get_class; +use function get_debug_type; use function implode; use function sprintf; @@ -218,7 +218,7 @@ public static function metadataCacheNotConfigured() */ public static function queryCacheUsesNonPersistentCache(CacheDriver $cache) { - return new self('Query Cache uses a non-persistent cache driver, ' . get_class($cache) . '.'); + return new self('Query Cache uses a non-persistent cache driver, ' . get_debug_type($cache) . '.'); } /** @@ -228,7 +228,7 @@ public static function queryCacheUsesNonPersistentCache(CacheDriver $cache) */ public static function metadataCacheUsesNonPersistentCache(CacheDriver $cache) { - return new self('Metadata Cache uses a non-persistent cache driver, ' . get_class($cache) . '.'); + return new self('Metadata Cache uses a non-persistent cache driver, ' . get_debug_type($cache) . '.'); } /** diff --git a/lib/Doctrine/ORM/ORMInvalidArgumentException.php b/lib/Doctrine/ORM/ORMInvalidArgumentException.php index 42782f9bcf0..cc61f056a20 100644 --- a/lib/Doctrine/ORM/ORMInvalidArgumentException.php +++ b/lib/Doctrine/ORM/ORMInvalidArgumentException.php @@ -9,10 +9,9 @@ use function array_map; use function count; -use function get_class; +use function get_debug_type; use function gettype; use function implode; -use function is_object; use function method_exists; use function reset; use function spl_object_id; @@ -218,7 +217,7 @@ public static function invalidAssociation(ClassMetadata $targetClass, $assoc, $a $expectedType, $assoc['sourceEntity'], $assoc['fieldName'], - is_object($actualValue) ? get_class($actualValue) : gettype($actualValue) + get_debug_type($actualValue) )); } @@ -231,7 +230,7 @@ public static function invalidAssociation(ClassMetadata $targetClass, $assoc, $a */ public static function invalidEntityName($entityName) { - return new self(sprintf('Entity name must be a string, %s given', gettype($entityName))); + return new self(sprintf('Entity name must be a string, %s given', get_debug_type($entityName))); } /** @@ -241,7 +240,7 @@ public static function invalidEntityName($entityName) */ private static function objToStr($obj): string { - return method_exists($obj, '__toString') ? (string) $obj : get_class($obj) . '@' . spl_object_id($obj); + return method_exists($obj, '__toString') ? (string) $obj : get_debug_type($obj) . '@' . spl_object_id($obj); } /** diff --git a/lib/Doctrine/ORM/Query/AST/ASTException.php b/lib/Doctrine/ORM/Query/AST/ASTException.php index d44a343d733..de99519a367 100644 --- a/lib/Doctrine/ORM/Query/AST/ASTException.php +++ b/lib/Doctrine/ORM/Query/AST/ASTException.php @@ -6,7 +6,7 @@ use Doctrine\ORM\Query\QueryException; -use function get_class; +use function get_debug_type; /** * Base exception class for AST exceptions. @@ -20,6 +20,6 @@ class ASTException extends QueryException */ public static function noDispatchForNode($node) { - return new self('Double-dispatch for node ' . get_class($node) . ' is not supported.'); + return new self('Double-dispatch for node ' . get_debug_type($node) . ' is not supported.'); } } diff --git a/lib/Doctrine/ORM/Query/AST/Node.php b/lib/Doctrine/ORM/Query/AST/Node.php index 447352233e6..4bc3245d14b 100644 --- a/lib/Doctrine/ORM/Query/AST/Node.php +++ b/lib/Doctrine/ORM/Query/AST/Node.php @@ -6,7 +6,7 @@ use Doctrine\ORM\Query\SqlWalker; -use function get_class; +use function get_debug_type; use function get_object_vars; use function is_array; use function is_object; @@ -60,7 +60,7 @@ public function dump($obj) $str = ''; if ($obj instanceof Node) { - $str .= get_class($obj) . '(' . PHP_EOL; + $str .= get_debug_type($obj) . '(' . PHP_EOL; $props = get_object_vars($obj); foreach ($props as $name => $prop) { @@ -85,7 +85,7 @@ public function dump($obj) $ident -= 4; $str .= ($some ? PHP_EOL . str_repeat(' ', $ident) : '') . ')'; } elseif (is_object($obj)) { - $str .= 'instanceof(' . get_class($obj) . ')'; + $str .= 'instanceof(' . get_debug_type($obj) . ')'; } else { $str .= var_export($obj, true); } diff --git a/lib/Doctrine/ORM/Query/Expr/Base.php b/lib/Doctrine/ORM/Query/Expr/Base.php index cdbd51cd9c1..2933384b28f 100644 --- a/lib/Doctrine/ORM/Query/Expr/Base.php +++ b/lib/Doctrine/ORM/Query/Expr/Base.php @@ -8,6 +8,7 @@ use function count; use function get_class; +use function get_debug_type; use function implode; use function in_array; use function is_string; @@ -69,15 +70,11 @@ public function add($arg) { if ($arg !== null && (! $arg instanceof self || $arg->count() > 0)) { // If we decide to keep Expr\Base instances, we can use this check - if (! is_string($arg)) { - $class = get_class($arg); - - if (! in_array($class, $this->allowedClasses, true)) { - throw new InvalidArgumentException(sprintf( - "Expression of type '%s' not allowed in this context.", - $class - )); - } + if (! is_string($arg) && ! in_array(get_class($arg), $this->allowedClasses, true)) { + throw new InvalidArgumentException(sprintf( + "Expression of type '%s' not allowed in this context.", + get_debug_type($arg) + )); } $this->parts[] = $arg; diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php index bec83a52686..2548c3df207 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/CollectionRegionCommand.php @@ -14,9 +14,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use function get_class; -use function gettype; -use function is_object; +use function get_debug_type; use function sprintf; /** @@ -93,7 +91,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (! $collectionRegion instanceof DefaultRegion) { throw new InvalidArgumentException(sprintf( 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', - is_object($collectionRegion) ? get_class($collectionRegion) : gettype($collectionRegion) + get_debug_type($collectionRegion) )); } diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php index 1562cbbfc85..779666a6f60 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/EntityRegionCommand.php @@ -14,9 +14,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use function get_class; -use function gettype; -use function is_object; +use function get_debug_type; use function sprintf; /** @@ -91,7 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (! $entityRegion instanceof DefaultRegion) { throw new InvalidArgumentException(sprintf( 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', - is_object($entityRegion) ? get_class($entityRegion) : gettype($entityRegion) + get_debug_type($entityRegion) )); } diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php index f0fd4bfc695..b88e270609b 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php @@ -17,7 +17,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use function get_class; +use function get_debug_type; use function sprintf; /** @@ -84,7 +84,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (! ($cacheDriver instanceof ClearableCache)) { throw new LogicException(sprintf( 'Can only clear cache when ClearableCache interface is implemented, %s does not implement.', - get_class($cacheDriver) + get_debug_type($cacheDriver) )); } @@ -97,7 +97,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (! ($cacheDriver instanceof FlushableCache)) { throw new LogicException(sprintf( 'Can only clear cache when FlushableCache interface is implemented, %s does not implement.', - get_class($cacheDriver) + get_debug_type($cacheDriver) )); } diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php index 03f210ef94b..c5800953268 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php @@ -14,9 +14,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use function get_class; -use function gettype; -use function is_object; +use function get_debug_type; use function sprintf; /** @@ -90,7 +88,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (! $queryRegion instanceof DefaultRegion) { throw new InvalidArgumentException(sprintf( 'The option "--flush" expects a "Doctrine\ORM\Cache\Region\DefaultRegion", but got "%s".', - is_object($queryRegion) ? get_class($queryRegion) : gettype($queryRegion) + get_debug_type($queryRegion) )); } diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php index c7e52c6ebd1..e9336965958 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php @@ -18,7 +18,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use function get_class; +use function get_debug_type; use function method_exists; use function sprintf; @@ -86,7 +86,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (! $cache && ! ($cacheDriver instanceof ClearableCache)) { throw new LogicException(sprintf( 'Can only clear cache when ClearableCache interface is implemented, %s does not implement.', - get_class($cacheDriver) + get_debug_type($cacheDriver) )); } @@ -99,7 +99,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (! ($cacheDriver instanceof FlushableCache)) { throw new LogicException(sprintf( 'Can only clear cache when FlushableCache interface is implemented, %s does not implement.', - get_class($cacheDriver) + get_debug_type($cacheDriver) )); } diff --git a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php index 913711e32b6..5481ea371ec 100644 --- a/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php +++ b/lib/Doctrine/ORM/Tools/Console/Command/MappingDescribeCommand.php @@ -19,7 +19,7 @@ use function array_merge; use function count; use function current; -use function get_class; +use function get_debug_type; use function implode; use function is_array; use function is_bool; @@ -214,7 +214,7 @@ private function formatValue($value): string } if (is_object($value)) { - return sprintf('<%s>', get_class($value)); + return sprintf('<%s>', get_debug_type($value)); } if (is_scalar($value)) { diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 18541b5681c..865225c544c 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -56,6 +56,7 @@ use function count; use function current; use function get_class; +use function get_debug_type; use function implode; use function in_array; use function is_array; @@ -912,7 +913,7 @@ private function computeAssociationChanges(array $assoc, $value): void throw UnexpectedAssociationValue::create( $assoc['sourceEntity'], $assoc['fieldName'], - get_class($entry), + get_debug_type($entry), $assoc['targetEntity'] ); } @@ -3061,7 +3062,7 @@ public function setOriginalEntityProperty($oid, $property, $value) public function getEntityIdentifier($entity) { if (! isset($this->entityIdentifiers[spl_object_id($entity)])) { - throw EntityNotFoundException::noIdentifierFound(get_class($entity)); + throw EntityNotFoundException::noIdentifierFound(get_debug_type($entity)); } return $this->entityIdentifiers[spl_object_id($entity)]; @@ -3370,7 +3371,7 @@ public function initializeObject($obj) */ private static function objToStr($obj): string { - return method_exists($obj, '__toString') ? (string) $obj : get_class($obj) . '@' . spl_object_id($obj); + return method_exists($obj, '__toString') ? (string) $obj : get_debug_type($obj) . '@' . spl_object_id($obj); } /** diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index eaa04b2691e..a0b848e0c9d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -132,7 +132,7 @@ parameters: - message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#" - count: 2 + count: 1 path: lib/Doctrine/ORM/EntityManager.php - @@ -2041,11 +2041,6 @@ parameters: count: 1 path: lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryCommand.php - - - message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#" - count: 1 - path: lib/Doctrine/ORM/Tools/Console/Command/ClearCache/QueryRegionCommand.php - - message: "#^Class Doctrine\\\\Common\\\\Cache\\\\ApcCache not found\\.$#" count: 1 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 5c8bbbbb15a..e214b4b3b9a 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -464,13 +464,11 @@ new $metadataFactoryClassName() - - is_object($connection) + is_object($connection) - + ': "' . $connection . '"' - gettype($connection) @@ -3190,23 +3188,14 @@ - - gettype($queryRegion) - configure - - is_object($queryRegion) - configure - - $cacheDriver - diff --git a/tests/Doctrine/Tests/ORM/EntityManagerTest.php b/tests/Doctrine/Tests/ORM/EntityManagerTest.php index 0162f7d7d70..9e69504de99 100644 --- a/tests/Doctrine/Tests/ORM/EntityManagerTest.php +++ b/tests/Doctrine/Tests/ORM/EntityManagerTest.php @@ -275,7 +275,7 @@ public function transactionalCallback($em): string public function testCreateInvalidConnection(): void { $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid $connection argument of type integer given: "1".'); + $this->expectExceptionMessage('Invalid $connection argument of type int given: "1".'); $config = new Configuration(); $config->setMetadataDriverImpl($this->createMock(MappingDriver::class)); diff --git a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php index 98a922e94ba..cd2bcae877a 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ClassTableInheritanceTest.php @@ -19,6 +19,7 @@ use Doctrine\Tests\OrmFunctionalTestCase; use function get_class; +use function get_debug_type; use function sprintf; /** @@ -280,7 +281,7 @@ public function testLazyLoading2(): void $result = $q->getResult(); self::assertCount(1, $result); - self::assertInstanceOf(CompanyAuction::class, $result[0], sprintf('Is of class %s', get_class($result[0]))); + self::assertInstanceOf(CompanyAuction::class, $result[0], sprintf('Is of class %s', get_debug_type($result[0]))); $this->_em->clear(); diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1383Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1383Test.php index 44c40451db4..828d493d6d9 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1383Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1383Test.php @@ -15,7 +15,7 @@ use Doctrine\Tests\OrmFunctionalTestCase; use Exception; -use function get_class; +use function get_debug_type; /** * @group DDC-1383 @@ -59,13 +59,13 @@ public function testFailingCase(): void // Parent is not instance of the abstract class self::assertTrue( $parent instanceof DDC1383AbstractEntity, - 'Entity class is ' . get_class($parent) . ', "DDC1383AbstractEntity" was expected' + 'Entity class is ' . get_debug_type($parent) . ', "DDC1383AbstractEntity" was expected' ); // Parent is NOT instance of entity self::assertTrue( $parent instanceof DDC1383Entity, - 'Entity class is ' . get_class($parent) . ', "DDC1383Entity" was expected' + 'Entity class is ' . get_debug_type($parent) . ', "DDC1383Entity" was expected' ); } } diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1655Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1655Test.php index 599c28ab0fc..d483a974a09 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1655Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1655Test.php @@ -19,6 +19,7 @@ use Exception; use function get_class; +use function get_debug_type; /** * @group DDC-1655 @@ -65,7 +66,7 @@ public function testPostLoadOneToManyInheritance(): void $baz = $this->_em->find(get_class($baz), $baz->id); foreach ($baz->foos as $foo) { - self::assertEquals(1, $foo->loaded, 'should have loaded callback counter incremented for ' . get_class($foo)); + self::assertEquals(1, $foo->loaded, 'should have loaded callback counter incremented for ' . get_debug_type($foo)); } } diff --git a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php index cf0203374e0..8bd62625c3f 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php @@ -70,7 +70,7 @@ use function assert; use function count; -use function get_class; +use function get_debug_type; use function sprintf; use function strpos; use function strtolower; @@ -635,7 +635,7 @@ public function testNamedQuery(): void $driver = $this->loadDriver(); $class = $this->createClassMetadata(User::class); - self::assertCount(1, $class->getNamedQueries(), sprintf('Named queries not processed correctly by driver %s', get_class($driver))); + self::assertCount(1, $class->getNamedQueries(), sprintf('Named queries not processed correctly by driver %s', get_debug_type($driver))); } /** diff --git a/tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php b/tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php index d687a82041a..2b55c3fc6e7 100644 --- a/tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php +++ b/tests/Doctrine/Tests/ORM/ORMInvalidArgumentExceptionTest.php @@ -35,11 +35,11 @@ public function testInvalidEntityName($value, string $expectedMessage): void public function invalidEntityNames(): array { return [ - [null, 'Entity name must be a string, NULL given'], - [true, 'Entity name must be a string, boolean given'], - [123, 'Entity name must be a string, integer given'], - [123.45, 'Entity name must be a string, double given'], - [new stdClass(), 'Entity name must be a string, object given'], + [null, 'Entity name must be a string, null given'], + [true, 'Entity name must be a string, bool given'], + [123, 'Entity name must be a string, int given'], + [123.45, 'Entity name must be a string, float given'], + [new stdClass(), 'Entity name must be a string, stdClass given'], ]; } diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php index 478b154dc58..8e142e1c2f0 100644 --- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php +++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php @@ -36,7 +36,7 @@ use function array_slice; use function count; use function explode; -use function get_class; +use function get_debug_type; use function getenv; use function implode; use function is_object; @@ -823,7 +823,7 @@ protected function onNotSuccessfulTest(Throwable $e): void $last25queries = array_slice(array_reverse($this->_sqlLoggerStack->queries, true), 0, 25, true); foreach ($last25queries as $i => $query) { $params = array_map(static function ($p) { - return is_object($p) ? get_class($p) : var_export($p, true); + return is_object($p) ? get_debug_type($p) : var_export($p, true); }, $query['params'] ?: []); $queries .= $i . ". SQL: '" . $query['sql'] . "' Params: " . implode(', ', $params) . PHP_EOL; } @@ -841,7 +841,7 @@ protected function onNotSuccessfulTest(Throwable $e): void } } - $message = '[' . get_class($e) . '] ' . $e->getMessage() . PHP_EOL . PHP_EOL . 'With queries:' . PHP_EOL . $queries . PHP_EOL . 'Trace:' . PHP_EOL . $traceMsg; + $message = '[' . get_debug_type($e) . '] ' . $e->getMessage() . PHP_EOL . PHP_EOL . 'With queries:' . PHP_EOL . $queries . PHP_EOL . 'Trace:' . PHP_EOL . $traceMsg; throw new Exception($message, (int) $e->getCode(), $e); } diff --git a/tests/Doctrine/Tests/TestUtil.php b/tests/Doctrine/Tests/TestUtil.php index cb72f0f373c..f3bb3a1c212 100644 --- a/tests/Doctrine/Tests/TestUtil.php +++ b/tests/Doctrine/Tests/TestUtil.php @@ -12,7 +12,7 @@ use function explode; use function fwrite; -use function get_class; +use function get_debug_type; use function method_exists; use function sprintf; use function strlen; @@ -78,7 +78,7 @@ private static function initializeDatabase(): void // Note, writes direct to STDERR to prevent phpunit detecting output - otherwise this would cause either an // "unexpected output" warning or a failure on the first test case to call this method. - fwrite(STDERR, sprintf("\nUsing DB driver %s\n", get_class($testConn->getDriver()))); + fwrite(STDERR, sprintf("\nUsing DB driver %s\n", get_debug_type($testConn->getDriver()))); // Connect as a privileged user to create and drop the test database. $privConn = DriverManager::getConnection($privConnParams);