Completed
Push — master ( 944ed2...1d6f2d )
by Jared
01:29
created

EventManager::dispatch()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
cc 4
nc 6
nop 3
1
<?php
2
3
namespace Pulsar;
4
5
use Pulsar\Event\AbstractEvent;
6
use Pulsar\Exception\ListenerException;
7
use Symfony\Component\EventDispatcher\EventDispatcher;
8
9
/**
10
 * Manages the event bus for model lifecycle events.
11
 */
12
class EventManager
13
{
14
    /** @var array */
15
    private static $dispatchers = [];
16
17
    /**
18
     * Gets the event dispatcher.
19
     */
20
    public static function getDispatcher(string $class): EventDispatcher
21
    {
22
        if (!isset(self::$dispatchers[$class])) {
23
            self::$dispatchers[$class] = new EventDispatcher();
24
        }
25
26
        return self::$dispatchers[$class];
27
    }
28
29
    /**
30
     * Resets the event dispatcher for a given class.
31
     */
32
    public static function reset(string $class): void
33
    {
34
        if (isset(self::$dispatchers[$class])) {
35
            unset(self::$dispatchers[$class]);
36
        }
37
    }
38
39
    /**
40
     * Subscribes to a listener to an event.
41
     *
42
     * @param string $event    event name
43
     * @param int    $priority optional priority, higher #s get called first
44
     */
45
    public static function listen(string $class, string $event, callable $listener, int $priority = 0): void
46
    {
47
        self::getDispatcher($class)->addListener($event, $listener, $priority);
48
    }
49
50
    /**
51
     * Dispatches the given event and checks if it was successful.
52
     * If it fails then any active transaction will be rolled back
53
     * on the model.
54
     *
55
     * @return bool true if the events were successfully propagated
56
     */
57
    public static function dispatch(Model $model, AbstractEvent $event, bool $usesTransactions): bool
58
    {
59
        // Model events can fail whenever $event->stopPropagation() is called
60
        // or when a specific exception type is thrown by the listener.
61
        try {
62
            self::getDispatcher(get_class($model))->dispatch($event, $event::NAME);
63
        } catch (ListenerException $e) {
64
            // Listener exceptions provide the error message to be stored on the model
65
            $model->getErrors()->add($e->getMessage(), $e->getContext());
66
            $event->stopPropagation();
67
        }
68
69
        if (!$event->isPropagationStopped()) {
70
            return true;
71
        }
72
73
        // when listeners fail roll back any database transaction
74
        if ($usesTransactions) {
75
            $model::getDriver()->rollBackTransaction($model->getConnection());
76
        }
77
78
        return false;
79
    }
80
}
81