From 28ad9056f742bd8d175c5285738a00f563305465 Mon Sep 17 00:00:00 2001 From: Fran Moreno Date: Fri, 29 Apr 2022 13:54:05 +0200 Subject: [PATCH 1/2] Add iterable types --- .../ODM/MongoDB/Aggregation/Builder.php | 8 +- .../ODM/MongoDB/Aggregation/Stage/Sort.php | 12 ++- lib/Doctrine/ODM/MongoDB/DocumentManager.php | 5 ++ .../ODM/MongoDB/Mapping/ClassMetadata.php | 3 +- lib/Doctrine/ODM/MongoDB/MongoDBException.php | 4 +- .../PersistentCollectionFactory.php | 5 ++ .../PersistentCollectionInterface.php | 20 +++-- .../PersistentCollectionTrait.php | 4 +- .../Persisters/CollectionPersister.php | 35 ++++---- .../MongoDB/Persisters/DocumentPersister.php | 85 +++++++++++++++++-- .../MongoDB/Persisters/PersistenceBuilder.php | 22 ++--- lib/Doctrine/ODM/MongoDB/Query/Query.php | 4 +- phpstan-baseline.neon | 29 +++++++ psalm-baseline.xml | 13 +++ .../ODM/MongoDB/Tests/DocumentManagerTest.php | 5 +- .../Functional/CustomCollectionsTest.php | 3 +- .../Tests/Functional/ReferencePrimerTest.php | 6 +- 17 files changed, 207 insertions(+), 56 deletions(-) diff --git a/lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php b/lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php index f4bbb8d40a..120df14be1 100644 --- a/lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php +++ b/lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php @@ -4,6 +4,7 @@ namespace Doctrine\ODM\MongoDB\Aggregation; +use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Iterator\Iterator; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; @@ -26,6 +27,8 @@ /** * Fluent interface for building aggregation pipelines. + * + * @psalm-import-type SortShape from Sort */ class Builder { @@ -533,8 +536,9 @@ public function skip(int $skip): Stage\Skip * * @see https://docs.mongodb.com/manual/reference/operator/aggregation/sort/ * - * @param array|string $fieldName Field name or array of field/order pairs - * @param int|string $order Field order (if one field is specified) + * @param array>|string $fieldName Field name or array of field/order pairs + * @param int|string|null $order Field order (if one field is specified) + * @psalm-param SortShape|string $fieldName Field name or array of field/order pairs */ public function sort($fieldName, $order = null): Stage\Sort { diff --git a/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Sort.php b/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Sort.php index b930d8e9e3..ec4d282154 100644 --- a/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Sort.php +++ b/lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Sort.php @@ -14,15 +14,19 @@ /** * Fluent interface for adding a $sort stage to an aggregation pipeline. + * + * @psalm-type SortMeta = array{"$meta": 'textScore'} + * @psalm-type SortShape = array */ class Sort extends Stage { - /** @var array */ + /** @var array */ private $sort = []; /** - * @param array|string $fieldName Field name or array of field/order pairs - * @param int|string $order Field order (if one field is specified) + * @param array>|string $fieldName Field name or array of field/order pairs + * @param int|string $order Field order (if one field is specified) + * @psalm-param SortShape|string $fieldName */ public function __construct(Builder $builder, $fieldName, $order = null) { @@ -34,7 +38,7 @@ public function __construct(Builder $builder, $fieldName, $order = null) foreach ($fields as $fieldName => $order) { if (is_string($order)) { - if (in_array($order, $allowedMetaSort)) { + if (in_array($order, $allowedMetaSort, true)) { $order = ['$meta' => $order]; } else { $order = strtolower($order) === 'asc' ? 1 : -1; diff --git a/lib/Doctrine/ODM/MongoDB/DocumentManager.php b/lib/Doctrine/ODM/MongoDB/DocumentManager.php index a19ccf8e4e..13c9dc9b53 100644 --- a/lib/Doctrine/ODM/MongoDB/DocumentManager.php +++ b/lib/Doctrine/ODM/MongoDB/DocumentManager.php @@ -50,6 +50,7 @@ * $dm = DocumentManager::create(new Connection(), $config); * * @psalm-import-type CommitOptions from UnitOfWork + * @psalm-import-type FieldMapping from ClassMetadata */ class DocumentManager implements ObjectManager { @@ -760,6 +761,8 @@ public function getConfiguration(): Configuration /** * Returns a reference to the supplied document. * + * @psalm-param FieldMapping $referenceMapping + * * @return mixed The reference for the document in question, according to the desired mapping * * @throws MappingException @@ -816,8 +819,10 @@ public function createReference(object $document, array $referenceMapping) * * @param array $referenceMapping Mappings of reference for which discriminator data is created. * @param ClassMetadata $class Metadata of reference document class. + * @psalm-param FieldMapping $referenceMapping * * @return array with next structure [{discriminator field} => {discriminator value}] + * @psalm-return array * * @throws MappingException When discriminator map is present and reference class in not registered in it. */ diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php index fc33d8aaee..3d5d13ea90 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php @@ -591,7 +591,8 @@ * * @see discriminatorField * - * @var mixed + * @var string|null + * @psalm-var class-string|null */ public $discriminatorValue; diff --git a/lib/Doctrine/ODM/MongoDB/MongoDBException.php b/lib/Doctrine/ODM/MongoDB/MongoDBException.php index 5fdb6f3e11..b6281681dc 100644 --- a/lib/Doctrine/ODM/MongoDB/MongoDBException.php +++ b/lib/Doctrine/ODM/MongoDB/MongoDBException.php @@ -62,8 +62,8 @@ public static function invalidGridFSRepository(string $className): self } /** - * @param string|array $expected - * @param mixed $got + * @param string|string[] $expected + * @param mixed $got * * @return MongoDBException */ diff --git a/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionFactory.php b/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionFactory.php index 23c0aa0aab..56d5fa0059 100644 --- a/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionFactory.php +++ b/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionFactory.php @@ -6,14 +6,19 @@ use Doctrine\Common\Collections\Collection as BaseCollection; use Doctrine\ODM\MongoDB\DocumentManager; +use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; /** * Interface for persistent collection classes factory. + * + * @psalm-import-type FieldMapping from ClassMetadata */ interface PersistentCollectionFactory { /** * Creates specified persistent collection to work with given collection class. + * + * @psalm-param FieldMapping $mapping */ public function create(DocumentManager $dm, array $mapping, ?BaseCollection $coll = null): PersistentCollectionInterface; } diff --git a/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionInterface.php b/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionInterface.php index d600466a5a..cee160dfe7 100644 --- a/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionInterface.php +++ b/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionInterface.php @@ -7,6 +7,7 @@ use Doctrine\Common\Collections\Collection; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\MongoDBException; +use Doctrine\ODM\MongoDB\UnitOfWork; use Doctrine\Persistence\Mapping\ClassMetadata; /** @@ -15,6 +16,7 @@ * @internal * * @psalm-import-type FieldMapping from \Doctrine\ODM\MongoDB\Mapping\ClassMetadata + * @psalm-import-type Hints from UnitOfWork * * @template TKey of array-key * @template T of object @@ -32,7 +34,7 @@ public function setDocumentManager(DocumentManager $dm); /** * Sets the array of raw mongo data that will be used to initialize this collection. * - * @param array $mongoData + * @param mixed[] $mongoData * * @return void */ @@ -41,14 +43,14 @@ public function setMongoData(array $mongoData); /** * Gets the array of raw mongo data that will be used to initialize this collection. * - * @return array $mongoData + * @return mixed[] $mongoData */ public function getMongoData(); /** * Set hints to account for during reconstitution/lookup of the documents. * - * @param array $hints + * @param Hints $hints * * @return void */ @@ -57,7 +59,7 @@ public function setHints(array $hints); /** * Get hints to account for during reconstitution/lookup of the documents. * - * @return array $hints + * @return Hints $hints */ public function getHints(); @@ -117,31 +119,31 @@ public function clearSnapshot(); /** * Returns the last snapshot of the elements in the collection. * - * @return array The last snapshot of the elements. + * @return object[] The last snapshot of the elements. */ public function getSnapshot(); /** - * @return array + * @return array */ public function getDeleteDiff(); /** * Get objects that were removed, unlike getDeleteDiff this doesn't care about indices. * - * @return array + * @return list */ public function getDeletedDocuments(); /** - * @return array + * @return array */ public function getInsertDiff(); /** * Get objects that were added, unlike getInsertDiff this doesn't care about indices. * - * @return array + * @return list */ public function getInsertedDocuments(); diff --git a/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionTrait.php b/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionTrait.php index 0ba1d2d3a6..77da3e92ba 100644 --- a/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionTrait.php +++ b/lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionTrait.php @@ -26,6 +26,7 @@ /** * Trait with methods needed to implement PersistentCollectionInterface. * + * @psalm-import-type Hints from UnitOfWork * @psalm-import-type FieldMapping from ClassMetadata * @template TKey of array-key * @template T of object @@ -92,7 +93,7 @@ trait PersistentCollectionTrait /** * The raw mongo data that will be used to initialize this collection. * - * @var array + * @var mixed[] */ private $mongoData = []; @@ -100,6 +101,7 @@ trait PersistentCollectionTrait * Any hints to account for during reconstitution/lookup of the documents. * * @var array + * @psalm-var Hints */ private $hints = []; diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php b/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php index 1ea3facd46..6ad3c883fe 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php @@ -64,7 +64,7 @@ public function __construct(DocumentManager $dm, PersistenceBuilder $pb, UnitOfW * Deletes a PersistentCollection instances completely from a document using $unset. * * @param PersistentCollectionInterface[] $collections - * @param array $options + * @param array $options */ public function delete(object $parent, array $collections, array $options): void { @@ -100,7 +100,7 @@ public function delete(object $parent, array $collections, array $options): void * Updates a list PersistentCollection instances deleting removed rows and inserting new rows. * * @param PersistentCollectionInterface[] $collections - * @param array $options + * @param array $options */ public function update(object $parent, array $collections, array $options): void { @@ -155,7 +155,7 @@ public function update(object $parent, array $collections, array $options): void * reindexed numerically before storage. * * @param PersistentCollectionInterface[] $collections - * @param array $options + * @param array $options */ private function setCollections(object $parent, array $collections, array $options): void { @@ -195,7 +195,7 @@ private function setCollections(object $parent, array $collections, array $optio * This method is intended to be used with the "pushAll" and "addToSet" strategies. * * @param PersistentCollectionInterface[] $collections - * @param array $options + * @param array $options */ private function deleteElements(object $parent, array $collections, array $options): void { @@ -258,7 +258,7 @@ private function deleteElements(object $parent, array $collections, array $optio * This method is intended to be used with the "pushAll" and "addToSet" strategies. * * @param PersistentCollectionInterface[] $collections - * @param array $options + * @param array $options */ private function insertElements(object $parent, array $collections, array $options): void { @@ -328,11 +328,11 @@ private function insertElements(object $parent, array $collections, array $optio /** * Perform collections update for 'pushAll' strategy. * - * @param object $parent Parent object to which passed collections is belong. - * @param array $collsPaths Paths of collections that is passed. - * @param array $pathCollsMap List of collections indexed by their paths. - * @param array $diffsMap List of collection diffs indexed by collections paths. - * @param array $options + * @param object $parent Parent object to which passed collections is belong. + * @param string[] $collsPaths Paths of collections that is passed. + * @param array> $pathCollsMap List of collections indexed by their paths. + * @param array $diffsMap List of collection diffs indexed by collections paths. + * @param array $options */ private function pushAllCollections(object $parent, array $collsPaths, array $pathCollsMap, array $diffsMap, array $options): void { @@ -362,11 +362,11 @@ private function pushAllCollections(object $parent, array $collsPaths, array $pa /** * Perform collections update by 'addToSet' strategy. * - * @param object $parent Parent object to which passed collections is belong. - * @param array $collsPaths Paths of collections that is passed. - * @param array $pathCollsMap List of collections indexed by their paths. - * @param array $diffsMap List of collection diffs indexed by collections paths. - * @param array $options + * @param object $parent Parent object to which passed collections is belong. + * @param string[] $collsPaths Paths of collections that is passed. + * @param array> $pathCollsMap List of collections indexed by their paths. + * @param array $diffsMap List of collection diffs indexed by collections paths. + * @param array $options */ private function addToSetCollections(object $parent, array $collsPaths, array $pathCollsMap, array $diffsMap, array $options): void { @@ -416,6 +416,8 @@ private function getValuePrepareCallback(PersistentCollectionInterface $coll): C * * list($path, $parent) = $this->getPathAndParent($coll) * + * + * @return array{string, object|null} */ private function getPathAndParent(PersistentCollectionInterface $coll): array { @@ -443,6 +445,9 @@ private function getPathAndParent(PersistentCollectionInterface $coll): array /** * Executes a query updating the given document. + * + * @param array $newObj + * @param array $options */ private function executeQuery(object $document, array $newObj, array $options): void { diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php b/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php index 5b7163d670..55352a1f70 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php @@ -5,6 +5,7 @@ namespace Doctrine\ODM\MongoDB\Persisters; use BadMethodCallException; +use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Hydrator\HydratorException; use Doctrine\ODM\MongoDB\Hydrator\HydratorFactory; @@ -73,6 +74,10 @@ * @template T of object * * @psalm-import-type CommitOptions from UnitOfWork + * @psalm-import-type Hints from UnitOfWork + * @psalm-import-type FieldMapping from ClassMetadata + * @psalm-import-type SortMeta from Sort + * @psalm-import-type SortShape from Sort */ final class DocumentPersister { @@ -100,14 +105,14 @@ final class DocumentPersister /** * Array of queued inserts for the persister to insert. * - * @var array + * @var array */ private $queuedInserts = []; /** * Array of queued inserts for the persister to insert. * - * @var array + * @var array */ private $queuedUpserts = []; @@ -152,6 +157,9 @@ public function __construct( $this->bucket = $dm->getDocumentBucket($class->name); } + /** + * @return array + */ public function getInserts(): array { return $this->queuedInserts; @@ -171,6 +179,9 @@ public function addInsert(object $document): void $this->queuedInserts[spl_object_hash($document)] = $document; } + /** + * @return array + */ public function getUpserts(): array { return $this->queuedUpserts; @@ -290,6 +301,8 @@ public function executeUpserts(array $options = []): void /** * Executes a single upsert in {@link executeUpserts} + * + * @param array $options */ private function executeUpsert(object $document, array $options): void { @@ -481,7 +494,10 @@ public function refresh(object $document): void * If a scalar or MongoDB\BSON\ObjectId is provided for $criteria, it will * be used to match an _id value. * - * @param mixed $criteria Query criteria + * @param array|scalar|ObjectId|null $criteria Query criteria + * @param array>|null $sort + * @psalm-param SortShape|null $sort + * @psalm-param Hints $hints * @psalm-param T|null $document * * @psalm-return T|null @@ -527,6 +543,9 @@ public function load($criteria, ?object $document = null, array $hints = [], int /** * Finds documents by a set of criteria. + * + * @param array $criteria + * @param array|null $sort */ public function loadAll(array $criteria = [], ?array $sort = null, ?int $limit = null, ?int $skip = null): Iterator { @@ -554,6 +573,8 @@ public function loadAll(array $criteria = [], ?array $sort = null, ?int $limit = } /** + * @return array + * * @throws MongoDBException */ private function getShardKeyQuery(object $document): array @@ -639,9 +660,10 @@ public function unlock(object $document): void /** * Creates or fills a single document object from an query result. * - * @param array $result The query result. - * @param object|null $document The document object to fill, if any. - * @param array $hints Hints for document creation. + * @param array $result The query result. + * @param object|null $document The document object to fill, if any. + * @param array $hints Hints for document creation. + * @psalm-param Hints $hints * @psalm-param T|null $document * * @return object The filled and managed document object. @@ -911,6 +933,10 @@ public function createReferenceManyWithRepositoryMethodCursor(PersistentCollecti /** * Prepare a projection array by converting keys, which are PHP property * names, to MongoDB field names. + * + * @param array $fields + * + * @return array */ public function prepareProjection(array $fields): array { @@ -924,9 +950,9 @@ public function prepareProjection(array $fields): array } /** - * @param int|string|null $sort + * @param int|string $sort * - * @return int|string|null + * @return int|string */ private function getSortDirection($sort) { @@ -944,6 +970,11 @@ private function getSortDirection($sort) /** * Prepare a sort specification array by converting keys to MongoDB field * names and changing direction strings to int. + * + * @param array> $fields + * @psalm-param SortShape $fields + * + * @psalm-return array */ public function prepareSort(array $fields): array { @@ -982,6 +1013,10 @@ public function prepareFieldName(string $fieldName): string * This method should be used once for query criteria and not be used for * nested expressions. It should be called before * {@link DocumentPerister::addFilterToPreparedQuery()}. + * + * @param array $preparedQuery + * + * @return array */ public function addDiscriminatorToPreparedQuery(array $preparedQuery): array { @@ -1010,6 +1045,10 @@ public function addDiscriminatorToPreparedQuery(array $preparedQuery): array * This method should be used once for query criteria and not be used for * nested expressions. It should be called after * {@link DocumentPerister::addDiscriminatorToPreparedQuery()}. + * + * @param array $preparedQuery + * + * @return array */ public function addFilterToPreparedQuery(array $preparedQuery): array { @@ -1031,6 +1070,10 @@ public function addFilterToPreparedQuery(array $preparedQuery): array * Prepares the query criteria or new document object. * * PHP field names and types will be converted to those used by MongoDB. + * + * @param array $query + * + * @return array */ public function prepareQueryOrNewObj(array $query, bool $isNewObj = false): array { @@ -1119,6 +1162,8 @@ private function convertToDatabaseValue(string $fieldName, $value) * different. * * @param mixed $value + * + * @return array */ private function prepareQueryElement(string $fieldName, $value = null, ?ClassMetadata $class = null, bool $prepareValue = true, bool $inNewObj = false): array { @@ -1319,6 +1364,11 @@ private function prepareQueryElement(string $fieldName, $value = null, ?ClassMet return [[$fieldName, $value]]; } + /** + * @param array $expression + * + * @return array + */ private function prepareQueryExpression(array $expression, ClassMetadata $class): array { foreach ($expression as $k => $v) { @@ -1424,6 +1474,8 @@ private function hasQueryOperators($value): bool /** * Returns the list of discriminator values for the given ClassMetadata + * + * @psalm-return list */ private function getClassDiscriminatorValues(ClassMetadata $metadata): array { @@ -1450,6 +1502,9 @@ private function getClassDiscriminatorValues(ClassMetadata $metadata): array return $discriminatorValues; } + /** + * @param array $options + */ private function handleCollections(object $document, array $options): void { // Collection deletions (deletions of complete collections) @@ -1491,6 +1546,8 @@ private function handleCollections(object $document, array $options): void * exception. Also, shard key field should be present in actual document * data. * + * @param array $actualDocumentData + * * @throws MongoDBException */ private function guardMissingShardKey(object $document, string $shardKeyField, array $actualDocumentData): void @@ -1512,6 +1569,8 @@ private function guardMissingShardKey(object $document, string $shardKeyField, a /** * Get shard key aware query for single document. + * + * @return array */ private function getQueryForDocument(object $document): array { @@ -1525,6 +1584,8 @@ private function getQueryForDocument(object $document): array /** * @psalm-param CommitOptions $options + * + * @psalm-return CommitOptions */ private function getWriteOptions(array $options = []): array { @@ -1549,6 +1610,14 @@ private function getWriteOptions(array $options = []): array return $writeOptions; } + /** + * @psalm-param FieldMapping $mapping + * + * @psalm-return array + * }> + */ private function prepareReference(string $fieldName, object $value, array $mapping, bool $inNewObj): array { $reference = $this->dm->createReference($value, $mapping); diff --git a/lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php b/lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php index 427ebf3b3c..faf5cbb813 100644 --- a/lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php +++ b/lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php @@ -26,6 +26,8 @@ * UnitOfWork to build queries using atomic operators like $set, $unset, etc. * * @internal + * + * @psalm-import-type FieldMapping from ClassMetadata */ final class PersistenceBuilder { @@ -57,7 +59,7 @@ public function __construct(DocumentManager $dm, UnitOfWork $uow) * * @param object $document * - * @return array $insertData + * @return array $insertData */ public function prepareInsertData($document) { @@ -122,7 +124,7 @@ public function prepareInsertData($document) * * @param object $document * - * @return array $updateData + * @return array $updateData */ public function prepareUpdateData($document) { @@ -232,7 +234,7 @@ public function prepareUpdateData($document) * * @param object $document * - * @return array $updateData + * @return array $updateData */ public function prepareUpsertData($document) { @@ -323,10 +325,10 @@ public function prepareUpsertData($document) * If the document does not have an identifier and the mapping calls for a * simple reference, null may be returned. * - * @param array $referenceMapping * @param object $document + * @psalm-param FieldMapping $referenceMapping * - * @return array|null + * @return array|null */ public function prepareReferencedDocumentValue(array $referenceMapping, $document) { @@ -347,11 +349,11 @@ public function prepareReferencedDocumentValue(array $referenceMapping, $documen * within this value were previously scheduled for deletion or update, they * will also be unscheduled. * - * @param array $embeddedMapping * @param object $embeddedDocument * @param bool $includeNestedCollections + * @psalm-param FieldMapping $embeddedMapping * - * @return array|object + * @return array|object * * @throws UnexpectedValueException If an unsupported associating mapping is found. */ @@ -462,11 +464,11 @@ public function prepareEmbeddedDocumentValue(array $embeddedMapping, $embeddedDo /** * Returns the embedded document or reference representation to be stored. * - * @param array $mapping * @param object $document * @param bool $includeNestedCollections + * @psalm-param FieldMapping $mapping * - * @return array|object|null + * @return mixed[]|object|null * * @throws InvalidArgumentException If the mapping is neither embedded nor reference. */ @@ -488,7 +490,7 @@ public function prepareAssociatedDocumentValue(array $mapping, $document, $inclu * * @param bool $includeNestedCollections * - * @return array + * @return mixed[] */ public function prepareAssociatedCollectionValue(PersistentCollectionInterface $coll, $includeNestedCollections = false) { diff --git a/lib/Doctrine/ODM/MongoDB/Query/Query.php b/lib/Doctrine/ODM/MongoDB/Query/Query.php index dfc2b8bce7..e4e75c85f3 100644 --- a/lib/Doctrine/ODM/MongoDB/Query/Query.php +++ b/lib/Doctrine/ODM/MongoDB/Query/Query.php @@ -5,6 +5,7 @@ namespace Doctrine\ODM\MongoDB\Query; use BadMethodCallException; +use Doctrine\ODM\MongoDB\Aggregation\Stage\Sort; use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Iterator\CachingIterator; use Doctrine\ODM\MongoDB\Iterator\HydratingIterator; @@ -54,11 +55,12 @@ * readPreference?: ReadPreference, * select?: array>, * skip?: int, - * sort?: array, + * sort?: array, * type?: Query::TYPE_*, * upsert?: bool, * } * @psalm-import-type Hints from UnitOfWork + * @psalm-import-type SortMeta from Sort */ final class Query implements IteratorAggregate { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index ac59535f61..8a386b7d06 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -185,3 +185,32 @@ parameters: message: "#^Parameter \\#4 \\$query of class Doctrine\\\\ODM\\\\MongoDB\\\\Query\\\\Query constructor expects array\\{distinct\\?\\: string, hint\\?\\: array\\\\|string, limit\\?\\: int, multiple\\?\\: bool, new\\?\\: bool, newObj\\?\\: array\\, query\\?\\: array\\, readPreference\\?\\: MongoDB\\\\Driver\\\\ReadPreference, \\.\\.\\.\\}, array\\{type\\: \\-1\\} given\\.$#" count: 1 path: tests/Doctrine/ODM/MongoDB/Tests/QueryTest.php + + - + message: "#^Parameter \\#2 \\$referenceMapping of method Doctrine\\\\ODM\\\\MongoDB\\\\DocumentManager\\:\\:createReference\\(\\) expects array\\{type\\: string, fieldName\\: string, name\\: string, isCascadeRemove\\: bool, isCascadePersist\\: bool, isCascadeRefresh\\: bool, isCascadeMerge\\: bool, isCascadeDetach\\: bool, \\.\\.\\.\\}, array\\{storeAs\\: 'dbRef'\\} given\\.$#" + count: 1 + path: tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php + + # import type in PHPStan does not work, see https://github.com/phpstan/phpstan/issues/5091 + - + message: "#^Property Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\:\\:\\$hints \\(Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\Hints\\) does not accept default value of type array\\.$#" + count: 1 + path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php + + # import type in PHPStan does not work, see https://github.com/phpstan/phpstan/issues/5091 + - + message: "#^Property Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\:\\:\\$hints has unknown class Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\Hints as its type\\.$#" + count: 1 + path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php + + # import type in PHPStan does not work, see https://github.com/phpstan/phpstan/issues/5091 + - + message: "#^Property Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\:\\:\\$hints \\(Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\Hints\\) does not accept array\\\\.$#" + count: 1 + path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php + + # import type in PHPStan does not work, see https://github.com/phpstan/phpstan/issues/5091 + - + message: "#^Method Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\:\\:getHints\\(\\) should return array\\ but returns Doctrine\\\\ODM\\\\MongoDB\\\\PersistentCollection\\\\Hints\\.$#" + count: 1 + path: lib/Doctrine/ODM/MongoDB/PersistentCollection.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index db97346db3..df7802006f 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,10 @@ + + + $fields + + $this->num($limit) @@ -93,6 +98,9 @@ + + $query + $this->query $this->query @@ -122,6 +130,11 @@ $mapping['targetDocument'] + + + ['storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF] + + new ArrayCollection([$project]) diff --git a/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php b/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php index 4fe83734b0..b85ef4b64a 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php @@ -184,7 +184,10 @@ public function testCreateDbRefWithNonNullEmptyId(): void $phonenumber->phonenumber = 0; $this->dm->persist($phonenumber); - $dbRef = $this->dm->createReference($phonenumber, ['storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF, 'targetDocument' => CmsPhonenumber::class]); + $dbRef = $this->dm->createReference($phonenumber, ClassMetadataTestUtil::getFieldMapping([ + 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF, + 'targetDocument' => CmsPhonenumber::class, + ])); $this->assertSame(['$ref' => 'CmsPhonenumber', '$id' => 0], $dbRef); } diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Functional/CustomCollectionsTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Functional/CustomCollectionsTest.php index 99c6b3d273..2e04aea537 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Functional/CustomCollectionsTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Functional/CustomCollectionsTest.php @@ -13,6 +13,7 @@ use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface; use Doctrine\ODM\MongoDB\Repository\GridFSRepository; use Doctrine\ODM\MongoDB\Tests\BaseTest; +use Doctrine\ODM\MongoDB\Tests\ClassMetadataTestUtil; use Documents\File; use Documents\ProfileNotify; use stdClass; @@ -58,7 +59,7 @@ public function testGeneratedClassExtendsBaseCollection(): void $coll = new MyEmbedsCollection(); $pcoll = $this->dm->getConfiguration()->getPersistentCollectionFactory()->create( $this->dm, - ['collectionClass' => MyEmbedsCollection::class], + ClassMetadataTestUtil::getFieldMapping(['collectionClass' => MyEmbedsCollection::class]), $coll ); $this->assertInstanceOf(PersistentCollectionInterface::class, $pcoll); diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Functional/ReferencePrimerTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Functional/ReferencePrimerTest.php index 22b1d99e49..2cf02229f3 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Functional/ReferencePrimerTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Functional/ReferencePrimerTest.php @@ -9,6 +9,7 @@ use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Query\Query; use Doctrine\ODM\MongoDB\Tests\BaseTest; +use Doctrine\ODM\MongoDB\Tests\ClassMetadataTestUtil; use Documents\Account; use Documents\Agent; use Documents\BlogPost; @@ -416,7 +417,10 @@ public function testPrimeReferencesInFindAndModifyResult(): void $this->dm->persist($group); $this->dm->flush(); - $groupDBRef = $this->dm->createReference($group, ['storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF, 'targetDocument' => Group::class]); + $groupDBRef = $this->dm->createReference($group, ClassMetadataTestUtil::getFieldMapping([ + 'storeAs' => ClassMetadata::REFERENCE_STORE_AS_DB_REF, + 'targetDocument' => Group::class, + ])); $this->dm->clear(); From 33d476556e4a9695bd16291c66f3eff6db166a7b Mon Sep 17 00:00:00 2001 From: Fran Moreno Date: Sat, 30 Apr 2022 08:42:46 +0200 Subject: [PATCH 2/2] Fix static analysis build --- psalm-baseline.xml | 4 ++-- .../ODM/MongoDB/Tests/Types/DateImmutableTypeTest.php | 2 -- tests/Doctrine/ODM/MongoDB/Tests/Types/DateTypeTest.php | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index df7802006f..307fbb16db 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -201,12 +201,12 @@ - assert($return instanceof DateTimeImmutable) + assertInstanceOf - assert($return instanceof DateTime) + assertInstanceOf diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Types/DateImmutableTypeTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Types/DateImmutableTypeTest.php index 77433d5365..080ea032f4 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Types/DateImmutableTypeTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Types/DateImmutableTypeTest.php @@ -136,8 +136,6 @@ public function testClosureToPHP($input, DateTimeImmutable $output): void })($input); // @phpstan-ignore-next-line - assert($return instanceof DateTimeImmutable); - $this->assertInstanceOf(DateTimeImmutable::class, $return); $this->assertTimestampEquals($output, $return); } diff --git a/tests/Doctrine/ODM/MongoDB/Tests/Types/DateTypeTest.php b/tests/Doctrine/ODM/MongoDB/Tests/Types/DateTypeTest.php index e0b072a377..94e666b6c8 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/Types/DateTypeTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/Types/DateTypeTest.php @@ -136,8 +136,6 @@ public function testClosureToPHP($input, DateTime $output): void })($input); // @phpstan-ignore-next-line - assert($return instanceof DateTime); - $this->assertInstanceOf(DateTime::class, $return); $this->assertTimestampEquals($output, $return); }