Completed
Push — master ( 77fd29...f7cf81 )
by Jacob
02:48
created

PhpQuickProfiler::getExplainQuery()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
rs 9.6667
cc 3
eloc 6
nc 3
nop 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
            if ($query['function'] !== 'perform') {
115
                continue;
116
            }
117
118
            array_push($data, array(
119
                'sql'     => $query['statement'],
120
                'explain' => $this->explainQuery($dbConnection, $query['statement'], $query['bind_values']),
121
                'time'    => $query['duration']
122
            ));
123
        }
124
        return $data;
125
    }
126
127
    /**
128
     * Attempts to explain a query
129
     *
130
     * @param object $dbConnection
131
     * @param string $query
132
     * @param array  $parameters
133
     * @throws Exception
134
     * @return array
135
     */
136
    protected function explainQuery($dbConnection, $query, $parameters = array())
137
    {
138
        $driver = $dbConnection->getAttribute(\PDO::ATTR_DRIVER_NAME);
139
        $query = $this->getExplainQuery($query, $driver);
140
        $statement = $dbConnection->prepare($query);
141
        if ($statement === false) {
142
            throw new Exception('Invalid query passed to explainQuery method');
143
        }
144
        $statement->execute($parameters);
145
        $result = $statement->fetch(\PDO::FETCH_ASSOC);
146
        if ($result === false) {
147
            throw new Exception('Query could not be explained with given parameters');
148
        }
149
        return $result;
150
    }
151
152
    /**
153
     * Attempts to figure out what kind of explain query format the db wants
154
     *
155
     * @param string $query
156
     * @param string $driver
157
     * @throws Exception
158
     * @return string
159
     */
160
    protected function getExplainQuery($query, $driver)
161
    {
162
        if ($driver == 'mysql') {
163
            return "EXPLAIN {$query}";
164
        } elseif ($driver == 'sqlite') {
165
            return "EXPLAIN QUERY PLAN {$query}";
166
        }
167
        throw new Exception('Could not process db driver');
168
    }
169
170
    /**
171
     * Get data about speed of the application
172
     *
173
     * @returns array
174
     */
175
    public function gatherSpeedData()
176
    {
177
        $elapsedTime = microtime(true) - $this->startTime;
178
        $elapsedTime = round($elapsedTime, 3);
179
        $allowedTime = ini_get('max_execution_time');
180
        return array(
181
            'elapsed' => $elapsedTime,
182
            'allowed' => $allowedTime
183
        );
184
    }
185
186
    /**
187
     * Triggers end display of the profiling data
188
     *
189
     * @param object $dbConnection
190
     * @throws Exception
191
     */
192
    public function display($dbConnection = null)
193
    {
194
        if (!isset($this->display)) {
195
            throw new Exception('Display object has not been injected into Profiler');
196
        }
197
198
        $this->display->setConsole($this->console);
199
        $this->display->setFileData($this->gatherFileData());
200
        $this->display->setMemoryData($this->gatherMemoryData());
201
        $this->display->setQueryData($this->gatherQueryData($dbConnection));
0 ignored issues
show
Bug introduced by
It seems like $dbConnection defined by parameter $dbConnection on line 192 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...
202
        $this->display->setSpeedData($this->gatherSpeedData());
203
204
        $this->display->__invoke();
205
    }
206
}
207