1: | <?php |
2: | |
3: | /* |
4: | * Library to use PortBilling events with PSR-14 event dispatch |
5: | */ |
6: | |
7: | namespace Porta\Psr14Event; |
8: | |
9: | use Psr\EventDispatcher\ListenerProviderInterface; |
10: | use Porta\Psr14Event\Event; |
11: | |
12: | /** |
13: | * Porta-Event specific ListenerProvider with extra features for Porta events |
14: | * |
15: | * Register event type patterns with register() methos and suppy the instance to |
16: | * PSR-14 dispatcher. |
17: | * |
18: | * @api |
19: | */ |
20: | class EventListenerProvider implements ListenerProviderInterface |
21: | { |
22: | |
23: | const PATTERNS = 'patterns'; |
24: | const HANDLERS = 'handlers'; |
25: | |
26: | protected array $handlers = []; |
27: | |
28: | /** |
29: | * Registre set of patterns to match and set of handlers to call if any pattern match |
30: | * |
31: | * While it is possible to setup multiple patterns and multiple handlers in |
32: | * one record, please be ecouraged to use 'one pattern to multiple handlers' |
33: | * or 'multiple patterns to one handler' approach. |
34: | * |
35: | * If your configuration will allow to call a handler meltiple times because |
36: | * it listed in two and more register() calls, and patterns will math - the |
37: | * same handler will be called multiple times. |
38: | * |
39: | * @param string[] $patterns Array of patterns to match agains event type. |
40: | * If any of array match the event type - all the handlers will run in order |
41: | * of given |
42: | * @param mixed[] $handlers Array of handlers to run. Basically, it should ne array |
43: | * of callable, any item which is not callable will try to resolve to callable by |
44: | * resolveHandler(), which do nothing for this base class. Override it if you wish |
45: | * to resolve your definition into callable. |
46: | * @return self for chaining |
47: | * @api |
48: | */ |
49: | public function register(array $patterns, array $handlers): self |
50: | { |
51: | $this->handlers[] = [ |
52: | self::PATTERNS => $patterns, |
53: | self::HANDLERS => $handlers, |
54: | ]; |
55: | return $this; |
56: | } |
57: | |
58: | public function getListenersForEvent(object $event): iterable |
59: | { |
60: | if ($event instanceof Event) { |
61: | foreach ($this->handlers as $handler) { |
62: | if ($event->isMatchPatterns($handler[self::PATTERNS])) { |
63: | yield from $this->yieldHandlers($handler[self::HANDLERS]); |
64: | } |
65: | } |
66: | } |
67: | } |
68: | |
69: | protected function yieldHandlers(array $handlers): iterable |
70: | { |
71: | foreach ($handlers as $handler) { |
72: | if (is_callable($handler)) { |
73: | yield $handler; |
74: | } else { |
75: | yield from $this->resolveHandler($handler); |
76: | } |
77: | } |
78: | } |
79: | |
80: | /** |
81: | * Method to override for add handler definitions other, that just callable |
82: | * |
83: | * Also may be used to catch and log wrong callable problems. Override this |
84: | * method, log $handler value and return [] for other handler work. |
85: | * |
86: | * @param mixed $handler Handler definition |
87: | * @return iterable Must yield callable |
88: | * @api |
89: | */ |
90: | protected function resolveHandler($handler): iterable |
91: | { |
92: | return []; // Do nothing for basic ListenerProvider; |
93: | } |
94: | } |
95: |