Completed
Push — master ( 5bd743...9075d8 )
by Jacob
02:21
created

Display::getMemoryMeta()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
rs 9.4286
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
3
/*****************************************
4
 * Title : Php Quick Profiler Display Class
5
 * Author : Created by Ryan Campbell
6
 * URL : http://particletree.com/features/php-quick-profiler/
7
 * Description : This is a hacky way of pushing profiling logic to the
8
 *  PQP HTML. This is great because it will just work in your project,
9
 *  but it is hard to maintain and read.
10
*****************************************/
11
12
namespace Particletree\Pqp;
13
14
class Display
15
{
16
17
    /** @var  array */
18
    protected $defaults = array(
19
        'script_path' => 'asset/script.js',
20
        'style_path'  => 'asset/style.css'
21
    );
22
23
    /** @var  array */
24
    protected $options;
25
26
    /** @var  double */
27
    protected $startTime;
28
29
    /** @var  Console */
30
    protected $console;
31
32
    /** @var  array */
33
    protected $speedData;
34
35
    /** @var  array */
36
    protected $queryData;
37
38
    /** @var  array */
39
    protected $memoryData;
40
41
    /** @var  array */
42
    protected $fileData;
43
44
    /**
45
     * @param array $options
46
     */
47
    public function __construct(array $options = array())
48
    {
49
        $options = array_intersect_key($options, $this->defaults);
50
        $this->options = array_replace($this->defaults, $options);
51
    }
52
53
    /**
54
     * @param double $startTime
55
     */
56
    public function setStartTime($startTime)
57
    {
58
        $this->startTime = $startTime;
59
    }
60
61
    /**
62
     * @param Console $console
63
     */
64
    public function setConsole(Console $console)
65
    {
66
        $this->console = $console;
67
    }
68
69
    /**
70
     * @return array
71
     */
72
    protected function formatConsoleData()
73
    {
74
        $console_data = array(
75
            'messages' => array(),
76
            'meta'    => array(
77
                'log'    => 0,
78
                'memory' => 0,
79
                'error'  => 0,
80
                'speed'  => 0
81
            )
82
        );
83
        foreach ($this->console->getLogs() as $log) {
84
            switch($log['type']) {
85
                case 'log':
86
                    $message = array(
87
                        'message' => print_r($log['data'], true),
88
                        'type'    => 'log'
89
                    );
90
                    $console_data['meta']['log']++;
91
                    break;
92
                case 'memory':
93
                    $message = array(
94
                        'message' => (!empty($log['data_type']) ? "{$log['data_type']}: " : '') . $log['name'],
95
                        'data'    => $this->getReadableMemory($log['data']),
96
                        'type'    => 'memory'
97
                    );
98
                    $console_data['meta']['memory']++;
99
                    break;
100
                case 'error':
101
                    $message = array(
102
                        'message' => "Line {$log['line']}: {$log['data']} in {$log['file']}",
103
                        'type'    => 'error'
104
                    );
105
                    $console_data['meta']['error']++;
106
                    break;
107
                case 'speed':
108
                    $elapsedTime = $log['data'] - $this->startTime;
109
                    $message = array(
110
                        'message' => $log['name'],
111
                        'data'    => $this->getReadableTime($elapsedTime),
112
                        'type'    => 'speed'
113
                    );
114
                    $console_data['meta']['speed']++;
115
                    break;
116
                default:
117
                    $message = array(
118
                        'message' => "Unrecognized console log type: {$log['type']}",
119
                        'type'    => 'error'
120
                    );
121
                    $console_data['meta']['error']++;
122
                    break;
123
            }
124
            array_push($console_data['messages'], $message);
125
        }
126
        return $console_data;
127
    }
128
129
    /**
130
     * Sets speed data
131
     *
132
     * @param array $data
133
     */
134
    public function setSpeedData(array $data)
135
    {
136
        $this->speedData = $data;
137
    }
138
139
    /**
140
     * @return array
141
     */
142
    protected function getSpeedMeta()
143
    {
144
        $elapsedTime = $this->getReadableTime($this->speedData['elapsed']);
145
        $allowedTime = $this->getReadableTime($this->speedData['allowed'], 0);
146
147
        return array(
148
            'elapsed' => $elapsedTime,
149
            'allowed' => $allowedTime,
150
        );
151
    }
152
153
    /**
154
     * Sets file data
155
     *
156
     * @param array $data
157
     */
158
    public function setFileData(array $data)
159
    {
160
        $this->fileData = $data;
161
    }
162
163
    /**
164
     * @return array
165
     */
166 View Code Duplication
    protected function formatFileData()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
167
    {
168
        $fileData = array(
169
            'messages' => array(),
170
            'meta'     => array(
171
                'count'   => count($this->fileData),
172
                'size'    => 0,
173
                'largest' => 0
174
            )
175
        );
176
177
        foreach ($this->fileData as $file) {
178
            array_push($fileData['messages'], array(
179
                'message' => $file['name'],
180
                'data'    => $this->getReadableMemory($file['size'])
181
            ));
182
183
            $fileData['meta']['size'] += $file['size'];
184
            if ($file['size'] > $fileData['meta']['largest']) {
185
                $fileData['meta']['largest'] = $file['size'];
186
            }
187
        }
188
189
        $fileData['meta']['size'] = $this->getReadableMemory($fileData['meta']['size']);
190
        $fileData['meta']['largest'] = $this->getReadableMemory($fileData['meta']['largest']);
191
192
        return $fileData;
193
    }
194
195
    /**
196
     * Sets memory data
197
     *
198
     * @param array $data
199
     */
200
    public function setMemoryData(array $data)
201
    {
202
        $this->memoryData = $data;
203
    }
204
205
    /**
206
     * @return array
207
     */
208
    public function getMemoryMeta()
209
    {
210
        $usedMemory = $this->getReadableMemory($this->memoryData['used']);
211
        $allowedMemory = $this->memoryData['allowed']; // todo parse this, maybe?
212
213
        return array(
214
            'used'    => $usedMemory,
215
            'allowed' => $allowedMemory
216
        );
217
    }
218
219
    /**
220
     * Sets query data
221
     *
222
     * @param array $data
223
     */
224
    public function setQueryData(array $data)
225
    {
226
        $this->queryData = $data;
227
    }
228
229
    /**
230
     * @return array
231
     */
232 View Code Duplication
    public function formatQueryData()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
233
    {
234
        $queryData = array(
235
            'messages' => array(),
236
            'meta'     => array(
237
                'count'   => count($this->queryData),
238
                'time'    => 0,
239
                'slowest' => 0
240
            )
241
        );
242
243
        foreach ($this->queryData as $query) {
244
            array_push($queryData['messages'], array(
245
                'message'  => $query['sql'],
246
                'sub_data' => array_filter($query['explain']),
247
                'data'     => $this->getReadableTime($query['time'])
248
            ));
249
            $queryData['meta']['time'] += $query['time'];
250
            if ($query['time'] > $queryData['meta']['slowest']) {
251
                $queryData['meta']['slowest'] = $query['time'];
252
            }
253
        }
254
255
        $queryData['meta']['time'] = $this->getReadableTime($queryData['meta']['time']);
256
        $queryData['meta']['slowest'] = $this->getReadableTime($queryData['meta']['slowest']);
257
258
        return $queryData;
259
    }
260
261
262
    /**
263
     * Formatter for human-readable time
264
     * Only handles time up to 60 minutes gracefully
265
     *
266
     * @param double  $time
267
     * @param integer $percision
268
     * @return string
269
     */
270
    protected function getReadableTime($time, $percision = 3)
271
    {
272
        $unit = 's';
273
        if ($time < 1) {
274
            $time *= 1000;
275
            $unit = 'ms';
276
        } else if ($time > 60) {
277
            $time /= 60;
278
            $unit = 'm';
279
        }
280
        $time = number_format($time, $percision);
281
        return "{$time} {$unit}";
282
    }
283
284
    /**
285
     * Formatter for human-readable memory
286
     * Only handles time up to a few gigs gracefully
287
     *
288
     * @param double  $size
289
     * @param integer $percision
290
     */
291
    protected function getReadableMemory($size, $percision = 2)
292
    {
293
        $unitOptions = array('b', 'k', 'M', 'G');
294
295
        $base = log($size, 1024);
296
297
        $memory = round(pow(1024, $base - floor($base)), $percision);
298
        $unit = $unitOptions[floor($base)];
299
        return "{$memory} {$unit}";
300
    }
301
302
    /**
303
     * @param array  $messages
304
     * @param string $type
305
     * @return array
306
     */
307
    protected function filterMessages($messages, $type)
308
    {
309
        return array_filter($messages, function ($message) use ($type) {
310
            return $message['type'] == $type;
311
        });
312
    }
313
 
314
    public function __invoke()
315
    {
316
        $console = $this->formatConsoleData();
317
        $speedMeta = $this->getSpeedMeta();
318
        $query= $this->formatQueryData();
319
        $memoryMeta = $this->getMemoryMeta();
320
        $files= $this->formatFileData();
321
322
        $header = array(
0 ignored issues
show
Unused Code introduced by
$header is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
323
            'console' => count($console['messages']),
324
            'speed'   => $speedMeta['elapsed'],
325
            'query'   => $query['meta']['count'],
326
            'memory'  => $memoryMeta['used'],
327
            'files'   => $files['meta']['count']
328
        );
329
330
        $speed = array(
0 ignored issues
show
Unused Code introduced by
$speed is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
331
            'meta' => $speedMeta,
332
            'messages' => $this->filterMessages($console['messages'], 'speed')
333
        );
334
335
        $memory = array(
0 ignored issues
show
Unused Code introduced by
$memory is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
336
            'meta' => $memoryMeta,
337
            'messages' => $this->filterMessages($console['messages'], 'memory')
338
        );
339
340
        // todo is this really the best way to load these?
341
        $styles = file_get_contents(__DIR__ . "/../{$this->options['style_path']}");
0 ignored issues
show
Unused Code introduced by
$styles is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
342
        $script = file_get_contents(__DIR__ . "/../{$this->options['script_path']}");
0 ignored issues
show
Unused Code introduced by
$script is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
343
344
        require_once __DIR__ .'/../asset/display.html';
345
    }
346
}
347