Completed
Pull Request — master (#16)
by Jacek
08:07 queued 05:58
created

EventManager::clearExceptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.2963

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 1
cts 3
cp 0.3333
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1.2963
1
<?php
2
3
/**
4
 * Copyright (c) 2016 Jacek Kobus <[email protected]>
5
 * See the file LICENSE.md for copying permission.
6
 */
7
8
namespace PHPExtra\EventManager;
9
10
use PHPExtra\EventManager\Event\Event;
11
use PHPExtra\EventManager\Exception\ListenerException;
12
use PHPExtra\EventManager\Listener\Listener;
13
use PHPExtra\EventManager\Worker\ArrayWorkerQueue;
14
use PHPExtra\EventManager\Worker\WorkerQueue;
15
use PHPExtra\EventManager\Worker\Worker;
16
use PHPExtra\EventManager\Worker\WorkerFactory;
17
use PHPExtra\EventManager\Worker\WorkerResult;
18
use Psr\Log\LoggerAwareInterface;
19
use Psr\Log\LoggerInterface;
20
use Psr\Log\NullLogger;
21
22
/**
23
 * The default EventManager implementation
24
 *
25
 * @author Jacek Kobus <[email protected]>
26
 */
27
class EventManager implements EventEmitter, LoggerAwareInterface
28
{
29
    /**
30
     * @var WorkerFactory
31
     */
32
    private $workerFactory = null;
33
34
    /**
35
     * @var WorkerQueue|Worker[]
36
     */
37
    private $workerQueue;
38
39
    /**
40
     * Whenever to throw exceptions caught from listeners or not
41
     *
42
     * @var bool
43
     */
44
    private $throwExceptions = false;
45
46
    /**
47
     * Currently running event
48
     *
49
     * @var Event
50
     */
51
    private $runningEvent = null;
52
53
    /**
54
     * @var LoggerInterface
55
     */
56
    private $logger;
57
58
    /**
59
     * @var ListenerException[]
60
     */
61 12
    private $exceptions = array();
62
63 12
    /**
64 12
     * Create new event manager
65 12
     */
66 12
    public function __construct()
67
    {
68
        $this->workerFactory = new WorkerFactory();
69
        $this->workerQueue = new ArrayWorkerQueue();
70
        $this->logger = new NullLogger();
71 10
    }
72
73 10
    /**
74 10
     * {@inheritdoc}
75
     */
76 10
    public function emit(Event $event)
77
    {
78 10
        if($this->runningEvent === null){
79 9
            $this->clearExceptions();
80 9
        }
81 8
82 8
        $previousRunningEvent = $this->runningEvent;
83 1
        $this->runningEvent = $event;
84
85
        $workers = $this->workerQueue->getWorkersFor($event);
86 9
87
        foreach ($workers as $worker) {
88 9
            $result = $this->runWorker($worker, $event);
89
90
            if (!$result->isSuccessful()) {
91
92
                $message = sprintf('Listener "%s" failed: "%s"', $result->getWorker()->getName(), $result->getMessage());
93
94
                $this->logger->warning($message);
95
                $exception = new ListenerException($event, $worker->getListener(), $message, $result->getException());
96
                $this->addException($exception);
97
98
                if ($this->throwExceptions) {
99
                    $this->logger->debug(sprintf('Throwing exception (throwExceptions is set to true)', $worker));
100
                    throw $exception;
101
                }
102
            }
103 9
        }
104
105 9
        $this->runningEvent = $previousRunningEvent;
106
    }
107
108
    /**
109
     * @return Event
110
     */
111 9
    public function getRunningEvent()
112
    {
113 9
        return $this->runningEvent;
114
    }
115
116
    /**
117
     * @param Worker $worker
118
     * @param Event  $event
119
     */
120
    protected function onWorkerStart(Worker $worker, Event $event)
121
    {
122 9
    }
123
124 9
    /**
125
     * @param Worker $worker
126 9
     * @param Event  $event
127 9
     */
128 9
    protected function onWorkerStop(Worker $worker, Event $event)
129
    {
130 9
    }
131 2
132
    /**
133 2
     * @param Worker $worker
134 1
     * @param Event  $event
135 1
     *
136
     * @throws ListenerException
137 1
     * @return WorkerResult
138
     */
139 1
    private function runWorker(Worker $worker, Event $event)
140
    {
141 8
        $this->logger->debug(sprintf('Starting %s', $worker->getName()));
142
143
        $this->onWorkerStart($worker, $event);
144
        $result = $worker->run($event);
145
        $this->onWorkerStop($worker, $event);
146
147
        return $result;
148
    }
149
150
    /**
151
     * Get all exceptions that occurred during emitting an event.
152 5
     *
153
     * @return ListenerException[]
154 5
     */
155
    public function getExceptions()
156 5
    {
157
        return $this->exceptions;
158
    }
159
160
    /**
161
     * Tell if the manager has collected any exceptions after last emit call.
162
     *
163
     * @return bool
164
     */
165
    public function hasExceptions()
166
    {
167 10
        return !empty($this->exceptions);
168
    }
169 10
170 10
    /**
171
     * @param ListenerException $exception
172 10
     */
173 1
    private function addException(ListenerException $exception)
174 1
    {
175
        $this->exceptions[] = $exception;
176 10
    }
177 10
178 10
    /**
179 10
     * Clear all collected exceptions
180
     */
181 10
    private function clearExceptions()
182
    {
183
        $this->exceptions = array();
184
    }
185 10
186
    /**
187
     * Set to true to throw exceptions coming from listeners.
188
     * By default all exceptions are suppressed.
189
     *
190
     * @param bool $throwExceptions
191
     *
192
     * @return $this
193 10
     */
194
    public function setThrowExceptions($throwExceptions = true)
195 10
    {
196
        $this->throwExceptions = (bool)$throwExceptions;
197 10
198
        return $this;
199
    }
200
201
    /**
202
     * @see Priority
203
     *
204
     * @param Listener $listener
205
     * @param int      $priority
206
     *
207
     * @return $this
208
     */
209
    public function add(Listener $listener, $priority = null)
210
    {
211
        $workers = $this->workerFactory->createWorkers($listener, $priority);
212
        $workersCount = 0;
213
214
        if ($priority !== null) {
215
            $this->logger->debug(sprintf('Overriding priority for all workers to %s in %s', $priority, get_class($listener)));
216
        }
217
218
        foreach ($workers as $worker) {
219
            $this->addWorker($worker);
220
            $workersCount++;
221
        }
222
223
        if ($workersCount == 0) {
224
            $this->logger->debug(sprintf('Listener "%s" does not have any workers', get_class($listener)));
225
        }
226
227
        return $this;
228
    }
229
230
    /**
231
     * @param Worker $worker
232
     *
233
     * @return $this
234
     */
235
    private function addWorker(Worker $worker)
236
    {
237
        $this->workerQueue->addWorker($worker);
238
239
        return $this;
240
    }
241
242
    /**
243
     * {@inheritdoc}
244
     */
245
    public function setLogger(LoggerInterface $logger)
246
    {
247
        $this->logger = $logger;
248
249
        return $this;
250
    }
251
}