Passed
Push — master ( 810fb9...d89e1c )
by Alexander
02:13
created

AbstractTarget::filterMessages()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Profiler\Target;
6
7
use Yiisoft\Profiler\Message;
8
use Yiisoft\Strings\WildcardPattern;
9
10
/**
11
 * Target is the base class for all profiling target classes.
12
 *
13
 * A profile target object will filter the messages stored by {@see Profiler} according
14
 * to its {@see AbstractTarget::include()} and {@see AbstractTarget::exclude()}.
15
 *
16
 * For more details and usage information on Target,
17
 * see the [guide article on profiling & targets](guide:runtime-profiling).
18
 */
19
abstract class AbstractTarget implements TargetInterface
20
{
21
    /**
22
     * @var array List of message categories that this target is interested in. Defaults to empty, meaning all
23
     * categories.
24
     *
25
     * You can use an asterisk at the end of a category so that the category may be used to
26
     * match those categories sharing the same common prefix. For example, 'Yiisoft\Db\**' will match
27
     * categories starting with 'Yiisoft\Db\', such as `Yiisoft\Db\Connection`.
28
     *
29
     * @see WildcardPattern
30
     */
31
    private array $include = [];
32
33
    /**
34
     * @var array List of message categories that this target is NOT interested in. Defaults to empty, meaning no
35
     * uninteresting messages.
36
     *
37
     * If this property is not empty, then any category listed here will be excluded from {@see include()}.
38
     * You can use an asterisk at the end of a category so that the category can be used to
39
     * match those categories sharing the same common prefix. For example, 'Yiisoft\Db\**' will match
40
     * categories starting with 'Yiisoft\Db\', such as `Yiisoft\Db\Connection`.
41
     *
42
     * @see WildcardPattern
43
     */
44
    private array $exclude = [];
45
46
    /**
47
     * @var bool Whether to enable this log target. Defaults to true.
48
     */
49
    private bool $enabled = true;
50
51
    /**
52
     * Processes the given log messages.
53
     *
54
     * This method will filter the given messages with {@see include()} and {@see exclude()}.
55
     * And if requested, it will also export the filtering result to specific medium (e.g. email).
56
     *
57
     * @param array $messages Profiling messages to be processed. See {@see Profiler::$messages} for the structure
58
     * of each message.
59
     */
60 5
    public function collect(array $messages): void
61
    {
62 5
        if (!$this->enabled) {
63 1
            return;
64
        }
65
66 4
        $messages = $this->filterMessages($messages);
67
68 4
        if (count($messages) > 0) {
69 3
            $this->export($messages);
70
        }
71 4
    }
72
73
    /**
74
     * @param array $include List of message categories that this target is interested in. Defaults to empty, meaning all
75
     * categories.
76
     *
77
     * You can use an asterisk at the end of a category so that the category may be used to
78
     * match those categories sharing the same common prefix. For example, 'Yiisoft\Db\**' will match
79
     * categories starting with 'Yiisoft\Db\', such as `Yiisoft\Db\Connection`.
80
     *
81
     * @see WildcardPattern
82
     *
83
     * @return $this
84
     */
85 5
    public function include(array $include): self
86
    {
87 5
        $new = clone $this;
88 5
        $new->include = $include;
89 5
        return $new;
90
    }
91
92
    /**
93
     * @param array $exclude List of message categories that this target is NOT interested in. Defaults to empty, meaning no
94
     * uninteresting messages.
95
     *
96
     * If this property is not empty, then any category listed here will be excluded from {@see include()}.
97
     * You can use an asterisk at the end of a category so that the category can be used to
98
     * match those categories sharing the same common prefix. For example, 'Yiisoft\Db\**' will match
99
     * categories starting with 'Yiisoft\Db\', such as `Yiisoft\Db\Connection`.
100
     *
101
     * @return $this
102
     */
103 6
    public function exclude(array $exclude): self
104
    {
105 6
        $new = clone $this;
106 6
        $new->exclude = $exclude;
107 6
        return $new;
108
    }
109
110
    /**
111
     * Enable or disable target.
112
     *
113
     * @return $this
114
     */
115 2
    public function enable(bool $value = true): self
116
    {
117 2
        $new = clone $this;
118 2
        $new->enabled = $value;
119 2
        return $new;
120
    }
121
122
    /**
123
     * Returns target is enabled.
124
     */
125 2
    public function isEnabled(): bool
126
    {
127 2
        return $this->enabled;
128
    }
129
130
    /**
131
     * Exports profiling messages to a specific destination.
132
     *
133
     * Child classes must implement this method.
134
     *
135
     * @param Message[] $messages Profiling messages to be exported.
136
     */
137
    abstract public function export(array $messages): void;
138
139
    /**
140
     * Filters the given messages according to their categories.
141
     *
142
     * @param Message[] $messages Messages to be filtered.
143
     * The message structure follows that in {@see Profiler::$messages}.
144
     *
145
     * @return array The filtered messages.
146
     */
147 9
    protected function filterMessages(array $messages): array
148
    {
149 9
        foreach ($messages as $i => $message) {
150 9
            if (!$this->isCategoryMatched($message->level())) {
151 3
                unset($messages[$i]);
152
            }
153
        }
154 9
        return $messages;
155
    }
156
157 9
    private function isCategoryMatched(string $category): bool
158
    {
159 9
        $matched = empty($this->include);
160
161 9
        foreach ($this->include as $pattern) {
162 2
            if ((new WildcardPattern($pattern))->match($category)) {
163 1
                $matched = true;
164 1
                break;
165
            }
166
        }
167
168 9
        if ($matched) {
169 8
            foreach ($this->exclude as $pattern) {
170 3
                if ((new WildcardPattern($pattern))->match($category)) {
171 2
                    $matched = false;
172 2
                    break;
173
                }
174
            }
175
        }
176 9
        return $matched;
177
    }
178
}
179