Skip to content

Commit 66a6f3f

Browse files
github-actions[bot]buffcodealcaeus
authored
Merge release 2.5.5 into 2.6.x (#2585)
* fix: Do not drop/re-create 2dsphere indexes (#2575) * Validate that targetDocument can be resolved (#2577) * fix: Validate that targetDocument can be resolved * refactor: Use exception factory * fix: Validate that all values in a discriminatorMap can be resolved * fix: PHPStan errors for intentionally missing class * fix: psalm/phpunit CI tests --------- Co-authored-by: buffcode <[email protected]> Co-authored-by: Andreas Braun <[email protected]>
1 parent 99aa043 commit 66a6f3f

File tree

7 files changed

+197
-56
lines changed

7 files changed

+197
-56
lines changed

lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
use function enum_exists;
4242
use function extension_loaded;
4343
use function in_array;
44+
use function interface_exists;
4445
use function is_array;
4546
use function is_string;
4647
use function is_subclass_of;
@@ -2310,6 +2311,22 @@ public function mapField(array $mapping): array
23102311
$mapping['discriminatorField'] = self::DEFAULT_DISCRIMINATOR_FIELD;
23112312
}
23122313

2314+
if (isset($mapping['targetDocument']) && ! class_exists($mapping['targetDocument']) && ! interface_exists($mapping['targetDocument'])) {
2315+
throw MappingException::invalidTargetDocument(
2316+
$mapping['targetDocument'],
2317+
$this->name,
2318+
$mapping['fieldName'],
2319+
);
2320+
}
2321+
2322+
if (isset($mapping['discriminatorMap'])) {
2323+
foreach ($mapping['discriminatorMap'] as $value => $class) {
2324+
if (! class_exists($class) && ! interface_exists($class)) {
2325+
throw MappingException::invalidClassInReferenceDiscriminatorMap($class, $this->name, $mapping['fieldName']);
2326+
}
2327+
}
2328+
}
2329+
23132330
if (isset($mapping['version'])) {
23142331
$mapping['notSaved'] = true;
23152332
$this->setVersionMapping($mapping);

lib/Doctrine/ODM/MongoDB/Mapping/MappingException.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ public static function invalidClassInDiscriminatorMap(string $className, string
7272
return new self(sprintf("Document class '%s' used in the discriminator map of class '%s' does not exist.", $className, $owningClass));
7373
}
7474

75+
public static function invalidClassInReferenceDiscriminatorMap(string $className, string $owningClass, string $fieldName): self
76+
{
77+
return new self(sprintf("Document class '%s' used in the discriminator map of field '%s' in class '%s' does not exist.", $className, $fieldName, $owningClass));
78+
}
79+
7580
public static function unlistedClassInDiscriminatorMap(string $className): self
7681
{
7782
return new self(sprintf('Document class "%s" is unlisted in the discriminator map.', $className));
@@ -82,6 +87,11 @@ public static function invalidDiscriminatorValue(string $value, string $owningCl
8287
return new self(sprintf("Discriminator value '%s' used in the declaration of class '%s' does not exist.", $value, $owningClass));
8388
}
8489

90+
public static function invalidTargetDocument(string $targetDocument, string $owningClass, string $owningField): self
91+
{
92+
return new self(sprintf("Target document class '%s' used in field '%s' of class '%s' does not exist.", $targetDocument, $owningField, $owningClass));
93+
}
94+
8595
public static function missingFieldName(string $className): self
8696
{
8797
return new self(sprintf("The Document class '%s' field mapping misses the 'fieldName' attribute.", $className));

lib/Doctrine/ODM/MongoDB/SchemaManager.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ final class SchemaManager
5252
'language_override',
5353
'textIndexVersion',
5454
'name',
55+
'2dsphereIndexVersion',
5556
];
5657

5758
public function __construct(protected DocumentManager $dm, protected ClassMetadataFactoryInterface $metadataFactory)

tests/Doctrine/ODM/MongoDB/Tests/Functional/IndexesTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,16 @@ public function testPartialIndexCreation(): void
239239
self::assertSame(['counter' => ['$gt' => 5]], $indexes[0]['options']['partialFilterExpression']);
240240
self::assertTrue($indexes[0]['options']['unique']);
241241
}
242+
243+
public function testGeoIndexCreation(): void
244+
{
245+
$className = GeoIndexDocument::class;
246+
$this->dm->getSchemaManager()->ensureDocumentIndexes(GeoIndexDocument::class);
247+
248+
$indexes = $this->dm->getSchemaManager()->getDocumentIndexes($className);
249+
self::assertSame(['coordinatesWith2DIndex' => '2d'], $indexes[0]['keys']);
250+
self::assertSame(['coordinatesWithSphereIndex' => '2dsphere'], $indexes[1]['keys']);
251+
}
242252
}
243253

244254
/** @ODM\Document */
@@ -657,3 +667,32 @@ class DocumentWithIndexInDiscriminatedEmbeds
657667
*/
658668
public $embedded;
659669
}
670+
671+
/**
672+
* @ODM\Document
673+
* @ODM\Index(keys={"coordinatesWith2DIndex"="2d"})
674+
* @ODM\Index(keys={"coordinatesWithSphereIndex"="2dsphere"})
675+
*/
676+
class GeoIndexDocument
677+
{
678+
/**
679+
* @ODM\Id
680+
*
681+
* @var string|null
682+
*/
683+
public $id;
684+
685+
/**
686+
* @ODM\Field(type="hash")
687+
*
688+
* @var array<float>
689+
*/
690+
public $coordinatesWith2DIndex;
691+
692+
/**
693+
* @ODM\Field(type="hash")
694+
*
695+
* @var array<float>
696+
*/
697+
public $coordinatesWithSphereIndex;
698+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\ODM\MongoDB\Tests\Functional;
6+
7+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
8+
use Doctrine\ODM\MongoDB\Mapping\MappingException;
9+
use Doctrine\ODM\MongoDB\Tests\BaseTestCase;
10+
use stdClass;
11+
12+
class TargetDocumentTest extends BaseTestCase
13+
{
14+
/** @doesNotPerformAssertions */
15+
public function testMappedSuperClassAsTargetDocument(): void
16+
{
17+
$test = new TargetDocumentTestDocument();
18+
$test->reference = new TargetDocumentTestReference();
19+
$this->dm->persist($test);
20+
$this->dm->persist($test->reference);
21+
$this->dm->flush();
22+
}
23+
24+
public function testTargetDocumentIsResolvable(): void
25+
{
26+
self::expectExceptionObject(
27+
MappingException::invalidTargetDocument(
28+
'Doctrine\ODM\MongoDB\Tests\Functional\SomeInvalidClass',
29+
InvalidTargetDocumentTestDocument::class,
30+
'reference',
31+
),
32+
);
33+
34+
$test = new InvalidTargetDocumentTestDocument();
35+
$test->reference = new stdClass();
36+
$this->dm->persist($test);
37+
}
38+
39+
public function testDiscriminatorTargetIsResolvable(): void
40+
{
41+
self::expectExceptionObject(
42+
MappingException::invalidClassInReferenceDiscriminatorMap(
43+
'Doctrine\ODM\MongoDB\Tests\Functional\SomeInvalidClass',
44+
InvalidDiscriminatorTargetsTestDocument::class,
45+
'reference',
46+
),
47+
);
48+
49+
$test = new InvalidDiscriminatorTargetsTestDocument();
50+
$test->reference = new stdClass();
51+
$this->dm->persist($test);
52+
}
53+
}
54+
55+
/** @ODM\Document */
56+
class TargetDocumentTestDocument
57+
{
58+
/**
59+
* @ODM\Id
60+
*
61+
* @var string|null
62+
*/
63+
public $id;
64+
65+
/**
66+
* @ODM\ReferenceOne(targetDocument=Doctrine\ODM\MongoDB\Tests\Functional\TargetDocumentTestReference::class)
67+
*
68+
* @var TargetDocumentTestReference|null
69+
*/
70+
public $reference;
71+
}
72+
73+
/** @ODM\MappedSuperclass */
74+
abstract class AbstractTargetDocumentTestReference
75+
{
76+
/**
77+
* @ODM\Id
78+
*
79+
* @var string|null
80+
*/
81+
public $id;
82+
}
83+
84+
/** @ODM\Document */
85+
class TargetDocumentTestReference extends AbstractTargetDocumentTestReference
86+
{
87+
}
88+
89+
/** @ODM\Document */
90+
class InvalidTargetDocumentTestDocument
91+
{
92+
/**
93+
* @ODM\Id
94+
*
95+
* @var string|null
96+
*/
97+
public $id;
98+
99+
/**
100+
* @ODM\ReferenceOne(targetDocument="Doctrine\ODM\MongoDB\Tests\Functional\SomeInvalidClass")
101+
*
102+
* @var object|null
103+
*/
104+
public $reference;
105+
}
106+
107+
108+
/** @ODM\Document */
109+
class InvalidDiscriminatorTargetsTestDocument
110+
{
111+
/**
112+
* @ODM\Id
113+
*
114+
* @var string|null
115+
*/
116+
public $id;
117+
118+
/**
119+
* @ODM\ReferenceOne(discriminatorField="referencedClass", discriminatorMap={"Foo"="Doctrine\ODM\MongoDB\Tests\Functional\SomeInvalidClass"})
120+
*
121+
* @var object|null
122+
*/
123+
public $reference;
124+
}

tests/Doctrine/ODM/MongoDB/Tests/Functional/TestTargetDocument.php

Lines changed: 0 additions & 56 deletions
This file was deleted.

tests/Doctrine/ODM/MongoDB/Tests/SchemaManagerTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,12 @@ public static function dataIsMongoIndexEquivalentToDocumentIndex(): array
934934
'mongoIndex' => ['background' => true],
935935
'documentIndex' => ['options' => ['background' => true]],
936936
],
937+
// 2dsphereIndexVersion index options
938+
'2dsphereIndexVersionOptionsDifferent' => [
939+
'expected' => true,
940+
'mongoIndex' => ['2dsphereIndexVersion' => 3],
941+
'documentIndex' => [],
942+
],
937943
];
938944
}
939945

0 commit comments

Comments
 (0)