Last active
August 29, 2015 14:11
-
-
Save zdenekdrahos/eeae57058a1b0fb894da to your computer and use it in GitHub Desktop.
Dispatch Symfony events in transaction. https://coderwall.com/p/zfvjsq
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<container xmlns="http://symfony.com/schema/dic/services" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://symfony.com/schema/dic/services/services-1.0.xsd"> | |
<services> | |
<service id="dispatcher.transactional" class="TransactionalDispatcher"> | |
<argument type="service" id="event_dispatcher"/> | |
<argument type="service" id="doctrine.orm.entity_manager"/> | |
</service> | |
</services> | |
</container> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
services: | |
dispatcher.transactional: | |
class: TransactionalDispatcher | |
arguments: | |
- "@event_dispatcher" | |
- "@doctrine.orm.entity_manager" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Doctrine\ORM\EntityManager; | |
use Symfony\Component\EventDispatcher\Event; | |
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |
class TransactionalDispatcher | |
{ | |
/** @var EventDispatcherInterface */ | |
private $dispatcher; | |
/** @var EntityManager */ | |
private $entityManager; | |
/** @var Event */ | |
private $event; | |
public function __construct(EventDispatcherInterface $dispatcher, EntityManager $manager) | |
{ | |
$this->dispatcher = $dispatcher; | |
$this->entityManager = $manager; | |
} | |
public function dispatch($eventName, Event $event) | |
{ | |
$this->beginTransaction(); | |
$this->dispatchEvent($eventName, $event); | |
$this->endTransaction(); | |
return $this->hasSucceed(); | |
} | |
private function beginTransaction() | |
{ | |
$this->entityManager->beginTransaction(); | |
} | |
private function dispatchEvent($eventName, Event $event) | |
{ | |
$this->event = $this->dispatcher->dispatch($eventName, $event); | |
} | |
private function endTransaction() | |
{ | |
if ($this->hasSucceed()) { | |
$this->entityManager->commit(); | |
} else { | |
$this->entityManager->rollback(); | |
} | |
} | |
private function hasSucceed() | |
{ | |
return !$this->event->isPropagationStopped(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Mockery as m; | |
class TransactionalDispatcherTest extends \PHPUnit_Framework_TestCase | |
{ | |
private $entityManager; | |
private $hasDispatcherSucceed; | |
public function setUp() | |
{ | |
$this->entityManager = m::mock('Doctrine\ORM\EntityManager'); | |
} | |
/** @dataProvider provideTransactions */ | |
public function testShouldDispatchEventInTransaction($hasDispatcherSucceed, $expectedMethod) | |
{ | |
$this->hasDispatcherSucceed = $hasDispatcherSucceed; | |
$this->entityManager->shouldReceive('beginTransaction')->once(); | |
$this->entityManager->shouldReceive($expectedMethod)->once(); | |
$this->assertSame($hasDispatcherSucceed, $this->dispatch()); | |
} | |
public function provideTransactions() | |
{ | |
return array( | |
'when propagation succeed should commit' => array(true, 'commit'), | |
'when propagation failed should rollback' => array(false, 'rollback'), | |
); | |
} | |
private function dispatch() | |
{ | |
$event = m::mock('Symfony\Component\EventDispatcher\Event'); | |
$event->shouldReceive('isPropagationStopped')->andReturn(!$this->hasDispatcherSucceed ); | |
$dispatcher = m::mock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); | |
$dispatcher->shouldReceive('dispatch')->once()->andReturn($event); | |
$transactionalDispatcher = new TransactionalDispatcher($dispatcher, $this->entityManager); | |
return $transactionalDispatcher->dispatch('irrelevant event', $event); | |
} | |
public function tearDown() | |
{ | |
m::close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment