8000 [DoctrineBridge] Inject the entity manager instead of the class metadata factory in DoctrineExtractor by dunglas · Pull Request #27829 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[DoctrineBridge] Inject the entity manager instead of the class metadata factory in DoctrineExtractor #27829

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

Merged
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
7 changes: 6 additions & 1 deletion UPGRADE-5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,18 @@ Console
$processHelper->run($output, Process::fromShellCommandline('ls -l'));
```


DependencyInjection
-------------------

* Removed the `TypedReference::canBeAutoregistered()` and `TypedReference::getRequiringClass()` methods.
* Removed support for auto-discovered extension configuration class which does not implement `ConfigurationInterface`.

DoctrineBridge
--------------

* Deprecated injecting `ClassMetadataFactory` in `D 8000 octrineExtractor`, an instance of `EntityManagerInterface` should be
injected instead

EventDispatcher
---------------

Expand Down
6 changes: 6 additions & 0 deletions src/Symfony/Bridge/Doctrine/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
CHANGELOG
=========

4.2.0
-----

* deprecated injecting `ClassMetadataFactory` in `DoctrineExtractor`,
an instance of `EntityManagerInterface` should be injected instead

4.1.0
-----

Expand Down
24 changes: 18 additions & 6 deletions src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
use Doctrine\Common\Persistence\Mapping\MappingException;
use Doctrine\DBAL\Types\Type as DBALType;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\MappingException as OrmMappingException;
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;
Expand All @@ -27,11 +28,22 @@
*/
class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeExtractorInterface
{
private $entityManager;
private $classMetadataFactory;
Copy link
Contributor
@ro0NL ro0NL Jul 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this one have a @deprecated tag?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, it's a private property anyway

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might help at time to clean up deprecated features from the next major branch.
With some well placed @deprecated flags for each deprecated feature, cleaning an entire component can be way easier (just greping) and free of leftovers (each one leading to "drop dead code" PRs, you know).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that, and the fact it hints to not use the property anymore


public function __construct(ClassMetadataFactory $classMetadataFactory)
/**
* @param EntityManagerInterface $entityManager
*/
public function __construct($entityManager)
{
$this->classMetadataFactory = $classMetadataFactory;
if ($entityManager instanceof EntityManagerInterface) {
$this->entityManager = $entityManager;
} elseif ($entityManager instanceof ClassMetadataFactory) {
@trigger_error(sprintf('Injecting an instance of "%s" in "%s" is deprecated since Symfony 4.2, inject an instance of "%s" instead.', ClassMetadataFactory::class, __CLASS__, EntityManagerInterface::class), E_USER_DEPRECATED);
$this->classMetadataFactory = $entityManager;
} else {
throw new \InvalidArgumentException(sprintf('$entityManager must be an instance of "%s", "%s" given.', EntityManagerInterface::class, \is_object($entityManager) ? \get_class($entityManager) : \gettype($entityManager)));
}
}

/**
Expand All @@ -40,7 +52,7 @@ public function __construct(ClassMetadataFactory $classMetadataFactory)
public function getProperties($class, array $context = array())
{
try {
$metadata = $this->classMetadataFactory->getMetadataFor($class);
$metadata = $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about extracting private method for that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't worth it: it will introduce a performance penalty and anyway it will be dropped in Symfony 5.

} catch (MappingException $exception) {
return;
} catch (OrmMappingException $exception) {
Expand All @@ -66,7 +78,7 @@ public function getProperties($class, array $context = array())
public function getTypes($class, $property, array $context = array())
{
try {
$metadata = $this->classMetadataFactory->getMetadataFor($class);
$metadata = $this->entityManager ? $this->entityManager->getClassMetadata($class) : $this->classMetadataFactory->getMetadataFor($class);
} catch (MappingException $exception) {
return;
} catch (OrmMappingException $exception) {
Expand Down Expand Up @@ -96,15 +108,15 @@ public function getTypes($class, $property, array $context = array())
if (isset($associationMapping['indexBy'])) {
$indexProperty = $associationMapping['indexBy'];
/** @var ClassMetadataInfo $subMetadata */
$subMetadata = $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']);
$subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']);
$typeOfField = $subMetadata->getTypeOfField($indexProperty);

if (null === $typeOfField) {
$associationMapping = $subMetadata->getAssociationMapping($indexProperty);

/** @var ClassMetadataInfo $subMetadata */
$indexProperty = $subMetadata->getSingleAssociationReferencedJoinColumnName($indexProperty);
$subMetadata = $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']);
$subMetadata = $this->entityManager ? $this->entityManager->getClassMetadata($associationMapping['targetEntity']) : $this->classMetadataFactory->getMetadataFor($associationMapping['targetEntity']);
$typeOfField = $subMetadata->getTypeOfField($indexProperty);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,30 @@
*/
class DoctrineExtractorTest extends TestCase
{
/**
* @var DoctrineExtractor
*/
private $extractor;

protected function setUp()
private function createExtractor(bool $legacy = false)
{
$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'), true);
$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__.\DIRECTORY_SEPARATOR.'Fixtures'), true);
$entityManager = EntityManager::create(array('driver' => 'pdo_sqlite'), $config);

if (!DBALType::hasType('foo')) {
DBALType::addType('foo', 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineFooType');
$entityManager->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('custom_foo', 'foo');
}

$this->extractor = new DoctrineExtractor($entityManager->getMetadataFactory());
return new DoctrineExtractor($legacy ? $entityManager->getMetadataFactory() : $entityManager);
}

public function testGetProperties()
{
$this->doTestGetProperties(false);
}

public function testLegacyGetProperties()
{
$this->doTestGetProperties(true);
}

private function doTestGetProperties(bool $legacy)
{
$this->assertEquals(
array(
Expand All @@ -63,11 +68,21 @@ public function testGetProperties()
'indexedBar',
'indexedFoo',
),
$this->extractor->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy')
$this->createExtractor($legacy)->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy')
);
}

public function testGetPropertiesWithEmbedded()
public function testTestGetPropertiesWithEmbedded()
{
$this->doTestGetPropertiesWithEmbedded(false);
}

public function testLegacyTestGetPropertiesWithEmbedded()
{
$this->doTestGetPropertiesWithEmbedded(true);
}

private function doTestGetPropertiesWithEmbedded(bool $legacy)
{
if (!class_exists('Doctrine\ORM\Mapping\Embedded')) {
$this->markTestSkipped('@Embedded is not available in Doctrine ORM lower than 2.5.');
Expand All @@ -78,7 +93,7 @@ public function testGetPropertiesWithEmbedded()
'id',
'embedded',
),
$this->extractor->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineWithEmbedded')
$this->createExtractor($legacy)->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineWithEmbedded')
);
}

Expand All @@ -87,10 +102,33 @@ public function testGetPropertiesWithEmbedded()
*/
public function testExtract($property, array $type = null)
{
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy', $property, array()));
$this->doTestExtract(false, $property, $type);
}

/**
* @dataProvider typesProvider
*/
public function testLegacyExtract($property, array $type = null)
{
$this->doTestExtract(true, $property, $type);
}

private function doTestExtract(bool $legacy, $property, array $type = null)
{
$this->assertEquals($type, $this->createExtractor($legacy)->getTypes('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy', $property, array()));
}

public function testExtractWithEmbedded()
{
$this->doTestExtractWithEmbedded(false);
}

public function testLegacyExtractWithEmbedded()
{
$this->doTestExtractWithEmbedded(true);
}

private function doTestExtractWithEmbedded(bool $legacy)
{
if (!class_exists('Doctrine\ORM\Mapping\Embedded')) {
$this->markTestSkipped('@Embedded is not available in Doctrine ORM lower than 2.5.');
Expand All @@ -102,7 +140,7 @@ public function testExtractWithEmbedded()
'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineEmbeddable'
));

$actualTypes = $this->extractor->getTypes(
$actualTypes = $this->createExtractor($legacy)->getTypes(
'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineWithEmbedded',
'embedded',
array()
Expand Down Expand Up @@ -158,11 +196,31 @@ public function typesProvider()

public function testGetPropertiesCatchException()
{
$this->assertNull($this->extractor->getProperties('Not\Exist'));
$this->doTestGetPropertiesCatchException(false);
}

public function testLegacyGetPropertiesCatchException()
{
$this->doTestGetPropertiesCatchException(true);
}

private function doTestGetPropertiesCatchException(bool $legacy)
{
$this->assertNull($this->createExtractor($legacy)->getProperties('Not\Exist'));
}

public function testGetTypesCatchException()
{
$this->assertNull($this->extractor->getTypes('Not\Exist', 'baz'));
return $this->doTestGetTypesCatchException(false);
}

public function testLegacyGetTypesCatchException()
{
return $this->doTestGetTypesCatchException(true);
}

private function doTestGetTypesCatchException(bool $legacy)
{
$this->assertNull($this->createExtractor($legacy)->getTypes('Not\Exist', 'baz'));
}
}
0