Skip to content

Commit b03d693

Browse files
authored
Merge pull request #1997 from emulienfou/listener-event-subscriber
Change `ResolveTargetDocumentListener` to be an event subscriber instead of an event listener
2 parents 363ea55 + 8d2f75a commit b03d693

File tree

4 files changed

+100
-5
lines changed

4 files changed

+100
-5
lines changed

UPGRADE-1.3.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,31 @@
11
# UPGRADE FROM 1.2 TO 1.3
22

3+
## Events
4+
5+
### `onClassMetadataNotFound` event added
6+
7+
The default ClassMetadataFactory now triggers an `onClassMetadataNotFound` event
8+
when no metadata was found for a given class. The event args contain information
9+
about the loaded class and can store a metadata object which can be used to load
10+
custom metadata when none was found.
11+
12+
### `ResolveTargetDocumentListener` is now an event subscriber
13+
14+
The `Doctrine\ODM\MongoDB\Tools\ResolveTargetDocumentListener` class now
15+
implements the `EventSubscriber` interface. You can still register it as a
16+
listener as was necessary previously, but in order to use new functionality you
17+
have to register it as an event subscriber.
18+
19+
### `ResolveTargetDocumentListener` resolves class names on document load
20+
21+
The `Doctrine\ODM\MongoDB\Tools\ResolveTargetDocumentListener` class not only
22+
resolves class names when looking up the `targetDoccumet` of an association in
23+
a document, but it also uses the new `onClassMetadataNotFound` event to resolve
24+
class names and trigger a secondary metadata load cycle if no metadata was found
25+
for the original class name. To use this functionality, either register an event
26+
listener for the `onClassMetadataNotFound` event or register the entire class as
27+
an event subscriber.
28+
329
## GridFS
430

531
GridFS support will be rewritten for 2.0 and was deprecated in its current form.

docs/en/cookbook/resolve-target-document-listener.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ Doctrine MongoDB ODM includes a utility called
1010
inside Doctrine and rewriting ``targetDocument`` parameters in your metadata
1111
mapping at runtime. This allows your bundle to use an interface or abstract
1212
class in its mappings while still allowing the mapping to resolve to a concrete
13-
document class at runtime.
13+
document class at runtime. It will also rewrite class names when no mapping
14+
metadata has been found for the original class name.
1415

1516
This functionality allows you to define relationships between different
1617
documents without creating hard dependencies.
@@ -126,7 +127,7 @@ you cannot be guaranteed that the targetDocument resolution will occur reliably:
126127
);
127128
128129
// Add the ResolveTargetDocumentListener
129-
$evm->addEventListener(\Doctrine\ODM\MongoDB\Events::loadClassMetadata, $rtdl);
130+
$evm->addEventSubscriber($rtdl);
130131
131132
// Create the document manager as you normally would
132133
$dm = \Doctrine\ODM\MongoDB\DocumentManager::create($connectionOptions, $config, $evm);

lib/Doctrine/ODM/MongoDB/Tools/ResolveTargetDocumentListener.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,35 @@
22

33
namespace Doctrine\ODM\MongoDB\Tools;
44

5+
use Doctrine\Common\EventSubscriber;
56
use Doctrine\ODM\MongoDB\Event\LoadClassMetadataEventArgs;
7+
use Doctrine\ODM\MongoDB\Event\OnClassMetadataNotFoundEventArgs;
8+
use Doctrine\ODM\MongoDB\Events;
69
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
710

811
/**
912
* ResolveTargetDocumentListener
1013
*
1114
* Mechanism to overwrite document interfaces or classes specified as association targets.
1215
*/
13-
class ResolveTargetDocumentListener
16+
class ResolveTargetDocumentListener implements EventSubscriber
1417
{
1518
/**
1619
* @var array
1720
*/
1821
private $resolveTargetDocuments = array();
1922

23+
/**
24+
* {@inheritDoc}
25+
*/
26+
public function getSubscribedEvents()
27+
{
28+
return [
29+
Events::loadClassMetadata,
30+
Events::onClassMetadataNotFound,
31+
];
32+
}
33+
2034
/**
2135
* Add a target-document class name to resolve to a new class name.
2236
*
@@ -31,6 +45,26 @@ public function addResolveTargetDocument($originalDocument, $newDocument, array
3145
$this->resolveTargetDocuments[ltrim($originalDocument, "\\")] = $mapping;
3246
}
3347

48+
/**
49+
* @param OnClassMetadataNotFoundEventArgs $args
50+
*
51+
* @internal this is an event callback, and should not be called directly
52+
*
53+
* @return void
54+
*/
55+
public function onClassMetadataNotFound(OnClassMetadataNotFoundEventArgs $args)
56+
{
57+
if (! array_key_exists($args->getClassName(), $this->resolveTargetDocuments)) {
58+
return;
59+
}
60+
61+
$args->setFoundMetadata(
62+
$args
63+
->getObjectManager()
64+
->getClassMetadata($this->resolveTargetDocuments[$args->getClassName()]['targetDocument'])
65+
);
66+
}
67+
3468
/**
3569
* Process event and resolve new target document names.
3670
*

tests/Doctrine/ODM/MongoDB/Tests/Tools/ResolveTargetDocumentListenerTest.php

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace Doctrine\ODM\MongoDB\Tests\Tools;
44

55
use Doctrine\ODM\MongoDB\Events;
6-
use Doctrine\ODM\MongoDB\Tools\ResolveTargetDocumentListener;
76
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
7+
use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory;
8+
use Doctrine\ODM\MongoDB\Tools\ResolveTargetDocumentListener;
89

910
class ResolveTargetDocumentListenerTest extends \Doctrine\ODM\MongoDB\Tests\BaseTest
1011
{
@@ -18,11 +19,17 @@ class ResolveTargetDocumentListenerTest extends \Doctrine\ODM\MongoDB\Tests\Base
1819
*/
1920
protected $listener;
2021

22+
/**
23+
* @var ClassMetadataFactory
24+
*/
25+
private $factory;
26+
2127
public function setUp()
2228
{
2329
parent::setUp();
2430

2531
$this->listener = new ResolveTargetDocumentListener();
32+
$this->factory = $this->dm->getMetadataFactory();
2633
}
2734

2835
public function testResolveTargetDocumentListenerCanResolveTargetDocument()
@@ -51,6 +58,28 @@ public function testResolveTargetDocumentListenerCanResolveTargetDocument()
5158
$this->assertSame('Doctrine\ODM\MongoDB\Tests\Tools\ResolveTargetDocument', $meta['embedOne']['targetDocument']);
5259
$this->assertSame('Doctrine\ODM\MongoDB\Tests\Tools\TargetDocument', $meta['embedMany']['targetDocument']);
5360
}
61+
62+
public function testResolveTargetDocumentListenerCanRetrieveTargetDocumentByInterfaceName()
63+
{
64+
$this->listener->addResolveTargetDocument(ResolveTargetInterface::class, ResolveTargetDocument::class, []);
65+
66+
$this->dm->getEventManager()->addEventSubscriber($this->listener);
67+
68+
$cm = $this->factory->getMetadataFor(ResolveTargetInterface::class);
69+
70+
$this->assertSame($this->factory->getMetadataFor(ResolveTargetDocument::class), $cm);
71+
}
72+
73+
public function testResolveTargetDocumentListenerCanRetrieveTargetDocumentByAbstractClassName()
74+
{
75+
$this->listener->addResolveTargetDocument(AbstractResolveTarget::class, ResolveTargetDocument::class, []);
76+
77+
$this->dm->getEventManager()->addEventSubscriber($this->listener);
78+
79+
$cm = $this->factory->getMetadataFor(AbstractResolveTarget::class);
80+
81+
$this->assertSame($this->factory->getMetadataFor(ResolveTargetDocument::class), $cm);
82+
}
5483
}
5584

5685
interface ResolveTargetInterface
@@ -62,10 +91,15 @@ interface TargetInterface extends ResolveTargetInterface
6291
{
6392
}
6493

94+
abstract class AbstractResolveTarget implements ResolveTargetInterface
95+
{
96+
97+
}
98+
6599
/**
66100
* @ODM\Document
67101
*/
68-
class ResolveTargetDocument implements ResolveTargetInterface
102+
class ResolveTargetDocument extends AbstractResolveTarget implements ResolveTargetInterface
69103
{
70104
/**
71105
* @ODM\Id

0 commit comments

Comments
 (0)