Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
228 changes: 135 additions & 93 deletions src/Mapping/ClassMetadata.php

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions src/Mapping/ClassMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ protected function doLoadMetadata(ClassMetadataInterface $class, ?ClassMetadataI
}

if ($parent->isFile) {
$class->isFile = true;
$class->markAsFile();

$class->setBucketName($parent->bucketName);

if ($parent->chunkSizeBytes !== null) {
Expand Down Expand Up @@ -321,7 +322,7 @@ private function completeIdGeneratorMapping(ClassMetadata $class): void
*/
private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass): void
{
foreach ($parentClass->fieldMappings as $fieldName => $mapping) {
foreach ($parentClass->fieldMappings as $mapping) {
if (! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
$mapping['inherited'] = $parentClass->name;
}
Expand All @@ -334,7 +335,7 @@ private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $pare
}

foreach ($parentClass->propertyAccessors as $name => $field) {
$subClass->propertyAccessors[$name] = $field;
$subClass->setPropertyAccessor($name, $field);
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/Mapping/Driver/AttributeDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public function loadMetadataForClass($className, PersistenceClassMetadata $metad
$metadata->setValidationLevel($attribute->level);
}
} elseif ($attribute instanceof ODM\Encrypt) {
$metadata->isEncrypted = true;
$metadata->markAsEncrypted();
}
}

Expand All @@ -141,11 +141,11 @@ public function loadMetadataForClass($className, PersistenceClassMetadata $metad
}

if ($documentAttribute instanceof ODM\MappedSuperclass) {
$metadata->isMappedSuperclass = true;
$metadata->markAsMappedSuperclass();
} elseif ($documentAttribute instanceof ODM\EmbeddedDocument) {
$metadata->isEmbeddedDocument = true;
$metadata->markAsEmbeddedDocument();
} elseif ($documentAttribute instanceof ODM\QueryResultDocument) {
$metadata->isQueryResultDocument = true;
$metadata->markAsQueryResultDocument();
} elseif ($documentAttribute instanceof ODM\View) {
if (! $documentAttribute->rootClass) {
throw MappingException::viewWithoutRootClass($className);
Expand All @@ -157,7 +157,7 @@ public function loadMetadataForClass($className, PersistenceClassMetadata $metad

$metadata->markViewOf($documentAttribute->rootClass);
} elseif ($documentAttribute instanceof ODM\File) {
$metadata->isFile = true;
$metadata->markAsFile();

if ($documentAttribute->chunkSizeBytes !== null) {
$metadata->setChunkSizeBytes($documentAttribute->chunkSizeBytes);
Expand Down
10 changes: 5 additions & 5 deletions src/Mapping/Driver/XmlDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,14 @@ public function loadMetadataForClass($className, \Doctrine\Persistence\Mapping\C
$metadata->setCustomRepositoryClass(
isset($xmlRoot['repository-class']) ? (string) $xmlRoot['repository-class'] : null,
);
$metadata->isMappedSuperclass = true;
$metadata->markAsMappedSuperclass();
} elseif ($xmlRoot->getName() === 'embedded-document') {
$metadata->isEmbeddedDocument = true;
$metadata->markAsEmbeddedDocument();
if (isset($xmlRoot->encrypt)) {
$metadata->isEncrypted = true;
$metadata->markAsEncrypted();
}
} elseif ($xmlRoot->getName() === 'query-result-document') {
$metadata->isQueryResultDocument = true;
$metadata->markAsQueryResultDocument();
} elseif ($xmlRoot->getName() === 'view') {
if (isset($xmlRoot['repository-class'])) {
$metadata->setCustomRepositoryClass((string) $xmlRoot['repository-class']);
Expand All @@ -121,7 +121,7 @@ public function loadMetadataForClass($className, \Doctrine\Persistence\Mapping\C

$metadata->markViewOf($rootClass);
} elseif ($xmlRoot->getName() === 'gridfs-file') {
$metadata->isFile = true;
$metadata->markAsFile();

if (isset($xmlRoot['chunk-size-bytes'])) {
$metadata->setChunkSizeBytes((int) $xmlRoot['chunk-size-bytes']);
Expand Down
4 changes: 2 additions & 2 deletions src/Persisters/DocumentPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -1342,7 +1342,7 @@ private function prepareQueryExpression(array $expression, ClassMetadata $class)
// Process query operators whose argument arrays need type conversion
if (in_array($k, ['$in', '$nin', '$all']) && is_array($v)) {
foreach ($v as $k2 => $v2) {
if ($v2 instanceof $class->name) {
if ($class->name !== null && $v2 instanceof $class->name) {
// If a value in a query is a target document, e.g. ['referenceField' => $targetDocument],
// retreive id from target document and convert this id using it's type
$expression[$k][$k2] = $class->getDatabaseIdentifierValue($class->getIdentifierValue($v2));
Expand All @@ -1369,7 +1369,7 @@ private function prepareQueryExpression(array $expression, ClassMetadata $class)
continue;
}

if ($v instanceof $class->name) {
if ($class->name !== null && $v instanceof $class->name) {
$expression[$k] = $class->getDatabaseIdentifierValue($class->getIdentifierValue($v));
} else {
$expression[$k] = $class->getDatabaseIdentifierValue($v);
Expand Down
4 changes: 2 additions & 2 deletions src/Tools/ResolveTargetDocumentListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ private function remapAssociation(ClassMetadata $classMetadata, array $mapping):
$newMapping['fieldName'] = $mapping['fieldName'];

// clear reference case of duplicate exception
unset($classMetadata->fieldMappings[$mapping['fieldName']]);
unset($classMetadata->associationMappings[$mapping['fieldName']]);
$classMetadata->unsetFieldMapping($mapping['fieldName']);
$classMetadata->unsetAssociationMapping($mapping['fieldName']);

switch ($mapping['association']) {
case ClassMetadata::REFERENCE_ONE:
Expand Down
13 changes: 10 additions & 3 deletions tests/Tests/DocumentManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use MongoDB\Client;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
use ReflectionProperty;
use RuntimeException;
use stdClass;
use TypeError;
Expand Down Expand Up @@ -250,9 +251,15 @@ public function testGetClassNameForAssociationWithClassMetadataDiscriminatorMap(
$mapping = ClassMetadataTestUtil::getFieldMapping(['targetDocument' => User::class]);
$data = ['type' => 'forum_user'];

$userClassMetadata = new ClassMetadata(ForumUser::class);
$userClassMetadata->discriminatorField = 'type';
$userClassMetadata->discriminatorMap = ['forum_user' => ForumUser::class];
$userClassMetadata = new ClassMetadata(ForumUser::class);
new ReflectionProperty(ClassMetadata::class, 'discriminatorField')->setValue(
$userClassMetadata,
'type',
);
new ReflectionProperty(ClassMetadata::class, 'discriminatorMap')->setValue(
$userClassMetadata,
['forum_user' => ForumUser::class],
);
$this->dm->getMetadataFactory()->setMetadataFor(User::class, $userClassMetadata);

self::assertEquals(ForumUser::class, $this->dm->getClassNameForAssociation($mapping, $data));
Expand Down
8 changes: 6 additions & 2 deletions tests/Tests/Functional/VectorSearchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use MongoDB\Driver\WriteConcern;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use ReflectionProperty;

#[Group('atlas')]
class VectorSearchTest extends BaseTestCase
Expand Down Expand Up @@ -105,8 +106,11 @@ public function testAtlasVectorSearchWithBinaryType(): void
{
$cm = $this->dm->getClassMetadata(VectorEmbedding::class);

$cm->fieldMappings['vectorFloat']['type'] = Type::VECTOR_FLOAT32;
$cm->fieldMappings['vectorInt']['type'] = Type::VECTOR_INT8;
$fieldMappings = $cm->fieldMappings;
$fieldMappings['vectorFloat']['type'] = Type::VECTOR_FLOAT32;
$fieldMappings['vectorInt']['type'] = Type::VECTOR_INT8;

new ReflectionProperty($cm, 'fieldMappings')->setValue($cm, $fieldMappings);

// Change the collection name to avoid conflicts with asynchronous index building
$cm->collection .= '_binary_type';
Expand Down
48 changes: 29 additions & 19 deletions tests/Tests/Mapping/ClassMetadataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
use PHPUnit\Framework\Attributes\TestWith;
use ReflectionClass;
use ReflectionException;
use ReflectionProperty;
use stdClass;

use function array_merge;
Expand Down Expand Up @@ -404,11 +405,11 @@ public static function dataProviderMetadataClasses(): array
{
$document = new ClassMetadata(CmsUser::class);

$embeddedDocument = new ClassMetadata(CmsUser::class);
$embeddedDocument->isEmbeddedDocument = true;
$embeddedDocument = new ClassMetadata(CmsUser::class);
$embeddedDocument->markAsEmbeddedDocument();

$mappedSuperclass = new ClassMetadata(CmsUser::class);
$mappedSuperclass->isMappedSuperclass = true;
$mappedSuperclass = new ClassMetadata(CmsUser::class);
$mappedSuperclass->markAsMappedSuperclass();

return [
'document' => [$document],
Expand Down Expand Up @@ -706,8 +707,8 @@ public function testAtomicCollectionUpdateUsageInEmbeddedDocument(): void
public $many;
};

$cm = new ClassMetadata($object::class);
$cm->isEmbeddedDocument = true;
$cm = new ClassMetadata($object::class);
$cm->markAsEmbeddedDocument();

$this->expectException(MappingException::class);
$this->expectExceptionMessage('atomicSet collection strategy can be used only in top level document, used in');
Expand All @@ -726,8 +727,8 @@ public function testDefaultStorageStrategyOfEmbeddedDocumentFields(): void
public $many;
};

$cm = new ClassMetadata($object::class);
$cm->isEmbeddedDocument = true;
$cm = new ClassMetadata($object::class);
new ReflectionProperty(ClassMetadata::class, 'isEmbeddedDocument')->setValue($cm, true);

$mapping = $cm->mapField([
'fieldName' => 'many',
Expand All @@ -747,8 +748,8 @@ public function testOwningAndInversedRefsNeedTargetDocument(array $config): void
'strategy' => ClassMetadata::STORAGE_STRATEGY_ATOMIC_SET,
]);

$cm = new ClassMetadata('stdClass');
$cm->isEmbeddedDocument = true;
$cm = new ClassMetadata('stdClass');
new ReflectionProperty(ClassMetadata::class, 'isEmbeddedDocument')->setValue($cm, true);
$this->expectException(MappingException::class);
$cm->mapField($config);
}
Expand Down Expand Up @@ -822,8 +823,11 @@ public function testSetShardKeyForClassWithoutInheritance(): void

public function testSetShardKeyForClassWithSingleCollectionInheritance(): void
{
$cm = new ClassMetadata('stdClass');
$cm->inheritanceType = ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION;
$cm = new ClassMetadata('stdClass');
new ReflectionProperty(ClassMetadata::class, 'inheritanceType')->setValue(
$cm,
ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION,
);
$cm->setShardKey(['id' => 'asc']);

$shardKey = $cm->getShardKey();
Expand All @@ -835,7 +839,10 @@ public function testSetShardKeyForClassWithSingleCollectionInheritanceWhichAlrea
{
$cm = new ClassMetadata('stdClass');
$cm->setShardKey(['id' => 'asc']);
$cm->inheritanceType = ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION;
new ReflectionProperty(ClassMetadata::class, 'inheritanceType')->setValue(
$cm,
ClassMetadata::INHERITANCE_TYPE_SINGLE_COLLECTION,
);

$this->expectException(MappingException::class);
$this->expectExceptionMessage('Shard key overriding in subclass is forbidden for single collection inheritance');
Expand All @@ -844,8 +851,11 @@ public function testSetShardKeyForClassWithSingleCollectionInheritanceWhichAlrea

public function testSetShardKeyForClassWithCollPerClassInheritance(): void
{
$cm = new ClassMetadata('stdClass');
$cm->inheritanceType = ClassMetadata::INHERITANCE_TYPE_COLLECTION_PER_CLASS;
$cm = new ClassMetadata('stdClass');
new ReflectionProperty(ClassMetadata::class, 'inheritanceType')->setValue(
$cm,
ClassMetadata::INHERITANCE_TYPE_COLLECTION_PER_CLASS,
);
$cm->setShardKey(['id' => 'asc']);

$shardKey = $cm->getShardKey();
Expand All @@ -870,8 +880,8 @@ public function testIsShardedIfThereIsAShardKey(): void

public function testEmbeddedDocumentCantHaveShardKey(): void
{
$cm = new ClassMetadata('stdClass');
$cm->isEmbeddedDocument = true;
$cm = new ClassMetadata('stdClass');
$cm->markAsEmbeddedDocument();
$this->expectException(MappingException::class);
$this->expectExceptionMessage('Embedded document can\'t have shard key: stdClass');
$cm->setShardKey(['id' => 'asc']);
Expand Down Expand Up @@ -947,8 +957,8 @@ public function testArbitraryFieldInGridFSFileThrowsException(): void
public $contentType;
};

$cm = new ClassMetadata($object::class);
$cm->isFile = true;
$cm = new ClassMetadata($object::class);
$cm->markAsFile();

$this->expectException(MappingException::class);
$this->expectExceptionMessageMatches("#^Field 'contentType' in class '.+' is not a valid field for GridFS documents. You should move it to an embedded metadata document.$#");
Expand Down
9 changes: 5 additions & 4 deletions tests/Tests/SchemaManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
use PHPUnit\Framework\Constraint\Constraint;
use PHPUnit\Framework\Constraint\IsEqual;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionProperty;

use function array_count_values;
use function array_key_exists;
Expand Down Expand Up @@ -749,10 +750,10 @@ public function testUpdateDocumentValidatorReset(array $expectedWriteOptions, ?i
#[DataProvider('getWriteOptions')]
public function testCreateDocumentCollection(array $expectedWriteOptions, ?int $maxTimeMs, ?WriteConcern $writeConcern): void
{
$cm = $this->dm->getClassMetadata(CmsArticle::class);
$cm->collectionCapped = true;
$cm->collectionSize = 1048576;
$cm->collectionMax = 32;
$cm = $this->dm->getClassMetadata(CmsArticle::class);
new ReflectionProperty(ClassMetadata::class, 'collectionCapped')->setValue($cm, true);
new ReflectionProperty(ClassMetadata::class, 'collectionSize')->setValue($cm, 1048576);
new ReflectionProperty(ClassMetadata::class, 'collectionMax')->setValue($cm, 32);

$options = [
'capped' => true,
Expand Down