Observer::__get()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Noair;
4
5
/**
6
 * Noair observer class -- to be extended.
7
 *
8
 * @author  Garrett Whitehorn
9
 * @author  David Tkachuk
10
 *
11
 * @version 1.0
12
 */
13
abstract class Observer
14
{
15
    /**
16
     * @api
17
     *
18
     * @var Observable The mediator instance our handlers are registered with
19
     *
20
     * @since   1.0
21
     */
22
    protected $mediator;
23
24
    /**
25
     * This can be set by child classes to explicitly define each handler's
26
     * function name, priority, and/or forceability.
27
     *
28
     * Terminology note: they're not subscribers until they're subscribed ;)
29
     *
30
     * @api
31
     *
32
     * @var array The event handlers we'll be subscribing
33
     *
34
     * @since   1.0
35
     */
36
    protected $handlers = [];
37
38
    /**
39
     * If calling subscribe() results in firing of pending events, this will
40
     * store the results of that event.
41
     *
42
     * @api
43
     *
44
     * @var array Results of firing pending events
45
     *
46
     * @since   1.0
47
     */
48
    protected $subResults = [];
49
50
    /**
51
     * @api
52
     *
53
     * @var bool Reflects whether we have subscribed to a Mediator instance
54
     *
55
     * @since   1.0
56
     */
57
    protected $subscribed = false;
58
59
    public function __construct(Observable $m)
60
    {
61
        $this->mediator = $m;
62
    }
63
64
    /**
65
     * @return mixed
66
     */
67
    public function __get($name)
68
    {
69
        return $this->$name;
70
    }
71
72
    /**
73
     * Registers our handlers with our Mediator instance.
74
     *
75
     * @api
76
     *
77
     * @throws \RuntimeException if there are no handlers to subscribe
78
     *
79
     * @param array|null $newhandler Individual handler to subscribe if needed
80
     *
81
     * @return self This observer object
82
     *
83
     * @since   1.0
84
     *
85
     * @version 1.0
86
     */
87
    public function subscribe($newhandler = null)
88
    {
89
        if (is_array($newhandler)) {
90
            $this->handlers = array_merge($this->handlers, $newhandler);
91
            $this->subResults = $this->mediator->subscribe($newhandler);
92
            $this->subscribed = true;
93
94
            return $this;
95
        }
96
97
        // get an array of the methods in the child class
98
        $methods = (new \ReflectionClass($this))->getMethods(\ReflectionMethod::IS_PUBLIC);
99
        // filter out any that don't begin with "on"
100
        $methods = array_filter(
101
            $methods,
102
            function (\ReflectionMethod $m) {
103
                return (strpos($m->name, 'on') === 0);
104
            }
105
        ); // slow, both array_filter and closure
106
107
        if (count($methods) === 0) {
108
            if (empty($this->handlers)) {
109
                throw new \RuntimeException('$this->handlers[] is empty or $this has no on*() methods!');
110
            }
111
        } else {
112
            $autohandlers = [];
113
114
            foreach ($methods as $method) { // slow
115
                //extract the event name from the method name
116
                $eventName = lcfirst(substr($method->name, 2));
117
118
                // if this is a timer handler, insert a colon before the interval
119
                if (strpos($eventName, 'timer') === 0) {
120
                    $eventName = substr_replace($eventName, ':', 5, 0);
121
                }
122
123
                // add it to our list
124
                $autohandlers[$eventName] = [[$this, $method->name]];
125
            }
126
127
            $this->handlers = array_merge($autohandlers, $this->handlers);
128
        }
129
130
        $this->subResults = $this->mediator->subscribe($this->handlers);
131
        $this->subscribed = true;
132
133
        return $this;
134
    }
135
136
    /**
137
     * Unregisters our handlers.
138
     *
139
     * @api
140
     *
141
     * @return self This observer object
142
     *
143
     * @since   1.0
144
     *
145
     * @version 1.0
146
     */
147
    public function unsubscribe()
148
    {
149
        if (empty($this->handlers)) {
150
            return $this;
151
        }
152
153
        $this->mediator->unsubscribe($this->handlers);
154
155
        // filter out auto-handlers so that a subsequent call to subscribe()
156
        // works predictably
157
        $this->handlers = array_filter($this->handlers, function ($v) {
158
            return (strpos($v[0][1], 'on') !== 0);
159
        });
160
161
        $this->subscribed = false;
162
163
        return $this;
164
    }
165
}
166