-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Support fetching entities by aliased name #1181
Changes from all commits
51528fb
19c52e4
437f812
3be43a1
d663565
efd4500
f5eb20b
d91b0b4
e4cbdb5
ce4df76
a710706
8ea394e
eaa9187
94a2036
f14063d
06f256b
6021e3a
762e798
6debf2c
662b496
d712ad9
ae8ab08
ba5378f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
<?php | ||
/* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
* | ||
* This software consists of voluntary contributions made by many individuals | ||
* and is licensed under the MIT license. For more information, see | ||
* <http://www.doctrine-project.org>. | ||
*/ | ||
|
||
namespace Doctrine\ORM\Event; | ||
|
||
use Doctrine\Common\EventArgs; | ||
use Doctrine\Common\Persistence\Event\ManagerEventArgs; | ||
use Doctrine\Common\Persistence\Mapping\ClassMetadata; | ||
use Doctrine\Common\Persistence\ObjectManager; | ||
use Doctrine\ORM\EntityManager; | ||
use Doctrine\ORM\EntityManagerInterface; | ||
|
||
/** | ||
* Class that holds event arguments for a `onClassMetadataNotFound` event. | ||
* | ||
* This object is mutable by design, allowing callbacks having access to it to set the | ||
* found metadata in it, and therefore "cancelling" a `onClassMetadataNotFound` event | ||
* | ||
* @author Marco Pivetta <[email protected]> | ||
* @since 2.5 | ||
*/ | ||
class OnClassMetadataNotFoundEventArgs extends ManagerEventArgs | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
private $className; | ||
|
||
/** | ||
* @var ClassMetadata|null | ||
*/ | ||
private $foundMetadata; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param string $className | ||
* @param ObjectManager $objectManager | ||
*/ | ||
public function __construct($className, ObjectManager $objectManager) | ||
{ | ||
$this->className = (string) $className; | ||
|
||
parent::__construct($objectManager); | ||
} | ||
|
||
/** | ||
* @param ClassMetadata|null $classMetadata | ||
*/ | ||
public function setFoundMetadata(ClassMetadata $classMetadata = null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would be the use case to set found metadata to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just want to allow full mutability here. Having a failure in a different listener should cause a reset to |
||
{ | ||
$this->foundMetadata = $classMetadata; | ||
} | ||
|
||
/** | ||
* @return ClassMetadata|null | ||
*/ | ||
public function getFoundMetadata() | ||
{ | ||
return $this->foundMetadata; | ||
} | ||
|
||
/** | ||
* Retrieve class name for which a failed metadata fetch attempt was executed | ||
* | ||
* @return string | ||
*/ | ||
public function getClassName() | ||
{ | ||
return $this->className; | ||
} | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. EOF EOL |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,6 +120,14 @@ private function __construct() | |
*/ | ||
const loadClassMetadata = 'loadClassMetadata'; | ||
|
||
/** | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Newline before this line |
||
* The onClassMetadataNotFound event occurs whenever loading metadata for a class | ||
* failed. | ||
* | ||
* @var string | ||
*/ | ||
const onClassMetadataNotFound = 'onClassMetadataNotFound'; | ||
|
||
/** | ||
* The preFlush event occurs when the EntityManager#flush() operation is invoked, | ||
* but before any changes to managed entities have been calculated. This event is | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ | |
use Doctrine\DBAL\Platforms; | ||
use Doctrine\ORM\EntityManagerInterface; | ||
use Doctrine\ORM\Event\LoadClassMetadataEventArgs; | ||
use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs; | ||
use Doctrine\ORM\Events; | ||
use Doctrine\ORM\Id\BigIntegerIdentityGenerator; | ||
use Doctrine\ORM\Id\IdentityGenerator; | ||
|
@@ -78,7 +79,7 @@ public function setEntityManager(EntityManagerInterface $em) | |
} | ||
|
||
/** | ||
* {@inheritDoc}. | ||
* {@inheritDoc} | ||
*/ | ||
protected function initialize() | ||
{ | ||
|
@@ -88,6 +89,22 @@ protected function initialize() | |
$this->initialized = true; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no parent method here as far as I can see. Can you provide a descriptive DocBlock? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method is actually an override as per doctrine/common#342 |
||
*/ | ||
protected function onNotFoundMetadata($className) | ||
{ | ||
if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) { | ||
return; | ||
} | ||
|
||
$eventArgs = new OnClassMetadataNotFoundEventArgs($className, $this->em); | ||
|
||
$this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs); | ||
|
||
return $eventArgs->getFoundMetadata(); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,10 @@ | |
namespace Doctrine\ORM\Tools; | ||
|
||
use Doctrine\ORM\Event\LoadClassMetadataEventArgs; | ||
use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs; | ||
use Doctrine\ORM\Mapping\ClassMetadata; | ||
use Doctrine\Common\EventSubscriber; | ||
use Doctrine\ORM\Events; | ||
|
||
/** | ||
* ResolveTargetEntityListener | ||
|
@@ -31,13 +34,24 @@ | |
* @author Benjamin Eberlei <[email protected]> | ||
* @since 2.2 | ||
*/ | ||
class ResolveTargetEntityListener | ||
class ResolveTargetEntityListener implements EventSubscriber | ||
{ | ||
/** | ||
* @var array | ||
* @var array[] indexed by original entity name | ||
*/ | ||
private $resolveTargetEntities = array(); | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getSubscribedEvents() | ||
{ | ||
return array( | ||
Events::loadClassMetadata, | ||
Events::onClassMetadataNotFound | ||
); | ||
} | ||
|
||
/** | ||
* Adds a target-entity class name to resolve to a new class name. | ||
* | ||
|
@@ -49,26 +63,53 @@ class ResolveTargetEntityListener | |
*/ | ||
public function addResolveTargetEntity($originalEntity, $newEntity, array $mapping) | ||
{ | ||
$mapping['targetEntity'] = ltrim($newEntity, "\\"); | ||
$mapping['targetEntity'] = ltrim($newEntity, "\\"); | ||
$this->resolveTargetEntities[ltrim($originalEntity, "\\")] = $mapping; | ||
} | ||
|
||
/** | ||
* @param OnClassMetadataNotFoundEventArgs $args | ||
* | ||
* @internal this is an event callback, and should not be called directly | ||
* | ||
* @return void | ||
*/ | ||
public function onClassMetadataNotFound(OnClassMetadataNotFoundEventArgs $args) | ||
{ | ||
if (array_key_exists($args->getClassName(), $this->resolveTargetEntities)) { | ||
$args->setFoundMetadata( | ||
$args | ||
->getObjectManager() | ||
->getClassMetadata($this->resolveTargetEntities[$args->getClassname()]['targetEntity']) | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Processes event and resolves new target entity names. | ||
* | ||
* @param LoadClassMetadataEventArgs $args | ||
* | ||
* @return void | ||
* | ||
* @internal this is an event callback, and should not be called directly | ||
*/ | ||
public function loadClassMetadata(LoadClassMetadataEventArgs $args) | ||
{ | ||
/* @var $cm \Doctrine\ORM\Mapping\ClassMetadata */ | ||
$cm = $args->getClassMetadata(); | ||
|
||
foreach ($cm->associationMappings as $mapping) { | ||
if (isset($this->resolveTargetEntities[$mapping['targetEntity']])) { | ||
$this->remapAssociation($cm, $mapping); | ||
} | ||
} | ||
|
||
foreach ($this->resolveTargetEntities as $interface => $data) { | ||
if ($data['targetEntity'] == $cm->getName()) { | ||
$args->getEntityManager()->getMetadataFactory()->setMetadataFor($interface, $cm); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<?php | ||
|
||
namespace Doctrine\Tests\ORM; | ||
|
||
use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs; | ||
use PHPUnit_Framework_TestCase; | ||
|
||
/** | ||
* Tests for {@see \Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs} | ||
* | ||
* @covers \Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs | ||
*/ | ||
class OnClassMetadataNotFoundEventArgsTest extends PHPUnit_Framework_TestCase | ||
{ | ||
public function testEventArgsMutability() | ||
{ | ||
/* @var $objectManager \Doctrine\Common\Persistence\ObjectManager */ | ||
$objectManager = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); | ||
|
||
$args = new OnClassMetadataNotFoundEventArgs('foo', $objectManager); | ||
|
||
$this->assertSame('foo', $args->getClassName()); | ||
$this->assertSame($objectManager, $args->getObjectManager()); | ||
|
||
$this->assertNull($args->getFoundMetadata()); | ||
|
||
/* @var $metadata \Doctrine\Common\Persistence\Mapping\ClassMetadata */ | ||
$metadata = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadata'); | ||
|
||
$args->setFoundMetadata($metadata); | ||
|
||
$this->assertSame($metadata, $args->getFoundMetadata()); | ||
|
||
$args->setFoundMetadata(null); | ||
|
||
$this->assertNull($args->getFoundMetadata()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why this wasn't there: we depend on the package, therefore it must be in the list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, it must be there