Skip to content

Commit

Permalink
Merge pull request #2555 from doctrine/2.5.x-merge-up-into-2.6.x_KOlV…
Browse files Browse the repository at this point in the history
…K6XK

Merge release 2.5.3 into 2.6.x
  • Loading branch information
malarzm authored Oct 23, 2023
2 parents 9b7ed61 + 6be04f7 commit d3c8966
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 25 deletions.
5 changes: 4 additions & 1 deletion docs/en/cookbook/soft-delete-extension.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ An implementation might look like this in a ``User`` document:
{
// ...
/** @ODM\Field(type="date") @ODM\Index */
/**
* @ODM\Field(type="date")
* @ODM\Index
*/
private $deletedAt;
public function getDeletedAt(): ?\DateTime
Expand Down
19 changes: 15 additions & 4 deletions lib/Doctrine/ODM/MongoDB/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Doctrine\Common\Cache\Psr6\CacheAdapter;
use Doctrine\Common\Cache\Psr6\DoctrineProvider;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactoryInterface;
use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;
use Doctrine\ODM\MongoDB\PersistentCollection\DefaultPersistentCollectionFactory;
use Doctrine\ODM\MongoDB\PersistentCollection\DefaultPersistentCollectionGenerator;
Expand Down Expand Up @@ -86,7 +87,7 @@ class Configuration
* @psalm-var array{
* autoGenerateHydratorClasses?: self::AUTOGENERATE_*,
* autoGeneratePersistentCollectionClasses?: self::AUTOGENERATE_*,
* classMetadataFactoryName?: class-string<ClassMetadataFactory>,
* classMetadataFactoryName?: class-string<ClassMetadataFactoryInterface>,
* defaultCommitOptions?: CommitOptions,
* defaultDocumentRepositoryClassName?: class-string<ObjectRepository<object>>,
* defaultGridFSRepositoryClassName?: class-string<GridFSRepository<object>>,
Expand Down Expand Up @@ -409,13 +410,23 @@ public function getDefaultDB(): ?string
return $this->attributes['defaultDB'] ?? null;
}

/** @psalm-param class-string<ClassMetadataFactory> $cmfName */
/**
* @psalm-param class-string<ClassMetadataFactoryInterface> $cmfName
*
* @throws MongoDBException If is not a ClassMetadataFactoryInterface.
*/
public function setClassMetadataFactoryName(string $cmfName): void
{
$reflectionClass = new ReflectionClass($cmfName);

if (! $reflectionClass->implementsInterface(ClassMetadataFactoryInterface::class)) {
throw MongoDBException::invalidClassMetadataFactory($cmfName);
}

$this->attributes['classMetadataFactoryName'] = $cmfName;
}

/** @psalm-return class-string<ClassMetadataFactory> */
/** @psalm-return class-string<ClassMetadataFactoryInterface> */
public function getClassMetadataFactoryName(): string
{
if (! isset($this->attributes['classMetadataFactoryName'])) {
Expand Down Expand Up @@ -474,7 +485,7 @@ public function getFilterParameters(string $name): array
/**
* @psalm-param class-string<ObjectRepository<object>> $className
*
* @throws MongoDBException If not is a ObjectRepository.
* @throws MongoDBException If is not an ObjectRepository.
*/
public function setDefaultDocumentRepositoryClassName(string $className): void
{
Expand Down
16 changes: 9 additions & 7 deletions lib/Doctrine/ODM/MongoDB/DocumentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Doctrine\Common\EventManager;
use Doctrine\ODM\MongoDB\Hydrator\HydratorFactory;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactoryInterface;
use Doctrine\ODM\MongoDB\Mapping\MappingException;
use Doctrine\ODM\MongoDB\Proxy\Factory\ProxyFactory;
use Doctrine\ODM\MongoDB\Proxy\Factory\StaticProxyFactory;
Expand All @@ -19,6 +19,7 @@
use Doctrine\ODM\MongoDB\Repository\GridFSRepository;
use Doctrine\ODM\MongoDB\Repository\RepositoryFactory;
use Doctrine\ODM\MongoDB\Repository\ViewRepository;
use Doctrine\Persistence\Mapping\ProxyClassNameResolver;
use Doctrine\Persistence\ObjectManager;
use InvalidArgumentException;
use Jean85\PrettyVersions;
Expand Down Expand Up @@ -68,7 +69,7 @@ class DocumentManager implements ObjectManager
/**
* The metadata factory, used to retrieve the ODM metadata of document classes.
*/
private ClassMetadataFactory $metadataFactory;
private ClassMetadataFactoryInterface $metadataFactory;

/**
* The UnitOfWork used to coordinate object-level transactions.
Expand Down Expand Up @@ -131,7 +132,8 @@ class DocumentManager implements ObjectManager
*/
private ?FilterCollection $filterCollection = null;

private ClassNameResolver $classNameResolver;
/** @var ProxyClassNameResolver&ClassNameResolver */
private ProxyClassNameResolver $classNameResolver;

private static ?string $version = null;

Expand All @@ -154,10 +156,13 @@ protected function __construct(?Client $client = null, ?Configuration $config =
],
);

$this->classNameResolver = new CachingClassNameResolver(new ProxyManagerClassNameResolver($this->config));

$metadataFactoryClassName = $this->config->getClassMetadataFactoryName();
$this->metadataFactory = new $metadataFactoryClassName();
$this->metadataFactory->setDocumentManager($this);
$this->metadataFactory->setConfiguration($this->config);
$this->metadataFactory->setProxyClassNameResolver($this->classNameResolver);

$cacheDriver = $this->config->getMetadataCache();
if ($cacheDriver) {
Expand All @@ -179,9 +184,6 @@ protected function __construct(?Client $client = null, ?Configuration $config =
$this->schemaManager = new SchemaManager($this, $this->metadataFactory);
$this->proxyFactory = new StaticProxyFactory($this);
$this->repositoryFactory = $this->config->getRepositoryFactory();
$this->classNameResolver = new CachingClassNameResolver(new ProxyManagerClassNameResolver($this->config));

$this->metadataFactory->setProxyClassNameResolver($this->classNameResolver);
}

/**
Expand Down Expand Up @@ -220,7 +222,7 @@ public function getClient(): Client
/**
* Gets the metadata factory used to gather the metadata of classes.
*
* @return ClassMetadataFactory
* @return ClassMetadataFactoryInterface
*/
public function getMetadataFactory()
{
Expand Down
6 changes: 1 addition & 5 deletions lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,8 @@
* @internal
*
* @template-extends AbstractClassMetadataFactory<ClassMetadata>
*
* @method list<ClassMetadata> getAllMetadata()
* @method ClassMetadata[] getLoadedMetadata()
* @method ClassMetadata getMetadataFor($className)
*/
final class ClassMetadataFactory extends AbstractClassMetadataFactory
final class ClassMetadataFactory extends AbstractClassMetadataFactory implements ClassMetadataFactoryInterface
{
/** @var string */
protected $cacheSalt = '$MONGODBODMCLASSMETADATA';
Expand Down
40 changes: 40 additions & 0 deletions lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Doctrine\ODM\MongoDB\Mapping;

use Doctrine\ODM\MongoDB\Configuration;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\Persistence\Mapping\ClassMetadataFactory;
use Doctrine\Persistence\Mapping\ProxyClassNameResolver;
use Psr\Cache\CacheItemPoolInterface;

/**
* @template-extends ClassMetadataFactory<ClassMetadata>
* @method list<ClassMetadata> getAllMetadata()
* @method ClassMetadata[] getLoadedMetadata()
* @method ClassMetadata getMetadataFor($className)
*/
interface ClassMetadataFactoryInterface extends ClassMetadataFactory
{
/**
* Sets the cache for created metadata.
*/
public function setCache(CacheItemPoolInterface $cache): void;

/**
* Sets the configuration for the factory.
*/
public function setConfiguration(Configuration $config): void;

/**
* Sets the document manager owning the factory.
*/
public function setDocumentManager(DocumentManager $dm): void;

/**
* Sets a resolver for real class names of a proxy.
*/
public function setProxyClassNameResolver(ProxyClassNameResolver $resolver): void;
}
6 changes: 6 additions & 0 deletions lib/Doctrine/ODM/MongoDB/MongoDBException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Doctrine\ODM\MongoDB;

use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactoryInterface;
use Doctrine\ODM\MongoDB\Repository\GridFSRepository;
use Doctrine\Persistence\ObjectRepository;
use Exception;
Expand Down Expand Up @@ -60,6 +61,11 @@ public static function invalidGridFSRepository(string $className): self
return new self(sprintf("Invalid repository class '%s'. It must be a %s.", $className, GridFSRepository::class));
}

public static function invalidClassMetadataFactory(string $className): self
{
return new self(sprintf("Invalid class metadata factory class '%s'. It must be a %s.", $className, ClassMetadataFactoryInterface::class));
}

/**
* @param string|string[] $expected
* @param mixed $got
Expand Down
4 changes: 2 additions & 2 deletions lib/Doctrine/ODM/MongoDB/SchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Doctrine\ODM\MongoDB;

use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactoryInterface;
use Doctrine\ODM\MongoDB\Repository\ViewRepository;
use InvalidArgumentException;
use MongoDB\Driver\Exception\RuntimeException;
Expand Down Expand Up @@ -54,7 +54,7 @@ final class SchemaManager
'name',
];

public function __construct(protected DocumentManager $dm, protected ClassMetadataFactory $metadataFactory)
public function __construct(protected DocumentManager $dm, protected ClassMetadataFactoryInterface $metadataFactory)
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Doctrine\ODM\MongoDB\Tools\Console\Command\Schema;

use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactoryInterface;
use Doctrine\ODM\MongoDB\SchemaManager;
use MongoDB\Driver\WriteConcern;
use Symfony\Component\Console\Command\Command;
Expand Down Expand Up @@ -64,7 +64,7 @@ protected function getDocumentManager()
return $this->getHelper('documentManager')->getDocumentManager();
}

/** @return ClassMetadataFactory */
/** @return ClassMetadataFactoryInterface */
protected function getMetadataFactory()
{
return $this->getDocumentManager()->getMetadataFactory();
Expand Down
2 changes: 1 addition & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ parameters:
path: lib/Doctrine/ODM/MongoDB/Aggregation/Stage/UnionWith.php

-
message: "#^Return type \\(Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\ClassMetadataFactory\\) of method Doctrine\\\\ODM\\\\MongoDB\\\\DocumentManager\\:\\:getMetadataFactory\\(\\) should be compatible with return type \\(Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadataFactory\\<Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<object\\>\\>\\) of method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:getMetadataFactory\\(\\)$#"
message: "#^Return type \\(Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\ClassMetadataFactoryInterface\\) of method Doctrine\\\\ODM\\\\MongoDB\\\\DocumentManager\\:\\:getMetadataFactory\\(\\) should be compatible with return type \\(Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadataFactory\\<Doctrine\\\\Persistence\\\\Mapping\\\\ClassMetadata\\<object\\>\\>\\) of method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:getMetadataFactory\\(\\)$#"
count: 1
path: lib/Doctrine/ODM/MongoDB/DocumentManager.php

Expand Down
3 changes: 2 additions & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
</file>
<file src="lib/Doctrine/ODM/MongoDB/Configuration.php">
<TypeDoesNotContainType>
<code><![CDATA[$reflectionClass->implementsInterface(ClassMetadataFactoryInterface::class)]]></code>
<code><![CDATA[$reflectionClass->implementsInterface(GridFSRepository::class)]]></code>
<code><![CDATA[$reflectionClass->implementsInterface(ObjectRepository::class)]]></code>
</TypeDoesNotContainType>
</file>
<file src="lib/Doctrine/ODM/MongoDB/DocumentManager.php">
<ImplementedReturnTypeMismatch>
<code>ClassMetadataFactory</code>
<code>ClassMetadataFactoryInterface</code>
</ImplementedReturnTypeMismatch>
</file>
<file src="lib/Doctrine/ODM/MongoDB/Event/OnClearEventArgs.php">
Expand Down
21 changes: 21 additions & 0 deletions tests/Doctrine/ODM/MongoDB/Tests/Functional/EnumTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
use Documents81\Card;
use Documents81\Suit;
use Error;
use Jean85\PrettyVersions;
use MongoDB\BSON\ObjectId;
use ValueError;

use function preg_quote;
use function sprintf;
use function version_compare;

/** @requires PHP >= 8.1 */
class EnumTest extends BaseTestCase
Expand All @@ -35,6 +37,25 @@ public function testPersistNew(): void
self::assertNull($saved->nullableSuit);
}

public function testArrayOfEnums(): void
{
$persistenceVersion = PrettyVersions::getVersion('doctrine/persistence')->getPrettyVersion();
if (version_compare('3.2.0', $persistenceVersion, '>')) {
self::markTestSkipped('Support for array of enums was introduced in doctrine/persistence 3.2.0');
}

$doc = new Card();
$doc->suits = ['foo' => Suit::Clubs, 'bar' => Suit::Diamonds];

$this->dm->persist($doc);
$this->dm->flush();
$this->dm->clear();

$saved = $this->dm->find(Card::class, $doc->id);
self::assertInstanceOf(Card::class, $saved);
self::assertSame(['foo' => Suit::Clubs, 'bar' => Suit::Diamonds], $saved->suits);
}

public function testLoadingInvalidBackingValueThrowsError(): void
{
$document = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
use Doctrine\Common\Collections\Collection;
use Doctrine\ODM\MongoDB\Events;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactoryInterface;
use Doctrine\ODM\MongoDB\Tests\BaseTestCase;
use Doctrine\ODM\MongoDB\Tools\ResolveTargetDocumentListener;

class ResolveTargetDocumentListenerTest extends BaseTestCase
{
protected ResolveTargetDocumentListener $listener;

private ClassMetadataFactory $factory;
private ClassMetadataFactoryInterface $factory;

public function setUp(): void
{
Expand Down
8 changes: 8 additions & 0 deletions tests/Documents81/Card.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,13 @@ class Card
#[ODM\Field(type: 'string', enumType: Suit::class, nullable: true)]
public ?Suit $nullableSuit;

/**
* @ODM\Field(enumType=Suit::class)
*
* @var Suit[]
*/
#[ODM\Field(enumType: Suit::class)]
public array $suits;

public ?SuitNonBacked $suitNonBacked;
}

0 comments on commit d3c8966

Please sign in to comment.