EventDispatcher::dispatchToListerners()   B
last analyzed

Complexity

Conditions 8
Paths 13

Size

Total Lines 28
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 20
c 0
b 0
f 0
nc 13
nop 1
dl 0
loc 28
rs 8.4444
1
<?php
2
    defined('ROOT_PATH') or exit('Access denied');
3
    /**
4
     * TNH Framework
5
     *
6
     * A simple PHP framework using HMVC architecture
7
     *
8
     * This content is released under the MIT License (MIT)
9
     *
10
     * Copyright (c) 2017 TNH Framework
11
     *
12
     * Permission is hereby granted, free of charge, to any person obtaining a copy
13
     * of this software and associated documentation files (the "Software"), to deal
14
     * in the Software without restriction, including without limitation the rights
15
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
     * copies of the Software, and to permit persons to whom the Software is
17
     * furnished to do so, subject to the following conditions:
18
     *
19
     * The above copyright notice and this permission notice shall be included in all
20
     * copies or substantial portions of the Software.
21
     *
22
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
     * SOFTWARE.
29
     */
30
31
    /**
32
     * This class represent the event dispatcher management, permit to record the listener and 
33
     * also to dispatch the event
34
     */
35
	
36
    class EventDispatcher extends BaseClass {
37
		
38
        /**
39
         * The list of the registered listeners
40
         * @var array
41
         */
42
        private $listeners = array();
43
		
44
45
        public function __construct() {
46
            parent::__construct();
47
        }
48
49
        /**
50
         * Register new listener
51
         * @param string   $eventName the name of the event to register for
52
         * @param callable $listener  the function or class method to receive the event information after dispatch
53
         */
54
        public function addListener($eventName, callable $listener) {
55
            $this->logger->debug('Adding new event listener for the event name [' . $eventName . '], listener [' . stringify_vars($listener) . ']');
56
            if (!isset($this->listeners[$eventName])) {
57
                $this->logger->info('This event does not have the registered event listener before, adding new one');
58
                $this->listeners[$eventName] = array();
59
            } else {
60
                $this->logger->info('This event already have the registered listener, add this listener to the list');
61
            }
62
            $this->listeners[$eventName][] = $listener;
63
        }
64
		
65
        /**
66
         * Remove the event listener from list
67
         * @param  string   $eventName the event name
68
         * @param  callable $listener  the listener callback
69
         */
70
        public function removeListener($eventName, callable $listener) {
71
            $this->logger->debug('Removing of the event listener, the event name [' . $eventName . '], listener [' . stringify_vars($listener) . ']');
72
            if (isset($this->listeners[$eventName])) {
73
                $this->logger->info('This event have the listeners, check if this listener exists');
74
                $index = array_search($listener, $this->listeners[$eventName], true);
75
                if ($index !== false) {
76
                    $this->logger->info('Found the listener at index [' . $index . '] remove it');
77
                    unset($this->listeners[$eventName][$index]);
78
                } else {
79
                    $this->logger->info('Cannot found this listener in the event listener list');
80
                }
81
            } else {
82
                $this->logger->info('This event does not have this listener ignore remove');
83
            }
84
        }
85
		
86
        /**
87
         * Remove all the event listener. If event name is null will remove all listeners, else will just 
88
         * remove all listeners for this event
89
         * @param  string $eventName the event name
90
         */
91
        public function removeAllListener($eventName = null) {
92
            $this->logger->debug('Removing of all event listener, the event name [' . $eventName . ']');
93
            if ($eventName !== null) {
94
                if (isset($this->listeners[$eventName])) {
95
                    $this->logger->info('The event name is set and exist in the listener just remove all event listener for this event');
96
                    unset($this->listeners[$eventName]);
97
                } else {
98
                    $this->logger->info('The event name is set and not exist in the listener nothing to do');
99
                }
100
            } else {
101
                $this->logger->info('The event name is not set, so remove all event listener');
102
                $this->listeners = array();
103
            }
104
        }
105
		
106
        /**
107
         * Get the list of listener for this event or all if event is null
108
         * @param string $eventName the event name
109
         * @return array the listeners for this event or all listeners if this event is null
110
         */
111
        public function getListeners($eventName = null) {
112
            if ($eventName === null) {
113
                return $this->listeners;
114
            }
115
            if (isset($this->listeners[$eventName])) {
116
                return $this->listeners[$eventName];
117
            }
118
            return array();
119
        }
120
		
121
        /**
122
         * Dispatch the event to the registered listeners.
123
         * @param  mixed|object $event the event information
124
         * @return void|object if event need return, will return the final EventInfo object.
125
         */	
126
        public function dispatch($event) {
127
            if (!$event instanceof EventInfo) {
128
                $this->logger->info('The event is not an instance of "EventInfo" create the default "EventInfo" object to use instead of.');
129
                $event = new EventInfo((string) $event);
130
            }			
131
            $this->logger->debug('Dispatch to the event listener, the event [' . stringify_vars($event) . ']');
132
            if ($event->isStop() === true) {
133
                $this->logger->info('This event need stopped, no need call any listener');
134
                return;
135
            }
136
            if ($event->isReturnBack() === true) {
137
                $this->logger->info('This event need return back, return the result for future use');
138
                return $this->dispatchToListerners($event);
139
            } 
140
            $this->logger->info('This event no need return back the result, just dispatch it');
141
            $this->dispatchToListerners($event);
142
        }
143
		
144
        /**
145
         * Dispatch the event to the registered listeners.
146
         * @param  object EventInfo $event  the event information
147
         * @return void|object if event need return, will return the final EventInfo instance.
148
         */	
149
        private function dispatchToListerners(EventInfo $event) {
150
            $list = $this->getListeners($event->getName());
151
            if (empty($list)) {
152
                $this->logger->info('No event listener is registered for the event [' . $event->getName() . '] skipping.');
153
                if ($event->isReturnBack()) {
154
                    return $event;
155
                }
156
                return;
157
            } 
158
            $this->logger->info('Found the registered event listener for the '
159
                                 . 'event [' . $event->getName() . '] the list are: ' . stringify_vars($list));
160
            foreach ($list as $listener) {
161
                $result = call_user_func_array($listener, array($event));
162
                if ($event->isReturnBack() === true) {
163
                    if ($result instanceof EventInfo) {
164
                        $event = $result;
165
                    } else {
166
                        show_error('The event [' . $event->getName() . '] need you return the event object after processing');
167
                        return;
168
                    }
169
                }
170
                if ($event->isStop() === true) {
171
                    break;
172
                }
173
            }
174
            //only test for original event may be during the flow some listeners change this parameter
175
            if ($event->isReturnBack() === true) {
176
                return $event;
177
            }
178
        }
179
    }
180