Skip to content

Commit

Permalink
Merge pull request #2552 from malarzm/gh-2551-cmf-interface
Browse files Browse the repository at this point in the history
Introduce ClassMetadataFactoryInterface to allow switching implementations
  • Loading branch information
malarzm authored Oct 23, 2023
2 parents eb7560e + fbff519 commit bdbb370
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 25 deletions.
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 @@ -69,7 +70,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 @@ -132,7 +133,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 @@ -155,10 +157,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 @@ -180,9 +185,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 @@ -221,7 +223,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 @@ -38,12 +38,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 @@ -61,6 +62,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
6 changes: 3 additions & 3 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 @@ -56,9 +56,9 @@ final class SchemaManager

protected DocumentManager $dm;

protected ClassMetadataFactory $metadataFactory;
protected ClassMetadataFactoryInterface $metadataFactory;

public function __construct(DocumentManager $dm, ClassMetadataFactory $cmf)
public function __construct(DocumentManager $dm, ClassMetadataFactoryInterface $cmf)
{
$this->dm = $dm;
$this->metadataFactory = $cmf;
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 @@ -15,7 +15,7 @@ parameters:

# This cannot be solved the way it is, see https://github.com/vimeo/psalm/issues/5788
-
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 @@ -12,13 +12,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
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

0 comments on commit bdbb370

Please sign in to comment.