ExtendedLoggerTrait::runHandlers()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.0534
c 0
b 0
f 0
cc 4
eloc 9
nc 3
nop 1
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Logger
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\Logger\Traits;
16
17
use Phossa2\Logger\LogLevel;
18
use Phossa2\Shared\Queue\PriorityQueue;
19
use Phossa2\Shared\Globbing\GlobbingTrait;
20
use Phossa2\Logger\Entry\LogEntryInterface;
21
use Phossa2\Shared\Queue\PriorityQueueInterface;
22
23
/**
24
 * ExtendedLoggerTrait
25
 *
26
 * @package Phossa2\Logger
27
 * @author  Hong Zhang <[email protected]>
28
 * @see     interface
29
 * @version 2.0.0
30
 * @since   2.0.0 added
31
 * @since   2.0.1 updated addCallable(), runHandlers()
32
 */
33
trait ExtendedLoggerTrait
34
{
35
    use GlobbingTrait;
36
37
    /**
38
     * Collection of handler queues
39
     *
40
     * @var    array
41
     * @access protected
42
     */
43
    protected $handlers = [];
44
45
    /**
46
     * Collection of processor queues
47
     *
48
     * @var    array
49
     * @access protected
50
     */
51
    protected $processors = [];
52
53
    /**
54
     * default channel name
55
     *
56
     * @var    string
57
     * @access protected
58
     */
59
    protected $default_channel;
60
61
    /**
62
     * Current channel name
63
     *
64
     * @var    string
65
     * @access protected
66
     */
67
    protected $current_channel;
68
69
    /**
70
     * Get current channel, if not set, get the default channel
71
     *
72
     * @return string
73
     * @access protected
74
     */
75
    protected function getChannel()/*# : string */
76
    {
77
        return $this->current_channel ?: $this->default_channel;
78
    }
79
80
    /**
81
     * Add callable to the $type queue
82
     *
83
     * @param  string $type 'handlers' or 'processors'
84
     * @param  callable $callable
85
     * @param  string $channel
86
     * @param  int $priority  -100 - +100
87
     * @param  string $level
88
     * @return $this
89
     * @access protected
90
     * @since  2.0.1 added level here
91
     */
92
    protected function addCallable(
93
        /*# string */ $type,
94
        callable $callable,
95
        /*# string */ $channel,
96
        /*# int */ $priority,
97
        /*# string */ $level = ''
98
    ) {
99
        $q = &$this->$type;
100
        $c = strtoupper($channel);
101
102
        if (!isset($q[$c])) {
103
            $q[$c] = new PriorityQueue();
104
        }
105
106
        /* @var PriorityQueue $queue */
107
        $queue = $q[$c];
108
        $queue->insert($callable, $priority, $level);
109
110
        return $this;
111
    }
112
113
    /**
114
     * Remove callable for $type
115
     *
116
     * @param  string $type
117
     * @param  callable|string $callableOrClassname
118
     * @param  string $channel
119
     * @return $this
120
     * @access protected
121
     */
122
    protected function removeCallable(
123
        /*# string */ $type,
124
        $callableOrClassname,
125
        /*# string */ $channel
126
    ) {
127
        $channels = $channel ? (array) $channel : $this->getAllChannels($type);
128
129
        $q = &$this->$type;
130
        foreach ($channels as $ch) {
131
            $c = strtoupper($ch);
132
            /* @var PriorityQueue $queue */
133
            if (isset($q[$c])) {
134
                $this->removeFromQueue($q[$c], $callableOrClassname);
135
            }
136
        }
137
        return $this;
138
    }
139
140
    /**
141
     * Remove callable or matching classname object from the queue
142
     *
143
     * @param  PriorityQueueInterface $queue
144
     * @param  callable|string $callabOrClassname
145
     * @access protected
146
     */
147
    protected function removeFromQueue(
148
        PriorityQueueInterface $queue,
149
        $callabOrClassname
150
    ) {
151
        if (is_object($callabOrClassname)) {
152
            $queue->remove($callabOrClassname);
153
        } else {
154
            foreach ($queue as $data) {
155
                if (is_a($data['data'], $callabOrClassname)) {
156
                    $queue->remove($data['data']);
157
                }
158
            }
159
        }
160
    }
161
162
    /**
163
     * Get all the channels for handlers or processors
164
     *
165
     * @param  string $type 'handlers' or 'processors'
166
     * @return array
167
     * @access protected
168
     */
169
    protected function getAllChannels(/*# string */ $type)/*# : array */
170
    {
171
        return array_keys($this->$type);
172
    }
173
174
    /**
175
     * Execute related processors on the log entry
176
     *
177
     * @param  LogEntryInterface $logEntry
178
     * @return $this
179
     * @access protected
180
     */
181
    protected function runProcessors(LogEntryInterface $logEntry)
182
    {
183
        // get related processors
184
        $queue = $this->getCallables('processors', $logEntry->getChannel());
185
186
        // loop thru these processors
187
        foreach ($queue as $data) {
188
            call_user_func($data['data'], $logEntry);
189
        }
190
191
        return $this;
192
    }
193
194
    /**
195
     * Execute related handlers on the log entry
196
     *
197
     * @param  LogEntryInterface $logEntry
198
     * @return $this
199
     * @access protected
200
     * @since  2.0.1 added level checking here
201
     */
202
    protected function runHandlers(LogEntryInterface $logEntry)
203
    {
204
        // get related handlers
205
        $queue = $this->getCallables('handlers', $logEntry->getChannel());
206
207
        // loop thru these handlers
208
        foreach ($queue as $data) {
209
            // stopped ?
210
            if ($logEntry->isPropagationStopped()) {
211
                break;
212
            }
213
214
            // run handler only if level allowed
215
            if (LogLevel::$levels[$logEntry->getLevel()] >=
216
                LogLevel::$levels[$data['extra']]) {
217
                call_user_func($data['data'], $logEntry);
218
            }
219
        }
220
221
        return $this;
222
    }
223
224
    /**
225
     * Get all matching handlers/processors with channel name globbing
226
     *
227
     * @param  string $type
228
     * @param  string $channel
229
     * @return PriorityQueue
230
     * @access protected
231
     */
232
    protected function getCallables(
233
        /*# string */ $type,
234
        /*# string */ $channel
235
    )/*# : PriorityQueue */ {
236
237
        // name globbing with all channels
238
        $matchedChannels = $this->globbingNames(
239
            $channel,
240
            $this->getAllChannels($type)
241
        );
242
243
        // type queues
244
        $q = &$this->$type;
245
246
        // merge queues
247
        $queue = new PriorityQueue();
248
        foreach ($matchedChannels as $c) {
249
            $queue = $queue->combine($q[$c]);
250
        }
251
252
        return $queue;
253
    }
254
}
255