From 1dc61d4e3f3016efd04ce81e96c51bba2e44f6e3 Mon Sep 17 00:00:00 2001 From: Maciej Malarz Date: Fri, 15 Apr 2022 20:41:23 +0200 Subject: [PATCH] Allow doctrine/persistence ^3.0 --- UPGRADE-2.4.md | 11 ++++++++ composer.json | 2 +- .../ODM/MongoDB/Event/OnClearEventArgs.php | 7 +++-- .../ODM/MongoDB/Mapping/ClassMetadata.php | 28 +++++++++++++++++++ .../MongoDB/Mapping/ClassMetadataFactory.php | 14 +++++++++- .../ODM/MongoDB/Mapping/Driver/XmlDriver.php | 3 ++ .../MongoDB/Repository/DocumentRepository.php | 3 ++ phpstan-baseline.neon | 6 ++++ psalm-baseline.xml | 19 +++++++++++-- 9 files changed, 87 insertions(+), 6 deletions(-) diff --git a/UPGRADE-2.4.md b/UPGRADE-2.4.md index 973d07863c..e3fb067781 100644 --- a/UPGRADE-2.4.md +++ b/UPGRADE-2.4.md @@ -14,6 +14,17 @@ private int $myProp; This property will be stored in DB as `string` but casted back to `int`. Please note that at this time, due to backward compatibility reasons, nullable type does not imply `nullable` mapping. +## doctrine/persistence ^2.4 || ^3.0 + +ODM now supports two major versions of `doctrine/persistence` and provides forward compatibility where possible. +We strongly recommend checking [package's upgrade notes](https://github.com/doctrine/persistence/blob/3.0.x/UPGRADE.md) +and [ODM's todo list](https://github.com/doctrine/mongodb-odm/issues/2419). Please require 2.x version of +`doctrine/persistence` in your composer.json should you need to use functionalities without a forward +compatibility layer. Most notable examples are: + +* removed `LifecycleEventArgs::getEntity()` +* removed support for short namespace aliases + ## BC Break: `AttributeDriver` and `AnnotationDriver` no longer extends parent class from `doctrine/persistence` Both these classes used to extend an abstract `AnnotationDriver` class defined diff --git a/composer.json b/composer.json index f6c4c911e3..0c65dd7540 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "doctrine/collections": "^1.5", "doctrine/event-manager": "^1.0", "doctrine/instantiator": "^1.1", - "doctrine/persistence": "^2.4", + "doctrine/persistence": "^2.4 || ^3.0", "friendsofphp/proxy-manager-lts": "^1.0", "jean85/pretty-package-versions": "^1.3.0 || ^2.0.1", "mongodb/mongodb": "^1.2.0", diff --git a/lib/Doctrine/ODM/MongoDB/Event/OnClearEventArgs.php b/lib/Doctrine/ODM/MongoDB/Event/OnClearEventArgs.php index 7ce68d01fa..53aee99815 100644 --- a/lib/Doctrine/ODM/MongoDB/Event/OnClearEventArgs.php +++ b/lib/Doctrine/ODM/MongoDB/Event/OnClearEventArgs.php @@ -24,6 +24,9 @@ final class OnClearEventArgs extends BaseOnClearEventArgs */ private $entityClass; + /** + * @param class-string|null $entityClass + */ public function __construct($objectManager, $entityClass = null) { if (method_exists(parent::class, 'getEntityClass') && $entityClass !== null) { @@ -90,7 +93,7 @@ public function clearsAllDocuments(): bool /** * @deprecated no replacement planned */ - public function clearsAllEntities() + public function clearsAllEntities(): bool { if (method_exists(parent::class, 'clearsAllEntities')) { return parent::clearsAllEntities(); @@ -111,7 +114,7 @@ public function clearsAllEntities() * * @return class-string|null */ - public function getEntityClass() + public function getEntityClass(): ?string { if (method_exists(parent::class, 'getEntityClass')) { return parent::getEntityClass(); diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php index 7e9dcb2fb6..fc33d8aaee 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php @@ -793,6 +793,9 @@ public function getReflectionClass(): ReflectionClass return $this->reflClass; } + /** + * @param string $fieldName + */ public function isIdentifier($fieldName): bool { return $this->identifier === $fieldName; @@ -811,6 +814,8 @@ public function setIdentifier(?string $identifier): void /** * Since MongoDB only allows exactly one identifier field * this will always return an array with only one value + * + * @return array */ public function getIdentifier(): array { @@ -828,6 +833,9 @@ public function getIdentifierFieldNames(): array return [$this->identifier]; } + /** + * @param string $fieldName + */ public function hasField($fieldName): bool { return isset($this->fieldMappings[$fieldName]); @@ -1631,6 +1639,8 @@ public function hasEmbed(string $fieldName): bool /** * Checks whether the class has a mapped association (embed or reference) with the given field name. + * + * @param string $fieldName */ public function hasAssociation($fieldName): bool { @@ -1640,6 +1650,8 @@ public function hasAssociation($fieldName): bool /** * Checks whether the class has a mapped reference or embed for the specified field and * is a single valued association. + * + * @param string $fieldName */ public function isSingleValuedAssociation($fieldName): bool { @@ -1649,6 +1661,8 @@ public function isSingleValuedAssociation($fieldName): bool /** * Checks whether the class has a mapped reference or embed for the specified field and * is a collection valued association. + * + * @param string $fieldName */ public function isCollectionValuedAssociation($fieldName): bool { @@ -1758,6 +1772,8 @@ public function getIdentifierValue(object $document) * Since MongoDB only allows exactly one identifier field this is a proxy * to {@see getIdentifierValue()} and returns an array with the identifier * field as a key. + * + * @param object $object */ public function getIdentifierValues($object): array { @@ -2082,12 +2098,18 @@ public function getAssociationNames(): array return array_keys($this->associationMappings); } + /** + * @param string $fieldName + */ public function getTypeOfField($fieldName): ?string { return isset($this->fieldMappings[$fieldName]) ? $this->fieldMappings[$fieldName]['type'] : null; } + /** + * @param string $assocName + */ public function getAssociationTargetClass($assocName): ?string { if (! isset($this->associationMappings[$assocName])) { @@ -2113,11 +2135,17 @@ public function getAssociationCollectionClass(string $assocName): string return $this->associationMappings[$assocName]['collectionClass']; } + /** + * @param string $assocName + */ public function isAssociationInverseSide($assocName): bool { throw new BadMethodCallException(__METHOD__ . '() is not implemented yet.'); } + /** + * @param string $assocName + */ public function getAssociationMappedByTargetField($assocName) { throw new BadMethodCallException(__METHOD__ . '() is not implemented yet.'); diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php index f948ec6c44..ee0679cbe2 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php @@ -83,6 +83,9 @@ protected function initialize(): void $this->initialized = true; } + /** + * @param string $className + */ protected function onNotFoundMetadata($className) { if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) { @@ -96,12 +99,18 @@ protected function onNotFoundMetadata($className) return $eventArgs->getFoundMetadata(); } + /** + * @deprecated + * + * @param string $namespaceAlias + * @param string $simpleClassName + */ protected function getFqcnFromAlias($namespaceAlias, $simpleClassName): string { return $this->config->getDocumentNamespace($namespaceAlias) . '\\' . $simpleClassName; } - protected function getDriver() + protected function getDriver(): MappingDriver { return $this->driver; } @@ -121,6 +130,9 @@ protected function isEntity(ClassMetadataInterface $class): bool return ! $class->isMappedSuperclass && ! $class->isEmbeddedDocument && ! $class->isQueryResultDocument && ! $class->isView(); } + /** + * @param bool $rootEntityFound + */ protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents = []): void { assert($class instanceof ClassMetadata); diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php index 0f067d4b01..c533ef2c98 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php @@ -71,6 +71,9 @@ class XmlDriver extends FileDriver ], ]; + /** + * @param string|null $fileExtension + */ public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION) { parent::__construct($locator, $fileExtension); diff --git a/lib/Doctrine/ODM/MongoDB/Repository/DocumentRepository.php b/lib/Doctrine/ODM/MongoDB/Repository/DocumentRepository.php index 04e3faf952..5305f896d2 100644 --- a/lib/Doctrine/ODM/MongoDB/Repository/DocumentRepository.php +++ b/lib/Doctrine/ODM/MongoDB/Repository/DocumentRepository.php @@ -165,6 +165,9 @@ public function findAll(): array /** * Finds documents by a set of criteria. + * + * @param int|null $limit + * @param int|null $offset */ public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6b30c745fa..7ddfdda979 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -263,6 +263,12 @@ parameters: count: 1 path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php + # compatibility layer for doctrine/persistence ^2.4 || ^3.0 + - + message: "#.*#" + count: 3 + path: lib/Doctrine/ODM/MongoDB/Event/OnClearEventArgs + - message: "#Property .+ is never written, only read.#" path: tests diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 393ef04b8c..53bb92e1cc 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + $this->num($limit) @@ -8,6 +8,11 @@ self + + + parent::__construct($objectManager, $entityClass) + + TValue|false @@ -19,12 +24,17 @@ - + + array<string|null> array<string|null> [$this->identifier => $this->getIdentifierValue($object)] + + ?string + array + @@ -87,6 +97,11 @@ $options + ['metadata' => (object) $metadata] + + + array + + $datetime instanceof DateTime