Passed
Push — master ( f5e0e8...9bf844 )
by Waaaaaaaaaa
06:37
created

Frame   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 190
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 80
dl 0
loc 190
rs 8.5599
c 0
b 0
f 0
wmc 48

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getLine() 0 3 1
A hasCaller() 0 3 1
A setLine() 0 3 1
A getRelativeFilepath() 0 6 3
A setCaller() 0 3 1
A getArguments() 0 3 1
A setArguments() 0 6 2
A hasLine() 0 3 1
A hasFile() 0 3 2
A getCaller() 0 3 1
A getFile() 0 3 1
A setFile() 0 3 1
A create() 0 25 6
C normalise() 0 22 12
A getContext() 0 3 1
A normaliseArray() 0 25 6
A toArray() 0 23 5
A hasContext() 0 3 2

How to fix   Complexity   

Complex Class

Complex classes like Frame often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Frame, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace Logfile;
4
5
class Frame
6
{
7
    use PathTrait;
8
9
    protected $file;
10
11
    protected $line;
12
13
    protected $caller;
14
15
    protected $args;
16
17
    public static function create(array $params): self
18
    {
19
        $frame = new self;
20
21
        if (isset($params['file'])) {
22
            $frame->setFile($params['file']);
23
        }
24
25
        if (isset($params['line'])) {
26
            $frame->setLine($params['line']);
27
        }
28
29
        if (isset($params['class'])) {
30
            $frame->setCaller(\sprintf('%s%s%s', $params['class'], $params['type'], $params['function']));
31
        } elseif (isset($params['function'])) {
32
            $frame->setCaller($params['function']);
33
        }
34
35
        if (isset($params['args'])) {
36
            $frame->setArguments($params['args']);
37
        } else {
38
            $frame->setArguments([]);
39
        }
40
41
        return $frame;
42
    }
43
44
    public function getRelativeFilepath(): string
45
    {
46
        if ($this->hasPath() && \strpos($this->getFile(), $this->getPath()) === 0) {
47
            return substr($this->getFile(), \mb_strlen($this->getPath()));
48
        }
49
        return $this->getFile();
50
    }
51
52
    public function getFile(): string
53
    {
54
        return $this->file;
55
    }
56
57
    public function setFile(string $file): void
58
    {
59
        $this->file = $file;
60
    }
61
62
    public function hasFile(): bool
63
    {
64
        return $this->file !== null && \is_readable($this->file);
65
    }
66
67
    public function getLine(): int
68
    {
69
        return $this->line;
70
    }
71
72
    public function setLine(int $line): void
73
    {
74
        $this->line = $line;
75
    }
76
77
    public function hasLine(): bool
78
    {
79
        return $this->line !== null;
80
    }
81
82
    public function hasCaller(): bool
83
    {
84
        return !empty($this->caller);
85
    }
86
87
    public function getCaller(): string
88
    {
89
        return $this->caller;
90
    }
91
92
    public function setCaller(string $caller): void
93
    {
94
        $this->caller = $caller;
95
    }
96
97
    public function getArguments(): array
98
    {
99
        return $this->args;
100
    }
101
102
    public function setArguments(array $args): void
103
    {
104
        $this->args = [];
105
106
        foreach (\array_values($args) as $index => $arg) {
107
            $this->args['param'.($index + 1)] = $this->normalise($arg);
108
        }
109
    }
110
111
    protected function normaliseArray($value): string
112
    {
113
        $count = count($value);
114
115
        if ($count > 100) {
116
            return 'Array of length ' . $count;
117
        }
118
119
        $types = [];
120
121
        foreach ($value as $item) {
122
            $type = gettype($item);
123
            if ('object' === $type) {
124
                $type = get_class($item);
125
            }
126
            if (!in_array($type, $types)) {
127
                $types[] = $type;
128
            }
129
        }
130
131
        if (count($types) > 3) {
132
            return 'Mixed Array of length ' . $count;
133
        }
134
135
        return 'Array<'.implode('|', $types).'> of length ' . $count;
136
    }
137
138
    protected function normalise($value): string
139
    {
140
        if ($value === null) {
141
            return 'null';
142
        } elseif ($value === false) {
143
            return 'false';
144
        } elseif ($value === true) {
145
            return 'true';
146
        } elseif (is_float($value) && (int) $value == $value) {
147
            return $value.'.0';
148
        } elseif (is_integer($value) || is_float($value)) {
149
            return (string) $value;
150
        } elseif (is_object($value) || gettype($value) == 'object') {
151
            return 'Object '.get_class($value);
152
        } elseif (is_resource($value)) {
153
            return 'Resource '.get_resource_type($value);
154
        } elseif (is_array($value)) {
155
            return $this->normaliseArray($value);
156
        }
157
158
        $truncation = new Truncation($value);
159
        return $truncation->truncate();
160
    }
161
162
    public function hasContext(): bool
163
    {
164
        return $this->hasFile() && $this->hasLine();
165
    }
166
167
    public function getContext(): Context
168
    {
169
        return new Context($this->getFile(), $this->getLine());
170
    }
171
172
    public function toArray(): array
173
    {
174
        $frame = [];
175
176
        if ($this->hasFile()) {
177
            $frame['file'] = $this->getRelativeFilepath();
178
        }
179
180
        if ($this->hasLine()) {
181
            $frame['line'] = $this->getLine();
182
        }
183
184
        if ($this->hasCaller()) {
185
            $frame['caller'] = $this->getCaller();
186
        }
187
188
        $frame['args'] = $this->getArguments();
189
190
        if ($this->hasContext()) {
191
            $frame['context'] = $this->getContext()->getPlaceInFile();
192
        }
193
194
        return $frame;
195
    }
196
}
197