Skip to content

Allow to use both ORM and ODM #218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
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
8 changes: 6 additions & 2 deletions src/Type/Doctrine/ObjectMetadataResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,18 @@ public function getRepositoryClass(string $className): string
if ($metadata instanceof $ormMetadataClass) {
/** @var \Doctrine\ORM\Mapping\ClassMetadata $ormMetadata */
$ormMetadata = $metadata;
return $ormMetadata->customRepositoryClassName ?? $this->getResolvedRepositoryClass();
return $ormMetadata->customRepositoryClassName
?? $this->repositoryClass
?? 'Doctrine\ORM\EntityRepository';
}

$odmMetadataClass = 'Doctrine\ODM\MongoDB\Mapping\ClassMetadata';
if ($metadata instanceof $odmMetadataClass) {
/** @var \Doctrine\ODM\MongoDB\Mapping\ClassMetadata $odmMetadata */
$odmMetadata = $metadata;
return $odmMetadata->customRepositoryClassName ?? $this->getResolvedRepositoryClass();
return $odmMetadata->customRepositoryClassName
?? $this->repositoryClass
?? 'Doctrine\ODM\MongoDB\Repository\DocumentRepository';
}

return $this->getResolvedRepositoryClass();
Expand Down
23 changes: 23 additions & 0 deletions tests/Type/Doctrine/ObjectMetadataResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php declare(strict_types = 1);

namespace PHPStan\Type\Doctrine;

use PHPStan\Type\Doctrine\CustomObjectManager\MyDocument;
use PHPStan\Type\Doctrine\CustomObjectManager\MyEntity;

final class ObjectMetadataResolverTest extends \PHPStan\Testing\PHPStanTestCase
{

public function testGetRepositoryClassWithCustomObjectManager(): void
{
$objectMetadataResolver = new ObjectMetadataResolver(
$this->createReflectionProvider(),
__DIR__ . '/data/CustomObjectManager/custom-object-manager.php',
null
);

self::assertSame('Doctrine\ODM\MongoDB\Repository\DocumentRepository', $objectMetadataResolver->getRepositoryClass(MyDocument::class));
self::assertSame('Doctrine\ORM\EntityRepository', $objectMetadataResolver->getRepositoryClass(MyEntity::class));
}

}
25 changes: 25 additions & 0 deletions tests/Type/Doctrine/data/CustomObjectManager/MyDocument.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php declare(strict_types = 1);

namespace PHPStan\Type\Doctrine\CustomObjectManager;

use Doctrine\ODM\MongoDB\Mapping\Annotations\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations\Id;

/**
* @Document
*/
class MyDocument
{

/**
* @Id(strategy="NONE", type="string")
*
* @var string
*/
private $id;

public function doSomethingElse(): void
{
}

}
26 changes: 26 additions & 0 deletions tests/Type/Doctrine/data/CustomObjectManager/MyEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php declare(strict_types = 1);

namespace PHPStan\Type\Doctrine\CustomObjectManager;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
*/
class MyEntity
{

/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*
* @var int
*/
private $id;

public function doSomethingElse(): void
{
}

}
235 changes: 235 additions & 0 deletions tests/Type/Doctrine/data/CustomObjectManager/custom-object-manager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
<?php declare(strict_types = 1);

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\ODM\MongoDB;
use Doctrine\ORM;
use Doctrine\Persistence\Mapping\ClassMetadata;
use Doctrine\Persistence\Mapping\ClassMetadataFactory;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Persistence\ObjectRepository;

$config = new MongoDB\Configuration();
$config->setProxyDir(__DIR__);
$config->setProxyNamespace('PHPstan\Doctrine\OdmProxies');
$config->setMetadataCacheImpl(new ArrayCache());
$config->setHydratorDir(__DIR__);
$config->setHydratorNamespace('PHPstan\Doctrine\OdmHydrators');

$config->setMetadataDriverImpl(
new MongoDB\Mapping\Driver\AnnotationDriver(
new AnnotationReader(),
[__DIR__ . '/ObjectMetadataResolverTest.php']
)
);

$documentManager = MongoDB\DocumentManager::create(
null,
$config
);

$config = new ORM\Configuration();
$config->setProxyDir(__DIR__);
$config->setProxyNamespace('PHPstan\Doctrine\OrmProxies');
$config->setMetadataCacheImpl(new ArrayCache());

$config->setMetadataDriverImpl(
new ORM\Mapping\Driver\AnnotationDriver(
new AnnotationReader(),
[__DIR__ . '/ObjectMetadataResolverTest.php']
)
);

$entityManager = ORM\EntityManager::create(
[
'driver' => 'pdo_sqlite',
'memory' => true,
],
$config
);

$metadataFactory = new class($documentManager, $entityManager) implements ClassMetadataFactory
{

/** @var MongoDB\DocumentManager */
private $documentManager;

/** @var ORM\EntityManager */
private $entityManager;

public function __construct(MongoDB\DocumentManager $documentManager, ORM\EntityManager $entityManager)
{
$this->documentManager = $documentManager;
$this->entityManager = $entityManager;
}

public function getAllMetadata(): array
{
return array_merge(
$this->documentManager->getMetadataFactory()->getAllMetadata(),
$this->entityManager->getMetadataFactory()->getAllMetadata()
);
}

/**
* @param string $className
*/
public function getMetadataFor($className): void
{
throw new \Exception(__FILE__);
}

/**
* @param string $className
*/
public function isTransient($className): void
{
throw new \Exception(__FILE__);
}

/**
* @param string $className
*/
public function hasMetadataFor($className): void
{
throw new \Exception(__FILE__);
}

/**
* @param string $className
* @param ClassMetadata $class
*/
public function setMetadataFor($className, $class): void
{
throw new \Exception(__FILE__);
}

};

return new class($documentManager, $entityManager, $metadataFactory) implements ObjectManager
{

/** @var MongoDB\DocumentManager */
private $documentManager;

/** @var ORM\EntityManager */
private $entityManager;

/** @var ClassMetadataFactory */
private $classMetadataFactory;

public function __construct(MongoDB\DocumentManager $documentManager, ORM\EntityManager $entityManager, ClassMetadataFactory $classMetadataFactory)
{
$this->documentManager = $documentManager;
$this->entityManager = $entityManager;
$this->classMetadataFactory = $classMetadataFactory;
}

/**
* @param string $className
*/
public function getRepository($className): ObjectRepository
{
if (strpos($className, 'Entity') !== false) {
return $this->entityManager->getRepository($className);
}

return $this->documentManager->getRepository($className);
}

/**
* @param string $className
*/
public function getClassMetadata($className): ClassMetadata
{
if (strpos($className, 'Entity') !== false) {
return $this->entityManager->getClassMetadata($className);
}

return $this->documentManager->getClassMetadata($className);
}

public function getMetadataFactory(): ClassMetadataFactory
{
return $this->classMetadataFactory;
}

/**
* @param string $className
* @param mixed $id
*/
public function find($className, $id): void
{
throw new \Exception(__FILE__);
}

/**
* @param object $object
*/
public function persist($object): void
{
throw new \Exception(__FILE__);
}

/**
* @param object $object
*/
public function remove($object): void
{
throw new \Exception(__FILE__);
}

/**
* @param object $object
*/
public function merge($object): void
{
throw new \Exception(__FILE__);
}

/**
* @param string|null $objectName
*/
public function clear($objectName = null): void
{
throw new \Exception(__FILE__);
}

/**
* @param object $object
*/
public function detach($object): void
{
throw new \Exception(__FILE__);
}

/**
* @param object $object
*/
public function refresh($object): void
{
throw new \Exception(__FILE__);
}

public function flush(): void
{
throw new \Exception(__FILE__);
}

/**
* @param object $object
*/
public function initializeObject($object): void
{
throw new \Exception(__FILE__);
}

/**
* @param object $object
*/
public function contains($object): bool
{
throw new \Exception(__FILE__);
}

};