Query Monitor - Version 2.17.0

Version Description

Download this release

Release Info

Developer johnbillion
Plugin Icon 128x128 Query Monitor
Version 2.17.0
Comparing to
See all releases

Code changes from version 2.16.2 to 2.17.0

Files changed (53) hide show
  1. assets/query-monitor.css +19 -25
  2. assets/query-monitor.js +74 -65
  3. classes/Activation.php +3 -6
  4. classes/Backtrace.php +20 -32
  5. classes/Collector.php +13 -13
  6. classes/Collectors.php +1 -1
  7. classes/Dispatcher.php +4 -4
  8. classes/Dispatchers.php +1 -1
  9. classes/QueryMonitor.php +34 -0
  10. classes/Util.php +7 -14
  11. classes/debug_bar.php +2 -2
  12. collectors/admin.php +6 -6
  13. collectors/assets.php +3 -6
  14. collectors/cache.php +0 -2
  15. collectors/caps.php +1 -1
  16. collectors/conditionals.php +2 -4
  17. collectors/db_dupes.php +0 -2
  18. collectors/db_queries.php +23 -24
  19. collectors/environment.php +9 -10
  20. collectors/hooks.php +7 -9
  21. collectors/http.php +15 -16
  22. collectors/languages.php +1 -2
  23. collectors/overview.php +2 -2
  24. collectors/php_errors.php +8 -5
  25. collectors/redirects.php +1 -1
  26. collectors/request.php +42 -21
  27. collectors/theme.php +5 -5
  28. collectors/transients.php +1 -1
  29. composer.json +2 -0
  30. dispatchers/Html.php +4 -9
  31. dispatchers/REST.php +1 -0
  32. dispatchers/Redirect.php +1 -0
  33. output/Html.php +13 -3
  34. output/headers/php_errors.php +0 -1
  35. output/html/assets.php +4 -5
  36. output/html/caps.php +1 -1
  37. output/html/conditionals.php +3 -1
  38. output/html/db_callers.php +4 -4
  39. output/html/db_components.php +4 -4
  40. output/html/db_queries.php +16 -17
  41. output/html/debug_bar.php +1 -1
  42. output/html/environment.php +11 -16
  43. output/html/hooks.php +3 -5
  44. output/html/http.php +6 -6
  45. output/html/overview.php +1 -1
  46. output/html/php_errors.php +7 -8
  47. output/html/request.php +47 -18
  48. output/html/rewrites.php +0 -2
  49. output/html/theme.php +0 -2
  50. output/html/transients.php +3 -3
  51. query-monitor.php +1 -1
  52. readme.txt +2 -2
  53. wp-content/db.php +4 -4
assets/query-monitor.css CHANGED
@@ -130,18 +130,15 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
130
 
131
  #qm {
132
  clear: both !important;
133
- background: #f1f1f1 !important;
134
  margin: 25px 0 0 !important;
135
  border-top: 1px solid #ccc !important;
136
  padding: 0 0 35px !important;
137
  text-align: left !important;
138
  min-width: 800px !important;
139
  display: none;
140
- }
141
-
142
- #qm.qm-absolute {
143
- z-index: 9999 !important;
144
- position: absolute !important;
145
  }
146
 
147
  #qm.qm-show,
@@ -218,7 +215,7 @@ body.wp-admin.folded #qm {
218
  display: inline-block !important;
219
  width: 24em !important;
220
  background: #fff !important;
221
- border: 1px solid #e8e8e8 !important;
222
  margin: 0 5px 5px 0 !important;
223
  }
224
 
@@ -306,8 +303,8 @@ body.wp-admin.folded #qm {
306
  font-size: 11px !important;
307
  line-height: 18px !important;
308
  font-family: Menlo, Monaco, Consolas, monospace !important;
309
- border: 1px solid #e8e8e8 !important;
310
- padding: 4px 6px 3px !important;
311
  vertical-align: top !important;
312
  text-shadow: none !important;
313
  text-transform: none !important;
@@ -358,7 +355,7 @@ body.wp-admin.folded #qm {
358
 
359
  .qm td.qm-has-toggle p,
360
  .qm td .qm-toggler {
361
- padding: 4px 20px 3px 6px !important;
362
  position: relative !important;
363
  }
364
 
@@ -372,7 +369,7 @@ body.wp-admin.folded #qm {
372
  }
373
 
374
  .qm .qm-inner-toggle {
375
- padding: 4px 6px 3px !important;
376
  }
377
 
378
  .qm-has-inner .qm-toggled > table {
@@ -521,31 +518,28 @@ body.wp-admin.folded #qm {
521
 
522
  .qm .qm-toggle,
523
  html[dir="rtl"] .qm .qm-ltr .qm-toggle {
524
- color: #0073aa !important;
525
- padding: 4px 9px 3px !important;
526
- border-top: none !important;
527
- border-right: none !important;
528
- border-left: 1px solid #e8e8e8 !important;
529
- border-bottom: 1px solid #e8e8e8 !important;
530
  font-style: normal !important;
531
- font-weight: normal !important;
532
  font-size: 11px !important;
533
  line-height: 18px !important;
534
  font-family: Menlo, Monaco, Consolas, monospace !important;
535
  position: absolute !important;
536
- top: 0 !important;
537
- right: 0 !important;
538
  left: auto !important;
539
- background: #fff !important;
540
  cursor: pointer !important;
541
  }
542
 
543
  .qm .qm-toggle:focus,
544
  .qm .qm-toggle:hover {
545
  text-decoration: none !important;
546
- border-color: #e8e8e8 !important;
547
  color: #0073aa !important;
548
- background: #eee !important;
549
  }
550
 
551
  .qm tr.error,
@@ -748,7 +742,7 @@ html[dir="rtl"] .qm .qm-ltr {
748
  }
749
 
750
  html[dir="rtl"] .qm .qm-toggle {
751
- border-right: 1px solid #e8e8e8 !important;
752
  border-left: none !important;
753
  right: auto !important;
754
  left: 1px !important;
@@ -768,7 +762,7 @@ html[dir="rtl"] .qm .qm-toggle {
768
  .qm-debug-bar textarea,
769
  .qm-debug-bar pre {
770
  padding: 10px !important;
771
- border: 1px solid #e8e8e8 !important;
772
  margin: 4px 0 !important;
773
  color: inherit !important;
774
  background: transparent !important;
130
 
131
  #qm {
132
  clear: both !important;
133
+ background: #eee !important;
134
  margin: 25px 0 0 !important;
135
  border-top: 1px solid #ccc !important;
136
  padding: 0 0 35px !important;
137
  text-align: left !important;
138
  min-width: 800px !important;
139
  display: none;
140
+ position: relative !important;
141
+ z-index: 99998 !important;
 
 
 
142
  }
143
 
144
  #qm.qm-show,
215
  display: inline-block !important;
216
  width: 24em !important;
217
  background: #fff !important;
218
+ border: 1px solid #e0e0e0 !important;
219
  margin: 0 5px 5px 0 !important;
220
  }
221
 
303
  font-size: 11px !important;
304
  line-height: 18px !important;
305
  font-family: Menlo, Monaco, Consolas, monospace !important;
306
+ border: 1px solid #e0e0e0 !important;
307
+ padding: 5px 8px 4px !important;
308
  vertical-align: top !important;
309
  text-shadow: none !important;
310
  text-transform: none !important;
355
 
356
  .qm td.qm-has-toggle p,
357
  .qm td .qm-toggler {
358
+ padding: 5px 22px 4px 8px !important;
359
  position: relative !important;
360
  }
361
 
369
  }
370
 
371
  .qm .qm-inner-toggle {
372
+ padding: 5px 8px 4px !important;
373
  }
374
 
375
  .qm-has-inner .qm-toggled > table {
518
 
519
  .qm .qm-toggle,
520
  html[dir="rtl"] .qm .qm-ltr .qm-toggle {
521
+ color: #555 !important;
522
+ padding: 1px 6px 0 !important;
523
+ border: none !important;
 
 
 
524
  font-style: normal !important;
525
+ font-weight: bold !important;
526
  font-size: 11px !important;
527
  line-height: 18px !important;
528
  font-family: Menlo, Monaco, Consolas, monospace !important;
529
  position: absolute !important;
530
+ top: 4px !important;
531
+ right: 4px !important;
532
  left: auto !important;
533
+ background: #f1f1f1 !important;
534
  cursor: pointer !important;
535
  }
536
 
537
  .qm .qm-toggle:focus,
538
  .qm .qm-toggle:hover {
539
  text-decoration: none !important;
540
+ border-color: #e0e0e0 !important;
541
  color: #0073aa !important;
542
+ background: #e0e0e0 !important;
543
  }
544
 
545
  .qm tr.error,
742
  }
743
 
744
  html[dir="rtl"] .qm .qm-toggle {
745
+ border-right: 1px solid #e0e0e0 !important;
746
  border-left: none !important;
747
  right: auto !important;
748
  left: 1px !important;
762
  .qm-debug-bar textarea,
763
  .qm-debug-bar pre {
764
  padding: 10px !important;
765
+ border: 1px solid #e0e0e0 !important;
766
  margin: 4px 0 !important;
767
  color: inherit !important;
768
  background: transparent !important;
assets/query-monitor.js CHANGED
@@ -19,11 +19,13 @@ var QM_i18n = {
19
 
20
  number_format : function( number, decimals ) {
21
 
22
- if ( isNaN( number ) )
23
  return;
 
24
 
25
- if ( !decimals )
26
  decimals = 0;
 
27
 
28
  number = parseFloat( number );
29
 
@@ -34,15 +36,17 @@ var QM_i18n = {
34
  o = '';
35
 
36
  if ( num_str.length > 3 ) {
37
- for ( i = num_str.length; i > 3; i -= 3 )
38
  o = qm_locale.number_format.thousands_sep + num_str.slice( i - 3, i ) + o;
 
39
  o = num_str.slice( 0, i ) + o;
40
  } else {
41
  o = num_str;
42
  }
43
 
44
- if ( decimals )
45
  o = o + qm_locale.number_format.decimal_point + fraction;
 
46
 
47
  return o;
48
 
@@ -52,8 +56,9 @@ var QM_i18n = {
52
 
53
  jQuery( function($) {
54
 
55
- if ( !window.qm )
56
  return;
 
57
 
58
  var is_admin = $('body').hasClass('wp-admin');
59
 
@@ -73,7 +78,7 @@ jQuery( function($) {
73
 
74
  var new_menu = $('#wp-admin-bar-query-monitor-placeholder')
75
  .clone()
76
- .attr('id','wp-admin-bar-'+el.id)
77
  ;
78
  new_menu
79
  .find('a').eq(0)
@@ -81,8 +86,9 @@ jQuery( function($) {
81
  .attr('href',el.href)
82
  ;
83
 
84
- if ( ( typeof el.meta != 'undefined' ) && ( typeof el.meta.classname != 'undefined' ) )
85
  new_menu.addClass(el.meta.classname);
 
86
 
87
  container.appendChild( new_menu.get(0) );
88
 
@@ -175,7 +181,7 @@ jQuery( function($) {
175
 
176
  if ( $(this).val() !== '' ) {
177
  if ( hilite ) {
178
- tr.filter('[data-qm-'+hilite+'*="' + val + '"]').addClass('qm-highlight');
179
  }
180
  tr.not('[data-qm-' + filter + '*="' + val + '"]').addClass('qm-hide-' + filter);
181
  $(this).addClass('qm-highlight');
@@ -186,11 +192,13 @@ jQuery( function($) {
186
  var matches = tr.filter(':visible');
187
  matches.each(function(i){
188
  var row_time = $(this).attr('data-qm-time');
189
- if ( row_time )
190
  time += parseFloat( row_time );
 
191
  });
192
- if ( time )
193
  time = QM_i18n.number_format( time, 4 );
 
194
 
195
  var results = table.find('.qm-items-shown').removeClass('qm-hide');
196
  results.find('.qm-items-number').text( QM_i18n.number_format( matches.length, 0 ) );
@@ -214,8 +222,8 @@ jQuery( function($) {
214
 
215
  $('#qm').find('.qm-filter-trigger').on('click',function(e){
216
  var filter = $(this).data('qm-filter'),
217
- value = $(this).data('qm-value'),
218
- target = $(this).data('qm-target');
219
  $('#qm-' + target).find('.qm-filter').not('[data-filter="' + filter + '"]').val('').removeClass('qm-highlight').change();
220
  $('#qm-' + target).find('[data-filter="' + filter + '"]').val(value).addClass('qm-highlight').change();
221
  $('html, body').scrollTop( $(this).closest('.qm').offset().top );
@@ -244,14 +252,14 @@ jQuery( function($) {
244
  var subject = $(this).data('qm-highlight');
245
  var table = $(this).closest('table');
246
 
247
- if ( !subject ) {
248
  return;
249
  }
250
 
251
  $(this).addClass('qm-highlight');
252
 
253
  $.each( subject.split(' '), function( i, el ){
254
- table.find('tr[data-qm-subject="'+el+'"]').addClass('qm-highlight');
255
  });
256
 
257
  }).on('mouseleave',function(e){
@@ -265,8 +273,9 @@ jQuery( function($) {
265
 
266
  var errors = response.getResponseHeader( 'X-QM-error-count' );
267
 
268
- if ( !errors )
269
  return event;
 
270
 
271
  errors = parseInt( errors, 10 );
272
 
@@ -282,8 +291,8 @@ jQuery( function($) {
282
  if ( $('#wp-admin-bar-query-monitor').length ) {
283
  if ( ! qm.ajax_errors[error.type] ) {
284
  $('#wp-admin-bar-query-monitor')
285
- .addClass('qm-'+error.type)
286
- .find('a').first().append('<span class="ab-label qm-ajax-'+ error.type +'"> &nbsp; AJAX: '+ error.type +'</span>')
287
  ;
288
  }
289
  }
@@ -326,9 +335,9 @@ jQuery( function($) {
326
  } );
327
 
328
  /**
329
- * This is a modified version of:
330
- *
331
- * jQuery table-sort v0.1.1
332
  * https://github.com/gajus/table-sort
333
  *
334
  * Licensed under the BSD.
@@ -342,126 +351,126 @@ jQuery( function($) {
342
  var settings = $.extend({
343
  'debug': false
344
  }, options);
345
-
346
  // @param object columns NodeList table colums.
347
  // @param integer row_width defines the number of columns per row.
348
  var table_to_array = function (columns, row_width) {
349
  if (settings.debug) {
350
  console.time('table to array');
351
  }
352
-
353
  columns = Array.prototype.slice.call(columns, 0);
354
-
355
  var rows = [];
356
  var row_index = 0;
357
-
358
  for (var i = 0, j = columns.length; i < j; i += row_width) {
359
  var row = [];
360
-
361
  for (var k = 0, l = row_width; k < l; k++) {
362
- var e = columns[i+k];
363
-
364
  var data = e.dataset.qmSortWeight;
365
-
366
  if (data === undefined) {
367
  data = e.textContent || e.innerText;
368
  }
369
-
370
  var number = parseFloat(data);
371
-
372
  data = isNaN(number) ? data : number;
373
-
374
  row.push(data);
375
  }
376
-
377
  rows.push({index: row_index++, data: row});
378
  }
379
-
380
  if (settings.debug) {
381
  console.timeEnd('table to array');
382
  }
383
-
384
  return rows;
385
  };
386
-
387
- if (!settings.target || !settings.target instanceof $) {
388
  throw 'Target is not defined or it is not instance of jQuery.';
389
  }
390
-
391
  settings.target.each(function () {
392
  var table = $(this);
393
-
394
  table.find('.qm-sort').on('click', function (e) {
395
  var desc = $(this).hasClass('qm-sort-desc');
396
-
397
  var index = $(this).closest('th').index();
398
-
399
  table.find('th').removeClass('qm-sorted-asc qm-sorted-desc');
400
 
401
- if ( desc )
402
  $(this).closest('th').addClass('qm-sorted-desc');
403
- else
404
  $(this).closest('th').addClass('qm-sorted-asc');
 
405
 
406
  table.find('tbody:not(.qm-sort-no)').each(function () {
407
  var tbody = $(this);
408
-
409
  var rows = this.rows;
410
-
411
  var anomalies = $(rows).has('[colspan]').detach();
412
-
413
  var columns = this.getElementsByTagName('td');
414
-
415
  if (this.data_matrix === undefined) {
416
  this.data_matrix = table_to_array(columns, $(rows[0]).find('td').length);
417
  }
418
-
419
  var data = this.data_matrix;
420
-
421
  if (settings.debug) {
422
  console.time('sort data');
423
  }
424
-
425
  data.sort(function (a, b) {
426
  if (a.data[index] == b.data[index]) {
427
  return 0;
428
  }
429
-
430
  return (desc ? a.data[index] > b.data[index] : a.data[index] < b.data[index]) ? -1 : 1;
431
  });
432
-
433
  if (settings.debug) {
434
  console.timeEnd('sort data');
435
  console.time('build table');
436
  }
437
-
438
  // Will use this to re-attach the tbody object.
439
  var table = tbody.parent();
440
-
441
  // Detach the tbody to prevent unnecassy overhead related
442
  // to the browser environment.
443
  tbody = tbody.detach();
444
-
445
  // Convert NodeList into an array.
446
  rows = Array.prototype.slice.call(rows, 0);
447
-
448
- var last_row = rows[data[data.length-1].index];
449
-
450
- for (var i = 0, j = data.length-1; i < j; i++) {
451
  tbody[0].insertBefore(rows[data[i].index], last_row);
452
-
453
  // Restore the index.
454
  data[i].index = i;
455
  }
456
-
457
  // // Restore the index.
458
- data[data.length-1].index = data.length-1;
459
-
460
  tbody.prepend(anomalies);
461
-
462
  table.append(tbody);
463
-
464
-
465
  if (settings.debug) {
466
  console.timeEnd('build table');
467
  }
19
 
20
  number_format : function( number, decimals ) {
21
 
22
+ if ( isNaN( number ) ) {
23
  return;
24
+ }
25
 
26
+ if ( ! decimals ) {
27
  decimals = 0;
28
+ }
29
 
30
  number = parseFloat( number );
31
 
36
  o = '';
37
 
38
  if ( num_str.length > 3 ) {
39
+ for ( i = num_str.length; i > 3; i -= 3 ) {
40
  o = qm_locale.number_format.thousands_sep + num_str.slice( i - 3, i ) + o;
41
+ }
42
  o = num_str.slice( 0, i ) + o;
43
  } else {
44
  o = num_str;
45
  }
46
 
47
+ if ( decimals ) {
48
  o = o + qm_locale.number_format.decimal_point + fraction;
49
+ }
50
 
51
  return o;
52
 
56
 
57
  jQuery( function($) {
58
 
59
+ if ( ! window.qm ) {
60
  return;
61
+ }
62
 
63
  var is_admin = $('body').hasClass('wp-admin');
64
 
78
 
79
  var new_menu = $('#wp-admin-bar-query-monitor-placeholder')
80
  .clone()
81
+ .attr('id','wp-admin-bar-' + el.id)
82
  ;
83
  new_menu
84
  .find('a').eq(0)
86
  .attr('href',el.href)
87
  ;
88
 
89
+ if ( ( typeof el.meta != 'undefined' ) && ( typeof el.meta.classname != 'undefined' ) ) {
90
  new_menu.addClass(el.meta.classname);
91
+ }
92
 
93
  container.appendChild( new_menu.get(0) );
94
 
181
 
182
  if ( $(this).val() !== '' ) {
183
  if ( hilite ) {
184
+ tr.filter('[data-qm-' + hilite + '*="' + val + '"]').addClass('qm-highlight');
185
  }
186
  tr.not('[data-qm-' + filter + '*="' + val + '"]').addClass('qm-hide-' + filter);
187
  $(this).addClass('qm-highlight');
192
  var matches = tr.filter(':visible');
193
  matches.each(function(i){
194
  var row_time = $(this).attr('data-qm-time');
195
+ if ( row_time ) {
196
  time += parseFloat( row_time );
197
+ }
198
  });
199
+ if ( time ) {
200
  time = QM_i18n.number_format( time, 4 );
201
+ }
202
 
203
  var results = table.find('.qm-items-shown').removeClass('qm-hide');
204
  results.find('.qm-items-number').text( QM_i18n.number_format( matches.length, 0 ) );
222
 
223
  $('#qm').find('.qm-filter-trigger').on('click',function(e){
224
  var filter = $(this).data('qm-filter'),
225
+ value = $(this).data('qm-value'),
226
+ target = $(this).data('qm-target');
227
  $('#qm-' + target).find('.qm-filter').not('[data-filter="' + filter + '"]').val('').removeClass('qm-highlight').change();
228
  $('#qm-' + target).find('[data-filter="' + filter + '"]').val(value).addClass('qm-highlight').change();
229
  $('html, body').scrollTop( $(this).closest('.qm').offset().top );
252
  var subject = $(this).data('qm-highlight');
253
  var table = $(this).closest('table');
254
 
255
+ if ( ! subject ) {
256
  return;
257
  }
258
 
259
  $(this).addClass('qm-highlight');
260
 
261
  $.each( subject.split(' '), function( i, el ){
262
+ table.find('tr[data-qm-subject="' + el + '"]').addClass('qm-highlight');
263
  });
264
 
265
  }).on('mouseleave',function(e){
273
 
274
  var errors = response.getResponseHeader( 'X-QM-error-count' );
275
 
276
+ if ( ! errors ) {
277
  return event;
278
+ }
279
 
280
  errors = parseInt( errors, 10 );
281
 
291
  if ( $('#wp-admin-bar-query-monitor').length ) {
292
  if ( ! qm.ajax_errors[error.type] ) {
293
  $('#wp-admin-bar-query-monitor')
294
+ .addClass('qm-' + error.type)
295
+ .find('a').first().append('<span class="ab-label qm-ajax-' + error.type + '"> &nbsp; AJAX: ' + error.type + '</span>')
296
  ;
297
  }
298
  }
335
  } );
336
 
337
  /**
338
+ * Table sorting library.
339
+ *
340
+ * This is a modified version of jQuery table-sort v0.1.1
341
  * https://github.com/gajus/table-sort
342
  *
343
  * Licensed under the BSD.
351
  var settings = $.extend({
352
  'debug': false
353
  }, options);
354
+
355
  // @param object columns NodeList table colums.
356
  // @param integer row_width defines the number of columns per row.
357
  var table_to_array = function (columns, row_width) {
358
  if (settings.debug) {
359
  console.time('table to array');
360
  }
361
+
362
  columns = Array.prototype.slice.call(columns, 0);
363
+
364
  var rows = [];
365
  var row_index = 0;
366
+
367
  for (var i = 0, j = columns.length; i < j; i += row_width) {
368
  var row = [];
369
+
370
  for (var k = 0, l = row_width; k < l; k++) {
371
+ var e = columns[i + k];
372
+
373
  var data = e.dataset.qmSortWeight;
374
+
375
  if (data === undefined) {
376
  data = e.textContent || e.innerText;
377
  }
378
+
379
  var number = parseFloat(data);
380
+
381
  data = isNaN(number) ? data : number;
382
+
383
  row.push(data);
384
  }
385
+
386
  rows.push({index: row_index++, data: row});
387
  }
388
+
389
  if (settings.debug) {
390
  console.timeEnd('table to array');
391
  }
392
+
393
  return rows;
394
  };
395
+
396
+ if ( ! settings.target || ! settings.target instanceof $) {
397
  throw 'Target is not defined or it is not instance of jQuery.';
398
  }
399
+
400
  settings.target.each(function () {
401
  var table = $(this);
402
+
403
  table.find('.qm-sort').on('click', function (e) {
404
  var desc = $(this).hasClass('qm-sort-desc');
405
+
406
  var index = $(this).closest('th').index();
407
+
408
  table.find('th').removeClass('qm-sorted-asc qm-sorted-desc');
409
 
410
+ if ( desc ) {
411
  $(this).closest('th').addClass('qm-sorted-desc');
412
+ } else {
413
  $(this).closest('th').addClass('qm-sorted-asc');
414
+ }
415
 
416
  table.find('tbody:not(.qm-sort-no)').each(function () {
417
  var tbody = $(this);
418
+
419
  var rows = this.rows;
420
+
421
  var anomalies = $(rows).has('[colspan]').detach();
422
+
423
  var columns = this.getElementsByTagName('td');
424
+
425
  if (this.data_matrix === undefined) {
426
  this.data_matrix = table_to_array(columns, $(rows[0]).find('td').length);
427
  }
428
+
429
  var data = this.data_matrix;
430
+
431
  if (settings.debug) {
432
  console.time('sort data');
433
  }
434
+
435
  data.sort(function (a, b) {
436
  if (a.data[index] == b.data[index]) {
437
  return 0;
438
  }
439
+
440
  return (desc ? a.data[index] > b.data[index] : a.data[index] < b.data[index]) ? -1 : 1;
441
  });
442
+
443
  if (settings.debug) {
444
  console.timeEnd('sort data');
445
  console.time('build table');
446
  }
447
+
448
  // Will use this to re-attach the tbody object.
449
  var table = tbody.parent();
450
+
451
  // Detach the tbody to prevent unnecassy overhead related
452
  // to the browser environment.
453
  tbody = tbody.detach();
454
+
455
  // Convert NodeList into an array.
456
  rows = Array.prototype.slice.call(rows, 0);
457
+
458
+ var last_row = rows[data[data.length - 1].index];
459
+
460
+ for (var i = 0, j = data.length - 1; i < j; i++) {
461
  tbody[0].insertBefore(rows[data[i].index], last_row);
462
+
463
  // Restore the index.
464
  data[i].index = i;
465
  }
466
+
467
  // // Restore the index.
468
+ data[data.length - 1].index = data.length - 1;
469
+
470
  tbody.prepend(anomalies);
471
+
472
  table.append(tbody);
473
+
 
474
  if (settings.debug) {
475
  console.timeEnd('build table');
476
  }
classes/Activation.php CHANGED
@@ -33,10 +33,6 @@ class QM_Activation extends QM_Plugin {
33
 
34
  public function activate( $sitewide = false ) {
35
 
36
- if ( $admins = QM_Util::get_admins() ) {
37
- $admins->add_cap( 'view_query_monitor' );
38
- }
39
-
40
  if ( ! file_exists( $db = WP_CONTENT_DIR . '/db.php' ) && function_exists( 'symlink' ) ) {
41
  @symlink( plugin_dir_path( $this->file ) . 'wp-content/db.php', $db ); // @codingStandardsIgnoreLine
42
  }
@@ -51,6 +47,7 @@ class QM_Activation extends QM_Plugin {
51
 
52
  public function deactivate() {
53
 
 
54
  if ( $admins = QM_Util::get_admins() ) {
55
  $admins->remove_cap( 'view_query_monitor' );
56
  }
@@ -87,9 +84,9 @@ class QM_Activation extends QM_Plugin {
87
 
88
  $f = $this->plugin_base();
89
 
90
- if ( isset( $plugins[$f] ) ) {
91
 
92
- unset( $plugins[$f] );
93
 
94
  return array_merge( array(
95
  $f => time(),
33
 
34
  public function activate( $sitewide = false ) {
35
 
 
 
 
 
36
  if ( ! file_exists( $db = WP_CONTENT_DIR . '/db.php' ) && function_exists( 'symlink' ) ) {
37
  @symlink( plugin_dir_path( $this->file ) . 'wp-content/db.php', $db ); // @codingStandardsIgnoreLine
38
  }
47
 
48
  public function deactivate() {
49
 
50
+ // Remove legacy capability handling:
51
  if ( $admins = QM_Util::get_admins() ) {
52
  $admins->remove_cap( 'view_query_monitor' );
53
  }
84
 
85
  $f = $this->plugin_base();
86
 
87
+ if ( isset( $plugins[ $f ] ) ) {
88
 
89
+ unset( $plugins[ $f ] );
90
 
91
  return array_merge( array(
92
  $f => time(),
classes/Backtrace.php CHANGED
@@ -112,38 +112,36 @@ class QM_Backtrace {
112
  $components = array();
113
 
114
  foreach ( $this->trace as $item ) {
115
-
116
  try {
117
 
118
  if ( isset( $item['class'] ) ) {
119
- if ( !is_object( $item['class'] ) and !class_exists( $item['class'], false ) ) {
120
  continue;
121
  }
122
- if ( !method_exists( $item['class'], $item['function'] ) ) {
123
  continue;
124
  }
125
  $ref = new ReflectionMethod( $item['class'], $item['function'] );
126
  $file = $ref->getFileName();
127
- } else if ( function_exists( $item['function'] ) ) {
128
  $ref = new ReflectionFunction( $item['function'] );
129
  $file = $ref->getFileName();
130
- } else if ( isset( $item['file'] ) ) {
131
  $file = $item['file'];
132
  } else {
133
  continue;
134
  }
135
 
136
  $comp = QM_Util::get_file_component( $file );
137
- $components[$comp->type] = $comp;
138
  } catch ( ReflectionException $e ) {
139
  # nothing
140
  }
141
-
142
  }
143
 
144
  foreach ( QM_Util::get_file_dirs() as $type => $dir ) {
145
- if ( isset( $components[$type] ) ) {
146
- return $components[$type];
147
  }
148
  }
149
 
@@ -161,7 +159,7 @@ class QM_Backtrace {
161
 
162
  public function get_filtered_trace() {
163
 
164
- if ( !isset( $this->filtered_trace ) ) {
165
 
166
  $trace = array_map( array( $this, 'filter_trace' ), $this->trace );
167
  $trace = array_values( array_filter( $trace ) );
@@ -188,7 +186,7 @@ class QM_Backtrace {
188
 
189
  public function ignore( $num ) {
190
  for ( $i = 0; $i < absint( $num ); $i++ ) {
191
- unset( $this->trace[$i] );
192
  }
193
  $this->trace = array_values( $this->trace );
194
  return $this;
@@ -206,7 +204,7 @@ class QM_Backtrace {
206
 
207
  public function filter_trace( array $trace ) {
208
 
209
- if ( !self::$filtered and function_exists( 'did_action' ) and did_action( 'plugins_loaded' ) ) {
210
 
211
  # Only run apply_filters on these once
212
  self::$ignore_class = apply_filters( 'qm/trace/ignore_class', self::$ignore_class );
@@ -220,27 +218,21 @@ class QM_Backtrace {
220
  $return = $trace;
221
 
222
  if ( isset( $trace['class'] ) ) {
223
-
224
- if ( isset( self::$ignore_class[$trace['class']] ) ) {
225
  $return = null;
226
- } else if ( isset( self::$ignore_method[$trace['class']][$trace['function']] ) ) {
227
  $return = null;
228
- } else if ( 0 === strpos( $trace['class'], 'QM_' ) ) {
229
  $return = null;
230
  } else {
231
  $return['id'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
232
  $return['display'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
233
  }
234
-
235
  } else {
236
-
237
- if ( isset( self::$ignore_func[$trace['function']] ) ) {
238
-
239
  $return = null;
240
-
241
- } else if ( isset( self::$show_args[$trace['function']] ) ) {
242
-
243
- $show = self::$show_args[$trace['function']];
244
 
245
  if ( 'dir' === $show ) {
246
  if ( isset( $trace['args'][0] ) ) {
@@ -251,25 +243,21 @@ class QM_Backtrace {
251
  } else {
252
  $args = array();
253
  for ( $i = 0; $i < $show; $i++ ) {
254
- if ( isset( $trace['args'][$i] ) ) {
255
- if ( is_string( $trace['args'][$i] ) ) {
256
- $args[] = '\'' . $trace['args'][$i] . '\'';
257
  } else {
258
- $args[] = QM_Util::display_variable( $trace['args'][$i] );
259
  }
260
  }
261
  }
262
  $return['id'] = $trace['function'] . '()';
263
  $return['display'] = $trace['function'] . '(' . implode( ',', $args ) . ')';
264
  }
265
-
266
  } else {
267
-
268
  $return['id'] = $trace['function'] . '()';
269
  $return['display'] = $trace['function'] . '()';
270
-
271
  }
272
-
273
  }
274
 
275
  if ( $return ) {
112
  $components = array();
113
 
114
  foreach ( $this->trace as $item ) {
 
115
  try {
116
 
117
  if ( isset( $item['class'] ) ) {
118
+ if ( ! is_object( $item['class'] ) and ! class_exists( $item['class'], false ) ) {
119
  continue;
120
  }
121
+ if ( ! method_exists( $item['class'], $item['function'] ) ) {
122
  continue;
123
  }
124
  $ref = new ReflectionMethod( $item['class'], $item['function'] );
125
  $file = $ref->getFileName();
126
+ } elseif ( function_exists( $item['function'] ) ) {
127
  $ref = new ReflectionFunction( $item['function'] );
128
  $file = $ref->getFileName();
129
+ } elseif ( isset( $item['file'] ) ) {
130
  $file = $item['file'];
131
  } else {
132
  continue;
133
  }
134
 
135
  $comp = QM_Util::get_file_component( $file );
136
+ $components[ $comp->type ] = $comp;
137
  } catch ( ReflectionException $e ) {
138
  # nothing
139
  }
 
140
  }
141
 
142
  foreach ( QM_Util::get_file_dirs() as $type => $dir ) {
143
+ if ( isset( $components[ $type ] ) ) {
144
+ return $components[ $type ];
145
  }
146
  }
147
 
159
 
160
  public function get_filtered_trace() {
161
 
162
+ if ( ! isset( $this->filtered_trace ) ) {
163
 
164
  $trace = array_map( array( $this, 'filter_trace' ), $this->trace );
165
  $trace = array_values( array_filter( $trace ) );
186
 
187
  public function ignore( $num ) {
188
  for ( $i = 0; $i < absint( $num ); $i++ ) {
189
+ unset( $this->trace[ $i ] );
190
  }
191
  $this->trace = array_values( $this->trace );
192
  return $this;
204
 
205
  public function filter_trace( array $trace ) {
206
 
207
+ if ( ! self::$filtered and function_exists( 'did_action' ) and did_action( 'plugins_loaded' ) ) {
208
 
209
  # Only run apply_filters on these once
210
  self::$ignore_class = apply_filters( 'qm/trace/ignore_class', self::$ignore_class );
218
  $return = $trace;
219
 
220
  if ( isset( $trace['class'] ) ) {
221
+ if ( isset( self::$ignore_class[ $trace['class'] ] ) ) {
 
222
  $return = null;
223
+ } elseif ( isset( self::$ignore_method[ $trace['class'] ][ $trace['function'] ] ) ) {
224
  $return = null;
225
+ } elseif ( 0 === strpos( $trace['class'], 'QM_' ) ) {
226
  $return = null;
227
  } else {
228
  $return['id'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
229
  $return['display'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
230
  }
 
231
  } else {
232
+ if ( isset( self::$ignore_func[ $trace['function'] ] ) ) {
 
 
233
  $return = null;
234
+ } elseif ( isset( self::$show_args[ $trace['function'] ] ) ) {
235
+ $show = self::$show_args[ $trace['function'] ];
 
 
236
 
237
  if ( 'dir' === $show ) {
238
  if ( isset( $trace['args'][0] ) ) {
243
  } else {
244
  $args = array();
245
  for ( $i = 0; $i < $show; $i++ ) {
246
+ if ( isset( $trace['args'][ $i ] ) ) {
247
+ if ( is_string( $trace['args'][ $i ] ) ) {
248
+ $args[] = '\'' . $trace['args'][ $i ] . '\'';
249
  } else {
250
+ $args[] = QM_Util::display_variable( $trace['args'][ $i ] );
251
  }
252
  }
253
  }
254
  $return['id'] = $trace['function'] . '()';
255
  $return['display'] = $trace['function'] . '(' . implode( ',', $args ) . ')';
256
  }
 
257
  } else {
 
258
  $return['id'] = $trace['function'] . '()';
259
  $return['display'] = $trace['function'] . '()';
 
260
  }
 
261
  }
262
 
263
  if ( $return ) {
classes/Collector.php CHANGED
@@ -33,10 +33,10 @@ abstract class QM_Collector {
33
 
34
  protected function log_type( $type ) {
35
 
36
- if ( isset( $this->data['types'][$type] ) ) {
37
- $this->data['types'][$type]++;
38
  } else {
39
- $this->data['types'][$type] = 1;
40
  }
41
 
42
  }
@@ -54,22 +54,22 @@ abstract class QM_Collector {
54
 
55
  protected function log_component( $component, $ltime, $type ) {
56
 
57
- if ( !isset( $this->data['component_times'][$component->name] ) ) {
58
- $this->data['component_times'][$component->name] = array(
59
  'component' => $component->name,
60
  'calls' => 0,
61
  'ltime' => 0,
62
- 'types' => array()
63
  );
64
  }
65
 
66
- $this->data['component_times'][$component->name]['calls']++;
67
- $this->data['component_times'][$component->name]['ltime'] += $ltime;
68
 
69
- if ( isset( $this->data['component_times'][$component->name]['types'][$type] ) ) {
70
- $this->data['component_times'][$component->name]['types'][$type]++;
71
  } else {
72
- $this->data['component_times'][$component->name]['types'][$type] = 1;
73
  }
74
 
75
  }
@@ -80,10 +80,10 @@ abstract class QM_Collector {
80
  }
81
 
82
  public static function format_bool_constant( $constant ) {
83
- if ( !defined( $constant ) ) {
84
  /* translators: Undefined PHP constant */
85
  return __( 'undefined', 'query-monitor' );
86
- } else if ( !constant( $constant ) ) {
87
  return 'false';
88
  } else {
89
  return 'true';
33
 
34
  protected function log_type( $type ) {
35
 
36
+ if ( isset( $this->data['types'][ $type ] ) ) {
37
+ $this->data['types'][ $type ]++;
38
  } else {
39
+ $this->data['types'][ $type ] = 1;
40
  }
41
 
42
  }
54
 
55
  protected function log_component( $component, $ltime, $type ) {
56
 
57
+ if ( ! isset( $this->data['component_times'][ $component->name ] ) ) {
58
+ $this->data['component_times'][ $component->name ] = array(
59
  'component' => $component->name,
60
  'calls' => 0,
61
  'ltime' => 0,
62
+ 'types' => array(),
63
  );
64
  }
65
 
66
+ $this->data['component_times'][ $component->name ]['calls']++;
67
+ $this->data['component_times'][ $component->name ]['ltime'] += $ltime;
68
 
69
+ if ( isset( $this->data['component_times'][ $component->name ]['types'][ $type ] ) ) {
70
+ $this->data['component_times'][ $component->name ]['types'][ $type ]++;
71
  } else {
72
+ $this->data['component_times'][ $component->name ]['types'][ $type ] = 1;
73
  }
74
 
75
  }
80
  }
81
 
82
  public static function format_bool_constant( $constant ) {
83
+ if ( ! defined( $constant ) ) {
84
  /* translators: Undefined PHP constant */
85
  return __( 'undefined', 'query-monitor' );
86
+ } elseif ( ! constant( $constant ) ) {
87
  return 'false';
88
  } else {
89
  return 'true';
classes/Collectors.php CHANGED
@@ -40,7 +40,7 @@ class QM_Collectors implements IteratorAggregate {
40
  public static function init() {
41
  static $instance;
42
 
43
- if ( !$instance ) {
44
  $instance = new QM_Collectors;
45
  }
46
 
40
  public static function init() {
41
  static $instance;
42
 
43
+ if ( ! $instance ) {
44
  $instance = new QM_Collectors;
45
  }
46
 
classes/Dispatcher.php CHANGED
@@ -20,7 +20,7 @@ abstract class QM_Dispatcher {
20
  public function __construct( QM_Plugin $qm ) {
21
  $this->qm = $qm;
22
 
23
- if ( !defined( 'QM_COOKIE' ) ) {
24
  define( 'QM_COOKIE', 'query_monitor_' . COOKIEHASH );
25
  }
26
 
@@ -81,7 +81,7 @@ abstract class QM_Dispatcher {
81
 
82
  public function user_can_view() {
83
 
84
- if ( !did_action( 'plugins_loaded' ) ) {
85
  return false;
86
  }
87
 
@@ -94,8 +94,8 @@ abstract class QM_Dispatcher {
94
  }
95
 
96
  public static function user_verified() {
97
- if ( isset( $_COOKIE[QM_COOKIE] ) ) {
98
- return self::verify_cookie( wp_unslash( $_COOKIE[QM_COOKIE] ) );
99
  }
100
  return false;
101
  }
20
  public function __construct( QM_Plugin $qm ) {
21
  $this->qm = $qm;
22
 
23
+ if ( ! defined( 'QM_COOKIE' ) ) {
24
  define( 'QM_COOKIE', 'query_monitor_' . COOKIEHASH );
25
  }
26
 
81
 
82
  public function user_can_view() {
83
 
84
+ if ( ! did_action( 'plugins_loaded' ) ) {
85
  return false;
86
  }
87
 
94
  }
95
 
96
  public static function user_verified() {
97
+ if ( isset( $_COOKIE[QM_COOKIE] ) ) { // @codingStandardsIgnoreLine
98
+ return self::verify_cookie( wp_unslash( $_COOKIE[QM_COOKIE] ) ); // @codingStandardsIgnoreLine
99
  }
100
  return false;
101
  }
classes/Dispatchers.php CHANGED
@@ -38,7 +38,7 @@ class QM_Dispatchers implements IteratorAggregate {
38
  public static function init() {
39
  static $instance;
40
 
41
- if ( !$instance ) {
42
  $instance = new QM_Dispatchers;
43
  }
44
 
38
  public static function init() {
39
  static $instance;
40
 
41
+ if ( ! $instance ) {
42
  $instance = new QM_Dispatchers;
43
  }
44
 
classes/QueryMonitor.php CHANGED
@@ -22,6 +22,9 @@ class QueryMonitor extends QM_Plugin {
22
  add_action( 'plugins_loaded', array( $this, 'action_plugins_loaded' ) );
23
  add_action( 'init', array( $this, 'action_init' ) );
24
 
 
 
 
25
  # Parent setup:
26
  parent::__construct( $file );
27
 
@@ -32,6 +35,37 @@ class QueryMonitor extends QM_Plugin {
32
 
33
  }
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  public function action_plugins_loaded() {
36
 
37
  # Register additional collectors:
22
  add_action( 'plugins_loaded', array( $this, 'action_plugins_loaded' ) );
23
  add_action( 'init', array( $this, 'action_init' ) );
24
 
25
+ # Filters
26
+ add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 3 );
27
+
28
  # Parent setup:
29
  parent::__construct( $file );
30
 
35
 
36
  }
37
 
38
+ /**
39
+ * Filter a user's capabilities so they can be altered at runtime.
40
+ *
41
+ * This is used to:
42
+ * - Grant the 'view_query_monitor' capability to the user if they have the ability to manage options.
43
+ *
44
+ * This does not get called for Super Admins.
45
+ *
46
+ * @param bool[] $user_caps Concerned user's capabilities.
47
+ * @param string[] $required_caps Required primitive capabilities for the requested capability.
48
+ * @param array $args {
49
+ * Arguments that accompany the requested capability check.
50
+ *
51
+ * @type string $0 Requested capability.
52
+ * @type int $1 Concerned user ID.
53
+ * @type mixed ...$2 Optional second and further parameters.
54
+ * }
55
+ * @return bool[] Concerned user's capabilities.
56
+ */
57
+ public function filter_user_has_cap( array $user_caps, array $required_caps, array $args ) {
58
+ if ( 'view_query_monitor' !== $args[0] ) {
59
+ return $user_caps;
60
+ }
61
+
62
+ if ( ! is_multisite() && user_can( $args[1], 'manage_options' ) ) {
63
+ $user_caps['view_query_monitor'] = true;
64
+ }
65
+
66
+ return $user_caps;
67
+ }
68
+
69
  public function action_plugins_loaded() {
70
 
71
  # Register additional collectors:
classes/Util.php CHANGED
@@ -98,8 +98,8 @@ class QM_Util {
98
 
99
  $file = self::standard_dir( $file );
100
 
101
- if ( isset( self::$file_components[$file] ) ) {
102
- return self::$file_components[$file];
103
  }
104
 
105
  foreach ( self::get_file_dirs() as $type => $dir ) {
@@ -174,7 +174,7 @@ class QM_Util {
174
  break;
175
  }
176
 
177
- return self::$file_components[$file] = (object) compact( 'type', 'name', 'context' );
178
 
179
  }
180
 
@@ -187,7 +187,6 @@ class QM_Util {
187
  try {
188
 
189
  if ( is_array( $callback['function'] ) ) {
190
-
191
  if ( is_object( $callback['function'][0] ) ) {
192
  $class = get_class( $callback['function'][0] );
193
  $access = '->';
@@ -198,9 +197,7 @@ class QM_Util {
198
 
199
  $callback['name'] = $class . $access . $callback['function'][1] . '()';
200
  $ref = new ReflectionMethod( $class, $callback['function'][1] );
201
-
202
- } else if ( is_object( $callback['function'] ) ) {
203
-
204
  if ( is_a( $callback['function'], 'Closure' ) ) {
205
  $ref = new ReflectionFunction( $callback['function'] );
206
  $file = QM_Util::standard_dir( $ref->getFileName(), '' );
@@ -212,12 +209,9 @@ class QM_Util {
212
  $callback['name'] = $class . '->__invoke()';
213
  $ref = new ReflectionMethod( $class, '__invoke' );
214
  }
215
-
216
  } else {
217
-
218
  $callback['name'] = $callback['function'] . '()';
219
  $ref = new ReflectionFunction( $callback['function'] );
220
-
221
  }
222
 
223
  $callback['file'] = $ref->getFileName();
@@ -250,7 +244,6 @@ class QM_Util {
250
  'context' => '',
251
  );
252
  }
253
-
254
  } catch ( ReflectionException $e ) {
255
 
256
  $callback['error'] = new WP_Error( 'reflection_exception', $e->getMessage() );
@@ -272,7 +265,7 @@ class QM_Util {
272
  if ( self::is_ajax() ) {
273
  return true;
274
  }
275
- if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && 'xmlhttprequest' === strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) ) {
276
  return true;
277
  }
278
  return false;
@@ -382,7 +375,7 @@ class QM_Util {
382
  private static function _rsort( $a, $b ) {
383
  $field = self::$sort_field;
384
 
385
- if ( $a[ $field ] == $b[ $field ] ) {
386
  return 0;
387
  } else {
388
  return ( $a[ $field ] > $b[ $field ] ) ? -1 : 1;
@@ -392,7 +385,7 @@ class QM_Util {
392
  private static function _sort( $a, $b ) {
393
  $field = self::$sort_field;
394
 
395
- if ( $a[ $field ] == $b[ $field ] ) {
396
  return 0;
397
  } else {
398
  return ( $a[ $field ] > $b[ $field ] ) ? 1 : -1;
98
 
99
  $file = self::standard_dir( $file );
100
 
101
+ if ( isset( self::$file_components[ $file ] ) ) {
102
+ return self::$file_components[ $file ];
103
  }
104
 
105
  foreach ( self::get_file_dirs() as $type => $dir ) {
174
  break;
175
  }
176
 
177
+ return self::$file_components[ $file ] = (object) compact( 'type', 'name', 'context' );
178
 
179
  }
180
 
187
  try {
188
 
189
  if ( is_array( $callback['function'] ) ) {
 
190
  if ( is_object( $callback['function'][0] ) ) {
191
  $class = get_class( $callback['function'][0] );
192
  $access = '->';
197
 
198
  $callback['name'] = $class . $access . $callback['function'][1] . '()';
199
  $ref = new ReflectionMethod( $class, $callback['function'][1] );
200
+ } elseif ( is_object( $callback['function'] ) ) {
 
 
201
  if ( is_a( $callback['function'], 'Closure' ) ) {
202
  $ref = new ReflectionFunction( $callback['function'] );
203
  $file = QM_Util::standard_dir( $ref->getFileName(), '' );
209
  $callback['name'] = $class . '->__invoke()';
210
  $ref = new ReflectionMethod( $class, '__invoke' );
211
  }
 
212
  } else {
 
213
  $callback['name'] = $callback['function'] . '()';
214
  $ref = new ReflectionFunction( $callback['function'] );
 
215
  }
216
 
217
  $callback['file'] = $ref->getFileName();
244
  'context' => '',
245
  );
246
  }
 
247
  } catch ( ReflectionException $e ) {
248
 
249
  $callback['error'] = new WP_Error( 'reflection_exception', $e->getMessage() );
265
  if ( self::is_ajax() ) {
266
  return true;
267
  }
268
+ if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && 'xmlhttprequest' === strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) ) { // @codingStandardsIgnoreLine
269
  return true;
270
  }
271
  return false;
375
  private static function _rsort( $a, $b ) {
376
  $field = self::$sort_field;
377
 
378
+ if ( $a[ $field ] === $b[ $field ] ) {
379
  return 0;
380
  } else {
381
  return ( $a[ $field ] > $b[ $field ] ) ? -1 : 1;
385
  private static function _sort( $a, $b ) {
386
  $field = self::$sort_field;
387
 
388
+ if ( $a[ $field ] === $b[ $field ] ) {
389
  return 0;
390
  } else {
391
  return ( $a[ $field ] > $b[ $field ] ) ? 1 : -1;
classes/debug_bar.php CHANGED
@@ -26,10 +26,10 @@ class Debug_Bar {
26
 
27
  public function enqueue() {
28
  wp_register_style( 'debug-bar', false, array(
29
- 'query-monitor'
30
  ) );
31
  wp_register_script( 'debug-bar', false, array(
32
- 'query-monitor'
33
  ) );
34
 
35
  do_action( 'debug_bar_enqueue_scripts' );
26
 
27
  public function enqueue() {
28
  wp_register_style( 'debug-bar', false, array(
29
+ 'query-monitor',
30
  ) );
31
  wp_register_script( 'debug-bar', false, array(
32
+ 'query-monitor',
33
  ) );
34
 
35
  do_action( 'debug_bar_enqueue_scripts' );
collectors/admin.php CHANGED
@@ -28,7 +28,7 @@ class QM_Collector_Admin extends QM_Collector {
28
 
29
  $current_screen = get_current_screen();
30
 
31
- if ( isset( $_GET['page'] ) && null !== $current_screen ) {
32
  $this->data['base'] = $current_screen->base;
33
  } else {
34
  $this->data['base'] = $pagenow;
@@ -57,15 +57,15 @@ class QM_Collector_Admin extends QM_Collector {
57
 
58
  # And now, WordPress' legendary inconsistency comes into play:
59
 
60
- if ( !empty( $this->data['current_screen']['taxonomy'] ) ) {
61
  $list_table['column'] = $this->data['current_screen']['taxonomy'];
62
- } else if ( !empty( $this->data['current_screen']['post_type'] ) ) {
63
  $list_table['column'] = $this->data['current_screen']['post_type'] . '_posts';
64
  } else {
65
  $list_table['column'] = $this->data['current_screen']['base'];
66
  }
67
 
68
- if ( !empty( $this->data['current_screen']['post_type'] ) and empty( $this->data['current_screen']['taxonomy'] ) ) {
69
  $list_table['columns'] = $this->data['current_screen']['post_type'] . '_posts';
70
  } else {
71
  $list_table['columns'] = $this->data['current_screen']['id'];
@@ -73,9 +73,9 @@ class QM_Collector_Admin extends QM_Collector {
73
 
74
  if ( 'edit-comments' === $list_table['column'] ) {
75
  $list_table['column'] = 'comments';
76
- } else if ( 'upload' === $list_table['column'] ) {
77
  $list_table['column'] = 'media';
78
- } else if ( 'link-manager' === $list_table['column'] ) {
79
  $list_table['column'] = 'link';
80
  }
81
 
28
 
29
  $current_screen = get_current_screen();
30
 
31
+ if ( isset( $_GET['page'] ) && null !== $current_screen ) { // @codingStandardsIgnoreLine
32
  $this->data['base'] = $current_screen->base;
33
  } else {
34
  $this->data['base'] = $pagenow;
57
 
58
  # And now, WordPress' legendary inconsistency comes into play:
59
 
60
+ if ( ! empty( $this->data['current_screen']['taxonomy'] ) ) {
61
  $list_table['column'] = $this->data['current_screen']['taxonomy'];
62
+ } elseif ( ! empty( $this->data['current_screen']['post_type'] ) ) {
63
  $list_table['column'] = $this->data['current_screen']['post_type'] . '_posts';
64
  } else {
65
  $list_table['column'] = $this->data['current_screen']['base'];
66
  }
67
 
68
+ if ( ! empty( $this->data['current_screen']['post_type'] ) and empty( $this->data['current_screen']['taxonomy'] ) ) {
69
  $list_table['columns'] = $this->data['current_screen']['post_type'] . '_posts';
70
  } else {
71
  $list_table['columns'] = $this->data['current_screen']['id'];
73
 
74
  if ( 'edit-comments' === $list_table['column'] ) {
75
  $list_table['column'] = 'comments';
76
+ } elseif ( 'upload' === $list_table['column'] ) {
77
  $list_table['column'] = 'media';
78
+ } elseif ( 'link-manager' === $list_table['column'] ) {
79
  $list_table['column'] = 'link';
80
  }
81
 
collectors/assets.php CHANGED
@@ -53,7 +53,7 @@ class QM_Collector_Assets extends QM_Collector {
53
  }
54
 
55
  public function process() {
56
- if ( !isset( $this->data['raw'] ) ) {
57
  return;
58
  }
59
 
@@ -67,7 +67,7 @@ class QM_Collector_Assets extends QM_Collector {
67
  $broken = array_values( array_diff( $raw->queue, $raw->done ) );
68
  $missing = array_values( array_diff( $raw->queue, array_keys( $raw->registered ) ) );
69
 
70
- if ( !empty( $broken ) ) {
71
  foreach ( $broken as $key => $handle ) {
72
  if ( $item = $raw->query( $handle ) ) {
73
  $broken = array_merge( $broken, $this->get_broken_dependencies( $item, $raw ) );
@@ -77,7 +77,7 @@ class QM_Collector_Assets extends QM_Collector {
77
  }
78
  }
79
 
80
- if ( !empty( $broken ) ) {
81
  $this->data['broken'][ $type ] = array_unique( $broken );
82
  }
83
  }
@@ -91,7 +91,6 @@ class QM_Collector_Assets extends QM_Collector {
91
  }
92
  }
93
  }
94
-
95
  }
96
  }
97
 
@@ -100,13 +99,11 @@ class QM_Collector_Assets extends QM_Collector {
100
  $broken = array();
101
 
102
  foreach ( $item->deps as $handle ) {
103
-
104
  if ( $dep = $dependencies->query( $handle ) ) {
105
  $broken = array_merge( $broken, $this->get_broken_dependencies( $dep, $dependencies ) );
106
  } else {
107
  $broken[] = $item->handle;
108
  }
109
-
110
  }
111
 
112
  return $broken;
53
  }
54
 
55
  public function process() {
56
+ if ( ! isset( $this->data['raw'] ) ) {
57
  return;
58
  }
59
 
67
  $broken = array_values( array_diff( $raw->queue, $raw->done ) );
68
  $missing = array_values( array_diff( $raw->queue, array_keys( $raw->registered ) ) );
69
 
70
+ if ( ! empty( $broken ) ) {
71
  foreach ( $broken as $key => $handle ) {
72
  if ( $item = $raw->query( $handle ) ) {
73
  $broken = array_merge( $broken, $this->get_broken_dependencies( $item, $raw ) );
77
  }
78
  }
79
 
80
+ if ( ! empty( $broken ) ) {
81
  $this->data['broken'][ $type ] = array_unique( $broken );
82
  }
83
  }
91
  }
92
  }
93
  }
 
94
  }
95
  }
96
 
99
  $broken = array();
100
 
101
  foreach ( $item->deps as $handle ) {
 
102
  if ( $dep = $dependencies->query( $handle ) ) {
103
  $broken = array_merge( $broken, $this->get_broken_dependencies( $dep, $dependencies ) );
104
  } else {
105
  $broken[] = $item->handle;
106
  }
 
107
  }
108
 
109
  return $broken;
collectors/cache.php CHANGED
@@ -29,7 +29,6 @@ class QM_Collector_Cache extends QM_Collector {
29
  $this->data['cache_hit_percentage'] = 0;
30
 
31
  if ( is_object( $wp_object_cache ) ) {
32
-
33
  if ( property_exists( $wp_object_cache, 'cache_hits' ) ) {
34
  $this->data['stats']['cache_hits'] = (int) $wp_object_cache->cache_hits;
35
  }
@@ -46,7 +45,6 @@ class QM_Collector_Cache extends QM_Collector {
46
  $this->data['stats'][ $key ] = $value;
47
  }
48
  }
49
-
50
  }
51
 
52
  if ( isset( $this->data['stats']['cache_hits'] ) && isset( $this->data['stats']['cache_misses'] ) ) {
29
  $this->data['cache_hit_percentage'] = 0;
30
 
31
  if ( is_object( $wp_object_cache ) ) {
 
32
  if ( property_exists( $wp_object_cache, 'cache_hits' ) ) {
33
  $this->data['stats']['cache_hits'] = (int) $wp_object_cache->cache_hits;
34
  }
45
  $this->data['stats'][ $key ] = $value;
46
  }
47
  }
 
48
  }
49
 
50
  if ( isset( $this->data['stats']['cache_hits'] ) && isset( $this->data['stats']['cache_misses'] ) ) {
collectors/caps.php CHANGED
@@ -128,7 +128,7 @@ class QM_Collector_Caps extends QM_Collector {
128
  $all_parts = array_merge( $all_parts, $parts );
129
  $all_users[] = $cap['args'][1];
130
  $component = $cap['trace']->get_component();
131
- $components[$component->name] = $component->name;
132
  }
133
 
134
  $this->data['parts'] = array_unique( array_filter( $all_parts ) );
128
  $all_parts = array_merge( $all_parts, $parts );
129
  $all_users[] = $cap['args'][1];
130
  $component = $cap['trace']->get_component();
131
+ $components[ $component->name ] = $component->name;
132
  }
133
 
134
  $this->data['parts'] = array_unique( array_filter( $all_parts ) );
collectors/conditionals.php CHANGED
@@ -69,11 +69,10 @@ class QM_Collector_Conditionals extends QM_Collector {
69
 
70
  foreach ( $conds as $cond ) {
71
  if ( function_exists( $cond ) ) {
72
-
73
- if ( ( 'is_sticky' === $cond ) and !get_post( $id = null ) ) {
74
  # Special case for is_sticky to prevent PHP notices
75
  $false[] = $cond;
76
- } else if ( ! is_multisite() && in_array( $cond, array( 'is_main_network', 'is_main_site' ), true ) ) {
77
  # Special case for multisite conditionals to prevent them from being annoying on single site installs
78
  $na[] = $cond;
79
  } else {
@@ -83,7 +82,6 @@ class QM_Collector_Conditionals extends QM_Collector {
83
  $false[] = $cond;
84
  }
85
  }
86
-
87
  } else {
88
  $na[] = $cond;
89
  }
69
 
70
  foreach ( $conds as $cond ) {
71
  if ( function_exists( $cond ) ) {
72
+ if ( ( 'is_sticky' === $cond ) and ! get_post( $id = null ) ) {
 
73
  # Special case for is_sticky to prevent PHP notices
74
  $false[] = $cond;
75
+ } elseif ( ! is_multisite() && in_array( $cond, array( 'is_main_network', 'is_main_site' ), true ) ) {
76
  # Special case for multisite conditionals to prevent them from being annoying on single site installs
77
  $na[] = $cond;
78
  } else {
82
  $false[] = $cond;
83
  }
84
  }
 
85
  } else {
86
  $na[] = $cond;
87
  }
collectors/db_dupes.php CHANGED
@@ -49,7 +49,6 @@ class QM_Collector_DB_Dupes extends QM_Collector {
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();
@@ -60,7 +59,6 @@ class QM_Collector_DB_Dupes extends QM_Collector {
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
  }
49
  foreach ( $query_ids as $query_id ) {
50
 
51
  if ( isset( $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['trace'] ) ) {
 
52
  $trace = $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['trace'];
53
  $stack = wp_list_pluck( $trace->get_filtered_trace(), 'id' );
54
  $component = $trace->get_component();
59
  } else {
60
  $components[ $sql ][ $component->name ] = 1;
61
  }
 
62
  } else {
63
  $stack = array_reverse( explode( ', ', $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['stack'] ) );
64
  }
collectors/db_queries.php CHANGED
@@ -14,10 +14,10 @@ GNU General Public License for more details.
14
 
15
  */
16
 
17
- if ( !defined( 'SAVEQUERIES' ) ) {
18
  define( 'SAVEQUERIES', true );
19
  }
20
- if ( !defined( 'QM_DB_EXPENSIVE' ) ) {
21
  define( 'QM_DB_EXPENSIVE', 0.05 );
22
  }
23
 
@@ -35,14 +35,14 @@ class QM_Collector_DB_Queries extends QM_Collector {
35
  }
36
 
37
  public function get_errors() {
38
- if ( !empty( $this->data['errors'] ) ) {
39
  return $this->data['errors'];
40
  }
41
  return false;
42
  }
43
 
44
  public function get_expensive() {
45
- if ( !empty( $this->data['expensive'] ) ) {
46
  return $this->data['expensive'];
47
  }
48
  return false;
@@ -54,7 +54,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
54
 
55
  public function process() {
56
 
57
- if ( !SAVEQUERIES ) {
58
  return;
59
  }
60
 
@@ -63,7 +63,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
63
  $this->data['errors'] = array();
64
 
65
  $this->db_objects = apply_filters( 'qm/collect/db_objects', array(
66
- '$wpdb' => $GLOBALS['wpdb']
67
  ) );
68
 
69
  foreach ( $this->db_objects as $name => $db ) {
@@ -78,22 +78,22 @@ class QM_Collector_DB_Queries extends QM_Collector {
78
 
79
  protected function log_caller( $caller, $ltime, $type ) {
80
 
81
- if ( !isset( $this->data['times'][$caller] ) ) {
82
- $this->data['times'][$caller] = array(
83
  'caller' => $caller,
84
  'calls' => 0,
85
  'ltime' => 0,
86
- 'types' => array()
87
  );
88
  }
89
 
90
- $this->data['times'][$caller]['calls']++;
91
- $this->data['times'][$caller]['ltime'] += $ltime;
92
 
93
- if ( isset( $this->data['times'][$caller]['types'][$type] ) ) {
94
- $this->data['times'][$caller]['types'][$type]++;
95
  } else {
96
- $this->data['times'][$caller]['types'][$type] = 1;
97
  }
98
 
99
  }
@@ -111,7 +111,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
111
  foreach ( (array) $db->queries as $query ) {
112
 
113
  # @TODO: decide what I want to do with this:
114
- if ( false !== strpos( $query[2], 'wp_admin_bar' ) and !isset( $_REQUEST['qm_display_admin_bar'] ) ) {
115
  continue;
116
  }
117
 
@@ -149,7 +149,6 @@ class QM_Collector_DB_Queries extends QM_Collector {
149
  } else {
150
  $caller_name = $caller;
151
  }
152
-
153
  }
154
 
155
  $sql = trim( $sql );
@@ -164,19 +163,19 @@ class QM_Collector_DB_Queries extends QM_Collector {
164
  $this->log_component( $component, $ltime, $type );
165
  }
166
 
167
- if ( !isset( $types[$type]['total'] ) ) {
168
- $types[$type]['total'] = 1;
169
  } else {
170
- $types[$type]['total']++;
171
  }
172
 
173
- if ( !isset( $types[$type]['callers'][$caller] ) ) {
174
- $types[$type]['callers'][$caller] = 1;
175
  } else {
176
- $types[$type]['callers'][$caller]++;
177
  }
178
 
179
- $is_main_query = ( $sql === trim( $wp_the_query->request ) && ( false !== strpos( $stack, ' WP->main,' ) ) );
180
 
181
  $row = compact( 'caller', 'caller_name', 'stack', 'sql', 'ltime', 'result', 'type', 'component', 'trace', 'is_main_query' );
182
 
@@ -221,7 +220,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
221
 
222
  # @TODO put errors in here too:
223
  # @TODO proper class instead of (object)
224
- $this->data['dbs'][$id] = (object) compact( 'rows', 'types', 'has_result', 'has_trace', 'total_time', 'total_qs', 'has_main_query' );
225
 
226
  }
227
 
14
 
15
  */
16
 
17
+ if ( ! defined( 'SAVEQUERIES' ) ) {
18
  define( 'SAVEQUERIES', true );
19
  }
20
+ if ( ! defined( 'QM_DB_EXPENSIVE' ) ) {
21
  define( 'QM_DB_EXPENSIVE', 0.05 );
22
  }
23
 
35
  }
36
 
37
  public function get_errors() {
38
+ if ( ! empty( $this->data['errors'] ) ) {
39
  return $this->data['errors'];
40
  }
41
  return false;
42
  }
43
 
44
  public function get_expensive() {
45
+ if ( ! empty( $this->data['expensive'] ) ) {
46
  return $this->data['expensive'];
47
  }
48
  return false;
54
 
55
  public function process() {
56
 
57
+ if ( ! SAVEQUERIES ) {
58
  return;
59
  }
60
 
63
  $this->data['errors'] = array();
64
 
65
  $this->db_objects = apply_filters( 'qm/collect/db_objects', array(
66
+ '$wpdb' => $GLOBALS['wpdb'],
67
  ) );
68
 
69
  foreach ( $this->db_objects as $name => $db ) {
78
 
79
  protected function log_caller( $caller, $ltime, $type ) {
80
 
81
+ if ( ! isset( $this->data['times'][ $caller ] ) ) {
82
+ $this->data['times'][ $caller ] = array(
83
  'caller' => $caller,
84
  'calls' => 0,
85
  'ltime' => 0,
86
+ 'types' => array(),
87
  );
88
  }
89
 
90
+ $this->data['times'][ $caller ]['calls']++;
91
+ $this->data['times'][ $caller ]['ltime'] += $ltime;
92
 
93
+ if ( isset( $this->data['times'][ $caller ]['types'][ $type ] ) ) {
94
+ $this->data['times'][ $caller ]['types'][ $type ]++;
95
  } else {
96
+ $this->data['times'][ $caller ]['types'][ $type ] = 1;
97
  }
98
 
99
  }
111
  foreach ( (array) $db->queries as $query ) {
112
 
113
  # @TODO: decide what I want to do with this:
114
+ if ( false !== strpos( $query[2], 'wp_admin_bar' ) and !isset( $_REQUEST['qm_display_admin_bar'] ) ) { // @codingStandardsIgnoreLine
115
  continue;
116
  }
117
 
149
  } else {
150
  $caller_name = $caller;
151
  }
 
152
  }
153
 
154
  $sql = trim( $sql );
163
  $this->log_component( $component, $ltime, $type );
164
  }
165
 
166
+ if ( ! isset( $types[ $type ]['total'] ) ) {
167
+ $types[ $type ]['total'] = 1;
168
  } else {
169
+ $types[ $type ]['total']++;
170
  }
171
 
172
+ if ( ! isset( $types[ $type ]['callers'][ $caller ] ) ) {
173
+ $types[ $type ]['callers'][ $caller ] = 1;
174
  } else {
175
+ $types[ $type ]['callers'][ $caller ]++;
176
  }
177
 
178
+ $is_main_query = ( trim( $wp_the_query->request ) === $sql && ( false !== strpos( $stack, ' WP->main,' ) ) );
179
 
180
  $row = compact( 'caller', 'caller_name', 'stack', 'sql', 'ltime', 'result', 'type', 'component', 'trace', 'is_main_query' );
181
 
220
 
221
  # @TODO put errors in here too:
222
  # @TODO proper class instead of (object)
223
+ $this->data['dbs'][ $id ] = (object) compact( 'rows', 'types', 'has_result', 'has_trace', 'total_time', 'total_qs', 'has_main_query' );
224
 
225
  }
226
 
collectors/environment.php CHANGED
@@ -40,12 +40,12 @@ class QM_Collector_Environment extends QM_Collector {
40
  # caught early before any plugins had a chance to alter them
41
 
42
  foreach ( $this->php_vars as $setting ) {
43
- if ( isset( $wpdb->qm_php_vars ) and isset( $wpdb->qm_php_vars[$setting] ) ) {
44
- $val = $wpdb->qm_php_vars[$setting];
45
  } else {
46
  $val = ini_get( $setting );
47
  }
48
- $this->data['php']['variables'][$setting]['before'] = $val;
49
  }
50
 
51
  }
@@ -92,7 +92,7 @@ class QM_Collector_Environment extends QM_Collector {
92
  'max_connections' => false, # Max number of client connections
93
  'query_cache_limit' => true, # Individual query cache size limit
94
  'query_cache_size' => true, # Total cache size limit
95
- 'query_cache_type' => 'ON' # Query cache on or off
96
  );
97
 
98
  if ( $dbq = QM_Collectors::get( 'db_queries' ) ) {
@@ -107,7 +107,7 @@ class QM_Collector_Environment extends QM_Collector {
107
  if ( is_resource( $db->dbh ) ) {
108
  # Old mysql extension
109
  $extension = 'mysql';
110
- } else if ( is_object( $db->dbh ) ) {
111
  # mysqli or PDO
112
  $extension = get_class( $db->dbh );
113
  } else {
@@ -147,14 +147,13 @@ class QM_Collector_Environment extends QM_Collector {
147
  'database' => $db->dbname,
148
  );
149
 
150
- $this->data['db'][$id] = array(
151
  'info' => $info,
152
  'vars' => $mysql_vars,
153
- 'variables' => $variables
154
  );
155
 
156
  }
157
-
158
  }
159
 
160
  $this->data['php']['version'] = phpversion();
@@ -166,7 +165,7 @@ class QM_Collector_Environment extends QM_Collector {
166
  }
167
 
168
  foreach ( $this->php_vars as $setting ) {
169
- $this->data['php']['variables'][$setting]['after'] = ini_get( $setting );
170
  }
171
 
172
  if ( is_callable( 'get_loaded_extensions' ) ) {
@@ -225,7 +224,7 @@ class QM_Collector_Environment extends QM_Collector {
225
  'name' => $server[0],
226
  'version' => $server_version,
227
  'address' => $address,
228
- 'host' => php_uname( 'n' )
229
  );
230
 
231
  }
40
  # caught early before any plugins had a chance to alter them
41
 
42
  foreach ( $this->php_vars as $setting ) {
43
+ if ( isset( $wpdb->qm_php_vars ) and isset( $wpdb->qm_php_vars[ $setting ] ) ) {
44
+ $val = $wpdb->qm_php_vars[ $setting ];
45
  } else {
46
  $val = ini_get( $setting );
47
  }
48
+ $this->data['php']['variables'][ $setting ]['before'] = $val;
49
  }
50
 
51
  }
92
  'max_connections' => false, # Max number of client connections
93
  'query_cache_limit' => true, # Individual query cache size limit
94
  'query_cache_size' => true, # Total cache size limit
95
+ 'query_cache_type' => 'ON', # Query cache on or off
96
  );
97
 
98
  if ( $dbq = QM_Collectors::get( 'db_queries' ) ) {
107
  if ( is_resource( $db->dbh ) ) {
108
  # Old mysql extension
109
  $extension = 'mysql';
110
+ } elseif ( is_object( $db->dbh ) ) {
111
  # mysqli or PDO
112
  $extension = get_class( $db->dbh );
113
  } else {
147
  'database' => $db->dbname,
148
  );
149
 
150
+ $this->data['db'][ $id ] = array(
151
  'info' => $info,
152
  'vars' => $mysql_vars,
153
+ 'variables' => $variables,
154
  );
155
 
156
  }
 
157
  }
158
 
159
  $this->data['php']['version'] = phpversion();
165
  }
166
 
167
  foreach ( $this->php_vars as $setting ) {
168
+ $this->data['php']['variables'][ $setting ]['after'] = ini_get( $setting );
169
  }
170
 
171
  if ( is_callable( 'get_loaded_extensions' ) ) {
224
  'name' => $server[0],
225
  'version' => $server_version,
226
  'address' => $address,
227
+ 'host' => php_uname( 'n' ),
228
  );
229
 
230
  }
collectors/hooks.php CHANGED
@@ -52,10 +52,10 @@ class QM_Collector_Hooks extends QM_Collector {
52
 
53
  foreach ( $hook_names as $name ) {
54
 
55
- $hooks[$name] = self::process_action( $name, $wp_filter, self::$hide_qm, self::$hide_core );
56
 
57
- $all_parts = array_merge( $all_parts, $hooks[$name]['parts'] );
58
- $components = array_merge( $components, $hooks[$name]['components'] );
59
 
60
  }
61
 
@@ -69,10 +69,10 @@ class QM_Collector_Hooks extends QM_Collector {
69
 
70
  $actions = $components = array();
71
 
72
- if ( isset( $wp_filter[$name] ) ) {
73
 
74
  # http://core.trac.wordpress.org/ticket/17817
75
- $action = $wp_filter[$name];
76
 
77
  foreach ( $action as $priority => $callbacks ) {
78
 
@@ -83,12 +83,12 @@ class QM_Collector_Hooks extends QM_Collector {
83
  if ( isset( $callback['component'] ) ) {
84
  if (
85
  ( $hide_qm && 'query-monitor' === $callback['component']->context )
86
- || ( $hide_core && 'core' === $callback['component']->context )
87
  ) {
88
  continue;
89
  }
90
 
91
- $components[$callback['component']->name] = $callback['component']->name;
92
  }
93
 
94
  $actions[] = array(
@@ -97,9 +97,7 @@ class QM_Collector_Hooks extends QM_Collector {
97
  );
98
 
99
  }
100
-
101
  }
102
-
103
  }
104
 
105
  $parts = array_filter( preg_split( '#[_/-]#', $name ) );
52
 
53
  foreach ( $hook_names as $name ) {
54
 
55
+ $hooks[ $name ] = self::process_action( $name, $wp_filter, self::$hide_qm, self::$hide_core );
56
 
57
+ $all_parts = array_merge( $all_parts, $hooks[ $name ]['parts'] );
58
+ $components = array_merge( $components, $hooks[ $name ]['components'] );
59
 
60
  }
61
 
69
 
70
  $actions = $components = array();
71
 
72
+ if ( isset( $wp_filter[ $name ] ) ) {
73
 
74
  # http://core.trac.wordpress.org/ticket/17817
75
+ $action = $wp_filter[ $name ];
76
 
77
  foreach ( $action as $priority => $callbacks ) {
78
 
83
  if ( isset( $callback['component'] ) ) {
84
  if (
85
  ( $hide_qm && 'query-monitor' === $callback['component']->context )
86
+ || ( $hide_core && 'core' === $callback['component']->context )
87
  ) {
88
  continue;
89
  }
90
 
91
+ $components[ $callback['component']->name ] = $callback['component']->name;
92
  }
93
 
94
  $actions[] = array(
97
  );
98
 
99
  }
 
100
  }
 
101
  }
102
 
103
  $parts = array_filter( preg_split( '#[_/-]#', $name ) );
collectors/http.php CHANGED
@@ -36,7 +36,7 @@ class QM_Collector_HTTP extends QM_Collector {
36
  * Filter the arguments used in an HTTP request.
37
  *
38
  * Used to log the request, and to add the logging key to the arguments array.
39
- *
40
  * @param array $args HTTP request arguments.
41
  * @param string $url The request URL.
42
  * @return array HTTP request arguments.
@@ -47,12 +47,12 @@ class QM_Collector_HTTP extends QM_Collector {
47
  // Something has triggered another HTTP request from within the `pre_http_request` filter
48
  // (eg. WordPress Beta Tester does this). This allows for one level of nested queries.
49
  $args['_qm_original_key'] = $args['_qm_key'];
50
- $start = $this->data['http'][$args['_qm_key']]['start'];
51
  } else {
52
  $start = microtime( true );
53
  }
54
  $key = microtime( true ) . $url;
55
- $this->data['http'][$key] = array(
56
  'url' => $url,
57
  'args' => $args,
58
  'start' => $start,
@@ -89,7 +89,7 @@ class QM_Collector_HTTP extends QM_Collector {
89
 
90
  /**
91
  * Debugging action for the HTTP API.
92
- *
93
  * @param mixed $response A parameter which varies depending on $action.
94
  * @param string $action The debug action. Currently one of 'response' or 'transports_list'.
95
  * @param string $class The HTTP transport class name.
@@ -101,11 +101,10 @@ class QM_Collector_HTTP extends QM_Collector {
101
  switch ( $action ) {
102
 
103
  case 'response':
104
-
105
- if ( !empty( $class ) ) {
106
- $this->data['http'][$args['_qm_key']]['transport'] = str_replace( 'wp_http_', '', strtolower( $class ) );
107
  } else {
108
- $this->data['http'][$args['_qm_key']]['transport'] = null;
109
  }
110
 
111
  $this->log_http_response( $response, $args, $url );
@@ -128,12 +127,12 @@ class QM_Collector_HTTP extends QM_Collector {
128
  * @param string $url The request URL.
129
  */
130
  public function log_http_response( $response, array $args, $url ) {
131
- $this->data['http'][$args['_qm_key']]['end'] = microtime( true );
132
- $this->data['http'][$args['_qm_key']]['response'] = $response;
133
- $this->data['http'][$args['_qm_key']]['args'] = $args;
134
  if ( isset( $args['_qm_original_key'] ) ) {
135
- $this->data['http'][$args['_qm_original_key']]['end'] = $this->data['http'][$args['_qm_original_key']]['start'];
136
- $this->data['http'][$args['_qm_original_key']]['response'] = new WP_Error( 'http_request_not_executed', sprintf(
137
  /* translators: %s: Hook name */
138
  __( 'Request not executed due to a filter on %s', 'query-monitor' ),
139
  'pre_http_request'
@@ -158,7 +157,7 @@ class QM_Collector_HTTP extends QM_Collector {
158
  # @TODO this transformation should happen in the output, not the collector
159
  $val = 'true';
160
  }
161
- $this->data['vars'][$var] = $val;
162
  }
163
  }
164
 
@@ -170,12 +169,12 @@ class QM_Collector_HTTP extends QM_Collector {
170
 
171
  $silent = apply_filters( 'qm/collect/silent_http_errors', array(
172
  'http_request_not_executed',
173
- 'airplane_mode_enabled'
174
  ) );
175
 
176
  foreach ( $this->data['http'] as $key => & $http ) {
177
 
178
- if ( !isset( $http['response'] ) ) {
179
  // Timed out
180
  $http['response'] = new WP_Error( 'http_request_timed_out', __( 'Request timed out', 'query-monitor' ) );
181
  $http['end'] = floatval( $http['start'] + $http['args']['timeout'] );
36
  * Filter the arguments used in an HTTP request.
37
  *
38
  * Used to log the request, and to add the logging key to the arguments array.
39
+ *
40
  * @param array $args HTTP request arguments.
41
  * @param string $url The request URL.
42
  * @return array HTTP request arguments.
47
  // Something has triggered another HTTP request from within the `pre_http_request` filter
48
  // (eg. WordPress Beta Tester does this). This allows for one level of nested queries.
49
  $args['_qm_original_key'] = $args['_qm_key'];
50
+ $start = $this->data['http'][ $args['_qm_key'] ]['start'];
51
  } else {
52
  $start = microtime( true );
53
  }
54
  $key = microtime( true ) . $url;
55
+ $this->data['http'][ $key ] = array(
56
  'url' => $url,
57
  'args' => $args,
58
  'start' => $start,
89
 
90
  /**
91
  * Debugging action for the HTTP API.
92
+ *
93
  * @param mixed $response A parameter which varies depending on $action.
94
  * @param string $action The debug action. Currently one of 'response' or 'transports_list'.
95
  * @param string $class The HTTP transport class name.
101
  switch ( $action ) {
102
 
103
  case 'response':
104
+ if ( ! empty( $class ) ) {
105
+ $this->data['http'][ $args['_qm_key'] ]['transport'] = str_replace( 'wp_http_', '', strtolower( $class ) );
 
106
  } else {
107
+ $this->data['http'][ $args['_qm_key'] ]['transport'] = null;
108
  }
109
 
110
  $this->log_http_response( $response, $args, $url );
127
  * @param string $url The request URL.
128
  */
129
  public function log_http_response( $response, array $args, $url ) {
130
+ $this->data['http'][ $args['_qm_key'] ]['end'] = microtime( true );
131
+ $this->data['http'][ $args['_qm_key'] ]['response'] = $response;
132
+ $this->data['http'][ $args['_qm_key'] ]['args'] = $args;
133
  if ( isset( $args['_qm_original_key'] ) ) {
134
+ $this->data['http'][ $args['_qm_original_key'] ]['end'] = $this->data['http'][ $args['_qm_original_key'] ]['start'];
135
+ $this->data['http'][ $args['_qm_original_key'] ]['response'] = new WP_Error( 'http_request_not_executed', sprintf(
136
  /* translators: %s: Hook name */
137
  __( 'Request not executed due to a filter on %s', 'query-monitor' ),
138
  'pre_http_request'
157
  # @TODO this transformation should happen in the output, not the collector
158
  $val = 'true';
159
  }
160
+ $this->data['vars'][ $var ] = $val;
161
  }
162
  }
163
 
169
 
170
  $silent = apply_filters( 'qm/collect/silent_http_errors', array(
171
  'http_request_not_executed',
172
+ 'airplane_mode_enabled',
173
  ) );
174
 
175
  foreach ( $this->data['http'] as $key => & $http ) {
176
 
177
+ if ( ! isset( $http['response'] ) ) {
178
  // Timed out
179
  $http['response'] = new WP_Error( 'http_request_timed_out', __( 'Request timed out', 'query-monitor' ) );
180
  $http['end'] = floatval( $http['start'] + $http['args']['timeout'] );
collectors/languages.php CHANGED
@@ -65,7 +65,6 @@ class QM_Collector_Languages extends QM_Collector {
65
  }
66
  break;
67
  }
68
-
69
  }
70
 
71
  if ( empty( $caller ) ) {
@@ -85,7 +84,7 @@ class QM_Collector_Languages extends QM_Collector {
85
  'caller' => $caller,
86
  'domain' => $domain,
87
  'mofile' => $mofile,
88
- 'found' => file_exists( $mofile ) ? filesize( $mofile ): false,
89
  );
90
 
91
  return $override;
65
  }
66
  break;
67
  }
 
68
  }
69
 
70
  if ( empty( $caller ) ) {
84
  'caller' => $caller,
85
  'domain' => $domain,
86
  'mofile' => $mofile,
87
+ 'found' => file_exists( $mofile ) ? filesize( $mofile ) : false,
88
  );
89
 
90
  return $override;
collectors/overview.php CHANGED
@@ -28,7 +28,7 @@ class QM_Collector_Overview extends QM_Collector {
28
  $this->data['time_limit'] = ini_get( 'max_execution_time' );
29
  $this->data['time_start'] = $GLOBALS['timestart'];
30
 
31
- if ( !empty( $this->data['time_limit'] ) ) {
32
  $this->data['time_usage'] = ( 100 / $this->data['time_limit'] ) * $this->data['time_taken'];
33
  } else {
34
  $this->data['time_usage'] = 0;
@@ -36,7 +36,7 @@ class QM_Collector_Overview extends QM_Collector {
36
 
37
  if ( function_exists( 'memory_get_peak_usage' ) ) {
38
  $this->data['memory'] = memory_get_peak_usage();
39
- } else if ( function_exists( 'memory_get_usage' ) ) {
40
  $this->data['memory'] = memory_get_usage();
41
  } else {
42
  $this->data['memory'] = 0;
28
  $this->data['time_limit'] = ini_get( 'max_execution_time' );
29
  $this->data['time_start'] = $GLOBALS['timestart'];
30
 
31
+ if ( ! empty( $this->data['time_limit'] ) ) {
32
  $this->data['time_usage'] = ( 100 / $this->data['time_limit'] ) * $this->data['time_taken'];
33
  } else {
34
  $this->data['time_usage'] = 0;
36
 
37
  if ( function_exists( 'memory_get_peak_usage' ) ) {
38
  $this->data['memory'] = memory_get_peak_usage();
39
+ } elseif ( function_exists( 'memory_get_usage' ) ) {
40
  $this->data['memory'] = memory_get_usage();
41
  } else {
42
  $this->data['memory'] = 0;
collectors/php_errors.php CHANGED
@@ -40,6 +40,9 @@ class QM_Collector_PHP_Errors extends QM_Collector {
40
  }
41
 
42
  public function __construct() {
 
 
 
43
 
44
  parent::__construct();
45
  set_error_handler( array( $this, 'error_handler' ) );
@@ -117,10 +120,10 @@ class QM_Collector_PHP_Errors extends QM_Collector {
117
 
118
  $filename = QM_Util::standard_dir( $file, '' );
119
 
120
- if ( isset( $this->data['errors'][$type][$key] ) ) {
121
- $this->data['errors'][$type][$key]->calls++;
122
  } else {
123
- $this->data['errors'][$type][$key] = (object) array(
124
  'errno' => $errno,
125
  'type' => $type,
126
  'message' => $message,
@@ -128,7 +131,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
128
  'filename' => $filename,
129
  'line' => $line,
130
  'trace' => $trace,
131
- 'calls' => 1
132
  );
133
  }
134
 
@@ -150,7 +153,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
150
 
151
  if ( $e['type'] & E_RECOVERABLE_ERROR ) {
152
  $error = 'Catchable fatal error';
153
- } else if ( $e['type'] & E_COMPILE_WARNING ) {
154
  $error = 'Warning';
155
  } else {
156
  $error = 'Fatal error';
40
  }
41
 
42
  public function __construct() {
43
+ if ( defined( 'QM_DISABLE_ERROR_HANDLER' ) and QM_DISABLE_ERROR_HANDLER ) {
44
+ return;
45
+ }
46
 
47
  parent::__construct();
48
  set_error_handler( array( $this, 'error_handler' ) );
120
 
121
  $filename = QM_Util::standard_dir( $file, '' );
122
 
123
+ if ( isset( $this->data['errors'][ $type ][ $key ] ) ) {
124
+ $this->data['errors'][ $type ][ $key ]->calls++;
125
  } else {
126
+ $this->data['errors'][ $type ][ $key ] = (object) array(
127
  'errno' => $errno,
128
  'type' => $type,
129
  'message' => $message,
131
  'filename' => $filename,
132
  'line' => $line,
133
  'trace' => $trace,
134
+ 'calls' => 1,
135
  );
136
  }
137
 
153
 
154
  if ( $e['type'] & E_RECOVERABLE_ERROR ) {
155
  $error = 'Catchable fatal error';
156
+ } elseif ( $e['type'] & E_COMPILE_WARNING ) {
157
  $error = 'Warning';
158
  } else {
159
  $error = 'Fatal error';
collectors/redirects.php CHANGED
@@ -29,7 +29,7 @@ class QM_Collector_Redirects extends QM_Collector {
29
 
30
  public function filter_wp_redirect( $location, $status ) {
31
 
32
- if ( !$location ) {
33
  return $location;
34
  }
35
 
29
 
30
  public function filter_wp_redirect( $location, $status ) {
31
 
32
+ if ( ! $location ) {
33
  return $location;
34
  }
35
 
collectors/request.php CHANGED
@@ -27,11 +27,28 @@ class QM_Collector_Request extends QM_Collector {
27
  global $wp, $wp_query, $current_blog, $current_site;
28
 
29
  $qo = get_queried_object();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  if ( is_multisite() ) {
32
  $this->data['multisite']['current_blog'] = array(
33
  'title' => sprintf(
34
- /* translators: 1: Blog ID */
35
  __( 'Current blog: #%d', 'query-monitor' ),
36
  $current_blog->blog_id
37
  ),
@@ -42,7 +59,7 @@ class QM_Collector_Request extends QM_Collector {
42
  if ( QM_Util::is_multi_network() ) {
43
  $this->data['multisite']['current_site'] = array(
44
  'title' => sprintf(
45
- /* translators: 1: Site ID */
46
  __( 'Current site: #%d', 'query-monitor' ),
47
  $current_site->id
48
  ),
@@ -57,11 +74,11 @@ class QM_Collector_Request extends QM_Collector {
57
  $this->data['request']['request'] = '';
58
  }
59
  foreach ( array( 'query_string' ) as $item ) {
60
- $this->data['request'][$item] = $wp->$item;
61
  }
62
  } else {
63
  foreach ( array( 'request', 'matched_rule', 'matched_query', 'query_string' ) as $item ) {
64
- $this->data['request'][$item] = $wp->$item;
65
  }
66
  }
67
 
@@ -70,13 +87,13 @@ class QM_Collector_Request extends QM_Collector {
70
  $query_vars = array();
71
 
72
  foreach ( $qvars as $k => $v ) {
73
- if ( isset( $plugin_qvars[$k] ) ) {
74
  if ( '' !== $v ) {
75
- $query_vars[$k] = $v;
76
  }
77
  } else {
78
- if ( !empty( $v ) ) {
79
- $query_vars[$k] = $v;
80
  }
81
  }
82
  }
@@ -85,16 +102,16 @@ class QM_Collector_Request extends QM_Collector {
85
 
86
  # First add plugin vars to $this->data['qvars']:
87
  foreach ( $query_vars as $k => $v ) {
88
- if ( isset( $plugin_qvars[$k] ) ) {
89
- $this->data['qvars'][$k] = $v;
90
- $this->data['plugin_qvars'][$k] = $v;
91
  }
92
  }
93
 
94
  # Now add all other vars to $this->data['qvars']:
95
  foreach ( $query_vars as $k => $v ) {
96
- if ( !isset( $plugin_qvars[$k] ) ) {
97
- $this->data['qvars'][$k] = $v;
98
  }
99
  }
100
 
@@ -106,8 +123,9 @@ class QM_Collector_Request extends QM_Collector {
106
 
107
  case is_a( $qo, 'WP_Post' ):
108
  // Single post
109
- /* translators: 1: Post type name, 2: Post ID */
110
- $this->data['queried_object']['title'] = sprintf( __( 'Single %1$s: #%2$d', 'query-monitor' ),
 
111
  get_post_type_object( $qo->post_type )->labels->singular_name,
112
  $qo->ID
113
  );
@@ -115,8 +133,9 @@ class QM_Collector_Request extends QM_Collector {
115
 
116
  case is_a( $qo, 'WP_User' ):
117
  // Author archive
118
- /* translators: %s: Author name */
119
- $this->data['queried_object']['title'] = sprintf( __( 'Author archive: %s', 'query-monitor' ),
 
120
  $qo->user_nicename
121
  );
122
  break;
@@ -124,8 +143,9 @@ class QM_Collector_Request extends QM_Collector {
124
  case is_a( $qo, 'WP_Term' ):
125
  case property_exists( $qo, 'term_id' ):
126
  // Term archive
127
- /* translators: %s: Taxonomy term name */
128
- $this->data['queried_object']['title'] = sprintf( __( 'Term archive: %s', 'query-monitor' ),
 
129
  $qo->slug
130
  );
131
  break;
@@ -133,8 +153,9 @@ class QM_Collector_Request extends QM_Collector {
133
  case is_a( $qo, 'WP_Post_Type' ):
134
  case property_exists( $qo, 'has_archive' ):
135
  // Post type archive
136
- /* translators: %s: Post type name */
137
- $this->data['queried_object']['title'] = sprintf( __( 'Post type archive: %s', 'query-monitor' ),
 
138
  $qo->name
139
  );
140
  break;
27
  global $wp, $wp_query, $current_blog, $current_site;
28
 
29
  $qo = get_queried_object();
30
+ $user = wp_get_current_user();
31
+
32
+ if ( $user->exists() ) {
33
+ $user_title = sprintf(
34
+ /* translators: %d: User ID */
35
+ __( 'Current user: #%d', 'query-monitor' ),
36
+ $user->ID
37
+ );
38
+ } else {
39
+ /* translators: No user */
40
+ $user_title = _x( 'None', 'user', 'query-monitor' );
41
+ }
42
+
43
+ $this->data['user'] = array(
44
+ 'title' => $user_title,
45
+ 'data' => ( $user->exists() ? $user : false ),
46
+ );
47
 
48
  if ( is_multisite() ) {
49
  $this->data['multisite']['current_blog'] = array(
50
  'title' => sprintf(
51
+ /* translators: %d: Blog ID */
52
  __( 'Current blog: #%d', 'query-monitor' ),
53
  $current_blog->blog_id
54
  ),
59
  if ( QM_Util::is_multi_network() ) {
60
  $this->data['multisite']['current_site'] = array(
61
  'title' => sprintf(
62
+ /* translators: %d: Site ID */
63
  __( 'Current site: #%d', 'query-monitor' ),
64
  $current_site->id
65
  ),
74
  $this->data['request']['request'] = '';
75
  }
76
  foreach ( array( 'query_string' ) as $item ) {
77
+ $this->data['request'][ $item ] = $wp->$item;
78
  }
79
  } else {
80
  foreach ( array( 'request', 'matched_rule', 'matched_query', 'query_string' ) as $item ) {
81
+ $this->data['request'][ $item ] = $wp->$item;
82
  }
83
  }
84
 
87
  $query_vars = array();
88
 
89
  foreach ( $qvars as $k => $v ) {
90
+ if ( isset( $plugin_qvars[ $k ] ) ) {
91
  if ( '' !== $v ) {
92
+ $query_vars[ $k ] = $v;
93
  }
94
  } else {
95
+ if ( ! empty( $v ) ) {
96
+ $query_vars[ $k ] = $v;
97
  }
98
  }
99
  }
102
 
103
  # First add plugin vars to $this->data['qvars']:
104
  foreach ( $query_vars as $k => $v ) {
105
+ if ( isset( $plugin_qvars[ $k ] ) ) {
106
+ $this->data['qvars'][ $k ] = $v;
107
+ $this->data['plugin_qvars'][ $k ] = $v;
108
  }
109
  }
110
 
111
  # Now add all other vars to $this->data['qvars']:
112
  foreach ( $query_vars as $k => $v ) {
113
+ if ( ! isset( $plugin_qvars[ $k ] ) ) {
114
+ $this->data['qvars'][ $k ] = $v;
115
  }
116
  }
117
 
123
 
124
  case is_a( $qo, 'WP_Post' ):
125
  // Single post
126
+ $this->data['queried_object']['title'] = sprintf(
127
+ /* translators: 1: Post type name, 2: Post ID */
128
+ __( 'Single %1$s: #%2$d', 'query-monitor' ),
129
  get_post_type_object( $qo->post_type )->labels->singular_name,
130
  $qo->ID
131
  );
133
 
134
  case is_a( $qo, 'WP_User' ):
135
  // Author archive
136
+ $this->data['queried_object']['title'] = sprintf(
137
+ /* translators: %s: Author name */
138
+ __( 'Author archive: %s', 'query-monitor' ),
139
  $qo->user_nicename
140
  );
141
  break;
143
  case is_a( $qo, 'WP_Term' ):
144
  case property_exists( $qo, 'term_id' ):
145
  // Term archive
146
+ $this->data['queried_object']['title'] = sprintf(
147
+ /* translators: %s: Taxonomy term name */
148
+ __( 'Term archive: %s', 'query-monitor' ),
149
  $qo->slug
150
  );
151
  break;
153
  case is_a( $qo, 'WP_Post_Type' ):
154
  case property_exists( $qo, 'has_archive' ):
155
  // Post type archive
156
+ $this->data['queried_object']['title'] = sprintf(
157
+ /* translators: %s: Post type name */
158
+ __( 'Post type archive: %s', 'query-monitor' ),
159
  $qo->name
160
  );
161
  break;
collectors/theme.php CHANGED
@@ -63,13 +63,14 @@ class QM_Collector_Theme extends QM_Collector {
63
  break;
64
  }
65
 
66
- if ( function_exists( $conditional ) && call_user_func( $conditional ) ) {
 
 
67
  $filter = str_replace( '_', '', $template );
68
  add_filter( "{$filter}_template_hierarchy", array( $this, 'filter_template_hierarchy' ), 999 );
69
- call_user_func( "get_{$template}_template" );
70
  remove_filter( "{$filter}_template_hierarchy", array( $this, 'filter_template_hierarchy' ), 999 );
71
  }
72
-
73
  }
74
 
75
  }
@@ -148,7 +149,6 @@ class QM_Collector_Theme extends QM_Collector {
148
  }
149
  }
150
  }
151
-
152
  }
153
 
154
  $this->data['stylesheet'] = get_stylesheet();
@@ -168,6 +168,6 @@ function register_qm_collector_theme( array $collectors, QueryMonitor $qm ) {
168
  return $collectors;
169
  }
170
 
171
- if ( !is_admin() ) {
172
  add_filter( 'qm/collectors', 'register_qm_collector_theme', 10, 2 );
173
  }
63
  break;
64
  }
65
 
66
+ $get_template = "get_{$template}_template";
67
+
68
+ if ( function_exists( $conditional ) && function_exists( $get_template ) && call_user_func( $conditional ) ) {
69
  $filter = str_replace( '_', '', $template );
70
  add_filter( "{$filter}_template_hierarchy", array( $this, 'filter_template_hierarchy' ), 999 );
71
+ call_user_func( $get_template );
72
  remove_filter( "{$filter}_template_hierarchy", array( $this, 'filter_template_hierarchy' ), 999 );
73
  }
 
74
  }
75
 
76
  }
149
  }
150
  }
151
  }
 
152
  }
153
 
154
  $this->data['stylesheet'] = get_stylesheet();
168
  return $collectors;
169
  }
170
 
171
+ if ( ! is_admin() ) {
172
  add_filter( 'qm/collectors', 'register_qm_collector_theme', 10, 2 );
173
  }
collectors/transients.php CHANGED
@@ -44,7 +44,7 @@ class QM_Collector_Transients extends QM_Collector {
44
 
45
  public function setted_transient( $transient, $type, $value, $expiration ) {
46
  $trace = new QM_Backtrace( array(
47
- 'ignore_items' => 1 # Ignore the action_setted_(site|blog)_transient method
48
  ) );
49
  $this->data['trans'][] = array(
50
  'transient' => $transient,
44
 
45
  public function setted_transient( $transient, $type, $value, $expiration ) {
46
  $trace = new QM_Backtrace( array(
47
+ 'ignore_items' => 1, # Ignore the action_setted_(site|blog)_transient method
48
  ) );
49
  $this->data['trans'][] = array(
50
  'transient' => $transient,
composer.json CHANGED
@@ -19,6 +19,8 @@
19
  "composer/installers": "~1.0"
20
  },
21
  "require-dev" : {
 
 
22
  "phpunit/phpunit": "~5.7"
23
  }
24
  }
19
  "composer/installers": "~1.0"
20
  },
21
  "require-dev" : {
22
+ "wimg/php-compatibility": "^8",
23
+ "wp-coding-standards/wpcs": "^0.13",
24
  "phpunit/phpunit": "~5.7"
25
  }
26
  }
dispatchers/Html.php CHANGED
@@ -218,16 +218,11 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
218
  );
219
 
220
  if ( did_action( 'wp_head' ) ) {
221
- $absolute = function_exists( 'twentyfifteen_setup' ) || function_exists( 'twentyseventeen_setup' );
222
- if ( apply_filters( 'qm/output/absolute_position', $absolute ) ) {
223
- $class[] = 'qm-absolute';
224
- }
225
-
226
  $class[] = sprintf( 'qm-theme-%s', get_template() );
227
  $class[] = sprintf( 'qm-theme-%s', get_stylesheet() );
228
  }
229
 
230
- if ( !is_admin_bar_showing() ) {
231
  $class[] = 'qm-peek';
232
  }
233
 
@@ -279,7 +274,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
279
 
280
  $json = array(
281
  'menu' => $this->js_admin_bar_menu(),
282
- 'ajax_errors' => array() # @TODO move this into the php_errors collector
283
  );
284
 
285
  echo '<script type="text/javascript">' . "\n\n";
@@ -312,9 +307,9 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
312
  $admin_bar_menu = array(
313
  'top' => array(
314
  'title' => sprintf( '<span class="ab-icon">QM</span><span class="ab-label">%s</span>', $title ),
315
- 'classname' => $class
316
  ),
317
- 'sub' => array()
318
  );
319
 
320
  foreach ( apply_filters( 'qm/output/menus', array() ) as $menu ) {
218
  );
219
 
220
  if ( did_action( 'wp_head' ) ) {
 
 
 
 
 
221
  $class[] = sprintf( 'qm-theme-%s', get_template() );
222
  $class[] = sprintf( 'qm-theme-%s', get_stylesheet() );
223
  }
224
 
225
+ if ( ! is_admin_bar_showing() ) {
226
  $class[] = 'qm-peek';
227
  }
228
 
274
 
275
  $json = array(
276
  'menu' => $this->js_admin_bar_menu(),
277
+ 'ajax_errors' => array(), # @TODO move this into the php_errors collector
278
  );
279
 
280
  echo '<script type="text/javascript">' . "\n\n";
307
  $admin_bar_menu = array(
308
  'top' => array(
309
  'title' => sprintf( '<span class="ab-icon">QM</span><span class="ab-label">%s</span>', $title ),
310
+ 'classname' => $class,
311
  ),
312
+ 'sub' => array(),
313
  );
314
 
315
  foreach ( apply_filters( 'qm/output/menus', array() ) as $menu ) {
dispatchers/REST.php CHANGED
@@ -26,6 +26,7 @@ class QM_Dispatcher_REST extends QM_Dispatcher {
26
  }
27
 
28
  /**
 
29
  *
30
  * @param WP_HTTP_Response $result Result to send to the client. Usually a WP_REST_Response.
31
  * @param WP_REST_Server $server Server instance.
26
  }
27
 
28
  /**
29
+ * Filters a REST API response in order to add QM's headers.
30
  *
31
  * @param WP_HTTP_Response $result Result to send to the client. Usually a WP_REST_Response.
32
  * @param WP_REST_Server $server Server instance.
dispatchers/Redirect.php CHANGED
@@ -26,6 +26,7 @@ class QM_Dispatcher_Redirect extends QM_Dispatcher {
26
  }
27
 
28
  /**
 
29
  *
30
  * @param string $location The path to redirect to.
31
  * @param int $status Status code to use.
26
  }
27
 
28
  /**
29
+ * Filters a redirect location in order to output QM's headers.
30
  *
31
  * @param string $location The path to redirect to.
32
  * @param int $status Status code to use.
output/Html.php CHANGED
@@ -46,11 +46,11 @@ abstract class QM_Output_Html extends QM_Output {
46
  echo '<td class="qm-has-inner">';
47
  self::output_inner( $value );
48
  echo '</td>';
49
- } else if ( is_object( $value ) ) {
50
  echo '<td class="qm-has-inner">';
51
  self::output_inner( get_object_vars( $value ) );
52
  echo '</td>';
53
- } else if ( is_bool( $value ) ) {
54
  if ( $value ) {
55
  echo '<td class="qm-true">true</td>';
56
  } else {
@@ -140,11 +140,21 @@ abstract class QM_Output_Html extends QM_Output {
140
  return $out;
141
  }
142
 
 
 
 
 
 
 
 
 
 
 
143
  protected function menu( array $args ) {
144
 
145
  return array_merge( array(
146
  'id' => esc_attr( "query-monitor-{$this->collector->id}" ),
147
- 'href' => esc_attr( '#' . $this->collector->id() )
148
  ), $args );
149
 
150
  }
46
  echo '<td class="qm-has-inner">';
47
  self::output_inner( $value );
48
  echo '</td>';
49
+ } elseif ( is_object( $value ) ) {
50
  echo '<td class="qm-has-inner">';
51
  self::output_inner( get_object_vars( $value ) );
52
  echo '</td>';
53
+ } elseif ( is_bool( $value ) ) {
54
  if ( $value ) {
55
  echo '<td class="qm-true">true</td>';
56
  } else {
140
  return $out;
141
  }
142
 
143
+ /**
144
+ * Returns a toggle control. Safe for output.
145
+ *
146
+ * @return string Markup for the column sorter controls.
147
+ */
148
+ protected function build_toggler() {
149
+ $out = '<button class="qm-toggle" data-on="+" data-off="-">+</button>';
150
+ return $out;
151
+ }
152
+
153
  protected function menu( array $args ) {
154
 
155
  return array_merge( array(
156
  'id' => esc_attr( "query-monitor-{$this->collector->id}" ),
157
+ 'href' => esc_attr( '#' . $this->collector->id() ),
158
  ), $args );
159
 
160
  }
output/headers/php_errors.php CHANGED
@@ -49,7 +49,6 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
49
  $headers[ $key ] = json_encode( $output_error );
50
 
51
  }
52
-
53
  }
54
 
55
  return array_merge( array(
49
  $headers[ $key ] = json_encode( $output_error );
50
 
51
  }
 
52
  }
53
 
54
  return array_merge( array(
output/html/assets.php CHANGED
@@ -71,11 +71,9 @@ class QM_Output_Html_Assets extends QM_Output_Html {
71
  'header',
72
  'footer',
73
  ) as $position ) {
74
-
75
  if ( isset( $data[ $position ][ $type ] ) ) {
76
  $this->dependency_rows( $data[ $position ][ $type ], $data['raw'][ $type ], $position_labels[ $position ], $type );
77
  }
78
-
79
  }
80
 
81
  echo '</table>';
@@ -176,7 +174,8 @@ class QM_Output_Html_Assets extends QM_Output_Html {
176
 
177
  echo '<td class="qm-wrap qm-ltr">' . esc_html( $dependency->handle ) . '<br><span class="qm-info qm-supplemental">';
178
  if ( is_wp_error( $source ) ) {
179
- printf( '<span class="qm-warn">%s</span>',
 
180
  esc_html( $src )
181
  );
182
  } else {
@@ -217,7 +216,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
217
 
218
  $data = $this->collector->get_data();
219
 
220
- if ( !empty( $data['broken'] ) or !empty( $data['missing'] ) ) {
221
  $class[] = 'qm-error';
222
  }
223
 
@@ -237,7 +236,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
237
  $args = array(
238
  'title' => esc_html( $label ),
239
  'id' => esc_attr( "query-monitor-{$this->collector->id}-{$type}" ),
240
- 'href' => esc_attr( '#' . $this->collector->id() . '-' . $type )
241
  );
242
 
243
  if ( ! empty( $data['broken'][ $type ] ) or ! empty( $data['missing'][ $type ] ) ) {
71
  'header',
72
  'footer',
73
  ) as $position ) {
 
74
  if ( isset( $data[ $position ][ $type ] ) ) {
75
  $this->dependency_rows( $data[ $position ][ $type ], $data['raw'][ $type ], $position_labels[ $position ], $type );
76
  }
 
77
  }
78
 
79
  echo '</table>';
174
 
175
  echo '<td class="qm-wrap qm-ltr">' . esc_html( $dependency->handle ) . '<br><span class="qm-info qm-supplemental">';
176
  if ( is_wp_error( $source ) ) {
177
+ printf(
178
+ '<span class="qm-warn">%s</span>',
179
  esc_html( $src )
180
  );
181
  } else {
216
 
217
  $data = $this->collector->get_data();
218
 
219
+ if ( ! empty( $data['broken'] ) or ! empty( $data['missing'] ) ) {
220
  $class[] = 'qm-error';
221
  }
222
 
236
  $args = array(
237
  'title' => esc_html( $label ),
238
  'id' => esc_attr( "query-monitor-{$this->collector->id}-{$type}" ),
239
+ 'href' => esc_attr( '#' . $this->collector->id() . '-' . $type ),
240
  );
241
 
242
  if ( ! empty( $data['broken'][ $type ] ) or ! empty( $data['missing'][ $type ] ) ) {
output/html/caps.php CHANGED
@@ -143,7 +143,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
143
  $caller = array_pop( $stack );
144
 
145
  if ( ! empty( $stack ) ) {
146
- echo '<button class="qm-toggle" data-on="+" data-off="-">+</button>';
147
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
148
  }
149
 
143
  $caller = array_pop( $stack );
144
 
145
  if ( ! empty( $stack ) ) {
146
+ echo $this->build_toggler(); // WPCS: XSS ok;
147
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
148
  }
149
 
output/html/conditionals.php CHANGED
@@ -75,7 +75,9 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
75
  $menu[] = $this->menu( array(
76
  'title' => esc_html( $cond . '()' ),
77
  'id' => 'query-monitor-conditionals-' . esc_attr( $cond ),
78
- 'meta' => array( 'classname' => 'qm-true qm-ltr' )
 
 
79
  ) );
80
  }
81
 
75
  $menu[] = $this->menu( array(
76
  'title' => esc_html( $cond . '()' ),
77
  'id' => 'query-monitor-conditionals-' . esc_attr( $cond ),
78
+ 'meta' => array(
79
+ 'classname' => 'qm-true qm-ltr',
80
+ ),
81
  ) );
82
  }
83
 
output/html/db_callers.php CHANGED
@@ -53,7 +53,7 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
53
  echo '</tr>';
54
  echo '</thead>';
55
 
56
- if ( !empty( $data['times'] ) ) {
57
 
58
  echo '<tbody>';
59
 
@@ -65,8 +65,8 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
65
  echo '<th scope="row" class="qm-ltr"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="' . esc_attr( $row['caller'] ) . '">' . esc_html( $row['caller'] ) . '</a></th>';
66
 
67
  foreach ( $data['types'] as $type_name => $type_count ) {
68
- if ( isset( $row['types'][$type_name] ) ) {
69
- echo "<td class='qm-num'>" . esc_html( number_format_i18n( $row['types'][$type_name] ) ) . '</td>';
70
  } else {
71
  echo "<td class='qm-num'>&nbsp;</td>";
72
  }
@@ -115,7 +115,7 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
115
  $dbq_data = $dbq->get_data();
116
  if ( isset( $dbq_data['times'] ) ) {
117
  $menu[] = $this->menu( array(
118
- 'title' => esc_html__( 'Queries by Caller', 'query-monitor' )
119
  ) );
120
  }
121
  }
53
  echo '</tr>';
54
  echo '</thead>';
55
 
56
+ if ( ! empty( $data['times'] ) ) {
57
 
58
  echo '<tbody>';
59
 
65
  echo '<th scope="row" class="qm-ltr"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="' . esc_attr( $row['caller'] ) . '">' . esc_html( $row['caller'] ) . '</a></th>';
66
 
67
  foreach ( $data['types'] as $type_name => $type_count ) {
68
+ if ( isset( $row['types'][ $type_name ] ) ) {
69
+ echo "<td class='qm-num'>" . esc_html( number_format_i18n( $row['types'][ $type_name ] ) ) . '</td>';
70
  } else {
71
  echo "<td class='qm-num'>&nbsp;</td>";
72
  }
115
  $dbq_data = $dbq->get_data();
116
  if ( isset( $dbq_data['times'] ) ) {
117
  $menu[] = $this->menu( array(
118
+ 'title' => esc_html__( 'Queries by Caller', 'query-monitor' ),
119
  ) );
120
  }
121
  }
output/html/db_components.php CHANGED
@@ -38,7 +38,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
38
  echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
39
  echo '<thead>';
40
 
41
- if ( !empty( $data['times'] ) ) {
42
  echo '<tr>';
43
  echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
44
 
@@ -58,7 +58,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
58
 
59
  echo '</thead>';
60
 
61
- if ( !empty( $data['times'] ) ) {
62
 
63
  echo '<tbody>';
64
 
@@ -70,7 +70,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
70
  echo '<th scope="row"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="component" data-qm-value="' . esc_attr( $row['component'] ) . '">' . esc_html( $row['component'] ) . '</a></th>';
71
 
72
  foreach ( $data['types'] as $type_name => $type_count ) {
73
- if ( isset( $row['types'][$type_name] ) ) {
74
  echo '<td class="qm-num">' . esc_html( number_format_i18n( $row['types'][ $type_name ] ) ) . '</td>';
75
  } else {
76
  echo '<td class="qm-num">&nbsp;</td>';
@@ -126,7 +126,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
126
  $dbq_data = $dbq->get_data();
127
  if ( isset( $dbq_data['component_times'] ) ) {
128
  $menu[] = $this->menu( array(
129
- 'title' => esc_html__( 'Queries by Component', 'query-monitor' )
130
  ) );
131
  }
132
  }
38
  echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
39
  echo '<thead>';
40
 
41
+ if ( ! empty( $data['times'] ) ) {
42
  echo '<tr>';
43
  echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
44
 
58
 
59
  echo '</thead>';
60
 
61
+ if ( ! empty( $data['times'] ) ) {
62
 
63
  echo '<tbody>';
64
 
70
  echo '<th scope="row"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="component" data-qm-value="' . esc_attr( $row['component'] ) . '">' . esc_html( $row['component'] ) . '</a></th>';
71
 
72
  foreach ( $data['types'] as $type_name => $type_count ) {
73
+ if ( isset( $row['types'][ $type_name ] ) ) {
74
  echo '<td class="qm-num">' . esc_html( number_format_i18n( $row['types'][ $type_name ] ) ) . '</td>';
75
  } else {
76
  echo '<td class="qm-num">&nbsp;</td>';
126
  $dbq_data = $dbq->get_data();
127
  if ( isset( $dbq_data['component_times'] ) ) {
128
  $menu[] = $this->menu( array(
129
+ 'title' => esc_html__( 'Queries by Component', 'query-monitor' ),
130
  ) );
131
  }
132
  }
output/html/db_queries.php CHANGED
@@ -34,11 +34,11 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
34
  return;
35
  }
36
 
37
- if ( !empty( $data['errors'] ) ) {
38
  $this->output_error_queries( $data['errors'] );
39
  }
40
 
41
- if ( !empty( $data['expensive'] ) ) {
42
  $this->output_expensive_queries( $data['expensive'] );
43
  }
44
 
@@ -56,8 +56,9 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
56
  echo '<tbody>';
57
  echo '<tr>';
58
  echo '<td class="qm-warn">';
59
- /* translators: 1: Name of PHP constant, 2: Value of PHP constant */
60
- printf( esc_html__( 'No database queries were logged because the %1$s constant is set to %2$s', 'query-monitor' ),
 
61
  '<code>SAVEQUERIES</code>',
62
  '<code>false</code>'
63
  );
@@ -102,8 +103,9 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
102
  echo '<div class="qm qm-queries" id="qm-query-expensive">';
103
  echo '<table cellspacing="0">';
104
  echo '<caption>';
105
- /* translators: %s: Database query time in seconds */
106
- printf( esc_html__( 'Slow Database Queries (above %ss)', 'query-monitor' ),
 
107
  '<span class="qm-expensive">' . esc_html( number_format_i18n( QM_DB_EXPENSIVE, $dp ) ) . '</span>'
108
  );
109
  echo '</caption>';
@@ -152,7 +154,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
152
  echo '<caption>' . esc_html( sprintf( __( '%s Queries', 'query-monitor' ), $name ) ) . '</caption>';
153
  echo '<thead>';
154
 
155
- if ( !empty( $db->rows ) ) {
156
 
157
  /**
158
  * Filter whether to show the QM extended query information prompt.
@@ -170,7 +172,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
170
  $message = __( 'Extended query information such as the component and affected rows is not available. A conflicting %1$s file is present. <a href="%2$s" target="_blank">See this wiki page for more information.</a>', 'query-monitor' );
171
  } else {
172
  /* translators: 1: Symlink file name, 2: URL to wiki page */
173
- $message = __( 'Extended query information such as the component and affected rows is not available. Query Monitor was unable to symlink its %1$s file into place. <a href="%2$s" target="_blank">See this wiki page for more information.</a>', 'query-monitor' );
174
  }
175
  echo wp_kses( sprintf(
176
  $message,
@@ -246,7 +248,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
246
 
247
  echo '</thead>';
248
 
249
- if ( !empty( $db->rows ) ) {
250
 
251
  echo '<tbody>';
252
 
@@ -301,13 +303,13 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
301
 
302
  $cols = array_flip( $cols );
303
 
304
- if ( !isset( $row['component'] ) ) {
305
  unset( $cols['component'] );
306
  }
307
- if ( !isset( $row['result'] ) ) {
308
  unset( $cols['result'], $cols['errno'] );
309
  }
310
- if ( !isset( $row['stack'] ) ) {
311
  unset( $cols['stack'] );
312
  }
313
 
@@ -331,7 +333,6 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
331
  foreach ( $filtered_trace as $item ) {
332
  $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
333
  }
334
-
335
  } else {
336
 
337
  $caller_name = esc_html( $row['caller'] );
@@ -350,7 +351,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
350
  if ( isset( $cols['sql'] ) ) {
351
  $row_attr['data-qm-type'] = $row['type'];
352
  if ( 'SELECT' !== $row['type'] ) {
353
- $row_attr['data-qm-type'] .= ' non-select';
354
  }
355
  }
356
  if ( isset( $cols['component'] ) && $row['component'] ) {
@@ -366,7 +367,6 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
366
  if ( $row['is_main_query'] ) {
367
  $row_attr['data-qm-caller'] .= ' qm-main-query';
368
  }
369
-
370
  }
371
  if ( isset( $cols['time'] ) ) {
372
  $row_attr['data-qm-time'] = $row['ltime'];
@@ -395,7 +395,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
395
  echo "<td class='qm-row-caller qm-ltr qm-has-toggle qm-nowrap'><ol class='qm-toggler qm-numbered'>";
396
 
397
  if ( ! empty( $stack ) ) {
398
- echo '<button class="qm-toggle" data-on="+" data-off="-">+</button>';
399
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
400
  }
401
 
@@ -438,7 +438,6 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
438
  } else {
439
  echo "<td class='qm-row-result qm-num'>" . esc_html( $row['result'] ) . "</td>\n";
440
  }
441
-
442
  }
443
 
444
  if ( isset( $cols['time'] ) ) {
34
  return;
35
  }
36
 
37
+ if ( ! empty( $data['errors'] ) ) {
38
  $this->output_error_queries( $data['errors'] );
39
  }
40
 
41
+ if ( ! empty( $data['expensive'] ) ) {
42
  $this->output_expensive_queries( $data['expensive'] );
43
  }
44
 
56
  echo '<tbody>';
57
  echo '<tr>';
58
  echo '<td class="qm-warn">';
59
+ printf(
60
+ /* translators: 1: Name of PHP constant, 2: Value of PHP constant */
61
+ esc_html__( 'No database queries were logged because the %1$s constant is set to %2$s', 'query-monitor' ),
62
  '<code>SAVEQUERIES</code>',
63
  '<code>false</code>'
64
  );
103
  echo '<div class="qm qm-queries" id="qm-query-expensive">';
104
  echo '<table cellspacing="0">';
105
  echo '<caption>';
106
+ printf(
107
+ /* translators: %s: Database query time in seconds */
108
+ esc_html__( 'Slow Database Queries (above %ss)', 'query-monitor' ),
109
  '<span class="qm-expensive">' . esc_html( number_format_i18n( QM_DB_EXPENSIVE, $dp ) ) . '</span>'
110
  );
111
  echo '</caption>';
154
  echo '<caption>' . esc_html( sprintf( __( '%s Queries', 'query-monitor' ), $name ) ) . '</caption>';
155
  echo '<thead>';
156
 
157
+ if ( ! empty( $db->rows ) ) {
158
 
159
  /**
160
  * Filter whether to show the QM extended query information prompt.
172
  $message = __( 'Extended query information such as the component and affected rows is not available. A conflicting %1$s file is present. <a href="%2$s" target="_blank">See this wiki page for more information.</a>', 'query-monitor' );
173
  } else {
174
  /* translators: 1: Symlink file name, 2: URL to wiki page */
175
+ $message = __( 'Extended query information such as the component and affected rows is not available. Query Monitor was unable to symlink its %1$s file into place. <a href="%2$s" target="_blank">See this wiki page for more information.</a>', 'query-monitor' );
176
  }
177
  echo wp_kses( sprintf(
178
  $message,
248
 
249
  echo '</thead>';
250
 
251
+ if ( ! empty( $db->rows ) ) {
252
 
253
  echo '<tbody>';
254
 
303
 
304
  $cols = array_flip( $cols );
305
 
306
+ if ( ! isset( $row['component'] ) ) {
307
  unset( $cols['component'] );
308
  }
309
+ if ( ! isset( $row['result'] ) ) {
310
  unset( $cols['result'], $cols['errno'] );
311
  }
312
+ if ( ! isset( $row['stack'] ) ) {
313
  unset( $cols['stack'] );
314
  }
315
 
333
  foreach ( $filtered_trace as $item ) {
334
  $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
335
  }
 
336
  } else {
337
 
338
  $caller_name = esc_html( $row['caller'] );
351
  if ( isset( $cols['sql'] ) ) {
352
  $row_attr['data-qm-type'] = $row['type'];
353
  if ( 'SELECT' !== $row['type'] ) {
354
+ $row_attr['data-qm-type'] .= ' non-select';
355
  }
356
  }
357
  if ( isset( $cols['component'] ) && $row['component'] ) {
367
  if ( $row['is_main_query'] ) {
368
  $row_attr['data-qm-caller'] .= ' qm-main-query';
369
  }
 
370
  }
371
  if ( isset( $cols['time'] ) ) {
372
  $row_attr['data-qm-time'] = $row['ltime'];
395
  echo "<td class='qm-row-caller qm-ltr qm-has-toggle qm-nowrap'><ol class='qm-toggler qm-numbered'>";
396
 
397
  if ( ! empty( $stack ) ) {
398
+ echo $this->build_toggler(); // WPCS: XSS ok;
399
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
400
  }
401
 
438
  } else {
439
  echo "<td class='qm-row-result qm-num'>" . esc_html( $row['result'] ) . "</td>\n";
440
  }
 
441
  }
442
 
443
  if ( isset( $cols['time'] ) ) {
output/html/debug_bar.php CHANGED
@@ -60,7 +60,7 @@ function register_qm_output_html_debug_bar( array $output, QM_Collectors $collec
60
  $collector = QM_Collectors::get( "debug_bar_{$panel_id}" );
61
 
62
  if ( $collector and $collector->is_visible() ) {
63
- $output["debug_bar_{$panel_id}"] = new QM_Output_Html_Debug_Bar( $collector );
64
  }
65
  }
66
 
60
  $collector = QM_Collectors::get( "debug_bar_{$panel_id}" );
61
 
62
  if ( $collector and $collector->is_visible() ) {
63
+ $output[ "debug_bar_{$panel_id}" ] = new QM_Output_Html_Debug_Bar( $collector );
64
  }
65
  }
66
 
output/html/environment.php CHANGED
@@ -57,7 +57,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
57
 
58
  echo '<tr>';
59
  echo '<th scope="row">user</th>';
60
- if ( !empty( $data['php']['user'] ) ) {
61
  echo '<td>' . esc_html( $data['php']['user'] ) . '</td>';
62
  } else {
63
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
@@ -103,10 +103,8 @@ class QM_Output_Html_Environment extends QM_Output_Html {
103
  echo '<th scope="row">' . esc_html__( 'Error Reporting', 'query-monitor' ) . '</th>';
104
  echo '<td class="qm-has-toggle qm-ltr"><div class="qm-toggler">';
105
 
106
- printf(
107
- '%1$s <button class="qm-toggle" data-on="+" data-off="-">+</button>',
108
- esc_html( $data['php']['error_reporting'] )
109
- );
110
 
111
  echo '<div class="qm-toggled">';
112
  echo "<ul class='qm-supplemental'><li>{$error_levels}</li></ul>"; // WPCS: XSS ok.
@@ -120,10 +118,8 @@ class QM_Output_Html_Environment extends QM_Output_Html {
120
  echo '<th scope="row">' . esc_html__( 'Extensions', 'query-monitor' ) . '</th>';
121
  echo '<td class="qm-has-toggle qm-ltr"><div class="qm-toggler">';
122
 
123
- printf(
124
- '%1$s <button class="qm-toggle" data-on="+" data-off="-">+</button>',
125
- esc_html( number_format_i18n( count( $data['php']['extensions'] ) ) )
126
- );
127
 
128
  echo '<div class="qm-toggled"><ul class="qm-supplemental"><li>';
129
  echo implode( '</li><li>', array_map( 'esc_html', $data['php']['extensions'] ) );
@@ -186,9 +182,9 @@ class QM_Output_Html_Environment extends QM_Output_Html {
186
  $append = '';
187
  $show_warning = false;
188
 
189
- if ( ( true === $db['vars'][$key] ) and empty( $val ) ) {
190
  $show_warning = true;
191
- } elseif ( is_string( $db['vars'][$key] ) and ( $val !== $db['vars'][$key] ) ) {
192
  $show_warning = true;
193
  }
194
 
@@ -200,7 +196,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
200
  );
201
  }
202
 
203
- if ( is_numeric( $val ) and ( $val >= ( 1024*1024 ) ) ) {
204
  $append .= sprintf(
205
  '<br><span class="qm-info qm-supplemental">~%s</span>',
206
  esc_html( size_format( $val ) )
@@ -209,7 +205,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
209
 
210
  $class = ( $show_warning ) ? 'qm-warn' : '';
211
 
212
- if ( !$first ) {
213
  echo '<tr class="' . esc_attr( $class ) . '">';
214
  }
215
 
@@ -230,7 +226,6 @@ class QM_Output_Html_Environment extends QM_Output_Html {
230
  echo '</div>';
231
 
232
  }
233
-
234
  }
235
 
236
  echo '<div class="qm qm-third" style="float:right !important">';
@@ -275,7 +270,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
275
 
276
  echo '<tr>';
277
  echo '<th scope="row">' . esc_html__( 'version', 'query-monitor' ) . '</th>';
278
- if ( !empty( $data['server']['version'] ) ) {
279
  echo '<td class="qm-wrap">' . esc_html( $data['server']['version'] ) . '</td>';
280
  } else {
281
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
@@ -284,7 +279,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
284
 
285
  echo '<tr>';
286
  echo '<th scope="row">' . esc_html__( 'address', 'query-monitor' ) . '</th>';
287
- if ( !empty( $data['server']['address'] ) ) {
288
  echo '<td class="qm-wrap">' . esc_html( $data['server']['address'] ) . '</td>';
289
  } else {
290
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
57
 
58
  echo '<tr>';
59
  echo '<th scope="row">user</th>';
60
+ if ( ! empty( $data['php']['user'] ) ) {
61
  echo '<td>' . esc_html( $data['php']['user'] ) . '</td>';
62
  } else {
63
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
103
  echo '<th scope="row">' . esc_html__( 'Error Reporting', 'query-monitor' ) . '</th>';
104
  echo '<td class="qm-has-toggle qm-ltr"><div class="qm-toggler">';
105
 
106
+ echo esc_html( $data['php']['error_reporting'] );
107
+ echo $this->build_toggler(); // WPCS: XSS ok;
 
 
108
 
109
  echo '<div class="qm-toggled">';
110
  echo "<ul class='qm-supplemental'><li>{$error_levels}</li></ul>"; // WPCS: XSS ok.
118
  echo '<th scope="row">' . esc_html__( 'Extensions', 'query-monitor' ) . '</th>';
119
  echo '<td class="qm-has-toggle qm-ltr"><div class="qm-toggler">';
120
 
121
+ echo esc_html( number_format_i18n( count( $data['php']['extensions'] ) ) );
122
+ echo $this->build_toggler(); // WPCS: XSS ok;
 
 
123
 
124
  echo '<div class="qm-toggled"><ul class="qm-supplemental"><li>';
125
  echo implode( '</li><li>', array_map( 'esc_html', $data['php']['extensions'] ) );
182
  $append = '';
183
  $show_warning = false;
184
 
185
+ if ( ( true === $db['vars'][ $key ] ) and empty( $val ) ) {
186
  $show_warning = true;
187
+ } elseif ( is_string( $db['vars'][ $key ] ) and ( $val !== $db['vars'][ $key ] ) ) {
188
  $show_warning = true;
189
  }
190
 
196
  );
197
  }
198
 
199
+ if ( is_numeric( $val ) and ( $val >= ( 1024 * 1024 ) ) ) {
200
  $append .= sprintf(
201
  '<br><span class="qm-info qm-supplemental">~%s</span>',
202
  esc_html( size_format( $val ) )
205
 
206
  $class = ( $show_warning ) ? 'qm-warn' : '';
207
 
208
+ if ( ! $first ) {
209
  echo '<tr class="' . esc_attr( $class ) . '">';
210
  }
211
 
226
  echo '</div>';
227
 
228
  }
 
229
  }
230
 
231
  echo '<div class="qm qm-third" style="float:right !important">';
270
 
271
  echo '<tr>';
272
  echo '<th scope="row">' . esc_html__( 'version', 'query-monitor' ) . '</th>';
273
+ if ( ! empty( $data['server']['version'] ) ) {
274
  echo '<td class="qm-wrap">' . esc_html( $data['server']['version'] ) . '</td>';
275
  } else {
276
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
279
 
280
  echo '<tr>';
281
  echo '<th scope="row">' . esc_html__( 'address', 'query-monitor' ) . '</th>';
282
+ if ( ! empty( $data['server']['address'] ) ) {
283
  echo '<td class="qm-wrap">' . esc_html( $data['server']['address'] ) . '</td>';
284
  } else {
285
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
output/html/hooks.php CHANGED
@@ -64,14 +64,13 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
64
 
65
  echo '<tbody class="qm-group">';
66
 
67
- if ( !empty( $screen ) ) {
68
 
69
  if ( false !== strpos( $hook['name'], $screen . '.php' ) ) {
70
  $hook_name = str_replace( '-' . $screen . '.php', '-<span class="qm-current">' . $screen . '.php</span>', esc_html( $hook['name'] ) );
71
  } else {
72
  $hook_name = str_replace( '-' . $screen, '-<span class="qm-current">' . $screen . '</span>', esc_html( $hook['name'] ) );
73
  }
74
-
75
  } else {
76
  $hook_name = esc_html( $hook['name'] );
77
  }
@@ -86,7 +85,7 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
86
 
87
  $attr = '';
88
 
89
- if ( !empty( $hook['actions'] ) ) {
90
  $rowspan = count( $hook['actions'] );
91
  } else {
92
  $rowspan = 1;
@@ -96,7 +95,7 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
96
  $attr .= ' ' . $a . '="' . esc_attr( $v ) . '"';
97
  }
98
 
99
- if ( !empty( $hook['actions'] ) ) {
100
 
101
  $first = true;
102
 
@@ -157,7 +156,6 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
157
  echo '</tr>';
158
  $first = false;
159
  }
160
-
161
  } else {
162
  echo "<tr{$attr}>"; // WPCS: XSS ok.
163
  echo '<th scope="row" class="qm-ltr">';
64
 
65
  echo '<tbody class="qm-group">';
66
 
67
+ if ( ! empty( $screen ) ) {
68
 
69
  if ( false !== strpos( $hook['name'], $screen . '.php' ) ) {
70
  $hook_name = str_replace( '-' . $screen . '.php', '-<span class="qm-current">' . $screen . '.php</span>', esc_html( $hook['name'] ) );
71
  } else {
72
  $hook_name = str_replace( '-' . $screen, '-<span class="qm-current">' . $screen . '</span>', esc_html( $hook['name'] ) );
73
  }
 
74
  } else {
75
  $hook_name = esc_html( $hook['name'] );
76
  }
85
 
86
  $attr = '';
87
 
88
+ if ( ! empty( $hook['actions'] ) ) {
89
  $rowspan = count( $hook['actions'] );
90
  } else {
91
  $rowspan = 1;
95
  $attr .= ' ' . $a . '="' . esc_attr( $v ) . '"';
96
  }
97
 
98
+ if ( ! empty( $hook['actions'] ) ) {
99
 
100
  $first = true;
101
 
156
  echo '</tr>';
157
  $first = false;
158
  }
 
159
  } else {
160
  echo "<tr{$attr}>"; // WPCS: XSS ok.
161
  echo '<th scope="row" class="qm-ltr">';
output/html/http.php CHANGED
@@ -33,13 +33,13 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
33
 
34
  $vars = array();
35
 
36
- if ( !empty( $data['vars'] ) ) {
37
  foreach ( $data['vars'] as $key => $value ) {
38
  $vars[] = $key . ': ' . $value;
39
  }
40
  }
41
 
42
- if ( !empty( $data['http'] ) ) {
43
 
44
  echo '<caption class="screen-reader-text">' . esc_html__( 'HTTP API Calls', 'query-monitor' ) . '</caption>';
45
 
@@ -84,7 +84,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
84
  $css = '';
85
 
86
  if ( intval( $code ) >= 400 ) {
87
- $is_error = true;;
88
  }
89
 
90
  $response = $code . ' ' . $msg;
@@ -167,7 +167,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
167
  $caller = array_pop( $stack );
168
 
169
  if ( ! empty( $stack ) ) {
170
- echo '<button class="qm-toggle" data-on="+" data-off="-">+</button>';
171
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
172
  }
173
 
@@ -223,7 +223,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
223
  echo '<tr>';
224
  echo '<td style="text-align:center !important"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
225
  echo '</tr>';
226
- if ( !empty( $vars ) ) {
227
  echo '<tr>';
228
  printf(
229
  '<td>%s</td>',
@@ -275,7 +275,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
275
 
276
  if ( isset( $data['errors']['alert'] ) ) {
277
  $args['meta']['classname'] = 'qm-alert';
278
- } else if ( isset( $data['errors']['warning'] ) ) {
279
  $args['meta']['classname'] = 'qm-warning';
280
  }
281
 
33
 
34
  $vars = array();
35
 
36
+ if ( ! empty( $data['vars'] ) ) {
37
  foreach ( $data['vars'] as $key => $value ) {
38
  $vars[] = $key . ': ' . $value;
39
  }
40
  }
41
 
42
+ if ( ! empty( $data['http'] ) ) {
43
 
44
  echo '<caption class="screen-reader-text">' . esc_html__( 'HTTP API Calls', 'query-monitor' ) . '</caption>';
45
 
84
  $css = '';
85
 
86
  if ( intval( $code ) >= 400 ) {
87
+ $is_error = true;
88
  }
89
 
90
  $response = $code . ' ' . $msg;
167
  $caller = array_pop( $stack );
168
 
169
  if ( ! empty( $stack ) ) {
170
+ echo $this->build_toggler(); // WPCS: XSS ok;
171
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
172
  }
173
 
223
  echo '<tr>';
224
  echo '<td style="text-align:center !important"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
225
  echo '</tr>';
226
+ if ( ! empty( $vars ) ) {
227
  echo '<tr>';
228
  printf(
229
  '<td>%s</td>',
275
 
276
  if ( isset( $data['errors']['alert'] ) ) {
277
  $args['meta']['classname'] = 'qm-alert';
278
+ } elseif ( isset( $data['errors']['warning'] ) ) {
279
  $args['meta']['classname'] = 'qm-warning';
280
  }
281
 
output/html/overview.php CHANGED
@@ -139,7 +139,7 @@ class QM_Output_Html_Overview extends QM_Output_Html {
139
  if ( $cache_data['ext_object_cache'] ) {
140
  printf(
141
  '<a href="%s">%s</a>',
142
- network_admin_url( 'plugins.php?plugin_status=dropins' ),
143
  esc_html__( 'External object cache in use', 'query-monitor' )
144
  );
145
  } else {
139
  if ( $cache_data['ext_object_cache'] ) {
140
  printf(
141
  '<a href="%s">%s</a>',
142
+ esc_url( network_admin_url( 'plugins.php?plugin_status=dropins' ) ),
143
  esc_html__( 'External object cache in use', 'query-monitor' )
144
  );
145
  } else {
output/html/php_errors.php CHANGED
@@ -56,16 +56,16 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
56
 
57
  foreach ( $types as $type => $title ) {
58
 
59
- if ( isset( $data['errors'][$type] ) ) {
60
 
61
  echo '<tbody class="qm-group">';
62
  echo '<tr class="qm-php-error qm-php-error-' . esc_attr( $type ) . '">';
63
- echo '<th scope="row" rowspan="' . count( $data['errors'][$type] ) . '"><span class="dashicons dashicons-warning"></span>' . esc_html( $title ) . '</th>';
64
  $first = true;
65
 
66
- foreach ( $data['errors'][$type] as $error ) {
67
 
68
- if ( !$first ) {
69
  echo '<tr class="qm-php-error qm-php-error-' . esc_attr( $type ) . '">';
70
  }
71
 
@@ -88,7 +88,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
88
  foreach ( $filtered_trace as $i => $item ) {
89
  if ( isset( $item['file'] ) && isset( $item['line'] ) ) {
90
  $stack[] = self::output_filename( $item['display'], $item['file'], $item['line'] );
91
- } else if ( 0 === $i ) {
92
  $stack[] = self::output_filename( $item['display'], $error->file, $error->line );
93
  } else {
94
  $stack[] = $item['display'] . '<br><span class="qm-info qm-supplemental"><em>' . __( 'Unknown location', 'query-monitor' ) . '</em></span>';
@@ -113,7 +113,6 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
113
 
114
  echo '</tbody>';
115
  }
116
-
117
  }
118
 
119
  echo '</table>';
@@ -154,7 +153,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
154
 
155
  $count = 0;
156
 
157
- if ( isset( $data['errors']["{$type}-suppressed"] ) ) {
158
  $key = "{$type}-suppressed";
159
  $count = count( $data['errors'][ $key ] );
160
  }
@@ -172,7 +171,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
172
  'title' => esc_html( sprintf(
173
  $label,
174
  number_format_i18n( $count )
175
- ) )
176
  ) );
177
  }
178
 
56
 
57
  foreach ( $types as $type => $title ) {
58
 
59
+ if ( isset( $data['errors'][ $type ] ) ) {
60
 
61
  echo '<tbody class="qm-group">';
62
  echo '<tr class="qm-php-error qm-php-error-' . esc_attr( $type ) . '">';
63
+ echo '<th scope="row" rowspan="' . count( $data['errors'][ $type ] ) . '"><span class="dashicons dashicons-warning"></span>' . esc_html( $title ) . '</th>';
64
  $first = true;
65
 
66
+ foreach ( $data['errors'][ $type ] as $error ) {
67
 
68
+ if ( ! $first ) {
69
  echo '<tr class="qm-php-error qm-php-error-' . esc_attr( $type ) . '">';
70
  }
71
 
88
  foreach ( $filtered_trace as $i => $item ) {
89
  if ( isset( $item['file'] ) && isset( $item['line'] ) ) {
90
  $stack[] = self::output_filename( $item['display'], $item['file'], $item['line'] );
91
+ } elseif ( 0 === $i ) {
92
  $stack[] = self::output_filename( $item['display'], $error->file, $error->line );
93
  } else {
94
  $stack[] = $item['display'] . '<br><span class="qm-info qm-supplemental"><em>' . __( 'Unknown location', 'query-monitor' ) . '</em></span>';
113
 
114
  echo '</tbody>';
115
  }
 
116
  }
117
 
118
  echo '</table>';
153
 
154
  $count = 0;
155
 
156
+ if ( isset( $data['errors'][ "{$type}-suppressed" ] ) ) {
157
  $key = "{$type}-suppressed";
158
  $count = count( $data['errors'][ $key ] );
159
  }
171
  'title' => esc_html( sprintf(
172
  $label,
173
  number_format_i18n( $count )
174
+ ) ),
175
  ) );
176
  }
177
 
output/html/request.php CHANGED
@@ -45,15 +45,15 @@ class QM_Output_Html_Request extends QM_Output_Html {
45
  'query_string' => __( 'Query String', 'query-monitor' ),
46
  ) as $item => $name ) {
47
 
48
- if ( !isset( $data['request'][$item] ) ) {
49
  continue;
50
  }
51
 
52
- if ( ! empty( $data['request'][$item] ) ) {
53
  if ( in_array( $item, array( 'request', 'matched_query', 'query_string' ), true ) ) {
54
- $value = self::format_url( $data['request'][$item] );
55
  } else {
56
- $value = esc_html( $data['request'][$item] );
57
  }
58
  } else {
59
  $value = '<em>' . esc_html__( 'none', 'query-monitor' ) . '</em>';
@@ -87,17 +87,17 @@ class QM_Output_Html_Request extends QM_Output_Html {
87
 
88
  echo '</th>';
89
 
90
- if ( !empty( $data['qvars'] ) ) {
91
 
92
  $first = true;
93
 
94
- foreach( $data['qvars'] as $var => $value ) {
95
 
96
- if ( !$first ) {
97
  echo '<tr>';
98
  }
99
 
100
- if ( isset( $data['plugin_qvars'][$var] ) ) {
101
  echo '<td class="qm-ltr"><span class="qm-current">' . esc_html( $var ) . '</span></td>';
102
  } else {
103
  echo '<td class="qm-ltr">' . esc_html( $var ) . '</td>';
@@ -116,7 +116,6 @@ class QM_Output_Html_Request extends QM_Output_Html {
116
  $first = false;
117
 
118
  }
119
-
120
  } else {
121
 
122
  echo '<td colspan="2"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
@@ -133,10 +132,11 @@ class QM_Output_Html_Request extends QM_Output_Html {
133
  echo '<th>' . esc_html__( 'Queried Object', 'query-monitor' ) . '</th>';
134
  echo '<td colspan="2" class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
135
 
136
- printf(
137
- '<div class="qm-inner-toggle">%1$s (%2$s) <button class="qm-toggle" data-on="+" data-off="-">+</button></div>',
138
  esc_html( $data['queried_object']['title'] ),
139
- esc_html( get_class( $data['queried_object']['data'] ) )
 
140
  );
141
 
142
  echo '<div class="qm-toggled">';
@@ -149,7 +149,35 @@ class QM_Output_Html_Request extends QM_Output_Html {
149
 
150
  }
151
 
152
- if ( !empty( $data['multisite'] ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
  $rowspan = count( $data['multisite'] );
155
 
@@ -159,17 +187,18 @@ class QM_Output_Html_Request extends QM_Output_Html {
159
 
160
  $first = true;
161
 
162
- foreach( $data['multisite'] as $var => $value ) {
163
 
164
- if ( !$first ) {
165
  echo '<tr>';
166
  }
167
 
168
  echo '<td colspan="2" class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
169
 
170
- printf(
171
- '<div class="qm-inner-toggle">%1$s <button class="qm-toggle" data-on="+" data-off="-">+</button></div>',
172
- esc_html( $value['title'] )
 
173
  );
174
 
175
  echo '<div class="qm-toggled">';
45
  'query_string' => __( 'Query String', 'query-monitor' ),
46
  ) as $item => $name ) {
47
 
48
+ if ( ! isset( $data['request'][ $item ] ) ) {
49
  continue;
50
  }
51
 
52
+ if ( ! empty( $data['request'][ $item ] ) ) {
53
  if ( in_array( $item, array( 'request', 'matched_query', 'query_string' ), true ) ) {
54
+ $value = self::format_url( $data['request'][ $item ] );
55
  } else {
56
+ $value = esc_html( $data['request'][ $item ] );
57
  }
58
  } else {
59
  $value = '<em>' . esc_html__( 'none', 'query-monitor' ) . '</em>';
87
 
88
  echo '</th>';
89
 
90
+ if ( ! empty( $data['qvars'] ) ) {
91
 
92
  $first = true;
93
 
94
+ foreach ( $data['qvars'] as $var => $value ) {
95
 
96
+ if ( ! $first ) {
97
  echo '<tr>';
98
  }
99
 
100
+ if ( isset( $data['plugin_qvars'][ $var ] ) ) {
101
  echo '<td class="qm-ltr"><span class="qm-current">' . esc_html( $var ) . '</span></td>';
102
  } else {
103
  echo '<td class="qm-ltr">' . esc_html( $var ) . '</td>';
116
  $first = false;
117
 
118
  }
 
119
  } else {
120
 
121
  echo '<td colspan="2"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
132
  echo '<th>' . esc_html__( 'Queried Object', 'query-monitor' ) . '</th>';
133
  echo '<td colspan="2" class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
134
 
135
+ printf( // WPCS: XSS ok.
136
+ '<div class="qm-inner-toggle">%1$s (%2$s) %3$s</div>',
137
  esc_html( $data['queried_object']['title'] ),
138
+ esc_html( get_class( $data['queried_object']['data'] ) ),
139
+ $this->build_toggler()
140
  );
141
 
142
  echo '<div class="qm-toggled">';
149
 
150
  }
151
 
152
+ echo '<tbody class="qm-group">';
153
+ echo '<tr>';
154
+ echo '<th>' . esc_html__( 'User', 'query-monitor' ) . '</th>';
155
+
156
+ if ( $data['user']['data'] ) {
157
+ echo '<td colspan="2" class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
158
+
159
+ printf( // WPCS: XSS ok.
160
+ '<div class="qm-inner-toggle">%1$s %2$s</div>',
161
+ esc_html( $data['user']['title'] ),
162
+ $this->build_toggler()
163
+ );
164
+
165
+ echo '<div class="qm-toggled">';
166
+ self::output_inner( $data['user']['data'] );
167
+ echo '</div>';
168
+
169
+ echo '</div></td>';
170
+ } else {
171
+ echo '<td colspan="2">';
172
+ esc_html_e( 'No current user', 'query-monitor' );
173
+ echo '</td>';
174
+ }
175
+
176
+ echo '</tr>';
177
+
178
+ echo '</tbody>';
179
+
180
+ if ( ! empty( $data['multisite'] ) ) {
181
 
182
  $rowspan = count( $data['multisite'] );
183
 
187
 
188
  $first = true;
189
 
190
+ foreach ( $data['multisite'] as $var => $value ) {
191
 
192
+ if ( ! $first ) {
193
  echo '<tr>';
194
  }
195
 
196
  echo '<td colspan="2" class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
197
 
198
+ printf( // WPCS: XSS ok.
199
+ '<div class="qm-inner-toggle">%1$s %2$s</div>',
200
+ esc_html( $value['title'] ),
201
+ $this->build_toggler()
202
  );
203
 
204
  echo '<div class="qm-toggled">';
output/html/rewrites.php CHANGED
@@ -39,7 +39,6 @@ class QM_Output_Html_Rewrites extends QM_Output_Html {
39
  echo '<tbody>';
40
 
41
  if ( ! empty( $data['matching'] ) ) {
42
-
43
  foreach ( $data['matching'] as $rule => $query ) {
44
 
45
  $query = str_replace( 'index.php?', '', $query );
@@ -52,7 +51,6 @@ class QM_Output_Html_Rewrites extends QM_Output_Html {
52
  echo '</tr>';
53
 
54
  }
55
-
56
  } else {
57
 
58
  echo '<tr>';
39
  echo '<tbody>';
40
 
41
  if ( ! empty( $data['matching'] ) ) {
 
42
  foreach ( $data['matching'] as $rule => $query ) {
43
 
44
  $query = str_replace( 'index.php?', '', $query );
51
  echo '</tr>';
52
 
53
  }
 
54
  } else {
55
 
56
  echo '<tr>';
output/html/theme.php CHANGED
@@ -44,13 +44,11 @@ class QM_Output_Html_Theme extends QM_Output_Html {
44
  echo '<th scope="row">' . esc_html__( 'Template File', 'query-monitor' ) . '</th>';
45
 
46
  if ( ! empty( $data['template_path'] ) ) {
47
-
48
  if ( $data['is_child_theme'] ) {
49
  echo '<td class="qm-ltr">' . self::output_filename( $data['theme_template_file'], $data['template_path'] ) . '</td>'; // WPCS: XSS ok.
50
  } else {
51
  echo '<td class="qm-ltr">' . self::output_filename( $data['template_file'], $data['template_path'] ) . '</td>'; // WPCS: XSS ok.
52
  }
53
-
54
  } else {
55
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
56
  }
44
  echo '<th scope="row">' . esc_html__( 'Template File', 'query-monitor' ) . '</th>';
45
 
46
  if ( ! empty( $data['template_path'] ) ) {
 
47
  if ( $data['is_child_theme'] ) {
48
  echo '<td class="qm-ltr">' . self::output_filename( $data['theme_template_file'], $data['template_path'] ) . '</td>'; // WPCS: XSS ok.
49
  } else {
50
  echo '<td class="qm-ltr">' . self::output_filename( $data['template_file'], $data['template_path'] ) . '</td>'; // WPCS: XSS ok.
51
  }
 
52
  } else {
53
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
54
  }
output/html/transients.php CHANGED
@@ -28,7 +28,7 @@ class QM_Output_Html_Transients extends QM_Output_Html {
28
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
29
  echo '<table cellspacing="0">';
30
 
31
- if ( !empty( $data['trans'] ) ) {
32
 
33
  echo '<caption class="screen-reader-text">' . esc_html__( 'Transient Updates', 'query-monitor' ) . '</caption>';
34
 
@@ -50,7 +50,7 @@ class QM_Output_Html_Transients extends QM_Output_Html {
50
  foreach ( $data['trans'] as $row ) {
51
  $transient = str_replace( array(
52
  '_site_transient_',
53
- '_transient_'
54
  ), '', $row['transient'] );
55
 
56
  $component = $row['trace']->get_component();
@@ -98,7 +98,7 @@ class QM_Output_Html_Transients extends QM_Output_Html {
98
  $caller = array_pop( $stack );
99
 
100
  if ( ! empty( $stack ) ) {
101
- echo '<button class="qm-toggle" data-on="+" data-off="-">+</button>';
102
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
103
  }
104
 
28
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
29
  echo '<table cellspacing="0">';
30
 
31
+ if ( ! empty( $data['trans'] ) ) {
32
 
33
  echo '<caption class="screen-reader-text">' . esc_html__( 'Transient Updates', 'query-monitor' ) . '</caption>';
34
 
50
  foreach ( $data['trans'] as $row ) {
51
  $transient = str_replace( array(
52
  '_site_transient_',
53
+ '_transient_',
54
  ), '', $row['transient'] );
55
 
56
  $component = $row['trace']->get_component();
98
  $caller = array_pop( $stack );
99
 
100
  if ( ! empty( $stack ) ) {
101
+ echo $this->build_toggler(); // WPCS: XSS ok;
102
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
103
  }
104
 
query-monitor.php CHANGED
@@ -10,7 +10,7 @@
10
  *
11
  * Plugin Name: Query Monitor
12
  * Description: Monitoring of database queries, hooks, conditionals and more.
13
- * Version: 2.16.2
14
  * Plugin URI: https://github.com/johnbillion/query-monitor
15
  * Author: John Blackbourn
16
  * Author URI: https://johnblackbourn.com/
10
  *
11
  * Plugin Name: Query Monitor
12
  * Description: Monitoring of database queries, hooks, conditionals and more.
13
+ * Version: 2.17.0
14
  * Plugin URI: https://github.com/johnbillion/query-monitor
15
  * Author: John Blackbourn
16
  * Author URI: https://johnblackbourn.com/
readme.txt CHANGED
@@ -3,7 +3,7 @@ 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.9
6
- Stable tag: 2.16.2
7
  License: GPLv2 or later
8
 
9
  View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
@@ -125,7 +125,7 @@ In addition to this, you can set an authentication cookie which allows you to vi
125
 
126
  1. The admin toolbar menu showing an overview
127
  2. Aggregate database queries by component
128
- 3. Slow database queries highlighted in a separate panel
129
  4. Database queries complete with filter controls
130
  5. Hooks and actions
131
  6. HTTP requests (showing an HTTP error)
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.9
6
+ Stable tag: 2.17.0
7
  License: GPLv2 or later
8
 
9
  View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
125
 
126
  1. The admin toolbar menu showing an overview
127
  2. Aggregate database queries by component
128
+ 3. User capability checks with an active filter
129
  4. Database queries complete with filter controls
130
  5. Hooks and actions
131
  6. HTTP requests (showing an HTTP error)
wp-content/db.php CHANGED
@@ -48,7 +48,7 @@ if ( ! is_readable( $backtrace ) ) {
48
  }
49
  require_once $backtrace;
50
 
51
- if ( !defined( 'SAVEQUERIES' ) ) {
52
  define( 'SAVEQUERIES', true );
53
  }
54
 
@@ -104,7 +104,7 @@ class QM_DB extends wpdb {
104
  }
105
 
106
  $i = $this->num_queries - 1;
107
- $this->queries[$i]['trace'] = new QM_Backtrace( array(
108
  'ignore_items' => 1,
109
  ) );
110
 
@@ -119,9 +119,9 @@ class QM_DB extends wpdb {
119
  $code = mysql_errno( $this->dbh );
120
  }
121
  }
122
- $this->queries[$i]['result'] = new WP_Error( $code, $this->last_error );
123
  } else {
124
- $this->queries[$i]['result'] = $result;
125
  }
126
 
127
  return $result;
48
  }
49
  require_once $backtrace;
50
 
51
+ if ( ! defined( 'SAVEQUERIES' ) ) {
52
  define( 'SAVEQUERIES', true );
53
  }
54
 
104
  }
105
 
106
  $i = $this->num_queries - 1;
107
+ $this->queries[ $i ]['trace'] = new QM_Backtrace( array(
108
  'ignore_items' => 1,
109
  ) );
110
 
119
  $code = mysql_errno( $this->dbh );
120
  }
121
  }
122
+ $this->queries[ $i ]['result'] = new WP_Error( $code, $this->last_error );
123
  } else {
124
+ $this->queries[ $i ]['result'] = $result;
125
  }
126
 
127
  return $result;