EventManager::detach()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 2
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Event
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Event;
16
17
use Phossa2\Shared\Base\ObjectAbstract;
18
use Phossa2\Event\Interfaces\EventInterface;
19
use Phossa2\Event\Interfaces\EventQueueInterface;
20
use Phossa2\Event\Interfaces\EventManagerInterface;
21
22
/**
23
 * EventManager
24
 *
25
 * A basic implementation of EventManagerInterface
26
 *
27
 * ```php
28
 * $events = new EventManager();
29
 *
30
 * $events->attach('test', function() { echo 'test'; });
31
 *
32
 * $events->trigger('test');
33
 * ```
34
 *
35
 * @package Phossa2\Event
36
 * @author  Hong Zhang <[email protected]>
37
 * @see     ObjectAbstract
38
 * @see     EventManagerInterface
39
 * @version 2.1.0
40
 * @since   2.0.0 added
41
 * @since   2.1.0 updated to use the new EventManagerInterface
42
 */
43
class EventManager extends ObjectAbstract implements EventManagerInterface
44
{
45
    /**
46
     * Events managing
47
     *
48
     * @var    EventQueueInterface[]
49
     * @access protected
50
     */
51
    protected $events = [];
52
53
    /**
54
     * {@inheritDoc}
55
     */
56
    public function attach($event, $callback, $priority = 0)
57
    {
58
        if (!$this->hasEvent($event)) {
59
            $this->events[$event] = $this->newEventQueue();
60
        }
61
        $this->events[$event]->insert($callback, $priority);
62
        return true;
63
    }
64
65
    /**
66
     * if call is NULL, clear this event.
67
     * if event is '', clear all events
68
     *
69
     * {@inheritDoc}
70
     */
71
    public function detach($event, $callback)
72
    {
73
        if ($this->hasEvent($event)) {
74
            $this->removeEventCallable($event, $callback);
75
        } elseif ('' === $event) {
76
            $this->events = []; // remove all events
77
        }
78
        return true;
79
    }
80
81
    /**
82
     * {@inheritDoc}
83
     */
84
    public function clearListeners($event)
85
    {
86
        $this->detach($event, null);
87
    }
88
89
    /**
90
     * {@inheritDoc}
91
     */
92
    public function trigger($event, $target = null, $argv = array())
93
    {
94
        // result
95
        $res = true;
96
97
        // make sure is an event
98
        $evt = $this->newEvent($event, $target, $argv);
99
100
        // get handler queue
101
        $queue = $this->getMatchedQueue($evt->getName());
102
        foreach ($queue as $q) {
103
            // execute the handler
104
            $res = $q['data']($evt);
105
106
            // stopped ?
107
            if ($evt->isPropagationStopped()) {
108
                break;
109
            }
110
        }
111
112
        return $res;
113
    }
114
115
    /**
116
     * Has $eventName been bound ?
117
     *
118
     * @param  string $eventName
119
     * @return bool
120
     * @access protected
121
     */
122
    protected function hasEvent(/*# string */ $eventName)/*# : bool */
123
    {
124
        return isset($this->events[(string) $eventName]);
125
    }
126
127
    /**
128
     * Create a new event
129
     *
130
     * @param  string|EventInterface $eventName
131
     * @param  object|string|null $target
132
     * @param  array $parameters
133
     * @return EventInterface
134
     * @access protected
135
     */
136
    protected function newEvent(
137
        $eventName,
138
        $target = null,
139
        array $parameters = []
140
    )/*# : EventInterface */ {
141
        if (is_object($eventName)) {
142
            return $eventName;
143
        } else {
144
            return new Event($eventName, $target, $parameters);
145
        }
146
    }
147
148
    /**
149
     * Get a new event queue
150
     *
151
     * @return EventQueueInterface
152
     * @access protected
153
     */
154
    protected function newEventQueue()/*# : EventQueueInterface */
155
    {
156
        return new EventQueue();
157
    }
158
159
    /**
160
     * Get related event handler queue for this $eventName
161
     *
162
     * @param  string $eventName
163
     * @return EventQueueInterface
164
     * @access protected
165
     */
166
    protected function getMatchedQueue(
167
        /*# : string */ $eventName
168
    )/*# : EventQueueInterface */ {
169
        if ($this->hasEvent($eventName)) {
170
            return $this->events[$eventName];
171
        } else {
172
            return $this->newEventQueue();
173
        }
174
    }
175
176
    /**
177
     * Remove event or its callable
178
     *
179
     * @param  string $eventName
180
     * @param  callable|null $callable
181
     * @access protected
182
     */
183
    protected function removeEventCallable(
184
        /*# string */ $eventName,
185
        $callable
186
    ) {
187
        if (null === $callable) {
188
            // remove all callables
189
            $this->events[$eventName]->flush();
190
        } else {
191
            // remove one callable
192
            $this->events[$eventName]->remove($callable);
193
        }
194
195
        // when count is zeror, remove queue
196
        if (count($this->events[$eventName]) === 0) {
197
            unset($this->events[$eventName]);
198
        }
199
    }
200
}
201