Completed
Push — master ( f7cf81...0d805c )
by Jacob
02:47
created

PhpQuickProfiler   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 19
Bugs 4 Features 9
Metric Value
wmc 21
c 19
b 4
f 9
lcom 1
cbo 1
dl 0
loc 186
rs 10

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 2
A setConsole() 0 4 1
A setDisplay() 0 4 1
A gatherFileData() 0 12 2
A gatherMemoryData() 0 9 1
A setProfiledQueries() 0 4 1
A gatherQueryData() 0 16 4
A explainQuery() 0 15 3
A getExplainQuery() 0 9 3
A gatherSpeedData() 0 10 1
A display() 0 14 2
1
<?php
2
3
/*****************************************
4
 * Title : PHP Quick Profiler Class
5
 * Author : Created by Ryan Campbell
6
 * URL : http://particletree.com/features/php-quick-profiler/
7
 * Description : This class processes the logs and organizes the data
8
 *  for output to the browser. Initialize this class with a start time
9
 *  at the beginning of your code, and then call the display method when
10
 *  your code is terminating.
11
*****************************************/
12
13
namespace Particletree\Pqp;
14
15
use Exception;
16
17
class PhpQuickProfiler
18
{
19
20
    /** @var  integer */
21
    protected $startTime;
22
23
    /** @var  Console */
24
    protected $console;
25
26
    /** @var  Display */
27
    protected $display;
28
29
    /** @var  array */
30
    protected $profiledQueries = array();
31
32
    /**
33
     * @param double $startTime
34
     */
35
    public function __construct($startTime = null)
36
    {
37
        if (is_null($startTime)) {
38
            $startTime = microtime(true);
39
        }
40
        $this->startTime = $startTime;
0 ignored issues
show
Documentation Bug introduced by
The property $startTime was declared of type integer, but $startTime is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
41
    }
42
43
    /**
44
     * @param Console $console
45
     */
46
    public function setConsole(Console $console)
47
    {
48
        $this->console = $console;
49
    }
50
51
    /**
52
     * @param Display $display
53
     */
54
    public function setDisplay(Display $display)
55
    {
56
        $this->display = $display;
57
    }
58
59
    /**
60
     * Get data about files loaded for the application to current point
61
     *
62
     * @returns array
63
     */
64
    public function gatherFileData()
65
    {
66
        $files = get_included_files();
67
        $data = array();
68
        foreach ($files as $file) {
69
            array_push($data, array(
70
                'name' => $file,
71
                'size' => filesize($file)
72
            ));
73
        }
74
        return $data;
75
    }
76
77
    /**
78
     * Get data about memory usage of the application
79
     *
80
     * @returns array
81
     */
82
    public function gatherMemoryData()
83
    {
84
        $usedMemory = memory_get_peak_usage();
85
        $allowedMemory = ini_get('memory_limit');
86
        return array(
87
            'used'    => $usedMemory,
88
            'allowed' => $allowedMemory
89
        );
90
    }
91
92
    /**
93
     * @param array $profiled_queries
0 ignored issues
show
Documentation introduced by
There is no parameter named $profiled_queries. Did you maybe mean $profiledQueries?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
94
     */
95
    public function setProfiledQueries(array $profiledQueries)
96
    {
97
        $this->profiledQueries = $profiledQueries;
98
    }
99
100
    /**
101
     * Get data about sql usage of the application
102
     *
103
     * @param object $dbConnection
104
     * @returns array
105
     */
106
    public function gatherQueryData($dbConnection)
107
    {
108
        if (empty($this->profiledQueries) && property_exists($dbConnection, 'queries')) {
109
            $this->setProfiledQueries($dbConnection->queries);
110
        }
111
112
        $data = array();
113
        foreach ($this->profiledQueries as $query) {
114
            array_push($data, array(
115
                'sql'     => $query['sql'],
116
                'explain' => $this->explainQuery($dbConnection, $query['sql'], $query['parameters']),
117
                'time'    => $query['time']
118
            ));
119
        }
120
        return $data;
121
    }
122
123
    /**
124
     * Attempts to explain a query
125
     *
126
     * @param object $dbConnection
127
     * @param string $query
128
     * @param array  $parameters
129
     * @throws Exception
130
     * @return array
131
     */
132
    protected function explainQuery($dbConnection, $query, $parameters = array())
133
    {
134
        $driver = $dbConnection->getAttribute(\PDO::ATTR_DRIVER_NAME);
135
        $query = $this->getExplainQuery($query, $driver);
136
        $statement = $dbConnection->prepare($query);
137
        if ($statement === false) {
138
            throw new Exception('Invalid query passed to explainQuery method');
139
        }
140
        $statement->execute($parameters);
141
        $result = $statement->fetch(\PDO::FETCH_ASSOC);
142
        if ($result === false) {
143
            throw new Exception('Query could not be explained with given parameters');
144
        }
145
        return $result;
146
    }
147
148
    /**
149
     * Attempts to figure out what kind of explain query format the db wants
150
     *
151
     * @param string $query
152
     * @param string $driver
153
     * @throws Exception
154
     * @return string
155
     */
156
    protected function getExplainQuery($query, $driver)
157
    {
158
        if ($driver == 'mysql') {
159
            return "EXPLAIN {$query}";
160
        } elseif ($driver == 'sqlite') {
161
            return "EXPLAIN QUERY PLAN {$query}";
162
        }
163
        throw new Exception('Could not process db driver');
164
    }
165
166
    /**
167
     * Get data about speed of the application
168
     *
169
     * @returns array
170
     */
171
    public function gatherSpeedData()
172
    {
173
        $elapsedTime = microtime(true) - $this->startTime;
174
        $elapsedTime = round($elapsedTime, 3);
175
        $allowedTime = ini_get('max_execution_time');
176
        return array(
177
            'elapsed' => $elapsedTime,
178
            'allowed' => $allowedTime
179
        );
180
    }
181
182
    /**
183
     * Triggers end display of the profiling data
184
     *
185
     * @param object $dbConnection
186
     * @throws Exception
187
     */
188
    public function display($dbConnection = null)
189
    {
190
        if (!isset($this->display)) {
191
            throw new Exception('Display object has not been injected into Profiler');
192
        }
193
194
        $this->display->setConsole($this->console);
195
        $this->display->setFileData($this->gatherFileData());
196
        $this->display->setMemoryData($this->gatherMemoryData());
197
        $this->display->setQueryData($this->gatherQueryData($dbConnection));
0 ignored issues
show
Bug introduced by
It seems like $dbConnection defined by parameter $dbConnection on line 188 can also be of type null; however, Particletree\Pqp\PhpQuic...iler::gatherQueryData() does only seem to accept object, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
198
        $this->display->setSpeedData($this->gatherSpeedData());
199
200
        $this->display->__invoke();
201
    }
202
}
203