55use Doctrine \Common \Persistence \Event \LifecycleEventArgs ;
66use Doctrine \Common \Persistence \ObjectManager ;
77use Doctrine \ORM \Mapping \ClassMetadata ;
8+ use W3C \LifecycleEventsBundle \Tests \Services \Fixtures \MySubscriber ;
89use PHPUnit \Framework \TestCase ;
10+ use Symfony \Component \EventDispatcher \EventDispatcher ;
911use Symfony \Component \EventDispatcher \EventDispatcherInterface ;
1012use W3C \LifecycleEventsBundle \Annotation \Change ;
1113use W3C \LifecycleEventsBundle \Annotation \Create ;
@@ -56,8 +58,8 @@ public function setUp()
5658 parent ::setUp ();
5759
5860 $ this ->sfDispatcher = $ this
59- ->getMockBuilder (EventDispatcherInterface ::class)
60- ->disableOriginalConstructor ()
61+ ->getMockBuilder (EventDispatcher ::class)
62+ ->enableProxyingToOriginalMethods ()
6163 ->getMock ();
6264 ;
6365 $ this ->dispatcher = new LifecycleEventsDispatcher ($ this ->sfDispatcher , true );
@@ -81,6 +83,7 @@ public function testDispatchCreationEvents()
8183 $ this ->assertCount (1 , $ this ->dispatcher ->getCreations ());
8284
8385 $ expectedEvent = new LifecycleEvent ($ user );
86+
8487 $ this ->sfDispatcher ->expects ($ this ->once ())
8588 ->method ('dispatch ' )
8689 ->with (LifecycleEvents::CREATED , $ expectedEvent )
@@ -89,6 +92,29 @@ public function testDispatchCreationEvents()
8992 $ this ->dispatcher ->dispatchEvents ();
9093 }
9194
95+ /**
96+ * Test that if dispatchEvents is called recursively (could happen if flush happens in a listener),
97+ * events already fired aren't a second time.
98+ */
99+ public function testDispatchCreationEventsRecursive ()
100+ {
101+ $ user = new User ();
102+ $ annotation = new Create ();
103+ $ args = new LifecycleEventArgs ($ user , $ this ->objectManager );
104+
105+ $ this ->sfDispatcher ->addSubscriber (new MySubscriber ($ this ->dispatcher , $ annotation , $ args ));
106+
107+ $ this ->dispatcher ->addCreation ($ annotation , $ args );
108+
109+ $ this ->assertCount (1 , $ this ->dispatcher ->getCreations ());
110+
111+ // 2 === 1 addCreation above + 1 in MySubscriber::onCalled
112+ $ this ->sfDispatcher ->expects ($ this ->exactly (2 ))
113+ ->method ('dispatch ' );
114+
115+ $ this ->dispatcher ->dispatchEvents ();
116+ }
117+
92118 public function testDispatchCreationEventsCustom ()
93119 {
94120 $ user = new User ();
@@ -135,6 +161,37 @@ public function testDispatchDeletionEvents()
135161 $ this ->dispatcher ->dispatchEvents ();
136162 }
137163
164+ /**
165+ * Test that if dispatchEvents is called recursively (could happen if flush happens in a listener),
166+ * events already fired aren't a second time.
167+ */
168+ public function testDispatchDeletionEventsRecursive ()
169+ {
170+ $ user = new User ();
171+ $ annotation = new Delete ();
172+ $ args = new LifecycleEventArgs ($ user , $ this ->objectManager );
173+
174+ $ this ->sfDispatcher ->addSubscriber (new MySubscriber ($ this ->dispatcher , $ annotation , $ args ));
175+
176+ $ this ->objectManager ->method ('getClassMetadata ' )->willReturn ($ this ->classMetadata );
177+ $ this ->classMetadata ->expects ($ this ->once ())
178+ ->method ('getIdentifierFieldNames ' )
179+ ->willReturn (['name ' ]);
180+ $ this ->classMetadata ->expects ($ this ->once ())
181+ ->method ('getIdentifierValues ' )
182+ ->willReturn (['toto ' ]);
183+
184+ $ this ->dispatcher ->addDeletion ($ annotation , $ args );
185+
186+ $ this ->assertCount (1 , $ this ->dispatcher ->getDeletions ());
187+
188+ // 2 === 1 addDeletion above + 1 addCreation in MySubscriber::onCalled
189+ $ this ->sfDispatcher ->expects ($ this ->exactly (2 ))
190+ ->method ('dispatch ' );
191+
192+ $ this ->dispatcher ->dispatchEvents ();
193+ }
194+
138195 public function testDispatchDeletionEventsCustom ()
139196 {
140197 $ user = new User ();
@@ -185,6 +242,34 @@ public function testDispatchUpdatesEvents()
185242 $ this ->dispatcher ->dispatchEvents ();
186243 }
187244
245+ /**
246+ * Test that if dispatchEvents is called recursively (could happen if flush happens in a listener),
247+ * events already fired aren't a second time.
248+ */
249+ public function testDispatchUpdatesEventsRecursive ()
250+ {
251+ $ user = new User ();
252+ $ annotation = new Update ();
253+ $ args = new LifecycleEventArgs ($ user , $ this ->objectManager );
254+
255+ $ this ->sfDispatcher ->addSubscriber (new MySubscriber ($ this ->dispatcher , $ annotation , $ args ));
256+
257+ $ this ->dispatcher ->addUpdate (
258+ $ annotation ,
259+ $ user ,
260+ ['name ' => ['foo ' , 'bar ' ]],
261+ []
262+ );
263+
264+ $ this ->assertCount (1 , $ this ->dispatcher ->getUpdates ());
265+
266+ // 2 === 1 addUpdate above + 1 addCreation in MySubscriber::onCalled
267+ $ this ->sfDispatcher ->expects ($ this ->exactly (2 ))
268+ ->method ('dispatch ' );
269+
270+ $ this ->dispatcher ->dispatchEvents ();
271+ }
272+
188273 public function testDispatchUpdatesEventsCustom ()
189274 {
190275 $ user = new User ();
@@ -231,6 +316,35 @@ public function testDispatchPropertyChangeEvents()
231316 $ this ->dispatcher ->dispatchEvents ();
232317 }
233318
319+ /**
320+ * Test that if dispatchEvents is called recursively (could happen if flush happens in a listener),
321+ * events already fired aren't a second time.
322+ */
323+ public function testDispatchPropertyChangeEventsRecursive ()
324+ {
325+ $ user = new User ();
326+ $ annotation = new Change ();
327+ $ args = new LifecycleEventArgs ($ user , $ this ->objectManager );
328+
329+ $ this ->sfDispatcher ->addSubscriber (new MySubscriber ($ this ->dispatcher , $ annotation , $ args ));
330+
331+ $ this ->dispatcher ->addPropertyChange (
332+ $ annotation ,
333+ $ user ,
334+ 'name ' ,
335+ 'foo ' ,
336+ 'bar '
337+ );
338+
339+ $ this ->assertCount (1 , $ this ->dispatcher ->getPropertyChanges ());
340+
341+ // 2 === 1 addPropertyChange above + 1 addCreation in MySubscriber::onCalled
342+ $ this ->sfDispatcher ->expects ($ this ->exactly (2 ))
343+ ->method ('dispatch ' );
344+
345+ $ this ->dispatcher ->dispatchEvents ();
346+ }
347+
234348 public function testDispatchPropertyChangeEventsCustom ()
235349 {
236350 $ user = new User ();
@@ -279,6 +393,37 @@ public function testDispatchCollectionChangeEvents()
279393 $ this ->dispatcher ->dispatchEvents ();
280394 }
281395
396+ /**
397+ * Test that if dispatchEvents is called recursively (could happen if flush happens in a listener),
398+ * events already fired aren't a second time.
399+ */
400+ public function testDispatchCollectionChangeEventsRecursive ()
401+ {
402+ $ user = new User ();
403+ $ annotation = new Change ();
404+ $ args = new LifecycleEventArgs ($ user , $ this ->objectManager );
405+
406+ $ this ->sfDispatcher ->addSubscriber (new MySubscriber ($ this ->dispatcher , $ annotation , $ args ));
407+
408+ $ deleted = [new User ()];
409+ $ inserted = [new User (), new User ()];
410+ $ this ->dispatcher ->addCollectionChange (
411+ $ annotation ,
412+ $ user ,
413+ 'friends ' ,
414+ $ deleted ,
415+ $ inserted
416+ );
417+
418+ $ this ->assertCount (1 , $ this ->dispatcher ->getCollectionChanges ());
419+
420+ // 2 === 1 addCollectionChange above + 1 addCreation in MySubscriber::onCalled
421+ $ this ->sfDispatcher ->expects ($ this ->exactly (2 ))
422+ ->method ('dispatch ' );
423+
424+ $ this ->dispatcher ->dispatchEvents ();
425+ }
426+
282427 public function testDispatchCollectionChangeEventsCustom ()
283428 {
284429 $ user = new User ();
0 commit comments