diff --git a/composer.json b/composer.json index fe5766f6..67298cb6 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ }, "require-dev": { "doctrine/annotations": "^2.0", - "doctrine/orm": "^2.9", + "doctrine/orm": "^2.9|^3.0", "matthiasnoback/symfony-dependency-injection-test": "^4.3 || ^5.0", "nyholm/psr7": "^1.5.1", "php-cs-fixer/shim": "^3.14", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 5246556d..28e5679a 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -5,3 +5,5 @@ parameters: paths: - src - tests + ignoreErrors: + - '#Call to static method getClass\(\) on an unknown class Doctrine\\Common\\Util\\ClassUtils#' diff --git a/src/Services/MeilisearchService.php b/src/Services/MeilisearchService.php index 4325388e..c899e212 100644 --- a/src/Services/MeilisearchService.php +++ b/src/Services/MeilisearchService.php @@ -5,6 +5,7 @@ namespace Meilisearch\Bundle\Services; use Doctrine\Common\Util\ClassUtils; +use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver; use Doctrine\Persistence\ObjectManager; use Meilisearch\Bundle\Collection; use Meilisearch\Bundle\Engine; @@ -236,7 +237,7 @@ private function getBaseClassName($objectOrClass): string } if (is_object($objectOrClass)) { - return ClassUtils::getClass($objectOrClass); + return self::resolveClass($objectOrClass); } return $objectOrClass; @@ -306,7 +307,7 @@ private function getAggregatorsFromEntities(ObjectManager $objectManager, array $aggregators = []; foreach ($entities as $entity) { - $entityClassName = ClassUtils::getClass($entity); + $entityClassName = self::resolveClass($entity); if (array_key_exists($entityClassName, $this->entitiesAggregators)) { foreach ($this->entitiesAggregators[$entityClassName] as $aggregator) { $aggregators[] = new $aggregator( @@ -367,4 +368,21 @@ private function assertIsSearchable(string $className): void throw new Exception('Class '.$className.' is not searchable.'); } } + + private static function resolveClass(object $object): string + { + static $resolver; + + $resolver ??= (function () { + // Doctrine ORM v3+ compatibility + if (\class_exists(DefaultProxyClassNameResolver::class)) { + return fn (object $object) => DefaultProxyClassNameResolver::getClass($object); + } + + // Legacy Doctrine ORM compatibility + return fn (object $object) => ClassUtils::getClass($object); // @codeCoverageIgnore + })(); + + return $resolver($object); + } } diff --git a/tests/Dbal/Type/DummyObjectIdType.php b/tests/Dbal/Type/DummyObjectIdType.php index 160f7f02..66f10d14 100644 --- a/tests/Dbal/Type/DummyObjectIdType.php +++ b/tests/Dbal/Type/DummyObjectIdType.php @@ -28,7 +28,9 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?DummyObj } if (!\is_string($value) && !is_int($value)) { - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', 'int', DummyObjectId::class]); + $actualType = \get_debug_type($value); + $possibleTypes = ['null', 'string', 'int', self::class]; + throw new ConversionException(\sprintf("Could not convert PHP value '%s' of type '%s' to type '%s'. Expected one of the following types: %s", $value, $actualType, $this->getName(), \implode(', ', $possibleTypes))); } return new DummyObjectId((int) $value); @@ -48,7 +50,9 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform): ?int } if (!\is_string($value) && !is_int($value)) { - throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string', 'int', DummyObjectId::class]); + $actualType = \get_debug_type($value); + $possibleTypes = ['null', 'string', 'int', self::class]; + throw new ConversionException(\sprintf("Could not convert PHP value '%s' of type '%s' to type '%s'. Expected one of the following types: %s", $value, $actualType, $this->getName(), \implode(', ', $possibleTypes))); } return (int) $value;