Passed
Push — master ( 586cac...a1a23b )
by Zoilo
01:54
created

StacktraceFrame::argsFromDebugBacktrace()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 15
c 1
b 0
f 0
nc 9
nop 1
dl 0
loc 28
ccs 17
cts 17
cp 1
crap 7
rs 8.8333
1
<?php
2
3
namespace ZoiloMora\ElasticAPM\Events\Common;
4
5
class StacktraceFrame implements \JsonSerializable
6
{
7
    const CLASS_NAME = __CLASS__;
8
9
    /**
10
     * The absolute path of the file involved in the stack frame
11
     *
12
     * @var string|null
13
     */
14
    private $absPath;
15
16
    /**
17
     * Column number
18
     *
19
     * @var int|null
20
     */
21
    private $colno;
22
23
    /**
24
     * The line of code part of the stack frame
25
     *
26
     * @var string|null
27
     */
28
    private $contextLine;
29
30
    /**
31
     * The relative filename of the code involved in the stack frame, used e.g. to do error checksumming
32
     *
33
     * @var string|null
34
     */
35
    private $filename;
36
37
    /**
38
     * The classname of the code involved in the stack frame
39
     *
40
     * @var string|null
41
     */
42
    private $classname;
43
44
    /**
45
     * The function involved in the stack frame
46
     *
47
     * @var string|null
48
     */
49
    private $function;
50
51
    /**
52
     * A boolean, indicating if this frame is from a library or user code
53
     *
54
     * @var bool|null
55
     */
56
    private $libraryFrame;
57
58
    /**
59
     * The line number of code part of the stack frame, used e.g. to do error checksumming
60
     *
61
     * @var int|null
62
     */
63
    private $lineno;
64
65
    /**
66
     * The module to which frame belongs to
67
     *
68
     * @var string|null
69
     */
70
    private $module;
71
72
    /**
73
     * The lines of code after the stack frame
74
     *
75
     * @var array|null
76
     */
77
    private $postContext;
78
79
    /**
80
     * The lines of code before the stack frame
81
     *
82
     * @var array|null
83
     */
84
    private $preContext;
85
86
    /**
87
     * Local variables for this stack frame
88
     *
89
     * @var array|null
90
     */
91
    private $vars;
92
93
    /**
94
     * @param string|null $absPath
95
     * @param int|null $colno
96
     * @param string|null $contextLine
97
     * @param string $filename
98
     * @param string $classname
99
     * @param string|null $function
100
     * @param bool|null $libraryFrame
101
     * @param int|null $lineno
102
     * @param string|null $module
103
     * @param array|null $postContext
104
     * @param array|null $preContext
105
     * @param array|null $vars
106
     */
107 11
    public function __construct(
108
        $absPath = null,
109
        $colno = null,
110
        $contextLine = null,
111
        $filename = null,
112
        $classname = null,
113
        $function = null,
114
        $libraryFrame = null,
115
        $lineno = null,
116
        $module = null,
117
        array $postContext = null,
118
        array $preContext = null,
119
        array $vars = null
120
    ) {
121 11
        $this->absPath = $absPath;
122 11
        $this->colno = $colno;
123 11
        $this->contextLine = $contextLine;
124 11
        $this->filename = $filename;
125 11
        $this->classname = $classname;
126 11
        $this->function = $function;
127 11
        $this->libraryFrame = $libraryFrame;
128 11
        $this->lineno = $lineno;
129 11
        $this->module = $module;
130 11
        $this->postContext = $postContext;
131 11
        $this->preContext = $preContext;
132 11
        $this->vars = $vars;
133
134 11
        if (null === $this->classname && null === $this->filename) {
135 1
            throw new \InvalidArgumentException('At least one of the fields (classname, filename) must be a string');
136
        }
137 10
    }
138
139
    /**
140
     * @param array $debugBacktrace
141
     *
142
     * @return StacktraceFrame
143
     */
144 8
    public static function fromDebugBacktrace(array $debugBacktrace)
145
    {
146 8
        $file = self::valueOrNull($debugBacktrace, 'file');
147 8
        $class = self::valueOrNull($debugBacktrace, 'class');
148
149 8
        return new self(
150 8
            $file,
151 8
            null,
152 8
            null,
153 8
            null !== $file ? basename($file) : null,
154 8
            $class,
155 8
            self::valueOrNull($debugBacktrace, 'function'),
156 8
            null,
157 8
            self::valueOrNull($debugBacktrace, 'line'),
158 8
            $class,
159 8
            null,
160 8
            null,
161 8
            self::argsFromDebugBacktrace($debugBacktrace)
162 8
        );
163
    }
164
165
    /**
166
     * @param array $array
167
     * @param string $key
168
     *
169
     * @return mixed|null
170
     */
171 8
    private static function valueOrNull(array $array, $key)
172
    {
173 8
        return true === array_key_exists($key, $array)
174 8
            ? $array[$key]
175 8
            : null;
176
    }
177
178
    /**
179
     * @param array $debugBacktrace
180
     *
181
     * @return array|null
182
     */
183 8
    private static function argsFromDebugBacktrace(array $debugBacktrace)
184
    {
185 8
        if (false === array_key_exists('args', $debugBacktrace)) {
186 1
            return null;
187
        }
188
189 7
        $arguments = $debugBacktrace['args'];
190
191 7
        $args = [];
192 7
        foreach ($arguments as $argument) {
193 5
            if (true === is_object($argument)) {
194 4
                $args[] = 'Instance of ' . get_class($argument);
195
196 4
                continue;
197
            }
198
199 5
            if (true === is_string($argument) && false === mb_check_encoding($argument, 'utf-8')) {
200 1
                $args[] = 'Malformed UTF-8 characters, possibly incorrectly encoded';
201
202 1
                continue;
203
            }
204
205 4
            $args[] = $argument;
206 7
        }
207
208 7
        return 0 === count($args)
209 7
            ? null
210 7
            : $args;
211
    }
212
213
    /**
214
     * @return array
215
     */
216 3
    public function jsonSerialize()
217
    {
218
        return [
219 3
            'abs_path' => $this->absPath,
220 3
            'colno' => $this->colno,
221 3
            'context_line' => $this->contextLine,
222 3
            'filename' => $this->filename,
223 3
            'classname' => $this->classname,
224 3
            'function' => $this->function,
225 3
            'library_frame' => $this->libraryFrame,
226 3
            'lineno' => $this->lineno,
227 3
            'module' => $this->module,
228 3
            'post_context' => $this->postContext,
229 3
            'pre_context' => $this->preContext,
230 3
            'vars' => null === $this->vars
231 3
                ? null
232 3
                : (object) $this->vars,
233 3
        ];
234
    }
235
}
236