Version Description
- Add a new panel which lists duplicated database queries.
- Add support for displaying QM's output when viewing an embed.
- Differentiate regular plugins from mu-plugins when displaying components.
- Ensure early errors are always reported regardless of system level error reporting.
- Ensure that script and style dependency highlighting is restricted to the scripts and styles tables, respectively.
- Rearrange the Environment section output a little.
- Various minor tweaks.
Download this release
Release Info
Developer | johnbillion |
Plugin | Query Monitor |
Version | 2.10.0 |
Comparing to | |
See all releases |
Code changes from version 2.9.1 to 2.10.0
- assets/query-monitor.css +33 -4
- assets/query-monitor.js +14 -7
- classes/Backtrace.php +12 -9
- classes/Collector.php +11 -0
- classes/Util.php +5 -1
- collectors/assets.php +1 -0
- collectors/db_dupes.php +117 -0
- collectors/db_queries.php +5 -1
- collectors/overview.php +1 -0
- collectors/php_errors.php +22 -29
- collectors/request.php +2 -0
- collectors/theme.php +1 -1
- dispatchers/Html.php +6 -2
- output/html/assets.php +25 -16
- output/html/db_dupes.php +137 -0
- output/html/db_queries.php +6 -4
- output/html/environment.php +13 -13
- output/html/hooks.php +2 -2
- output/html/http.php +6 -6
- output/html/languages.php +2 -2
- output/html/transients.php +2 -2
- query-monitor.php +1 -1
- readme.txt +13 -3
assets/query-monitor.css
CHANGED
@@ -146,11 +146,19 @@ body.wp-admin #qm {
|
|
146 |
margin: 0 0 0 160px !important;
|
147 |
}
|
148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
body.wp-admin.folded #qm {
|
150 |
margin-left: 36px !important;
|
151 |
}
|
152 |
|
153 |
@media screen and (max-width: 782px) {
|
|
|
154 |
body.wp-admin #qm {
|
155 |
margin-left: 0 !important;
|
156 |
}
|
@@ -180,6 +188,12 @@ body.wp-admin.folded #qm {
|
|
180 |
clear: none !important;
|
181 |
}
|
182 |
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
.qm:focus {
|
184 |
outline: 0 !important;
|
185 |
}
|
@@ -194,6 +208,7 @@ body.wp-admin.folded #qm {
|
|
194 |
}
|
195 |
|
196 |
@media all and (max-width: 900px) {
|
|
|
197 |
.qm-half {
|
198 |
float: none !important;
|
199 |
width: 100% !important;
|
@@ -375,7 +390,7 @@ body.wp-admin.folded #qm {
|
|
375 |
}
|
376 |
|
377 |
.qm a {
|
378 |
-
color: #
|
379 |
text-decoration: none !important;
|
380 |
text-shadow: none !important;
|
381 |
font-weight: normal !important;
|
@@ -383,7 +398,7 @@ body.wp-admin.folded #qm {
|
|
383 |
.qm a:focus,
|
384 |
.qm a:hover {
|
385 |
text-decoration: underline !important;
|
386 |
-
color: #
|
387 |
}
|
388 |
|
389 |
.qm a.qm-warn {
|
@@ -391,7 +406,7 @@ body.wp-admin.folded #qm {
|
|
391 |
}
|
392 |
|
393 |
.qm a.qm-toggle {
|
394 |
-
color: #
|
395 |
padding: 4px 8px 3px !important;
|
396 |
border-left: 1px solid #e8e8e8 !important;
|
397 |
border-bottom: 1px solid #e8e8e8 !important;
|
@@ -405,7 +420,7 @@ body.wp-admin.folded #qm {
|
|
405 |
.qm a.qm-toggle:hover {
|
406 |
text-decoration: none !important;
|
407 |
border-color: #e8e8e8 !important;
|
408 |
-
color: #
|
409 |
background: #eee !important;
|
410 |
}
|
411 |
|
@@ -501,6 +516,13 @@ html[dir="rtl"] body.wp-admin #qm {
|
|
501 |
}
|
502 |
}
|
503 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
504 |
html[dir="rtl"] body.wp-admin.folded #qm {
|
505 |
margin-right: 36px !important;
|
506 |
margin-left: 0 !important;
|
@@ -515,6 +537,13 @@ html[dir="rtl"] .qm th {
|
|
515 |
text-align: right !important;
|
516 |
}
|
517 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
/* No-JS tweaks */
|
519 |
|
520 |
.qm-no-js #qm-authentication,
|
146 |
margin: 0 0 0 160px !important;
|
147 |
}
|
148 |
|
149 |
+
@media only screen and (max-width: 960px) {
|
150 |
+
body.wp-admin.auto-fold #qm {
|
151 |
+
margin-left: 36px !important;
|
152 |
+
margin-right: 0 !important;
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
body.wp-admin.folded #qm {
|
157 |
margin-left: 36px !important;
|
158 |
}
|
159 |
|
160 |
@media screen and (max-width: 782px) {
|
161 |
+
body.wp-admin.auto-fold #qm,
|
162 |
body.wp-admin #qm {
|
163 |
margin-left: 0 !important;
|
164 |
}
|
188 |
clear: none !important;
|
189 |
}
|
190 |
|
191 |
+
.qm-third {
|
192 |
+
float: left !important;
|
193 |
+
width: 33.33% !important;
|
194 |
+
clear: none !important;
|
195 |
+
}
|
196 |
+
|
197 |
.qm:focus {
|
198 |
outline: 0 !important;
|
199 |
}
|
208 |
}
|
209 |
|
210 |
@media all and (max-width: 900px) {
|
211 |
+
.qm-third,
|
212 |
.qm-half {
|
213 |
float: none !important;
|
214 |
width: 100% !important;
|
390 |
}
|
391 |
|
392 |
.qm a {
|
393 |
+
color: #00a0d2 !important;
|
394 |
text-decoration: none !important;
|
395 |
text-shadow: none !important;
|
396 |
font-weight: normal !important;
|
398 |
.qm a:focus,
|
399 |
.qm a:hover {
|
400 |
text-decoration: underline !important;
|
401 |
+
color: #00a0d2 !important;
|
402 |
}
|
403 |
|
404 |
.qm a.qm-warn {
|
406 |
}
|
407 |
|
408 |
.qm a.qm-toggle {
|
409 |
+
color: #00a0d2 !important;
|
410 |
padding: 4px 8px 3px !important;
|
411 |
border-left: 1px solid #e8e8e8 !important;
|
412 |
border-bottom: 1px solid #e8e8e8 !important;
|
420 |
.qm a.qm-toggle:hover {
|
421 |
text-decoration: none !important;
|
422 |
border-color: #e8e8e8 !important;
|
423 |
+
color: #00a0d2 !important;
|
424 |
background: #eee !important;
|
425 |
}
|
426 |
|
516 |
}
|
517 |
}
|
518 |
|
519 |
+
@media only screen and (max-width: 960px) {
|
520 |
+
html[dir="rtl"] body.wp-admin.auto-fold #qm {
|
521 |
+
margin-right: 36px !important;
|
522 |
+
margin-left: 0 !important;
|
523 |
+
}
|
524 |
+
}
|
525 |
+
|
526 |
html[dir="rtl"] body.wp-admin.folded #qm {
|
527 |
margin-right: 36px !important;
|
528 |
margin-left: 0 !important;
|
537 |
text-align: right !important;
|
538 |
}
|
539 |
|
540 |
+
html[dir="rtl"] .qm a.qm-toggle {
|
541 |
+
border-left: none !important;
|
542 |
+
border-right: 1px solid #e8e8e8 !important;
|
543 |
+
right: auto !important;
|
544 |
+
left: 1px !important;
|
545 |
+
}
|
546 |
+
|
547 |
/* No-JS tweaks */
|
548 |
|
549 |
.qm-no-js #qm-authentication,
|
assets/query-monitor.js
CHANGED
@@ -91,6 +91,8 @@ jQuery( function($) {
|
|
91 |
$('#wp-admin-bar-query-monitor ul').append(container);
|
92 |
|
93 |
$('#wp-admin-bar-query-monitor').find('a').on('click',function(e){
|
|
|
|
|
94 |
if ( is_admin ) {
|
95 |
$('#wpfooter').css('position','relative');
|
96 |
}
|
@@ -99,10 +101,6 @@ jQuery( function($) {
|
|
99 |
|
100 |
$( infinite_scroll.contentSelector ).infinitescroll('pause');
|
101 |
|
102 |
-
if ( window.console ) {
|
103 |
-
console.debug( qm_l10n.infinitescroll_paused );
|
104 |
-
}
|
105 |
-
|
106 |
} else if ( window.infiniteScroll && infiniteScroll.scroller ) {
|
107 |
// Jetpack Infinite Scroll module
|
108 |
|
@@ -110,11 +108,20 @@ jQuery( function($) {
|
|
110 |
return false;
|
111 |
};
|
112 |
|
113 |
-
|
114 |
-
|
115 |
-
}
|
116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
}
|
|
|
118 |
$('#qm').show();
|
119 |
});
|
120 |
|
91 |
$('#wp-admin-bar-query-monitor ul').append(container);
|
92 |
|
93 |
$('#wp-admin-bar-query-monitor').find('a').on('click',function(e){
|
94 |
+
var paused = true;
|
95 |
+
|
96 |
if ( is_admin ) {
|
97 |
$('#wpfooter').css('position','relative');
|
98 |
}
|
101 |
|
102 |
$( infinite_scroll.contentSelector ).infinitescroll('pause');
|
103 |
|
|
|
|
|
|
|
|
|
104 |
} else if ( window.infiniteScroll && infiniteScroll.scroller ) {
|
105 |
// Jetpack Infinite Scroll module
|
106 |
|
108 |
return false;
|
109 |
};
|
110 |
|
111 |
+
} else if ( window.wp && wp.themes && wp.themes.RunInstaller ) {
|
112 |
+
// Infinite scrolling on Appearance -> Add New screens
|
|
|
113 |
|
114 |
+
var view = wp.themes.RunInstaller.view.view;
|
115 |
+
view.stopListening( view.parent, 'theme:scroll' );
|
116 |
+
|
117 |
+
} else {
|
118 |
+
paused = false;
|
119 |
+
}
|
120 |
+
|
121 |
+
if ( paused && window.console ) {
|
122 |
+
console.debug( qm_l10n.infinitescroll_paused );
|
123 |
}
|
124 |
+
|
125 |
$('#qm').show();
|
126 |
});
|
127 |
|
classes/Backtrace.php
CHANGED
@@ -40,15 +40,18 @@ class QM_Backtrace {
|
|
40 |
'dbDelta' => true,
|
41 |
);
|
42 |
protected static $show_args = array(
|
43 |
-
'do_action'
|
44 |
-
'apply_filters'
|
45 |
-
'do_action_ref_array'
|
46 |
-
'apply_filters_ref_array'
|
47 |
-
'get_template_part'
|
48 |
-
'
|
49 |
-
'
|
50 |
-
'
|
51 |
-
'
|
|
|
|
|
|
|
52 |
);
|
53 |
protected static $filtered = false;
|
54 |
protected $trace = null;
|
40 |
'dbDelta' => true,
|
41 |
);
|
42 |
protected static $show_args = array(
|
43 |
+
'do_action' => 1,
|
44 |
+
'apply_filters' => 1,
|
45 |
+
'do_action_ref_array' => 1,
|
46 |
+
'apply_filters_ref_array' => 1,
|
47 |
+
'get_template_part' => 2,
|
48 |
+
'get_extended_template_part' => 2,
|
49 |
+
'load_template' => 'dir',
|
50 |
+
'dynamic_sidebar' => 1,
|
51 |
+
'get_header' => 1,
|
52 |
+
'get_sidebar' => 1,
|
53 |
+
'get_footer' => 1,
|
54 |
+
'get_site_by_path' => 3,
|
55 |
);
|
56 |
protected static $filtered = false;
|
57 |
protected $trace = null;
|
classes/Collector.php
CHANGED
@@ -40,6 +40,17 @@ abstract class QM_Collector {
|
|
40 |
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
protected function log_component( $component, $ltime, $type ) {
|
44 |
|
45 |
if ( !isset( $this->data['component_times'][$component->name] ) ) {
|
40 |
|
41 |
}
|
42 |
|
43 |
+
protected function maybe_log_dupe( $sql, $i ) {
|
44 |
+
|
45 |
+
$sql = str_replace( array( "\r\n", "\r", "\n" ), ' ', $sql );
|
46 |
+
$sql = str_replace( array( "\t" ), '', $sql );
|
47 |
+
$sql = preg_replace( '/[ ]+/', ' ', $sql );
|
48 |
+
$sql = trim( $sql );
|
49 |
+
|
50 |
+
$this->data['dupes'][ $sql ][] = $i;
|
51 |
+
|
52 |
+
}
|
53 |
+
|
54 |
protected function log_component( $component, $ltime, $type ) {
|
55 |
|
56 |
if ( !isset( $this->data['component_times'][$component->name] ) ) {
|
classes/Util.php
CHANGED
@@ -102,7 +102,11 @@ class QM_Util {
|
|
102 |
} else {
|
103 |
$plug = basename( $plug );
|
104 |
}
|
105 |
-
|
|
|
|
|
|
|
|
|
106 |
$context = $plug;
|
107 |
break;
|
108 |
case 'go-plugin':
|
102 |
} else {
|
103 |
$plug = basename( $plug );
|
104 |
}
|
105 |
+
if ( 'mu-plugin' === $type ) {
|
106 |
+
$name = sprintf( __( 'MU Plugin: %s', 'query-monitor' ), $plug );
|
107 |
+
} else {
|
108 |
+
$name = sprintf( __( 'Plugin: %s', 'query-monitor' ), $plug );
|
109 |
+
}
|
110 |
$context = $plug;
|
111 |
break;
|
112 |
case 'go-plugin':
|
collectors/assets.php
CHANGED
@@ -25,6 +25,7 @@ class QM_Collector_Assets extends QM_Collector {
|
|
25 |
add_action( 'admin_head', array( $this, 'action_head' ), 999 );
|
26 |
add_action( 'wp_head', array( $this, 'action_head' ), 999 );
|
27 |
add_action( 'login_head', array( $this, 'action_head' ), 999 );
|
|
|
28 |
}
|
29 |
|
30 |
public function action_head() {
|
25 |
add_action( 'admin_head', array( $this, 'action_head' ), 999 );
|
26 |
add_action( 'wp_head', array( $this, 'action_head' ), 999 );
|
27 |
add_action( 'login_head', array( $this, 'action_head' ), 999 );
|
28 |
+
add_action( 'embed_head', array( $this, 'action_head' ), 999 );
|
29 |
}
|
30 |
|
31 |
public function action_head() {
|
collectors/db_dupes.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Copyright 2009-2016 John Blackbourn
|
4 |
+
|
5 |
+
This program is free software; you can redistribute it and/or modify
|
6 |
+
it under the terms of the GNU General Public License as published by
|
7 |
+
the Free Software Foundation; either version 2 of the License, or
|
8 |
+
(at your option) any later version.
|
9 |
+
|
10 |
+
This program is distributed in the hope that it will be useful,
|
11 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
GNU General Public License for more details.
|
14 |
+
|
15 |
+
*/
|
16 |
+
|
17 |
+
class QM_Collector_DB_Dupes extends QM_Collector {
|
18 |
+
|
19 |
+
public $id = 'db_dupes';
|
20 |
+
|
21 |
+
public function name() {
|
22 |
+
return __( 'Duplicate Queries', 'query-monitor' );
|
23 |
+
}
|
24 |
+
|
25 |
+
public function process() {
|
26 |
+
|
27 |
+
if ( ! $dbq = QM_Collectors::get( 'db_queries' ) ) {
|
28 |
+
return;
|
29 |
+
}
|
30 |
+
if ( ! isset( $dbq->data['dupes'] ) ) {
|
31 |
+
return;
|
32 |
+
}
|
33 |
+
|
34 |
+
// Filter out SQL queries that do not have dupes
|
35 |
+
$this->data['dupes'] = array_filter( $dbq->data['dupes'], array( $this, '_filter_dupe_queries' ) );
|
36 |
+
|
37 |
+
// Ignore dupes from `WP_Query->set_found_posts()`
|
38 |
+
unset( $this->data['dupes']['SELECT FOUND_ROWS()'] );
|
39 |
+
|
40 |
+
$stacks = array();
|
41 |
+
$tops = array();
|
42 |
+
$callers = array();
|
43 |
+
$components = array();
|
44 |
+
|
45 |
+
// Loop over all SQL queries that have dupes
|
46 |
+
foreach ( $this->data['dupes'] as $sql => $query_ids ) {
|
47 |
+
|
48 |
+
// Loop over each query
|
49 |
+
foreach ( $query_ids as $query_id ) {
|
50 |
+
|
51 |
+
if ( isset( $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['trace'] ) ) {
|
52 |
+
|
53 |
+
$trace = $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['trace'];
|
54 |
+
$stack = wp_list_pluck( $trace->get_filtered_trace(), 'id' );
|
55 |
+
$component = $trace->get_component();
|
56 |
+
|
57 |
+
// Populate the component counts for this query
|
58 |
+
if ( isset( $components[ $sql ][ $component->name ] ) ) {
|
59 |
+
$components[ $sql ][ $component->name ]++;
|
60 |
+
} else {
|
61 |
+
$components[ $sql ][ $component->name ] = 1;
|
62 |
+
}
|
63 |
+
|
64 |
+
} else {
|
65 |
+
$stack = array_reverse( explode( ', ', $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['stack'] ) );
|
66 |
+
}
|
67 |
+
|
68 |
+
// Populate the caller counts for this query
|
69 |
+
if ( isset( $callers[ $sql ][ $stack[0] ] ) ) {
|
70 |
+
$callers[ $sql ][ $stack[0] ]++;
|
71 |
+
} else {
|
72 |
+
$callers[ $sql ][ $stack[0] ] = 1;
|
73 |
+
}
|
74 |
+
|
75 |
+
// Populate the stack for this query
|
76 |
+
$stacks[ $sql ][] = $stack;
|
77 |
+
|
78 |
+
}
|
79 |
+
|
80 |
+
// Get the callers which are common to all stacks for this query
|
81 |
+
$common = call_user_func_array( 'array_intersect', $stacks[ $sql ] );
|
82 |
+
|
83 |
+
// Remove callers which are common to all stacks for this query
|
84 |
+
foreach ( $stacks[ $sql ] as $i => $stack ) {
|
85 |
+
$stacks[ $sql ][ $i ] = array_values( array_diff( $stack, $common ) );
|
86 |
+
|
87 |
+
// No uncommon callers within the stack? Just use the topmost caller.
|
88 |
+
if ( empty( $stacks[ $sql ][ $i ] ) ) {
|
89 |
+
$stacks[ $sql ][ $i ] = array_keys( $callers[ $sql ] );
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
// Wave a magic wand
|
94 |
+
$sources[ $sql ] = array_count_values( wp_list_pluck( $stacks[ $sql ], 0 ) );
|
95 |
+
|
96 |
+
}
|
97 |
+
|
98 |
+
if ( ! empty( $sources ) ) {
|
99 |
+
$this->data['dupe_sources'] = $sources;
|
100 |
+
$this->data['dupe_callers'] = $callers;
|
101 |
+
$this->data['dupe_components'] = $components;
|
102 |
+
}
|
103 |
+
|
104 |
+
}
|
105 |
+
|
106 |
+
public function _filter_dupe_queries( $queries ) {
|
107 |
+
return ( count( $queries ) > 1 );
|
108 |
+
}
|
109 |
+
|
110 |
+
}
|
111 |
+
|
112 |
+
function register_qm_collector_db_dupes( array $collectors, QueryMonitor $qm ) {
|
113 |
+
$collectors['db_dupes'] = new QM_Collector_DB_Dupes;
|
114 |
+
return $collectors;
|
115 |
+
}
|
116 |
+
|
117 |
+
add_filter( 'qm/collectors', 'register_qm_collector_db_dupes', 25, 2 );
|
collectors/db_queries.php
CHANGED
@@ -101,6 +101,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
101 |
$total_time = 0;
|
102 |
$has_result = false;
|
103 |
$has_trace = false;
|
|
|
104 |
|
105 |
foreach ( (array) $db->queries as $query ) {
|
106 |
|
@@ -159,6 +160,8 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
159 |
$this->log_type( $type );
|
160 |
$this->log_caller( $caller_name, $ltime, $type );
|
161 |
|
|
|
|
|
162 |
if ( $component ) {
|
163 |
$this->log_component( $component, $ltime, $type );
|
164 |
}
|
@@ -185,7 +188,8 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
185 |
$this->data['expensive'][] = $row;
|
186 |
}
|
187 |
|
188 |
-
$rows[] = $row;
|
|
|
189 |
|
190 |
}
|
191 |
|
101 |
$total_time = 0;
|
102 |
$has_result = false;
|
103 |
$has_trace = false;
|
104 |
+
$i = 0;
|
105 |
|
106 |
foreach ( (array) $db->queries as $query ) {
|
107 |
|
160 |
$this->log_type( $type );
|
161 |
$this->log_caller( $caller_name, $ltime, $type );
|
162 |
|
163 |
+
$this->maybe_log_dupe( $sql, $i );
|
164 |
+
|
165 |
if ( $component ) {
|
166 |
$this->log_component( $component, $ltime, $type );
|
167 |
}
|
188 |
$this->data['expensive'][] = $row;
|
189 |
}
|
190 |
|
191 |
+
$rows[ $i ] = $row;
|
192 |
+
$i++;
|
193 |
|
194 |
}
|
195 |
|
collectors/overview.php
CHANGED
@@ -44,6 +44,7 @@ class QM_Collector_Overview extends QM_Collector {
|
|
44 |
$this->data['memory_limit'] = QM_Util::convert_hr_to_bytes( ini_get( 'memory_limit' ) );
|
45 |
$this->data['memory_usage'] = ( 100 / $this->data['memory_limit'] ) * $this->data['memory'];
|
46 |
|
|
|
47 |
}
|
48 |
|
49 |
}
|
44 |
$this->data['memory_limit'] = QM_Util::convert_hr_to_bytes( ini_get( 'memory_limit' ) );
|
45 |
$this->data['memory_usage'] = ( 100 / $this->data['memory_limit'] ) * $this->data['memory'];
|
46 |
|
47 |
+
$this->data['is_admin'] = is_admin();
|
48 |
}
|
49 |
|
50 |
}
|
collectors/php_errors.php
CHANGED
@@ -49,9 +49,6 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
49 |
|
50 |
public function error_handler( $errno, $message, $file = null, $line = null ) {
|
51 |
|
52 |
-
#if ( !( error_reporting() & $errno ) )
|
53 |
-
# return false;
|
54 |
-
|
55 |
switch ( $errno ) {
|
56 |
|
57 |
case E_WARNING:
|
@@ -79,35 +76,31 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
79 |
|
80 |
}
|
81 |
|
82 |
-
if (
|
|
|
|
|
83 |
|
84 |
-
|
85 |
-
|
86 |
-
|
|
|
|
|
87 |
|
88 |
-
|
89 |
-
'ignore_current_filter' => false,
|
90 |
-
) );
|
91 |
-
$caller = $trace->get_caller();
|
92 |
-
$key = md5( $message . $file . $line . $caller['id'] );
|
93 |
-
|
94 |
-
$filename = QM_Util::standard_dir( $file, '' );
|
95 |
-
|
96 |
-
if ( isset( $this->data['errors'][$type][$key] ) ) {
|
97 |
-
$this->data['errors'][$type][$key]->calls++;
|
98 |
-
} else {
|
99 |
-
$this->data['errors'][$type][$key] = (object) array(
|
100 |
-
'errno' => $errno,
|
101 |
-
'type' => $type,
|
102 |
-
'message' => $message,
|
103 |
-
'file' => $file,
|
104 |
-
'filename' => $filename,
|
105 |
-
'line' => $line,
|
106 |
-
'trace' => $trace,
|
107 |
-
'calls' => 1
|
108 |
-
);
|
109 |
-
}
|
110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
}
|
112 |
|
113 |
return apply_filters( 'qm/collect/php_errors_return_value', false );
|
49 |
|
50 |
public function error_handler( $errno, $message, $file = null, $line = null ) {
|
51 |
|
|
|
|
|
|
|
52 |
switch ( $errno ) {
|
53 |
|
54 |
case E_WARNING:
|
76 |
|
77 |
}
|
78 |
|
79 |
+
if ( ! class_exists( 'QM_Backtrace' ) ) {
|
80 |
+
return false;
|
81 |
+
}
|
82 |
|
83 |
+
$trace = new QM_Backtrace( array(
|
84 |
+
'ignore_current_filter' => false,
|
85 |
+
) );
|
86 |
+
$caller = $trace->get_caller();
|
87 |
+
$key = md5( $message . $file . $line . $caller['id'] );
|
88 |
|
89 |
+
$filename = QM_Util::standard_dir( $file, '' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
+
if ( isset( $this->data['errors'][$type][$key] ) ) {
|
92 |
+
$this->data['errors'][$type][$key]->calls++;
|
93 |
+
} else {
|
94 |
+
$this->data['errors'][$type][$key] = (object) array(
|
95 |
+
'errno' => $errno,
|
96 |
+
'type' => $type,
|
97 |
+
'message' => $message,
|
98 |
+
'file' => $file,
|
99 |
+
'filename' => $filename,
|
100 |
+
'line' => $line,
|
101 |
+
'trace' => $trace,
|
102 |
+
'calls' => 1
|
103 |
+
);
|
104 |
}
|
105 |
|
106 |
return apply_filters( 'qm/collect/php_errors_return_value', false );
|
collectors/request.php
CHANGED
@@ -133,6 +133,8 @@ class QM_Collector_Request extends QM_Collector {
|
|
133 |
$this->data['queried_object']['data'] = $qo;
|
134 |
}
|
135 |
|
|
|
|
|
136 |
}
|
137 |
|
138 |
}
|
133 |
$this->data['queried_object']['data'] = $qo;
|
134 |
}
|
135 |
|
136 |
+
$this->data['request_method'] = strtoupper( $_SERVER['REQUEST_METHOD'] );
|
137 |
+
|
138 |
}
|
139 |
|
140 |
}
|
collectors/theme.php
CHANGED
@@ -49,7 +49,7 @@ class QM_Collector_Theme extends QM_Collector {
|
|
49 |
|
50 |
$template_file = str_replace( array( $stylesheet_directory, $template_directory ), '', $template_path );
|
51 |
$template_file = ltrim( $template_file, '/' );
|
52 |
-
$theme_template_file = str_replace( $theme_directory, '', $template_path );
|
53 |
$theme_template_file = ltrim( $theme_template_file, '/' );
|
54 |
|
55 |
$this->data['template_path'] = $template_path;
|
49 |
|
50 |
$template_file = str_replace( array( $stylesheet_directory, $template_directory ), '', $template_path );
|
51 |
$template_file = ltrim( $template_file, '/' );
|
52 |
+
$theme_template_file = str_replace( array( $theme_directory, ABSPATH ), '', $template_path );
|
53 |
$theme_template_file = ltrim( $theme_template_file, '/' );
|
54 |
|
55 |
$this->data['template_path'] = $template_path;
|
dispatchers/Html.php
CHANGED
@@ -31,6 +31,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
31 |
add_action( 'wp_footer', array( $this, 'action_footer' ) );
|
32 |
add_action( 'admin_footer', array( $this, 'action_footer' ) );
|
33 |
add_action( 'login_footer', array( $this, 'action_footer' ) );
|
|
|
34 |
|
35 |
parent::__construct( $qm );
|
36 |
|
@@ -122,6 +123,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
122 |
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
123 |
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
124 |
add_action( 'login_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
|
|
125 |
add_action( 'send_headers', 'nocache_headers' );
|
126 |
|
127 |
}
|
@@ -202,7 +204,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
202 |
'qm-no-js',
|
203 |
);
|
204 |
|
205 |
-
if (
|
206 |
$absolute = function_exists( 'twentyfifteen_setup' );
|
207 |
if ( apply_filters( 'qm/output/absolute_position', $absolute ) ) {
|
208 |
$class[] = 'qm-absolute';
|
@@ -224,7 +226,9 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
224 |
|
225 |
protected function after_output() {
|
226 |
|
227 |
-
|
|
|
|
|
228 |
echo '<table cellspacing="0">';
|
229 |
echo '<thead>';
|
230 |
echo '<tr>';
|
31 |
add_action( 'wp_footer', array( $this, 'action_footer' ) );
|
32 |
add_action( 'admin_footer', array( $this, 'action_footer' ) );
|
33 |
add_action( 'login_footer', array( $this, 'action_footer' ) );
|
34 |
+
add_action( 'embed_footer', array( $this, 'action_footer' ) );
|
35 |
|
36 |
parent::__construct( $qm );
|
37 |
|
123 |
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
124 |
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
125 |
add_action( 'login_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
126 |
+
add_action( 'enqueue_embed_scripts', array( $this, 'enqueue_assets' ) );
|
127 |
add_action( 'send_headers', 'nocache_headers' );
|
128 |
|
129 |
}
|
204 |
'qm-no-js',
|
205 |
);
|
206 |
|
207 |
+
if ( did_action( 'wp_head' ) ) {
|
208 |
$absolute = function_exists( 'twentyfifteen_setup' );
|
209 |
if ( apply_filters( 'qm/output/absolute_position', $absolute ) ) {
|
210 |
$class[] = 'qm-absolute';
|
226 |
|
227 |
protected function after_output() {
|
228 |
|
229 |
+
$collectors = QM_Collectors::init();
|
230 |
+
|
231 |
+
echo '<div class="qm qm-half qm-clear" id="qm-authentication">';
|
232 |
echo '<table cellspacing="0">';
|
233 |
echo '<thead>';
|
234 |
echo '<tr>';
|
output/html/assets.php
CHANGED
@@ -63,7 +63,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
63 |
) as $position => $position_label ) {
|
64 |
|
65 |
if ( isset( $data[ $position ][ $type ] ) ) {
|
66 |
-
$this->dependency_rows( $data[ $position ][ $type ], $data['raw'][ $type ], sprintf( $position_label, $type_label ) );
|
67 |
}
|
68 |
|
69 |
}
|
@@ -77,7 +77,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
77 |
|
78 |
}
|
79 |
|
80 |
-
protected function dependency_rows( array $handles, WP_Dependencies $dependencies, $label ) {
|
81 |
|
82 |
$first = true;
|
83 |
|
@@ -92,9 +92,9 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
92 |
foreach ( $handles as $handle ) {
|
93 |
|
94 |
if ( in_array( $handle, $dependencies->done ) ) {
|
95 |
-
echo '<tr data-qm-subject="' . esc_attr( $handle ) . '">';
|
96 |
} else {
|
97 |
-
echo '<tr data-qm-subject="' . esc_attr( $handle ) . '" class="qm-warn">';
|
98 |
}
|
99 |
|
100 |
if ( $first ) {
|
@@ -102,7 +102,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
102 |
echo '<th rowspan="' . esc_attr( $rowspan ) . '" class="qm-nowrap">' . esc_html( $label ) . '</th>';
|
103 |
}
|
104 |
|
105 |
-
$this->dependency_row( $dependencies->query( $handle ), $dependencies );
|
106 |
|
107 |
echo '</tr>';
|
108 |
$first = false;
|
@@ -110,12 +110,12 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
110 |
|
111 |
}
|
112 |
|
113 |
-
protected function dependency_row( _WP_Dependency $
|
114 |
|
115 |
-
if ( empty( $
|
116 |
$ver = '';
|
117 |
} else {
|
118 |
-
$ver = $
|
119 |
}
|
120 |
|
121 |
/**
|
@@ -124,7 +124,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
124 |
* @param string $src Script loader source path.
|
125 |
* @param string $handle Script handle.
|
126 |
*/
|
127 |
-
$source = apply_filters( 'script_loader_src', $
|
128 |
|
129 |
if ( is_wp_error( $source ) ) {
|
130 |
$src = $source->get_error_message();
|
@@ -137,8 +137,8 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
137 |
$src = $source;
|
138 |
}
|
139 |
|
140 |
-
$dependents = self::get_dependents( $
|
141 |
-
$deps = $
|
142 |
sort( $deps );
|
143 |
|
144 |
foreach ( $deps as & $dep ) {
|
@@ -147,7 +147,12 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
147 |
}
|
148 |
}
|
149 |
|
150 |
-
|
|
|
|
|
|
|
|
|
|
|
151 |
if ( is_wp_error( $source ) ) {
|
152 |
printf( '<span class="qm-warn">%s</span>',
|
153 |
esc_html( $src )
|
@@ -156,13 +161,17 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
156 |
echo esc_html( $src );
|
157 |
}
|
158 |
echo '</span></td>';
|
159 |
-
echo '<td class="qm-nowrap qm-highlighter" data-qm-highlight="' . esc_attr( implode( ' ', $
|
160 |
-
echo '<td class="qm-nowrap qm-highlighter" data-qm-highlight="' . esc_attr( implode( ' ', $
|
161 |
echo '<td>' . esc_html( $ver ) . '</td>';
|
162 |
|
163 |
}
|
164 |
|
165 |
-
|
|
|
|
|
|
|
|
|
166 |
|
167 |
// @TODO move this into the collector
|
168 |
$dependents = array();
|
@@ -170,7 +179,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
|
|
170 |
|
171 |
foreach ( $handles as $handle ) {
|
172 |
if ( $item = $dependencies->query( $handle ) ) {
|
173 |
-
if ( in_array( $
|
174 |
$dependents[] = $handle;
|
175 |
}
|
176 |
}
|
63 |
) as $position => $position_label ) {
|
64 |
|
65 |
if ( isset( $data[ $position ][ $type ] ) ) {
|
66 |
+
$this->dependency_rows( $data[ $position ][ $type ], $data['raw'][ $type ], sprintf( $position_label, $type_label ), $type );
|
67 |
}
|
68 |
|
69 |
}
|
77 |
|
78 |
}
|
79 |
|
80 |
+
protected function dependency_rows( array $handles, WP_Dependencies $dependencies, $label, $type ) {
|
81 |
|
82 |
$first = true;
|
83 |
|
92 |
foreach ( $handles as $handle ) {
|
93 |
|
94 |
if ( in_array( $handle, $dependencies->done ) ) {
|
95 |
+
echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '">';
|
96 |
} else {
|
97 |
+
echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" class="qm-warn">';
|
98 |
}
|
99 |
|
100 |
if ( $first ) {
|
102 |
echo '<th rowspan="' . esc_attr( $rowspan ) . '" class="qm-nowrap">' . esc_html( $label ) . '</th>';
|
103 |
}
|
104 |
|
105 |
+
$this->dependency_row( $dependencies->query( $handle ), $dependencies, $type );
|
106 |
|
107 |
echo '</tr>';
|
108 |
$first = false;
|
110 |
|
111 |
}
|
112 |
|
113 |
+
protected function dependency_row( _WP_Dependency $dependency, WP_Dependencies $dependencies, $type ) {
|
114 |
|
115 |
+
if ( empty( $dependency->ver ) ) {
|
116 |
$ver = '';
|
117 |
} else {
|
118 |
+
$ver = $dependency->ver;
|
119 |
}
|
120 |
|
121 |
/**
|
124 |
* @param string $src Script loader source path.
|
125 |
* @param string $handle Script handle.
|
126 |
*/
|
127 |
+
$source = apply_filters( 'script_loader_src', $dependency->src, $dependency->handle );
|
128 |
|
129 |
if ( is_wp_error( $source ) ) {
|
130 |
$src = $source->get_error_message();
|
137 |
$src = $source;
|
138 |
}
|
139 |
|
140 |
+
$dependents = self::get_dependents( $dependency, $dependencies, $type );
|
141 |
+
$deps = $dependency->deps;
|
142 |
sort( $deps );
|
143 |
|
144 |
foreach ( $deps as & $dep ) {
|
147 |
}
|
148 |
}
|
149 |
|
150 |
+
$this->type = $type;
|
151 |
+
|
152 |
+
$highlight_deps = array_map( array( $this, '_prefix_type' ), $deps );
|
153 |
+
$highlight_dependents = array_map( array( $this, '_prefix_type' ), $dependents );
|
154 |
+
|
155 |
+
echo '<td class="qm-wrap">' . esc_html( $dependency->handle ) . '<br><span class="qm-info"> ';
|
156 |
if ( is_wp_error( $source ) ) {
|
157 |
printf( '<span class="qm-warn">%s</span>',
|
158 |
esc_html( $src )
|
161 |
echo esc_html( $src );
|
162 |
}
|
163 |
echo '</span></td>';
|
164 |
+
echo '<td class="qm-nowrap qm-highlighter" data-qm-highlight="' . esc_attr( implode( ' ', $highlight_deps ) ) . '">' . implode( '<br>', array_map( 'esc_html', $deps ) ) . '</td>';
|
165 |
+
echo '<td class="qm-nowrap qm-highlighter" data-qm-highlight="' . esc_attr( implode( ' ', $highlight_dependents ) ) . '">' . implode( '<br>', array_map( 'esc_html', $dependents ) ) . '</td>';
|
166 |
echo '<td>' . esc_html( $ver ) . '</td>';
|
167 |
|
168 |
}
|
169 |
|
170 |
+
public function _prefix_type( $val ) {
|
171 |
+
return $this->type . '-' . $val;
|
172 |
+
}
|
173 |
+
|
174 |
+
protected static function get_dependents( _WP_Dependency $dependency, WP_Dependencies $dependencies, $type ) {
|
175 |
|
176 |
// @TODO move this into the collector
|
177 |
$dependents = array();
|
179 |
|
180 |
foreach ( $handles as $handle ) {
|
181 |
if ( $item = $dependencies->query( $handle ) ) {
|
182 |
+
if ( in_array( $dependency->handle, $item->deps ) ) {
|
183 |
$dependents[] = $handle;
|
184 |
}
|
185 |
}
|
output/html/db_dupes.php
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
Copyright 2009-2015 John Blackbourn
|
4 |
+
|
5 |
+
This program is free software; you can redistribute it and/or modify
|
6 |
+
it under the terms of the GNU General Public License as published by
|
7 |
+
the Free Software Foundation; either version 2 of the License, or
|
8 |
+
(at your option) any later version.
|
9 |
+
|
10 |
+
This program is distributed in the hope that it will be useful,
|
11 |
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
+
GNU General Public License for more details.
|
14 |
+
|
15 |
+
*/
|
16 |
+
|
17 |
+
class QM_Output_Html_DB_Dupes extends QM_Output_Html {
|
18 |
+
|
19 |
+
public function __construct( QM_Collector $collector ) {
|
20 |
+
parent::__construct( $collector );
|
21 |
+
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 45 );
|
22 |
+
}
|
23 |
+
|
24 |
+
public function output() {
|
25 |
+
|
26 |
+
$data = $this->collector->get_data();
|
27 |
+
|
28 |
+
if ( empty( $data['dupes'] ) ) {
|
29 |
+
return;
|
30 |
+
}
|
31 |
+
|
32 |
+
$colspan = empty( $data['dupe_components'] ) ? 4 : 5;
|
33 |
+
|
34 |
+
echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
|
35 |
+
echo '<table cellspacing="0">';
|
36 |
+
echo '<thead>';
|
37 |
+
echo '<tr>';
|
38 |
+
echo '<th colspan="' . absint( $colspan ) . '">' . esc_html( $this->collector->name() ) . '</th>';
|
39 |
+
echo '</tr>';
|
40 |
+
|
41 |
+
echo '<tr>';
|
42 |
+
echo '<th>' . esc_html__( 'Query', 'query-monitor' ) . '</th>';
|
43 |
+
echo '<th class="qm-num">' . esc_html__( 'Count', 'query-monitor' ) . '</th>';
|
44 |
+
echo '<th>' . esc_html__( 'Callers', 'query-monitor' ) . '</th>';
|
45 |
+
if ( ! empty( $data['dupe_components'] ) ) {
|
46 |
+
echo '<th>' . esc_html__( 'Components', 'query-monitor' ) . '</th>';
|
47 |
+
}
|
48 |
+
echo '<th>' . esc_html__( 'Potential Troublemakers', 'query-monitor' ) . '</th>';
|
49 |
+
echo '</tr>';
|
50 |
+
|
51 |
+
echo '</thead>';
|
52 |
+
|
53 |
+
echo '<tbody>';
|
54 |
+
|
55 |
+
foreach ( $data['dupes'] as $sql => $queries ) {
|
56 |
+
echo '<tr>';
|
57 |
+
echo '<td>';
|
58 |
+
echo self::format_sql( $sql ); // WPCS: XSS ok;
|
59 |
+
echo '</td>';
|
60 |
+
echo '<td class="qm-num">';
|
61 |
+
echo esc_html( number_format_i18n( count( $queries ), 0 ) );
|
62 |
+
echo '</td>';
|
63 |
+
echo '<td class="qm-nowrap qm-ltr">';
|
64 |
+
foreach ( $data['dupe_callers'][ $sql ] as $caller => $calls ) {
|
65 |
+
printf(
|
66 |
+
'<a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="%s">%s</a><br><span class="qm-info"> %s</span><br>',
|
67 |
+
esc_attr( $caller ),
|
68 |
+
esc_html( $caller ),
|
69 |
+
esc_html( sprintf(
|
70 |
+
_n( '%s call', '%s calls', $calls, 'query-monitor' ),
|
71 |
+
number_format_i18n( $calls )
|
72 |
+
) )
|
73 |
+
);
|
74 |
+
}
|
75 |
+
echo '</td>';
|
76 |
+
if ( isset( $data['dupe_components'][ $sql ] ) ) {
|
77 |
+
echo '<td class="qm-nowrap">';
|
78 |
+
foreach ( $data['dupe_components'][ $sql ] as $component => $calls ) {
|
79 |
+
printf(
|
80 |
+
'%s<br><span class="qm-info"> %s</span><br>',
|
81 |
+
esc_html( $component ),
|
82 |
+
esc_html( sprintf(
|
83 |
+
_n( '%s call', '%s calls', $calls, 'query-monitor' ),
|
84 |
+
number_format_i18n( $calls )
|
85 |
+
) )
|
86 |
+
);
|
87 |
+
}
|
88 |
+
echo '</td>';
|
89 |
+
}
|
90 |
+
echo '<td class="qm-nowrap qm-ltr">';
|
91 |
+
foreach ( $data['dupe_sources'][ $sql ] as $source => $calls ) {
|
92 |
+
printf(
|
93 |
+
'%s<br><span class="qm-info"> %s</span><br>',
|
94 |
+
esc_html( $source ),
|
95 |
+
esc_html( sprintf(
|
96 |
+
_n( '%s call', '%s calls', $calls, 'query-monitor' ),
|
97 |
+
number_format_i18n( $calls )
|
98 |
+
) )
|
99 |
+
);
|
100 |
+
}
|
101 |
+
echo '</td>';
|
102 |
+
echo '</tr>';
|
103 |
+
}
|
104 |
+
echo '</tbody>';
|
105 |
+
|
106 |
+
echo '</table>';
|
107 |
+
echo '</div>';
|
108 |
+
|
109 |
+
}
|
110 |
+
|
111 |
+
public function admin_menu( array $menu ) {
|
112 |
+
|
113 |
+
if ( $dbq = QM_Collectors::get( 'db_dupes' ) ) {
|
114 |
+
$dbq_data = $dbq->get_data();
|
115 |
+
if ( isset( $dbq_data['dupes'] ) && count( $dbq_data['dupes'] ) ) {
|
116 |
+
$menu[] = $this->menu( array(
|
117 |
+
'title' => esc_html( sprintf(
|
118 |
+
__( 'Duplicate Queries (%s)', 'query-monitor' ),
|
119 |
+
count( $dbq_data['dupes'] )
|
120 |
+
) ),
|
121 |
+
) );
|
122 |
+
}
|
123 |
+
}
|
124 |
+
return $menu;
|
125 |
+
|
126 |
+
}
|
127 |
+
|
128 |
+
}
|
129 |
+
|
130 |
+
function register_qm_output_html_db_dupes( array $output, QM_Collectors $collectors ) {
|
131 |
+
if ( $collector = QM_Collectors::get( 'db_dupes' ) ) {
|
132 |
+
$output['db_dupes'] = new QM_Output_Html_DB_Dupes( $collector );
|
133 |
+
}
|
134 |
+
return $output;
|
135 |
+
}
|
136 |
+
|
137 |
+
add_filter( 'qm/outputter/html', 'register_qm_output_html_db_dupes', 45, 2 );
|
output/html/db_queries.php
CHANGED
@@ -352,9 +352,10 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
352 |
}
|
353 |
|
354 |
if ( isset( $cols['sql'] ) ) {
|
355 |
-
printf(
|
|
|
356 |
$sql
|
357 |
-
);
|
358 |
}
|
359 |
|
360 |
if ( isset( $cols['caller'] ) ) {
|
@@ -402,9 +403,10 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
402 |
$data = $this->collector->get_data();
|
403 |
|
404 |
if ( isset( $data['dbs'] ) ) {
|
405 |
-
foreach ( $data['dbs'] as $db ) {
|
406 |
$title[] = sprintf(
|
407 |
-
_x( '%s<small>S</small>', 'database query time', 'query-monitor' ),
|
|
|
408 |
number_format_i18n( $db->total_time, 4 )
|
409 |
);
|
410 |
$title[] = sprintf(
|
352 |
}
|
353 |
|
354 |
if ( isset( $cols['sql'] ) ) {
|
355 |
+
printf( // WPCS: XSS ok.
|
356 |
+
'<td class="qm-row-sql qm-ltr qm-wrap">%s</td>',
|
357 |
$sql
|
358 |
+
);
|
359 |
}
|
360 |
|
361 |
if ( isset( $cols['caller'] ) ) {
|
403 |
$data = $this->collector->get_data();
|
404 |
|
405 |
if ( isset( $data['dbs'] ) ) {
|
406 |
+
foreach ( $data['dbs'] as $key => $db ) {
|
407 |
$title[] = sprintf(
|
408 |
+
_x( '%s%s<small>S</small>', 'database query time', 'query-monitor' ),
|
409 |
+
( count( $data['dbs'] ) > 1 ? '• ' : '' ),
|
410 |
number_format_i18n( $db->total_time, 4 )
|
411 |
);
|
412 |
$title[] = sprintf(
|
output/html/environment.php
CHANGED
@@ -27,7 +27,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
27 |
|
28 |
echo '<div id="' . esc_attr( $this->collector->id() ) . '">';
|
29 |
|
30 |
-
echo '<div class="qm qm-
|
31 |
echo '<table cellspacing="0">';
|
32 |
echo '<thead>';
|
33 |
echo '<tr>';
|
@@ -66,7 +66,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
66 |
|
67 |
echo '<tr>';
|
68 |
echo '<td>' . esc_html( $key ) . '</td>';
|
69 |
-
echo '<td>';
|
70 |
echo esc_html( $val['after'] );
|
71 |
|
72 |
if ( $val['after'] !== $val['before'] ) {
|
@@ -87,7 +87,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
87 |
|
88 |
echo '<tr>';
|
89 |
echo '<td>error_reporting</td>';
|
90 |
-
echo '<td>' . esc_html( $data['php']['error_reporting'] ) . '<br><span class="qm-info"> ';
|
91 |
echo $error_levels; // WPCS: XSS ok.
|
92 |
echo '</span></td>';
|
93 |
echo '</tr>';
|
@@ -106,7 +106,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
106 |
$name = sprintf( __( 'Database: %s', 'query-monitor' ), $id );
|
107 |
}
|
108 |
|
109 |
-
echo '<div class="qm qm-
|
110 |
echo '<table cellspacing="0">';
|
111 |
echo '<thead>';
|
112 |
echo '<tr>';
|
@@ -123,7 +123,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
123 |
if ( ! isset( $value ) ) {
|
124 |
echo '<td><span class="qm-warn">' . esc_html__( 'Unknown', 'query-monitor' ) . '</span></td>';
|
125 |
} else {
|
126 |
-
echo '<td>' . esc_html( $value ) . '</td>';
|
127 |
}
|
128 |
|
129 |
echo '</tr>';
|
@@ -170,7 +170,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
170 |
}
|
171 |
|
172 |
echo '<td>' . esc_html( $key ) . '</td>';
|
173 |
-
echo '<td>';
|
174 |
echo esc_html( $val );
|
175 |
echo $append; // WPCS: XSS ok.
|
176 |
echo '</td>';
|
@@ -189,7 +189,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
189 |
|
190 |
}
|
191 |
|
192 |
-
echo '<div class="qm qm-
|
193 |
echo '<table cellspacing="0">';
|
194 |
echo '<thead>';
|
195 |
echo '<tr>';
|
@@ -202,7 +202,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
202 |
|
203 |
echo '<tr>';
|
204 |
echo '<td>' . esc_html( $key ) . '</td>';
|
205 |
-
echo '<td>' . esc_html( $val ) . '</td>';
|
206 |
echo '</tr>';
|
207 |
|
208 |
}
|
@@ -211,7 +211,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
211 |
echo '</table>';
|
212 |
echo '</div>';
|
213 |
|
214 |
-
echo '<div class="qm qm-
|
215 |
echo '<table cellspacing="0">';
|
216 |
echo '<thead>';
|
217 |
echo '<tr>';
|
@@ -222,13 +222,13 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
222 |
|
223 |
echo '<tr>';
|
224 |
echo '<td>' . esc_html__( 'software', 'query-monitor' ) . '</td>';
|
225 |
-
echo '<td>' . esc_html( $data['server']['name'] ) . '</td>';
|
226 |
echo '</tr>';
|
227 |
|
228 |
echo '<tr>';
|
229 |
echo '<td>' . esc_html__( 'version', 'query-monitor' ) . '</td>';
|
230 |
if ( !empty( $data['server']['version'] ) ) {
|
231 |
-
echo '<td>' . esc_html( $data['server']['version'] ) . '</td>';
|
232 |
} else {
|
233 |
echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
|
234 |
}
|
@@ -237,7 +237,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
237 |
echo '<tr>';
|
238 |
echo '<td>' . esc_html__( 'address', 'query-monitor' ) . '</td>';
|
239 |
if ( !empty( $data['server']['address'] ) ) {
|
240 |
-
echo '<td>' . esc_html( $data['server']['address'] ) . '</td>';
|
241 |
} else {
|
242 |
echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
|
243 |
}
|
@@ -245,7 +245,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
245 |
|
246 |
echo '<tr>';
|
247 |
echo '<td>' . esc_html__( 'host', 'query-monitor' ) . '</td>';
|
248 |
-
echo '<td>' . esc_html( $data['server']['host'] ) . '</td>';
|
249 |
echo '</tr>';
|
250 |
|
251 |
echo '</tbody>';
|
27 |
|
28 |
echo '<div id="' . esc_attr( $this->collector->id() ) . '">';
|
29 |
|
30 |
+
echo '<div class="qm qm-third">';
|
31 |
echo '<table cellspacing="0">';
|
32 |
echo '<thead>';
|
33 |
echo '<tr>';
|
66 |
|
67 |
echo '<tr>';
|
68 |
echo '<td>' . esc_html( $key ) . '</td>';
|
69 |
+
echo '<td class="qm-wrap">';
|
70 |
echo esc_html( $val['after'] );
|
71 |
|
72 |
if ( $val['after'] !== $val['before'] ) {
|
87 |
|
88 |
echo '<tr>';
|
89 |
echo '<td>error_reporting</td>';
|
90 |
+
echo '<td class="qm-wrap">' . esc_html( $data['php']['error_reporting'] ) . '<br><span class="qm-info"> ';
|
91 |
echo $error_levels; // WPCS: XSS ok.
|
92 |
echo '</span></td>';
|
93 |
echo '</tr>';
|
106 |
$name = sprintf( __( 'Database: %s', 'query-monitor' ), $id );
|
107 |
}
|
108 |
|
109 |
+
echo '<div class="qm qm-third">';
|
110 |
echo '<table cellspacing="0">';
|
111 |
echo '<thead>';
|
112 |
echo '<tr>';
|
123 |
if ( ! isset( $value ) ) {
|
124 |
echo '<td><span class="qm-warn">' . esc_html__( 'Unknown', 'query-monitor' ) . '</span></td>';
|
125 |
} else {
|
126 |
+
echo '<td class="qm-wrap">' . esc_html( $value ) . '</td>';
|
127 |
}
|
128 |
|
129 |
echo '</tr>';
|
170 |
}
|
171 |
|
172 |
echo '<td>' . esc_html( $key ) . '</td>';
|
173 |
+
echo '<td class="qm-wrap">';
|
174 |
echo esc_html( $val );
|
175 |
echo $append; // WPCS: XSS ok.
|
176 |
echo '</td>';
|
189 |
|
190 |
}
|
191 |
|
192 |
+
echo '<div class="qm qm-third" style="float:right !important">';
|
193 |
echo '<table cellspacing="0">';
|
194 |
echo '<thead>';
|
195 |
echo '<tr>';
|
202 |
|
203 |
echo '<tr>';
|
204 |
echo '<td>' . esc_html( $key ) . '</td>';
|
205 |
+
echo '<td class="qm-wrap">' . esc_html( $val ) . '</td>';
|
206 |
echo '</tr>';
|
207 |
|
208 |
}
|
211 |
echo '</table>';
|
212 |
echo '</div>';
|
213 |
|
214 |
+
echo '<div class="qm qm-third">';
|
215 |
echo '<table cellspacing="0">';
|
216 |
echo '<thead>';
|
217 |
echo '<tr>';
|
222 |
|
223 |
echo '<tr>';
|
224 |
echo '<td>' . esc_html__( 'software', 'query-monitor' ) . '</td>';
|
225 |
+
echo '<td class="qm-wrap">' . esc_html( $data['server']['name'] ) . '</td>';
|
226 |
echo '</tr>';
|
227 |
|
228 |
echo '<tr>';
|
229 |
echo '<td>' . esc_html__( 'version', 'query-monitor' ) . '</td>';
|
230 |
if ( !empty( $data['server']['version'] ) ) {
|
231 |
+
echo '<td class="qm-wrap">' . esc_html( $data['server']['version'] ) . '</td>';
|
232 |
} else {
|
233 |
echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
|
234 |
}
|
237 |
echo '<tr>';
|
238 |
echo '<td>' . esc_html__( 'address', 'query-monitor' ) . '</td>';
|
239 |
if ( !empty( $data['server']['address'] ) ) {
|
240 |
+
echo '<td class="qm-wrap">' . esc_html( $data['server']['address'] ) . '</td>';
|
241 |
} else {
|
242 |
echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
|
243 |
}
|
245 |
|
246 |
echo '<tr>';
|
247 |
echo '<td>' . esc_html__( 'host', 'query-monitor' ) . '</td>';
|
248 |
+
echo '<td class="qm-wrap">' . esc_html( $data['server']['host'] ) . '</td>';
|
249 |
echo '</tr>';
|
250 |
|
251 |
echo '</tbody>';
|
output/html/hooks.php
CHANGED
@@ -95,11 +95,11 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
|
|
95 |
$component = '';
|
96 |
}
|
97 |
|
98 |
-
printf(
|
99 |
'<tr data-qm-subject="%s" %s>',
|
100 |
esc_attr( $component ),
|
101 |
$attr
|
102 |
-
);
|
103 |
|
104 |
if ( $first ) {
|
105 |
|
95 |
$component = '';
|
96 |
}
|
97 |
|
98 |
+
printf( // WPCS: XSS ok.
|
99 |
'<tr data-qm-subject="%s" %s>',
|
100 |
esc_attr( $component ),
|
101 |
$attr
|
102 |
+
);
|
103 |
|
104 |
if ( $first ) {
|
105 |
|
output/html/http.php
CHANGED
@@ -122,20 +122,20 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
122 |
$attr .= ' ' . $a . '="' . esc_attr( $v ) . '"';
|
123 |
}
|
124 |
|
125 |
-
printf(
|
126 |
'<tr %s class="%s">',
|
127 |
$attr,
|
128 |
esc_attr( $css )
|
129 |
-
);
|
130 |
printf(
|
131 |
'<td class="qm-num">%s</td>',
|
132 |
intval( $i )
|
133 |
);
|
134 |
-
printf(
|
135 |
'<td class="qm-url qm-ltr qm-wrap">%s<br>%s</td>',
|
136 |
esc_html( $method ),
|
137 |
$url
|
138 |
-
);
|
139 |
printf(
|
140 |
'<td>%s</td>',
|
141 |
esc_html( $response )
|
@@ -144,10 +144,10 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
144 |
'<td>%s</td>',
|
145 |
esc_html( $transport )
|
146 |
);
|
147 |
-
printf(
|
148 |
'<td class="qm-nowrap qm-ltr">%s</td>',
|
149 |
implode( '<br>', $stack )
|
150 |
-
);
|
151 |
printf(
|
152 |
'<td class="qm-nowrap">%s</td>',
|
153 |
esc_html( $component->name )
|
122 |
$attr .= ' ' . $a . '="' . esc_attr( $v ) . '"';
|
123 |
}
|
124 |
|
125 |
+
printf( // WPCS: XSS ok.
|
126 |
'<tr %s class="%s">',
|
127 |
$attr,
|
128 |
esc_attr( $css )
|
129 |
+
);
|
130 |
printf(
|
131 |
'<td class="qm-num">%s</td>',
|
132 |
intval( $i )
|
133 |
);
|
134 |
+
printf( // WPCS: XSS ok.
|
135 |
'<td class="qm-url qm-ltr qm-wrap">%s<br>%s</td>',
|
136 |
esc_html( $method ),
|
137 |
$url
|
138 |
+
);
|
139 |
printf(
|
140 |
'<td>%s</td>',
|
141 |
esc_html( $response )
|
144 |
'<td>%s</td>',
|
145 |
esc_html( $transport )
|
146 |
);
|
147 |
+
printf( // WPCS: XSS ok.
|
148 |
'<td class="qm-nowrap qm-ltr">%s</td>',
|
149 |
implode( '<br>', $stack )
|
150 |
+
);
|
151 |
printf(
|
152 |
'<td class="qm-nowrap">%s</td>',
|
153 |
esc_html( $component->name )
|
output/html/languages.php
CHANGED
@@ -52,10 +52,10 @@ class QM_Output_Html_Languages extends QM_Output_Html {
|
|
52 |
echo '<tr>';
|
53 |
|
54 |
echo '<td>' . esc_html( $mofile['domain'] ) . '</td>';
|
55 |
-
echo '<td class="qm-nowrap">';
|
56 |
echo self::output_filename( $mofile['caller']['display'], $mofile['caller']['file'], $mofile['caller']['line'] ); // WPCS: XSS ok.
|
57 |
echo '</td>';
|
58 |
-
echo '<td>';
|
59 |
echo esc_html( QM_Util::standard_dir( $mofile['mofile'], '' ) );
|
60 |
echo '</td>';
|
61 |
|
52 |
echo '<tr>';
|
53 |
|
54 |
echo '<td>' . esc_html( $mofile['domain'] ) . '</td>';
|
55 |
+
echo '<td class="qm-nowrap qm-ltr">';
|
56 |
echo self::output_filename( $mofile['caller']['display'], $mofile['caller']['file'], $mofile['caller']['line'] ); // WPCS: XSS ok.
|
57 |
echo '</td>';
|
58 |
+
echo '<td class="qm-ltr">';
|
59 |
echo esc_html( QM_Util::standard_dir( $mofile['mofile'], '' ) );
|
60 |
echo '</td>';
|
61 |
|
output/html/transients.php
CHANGED
@@ -87,10 +87,10 @@ class QM_Output_Html_Transients extends QM_Output_Html {
|
|
87 |
$stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
|
88 |
}
|
89 |
|
90 |
-
printf(
|
91 |
'<td class="qm-nowrap qm-ltr">%s</td>',
|
92 |
implode( '<br>', $stack )
|
93 |
-
);
|
94 |
printf(
|
95 |
'<td class="qm-nowrap">%s</td>',
|
96 |
esc_html( $component->name )
|
87 |
$stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
|
88 |
}
|
89 |
|
90 |
+
printf( // WPCS: XSS ok.
|
91 |
'<td class="qm-nowrap qm-ltr">%s</td>',
|
92 |
implode( '<br>', $stack )
|
93 |
+
);
|
94 |
printf(
|
95 |
'<td class="qm-nowrap">%s</td>',
|
96 |
esc_html( $component->name )
|
query-monitor.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/*
|
3 |
Plugin Name: Query Monitor
|
4 |
Description: Monitoring of database queries, hooks, conditionals and more.
|
5 |
-
Version: 2.
|
6 |
Plugin URI: https://querymonitor.com/
|
7 |
Author: John Blackbourn
|
8 |
Author URI: https://johnblackbourn.com/
|
2 |
/*
|
3 |
Plugin Name: Query Monitor
|
4 |
Description: Monitoring of database queries, hooks, conditionals and more.
|
5 |
+
Version: 2.10.0
|
6 |
Plugin URI: https://querymonitor.com/
|
7 |
Author: John Blackbourn
|
8 |
Author URI: https://johnblackbourn.com/
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: johnbillion
|
3 |
Tags: ajax, debug, debug-bar, debugging, development, developer, performance, profiler, profiling, queries, query monitor, rest-api
|
4 |
Requires at least: 3.7
|
5 |
-
Tested up to: 4.
|
6 |
-
Stable tag: 2.
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
|
@@ -20,7 +20,7 @@ Here's an overview of what's shown:
|
|
20 |
|
21 |
* Shows all database queries performed on the current page
|
22 |
* Shows **affected rows** and time for all queries
|
23 |
-
*
|
24 |
* Filter queries by **query type** (`SELECT`, `UPDATE`, `DELETE`, etc)
|
25 |
* Filter queries by **component** (WordPress core, Plugin X, Plugin Y, theme)
|
26 |
* Filter queries by **calling function**
|
@@ -173,6 +173,16 @@ No, I do not accept donations. If you like the plugin, I'd love for you to [leav
|
|
173 |
|
174 |
== Changelog ==
|
175 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
= 2.9.1 =
|
177 |
|
178 |
* Query callers and query components can now be clicked to filter the main query list by that caller or component.
|
2 |
Contributors: johnbillion
|
3 |
Tags: ajax, debug, debug-bar, debugging, development, developer, performance, profiler, profiling, queries, query monitor, rest-api
|
4 |
Requires at least: 3.7
|
5 |
+
Tested up to: 4.5
|
6 |
+
Stable tag: 2.10.0
|
7 |
License: GPLv2 or later
|
8 |
|
9 |
View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
|
20 |
|
21 |
* Shows all database queries performed on the current page
|
22 |
* Shows **affected rows** and time for all queries
|
23 |
+
* Shows notifications for **slow queries**, **duplicate queries**, and **queries with errors**
|
24 |
* Filter queries by **query type** (`SELECT`, `UPDATE`, `DELETE`, etc)
|
25 |
* Filter queries by **component** (WordPress core, Plugin X, Plugin Y, theme)
|
26 |
* Filter queries by **calling function**
|
173 |
|
174 |
== Changelog ==
|
175 |
|
176 |
+
= 2.10.0 =
|
177 |
+
|
178 |
+
* Add a new panel which lists duplicated database queries.
|
179 |
+
* Add support for displaying QM's output when viewing an embed.
|
180 |
+
* Differentiate regular plugins from mu-plugins when displaying components.
|
181 |
+
* Ensure early errors are always reported regardless of system level error reporting.
|
182 |
+
* Ensure that script and style dependency highlighting is restricted to the scripts and styles tables, respectively.
|
183 |
+
* Rearrange the Environment section output a little.
|
184 |
+
* Various minor tweaks.
|
185 |
+
|
186 |
= 2.9.1 =
|
187 |
|
188 |
* Query callers and query components can now be clicked to filter the main query list by that caller or component.
|