Query Monitor - Version 3.4.0

Version Description

Download this release

Release Info

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

Code changes from version 3.3.7 to 3.4.0

Files changed (50) hide show
  1. assets/query-monitor-dark.css +71 -60
  2. assets/query-monitor.css +68 -57
  3. assets/query-monitor.js +10 -8
  4. classes/Backtrace.php +1 -1
  5. classes/Collectors.php +7 -1
  6. classes/Dispatcher.php +20 -0
  7. classes/Output.php +11 -0
  8. classes/Timer.php +16 -0
  9. collectors/admin.php +3 -0
  10. collectors/cache.php +7 -2
  11. collectors/db_queries.php +6 -5
  12. collectors/environment.php +8 -8
  13. collectors/php_errors.php +66 -6
  14. collectors/raw_request.php +99 -0
  15. collectors/request.php +2 -0
  16. collectors/timing.php +16 -1
  17. composer.json +2 -2
  18. dispatchers/AJAX.php +0 -1
  19. dispatchers/Html.php +35 -9
  20. dispatchers/WP_Die.php +3 -2
  21. output/Html.php +1 -1
  22. output/headers/overview.php +7 -0
  23. output/headers/php_errors.php +11 -5
  24. output/headers/redirects.php +7 -0
  25. output/html/admin.php +33 -2
  26. output/html/assets.php +24 -5
  27. output/html/assets_scripts.php +9 -2
  28. output/html/assets_styles.php +9 -2
  29. output/html/block_editor.php +9 -2
  30. output/html/caps.php +16 -7
  31. output/html/conditionals.php +7 -0
  32. output/html/db_callers.php +8 -1
  33. output/html/db_components.php +8 -1
  34. output/html/db_dupes.php +11 -3
  35. output/html/db_queries.php +29 -13
  36. output/html/debug_bar.php +7 -0
  37. output/html/environment.php +7 -0
  38. output/html/headers.php +106 -0
  39. output/html/hooks.php +10 -1
  40. output/html/http.php +14 -5
  41. output/html/languages.php +12 -1
  42. output/html/logger.php +10 -2
  43. output/html/overview.php +26 -3
  44. output/html/php_errors.php +12 -4
  45. output/html/request.php +32 -2
  46. output/html/theme.php +7 -0
  47. output/html/timing.php +23 -1
  48. output/html/transients.php +13 -5
  49. query-monitor.php +1 -1
  50. readme.txt +1 -1
assets/query-monitor-dark.css CHANGED
@@ -43,6 +43,21 @@
43
  #wpadminbar .qm-error {
44
  background-color: #c00;
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  #wp-admin-bar-query-monitor *,
48
  #wp-admin-bar-query-monitor {
@@ -75,23 +90,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
75
  display: none;
76
  }
77
 
78
- #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
79
- color: #aaa !important;
80
- display: none !important;
81
- font: 18px/44px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
82
- padding: 0 10px !important;
83
- width: auto !important;
84
- }
85
-
86
- @media screen and (max-width: 782px) {
87
- #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
88
- display: block !important;
89
- }
90
-
91
- #wpadminbar #wp-admin-bar-query-monitor .ab-label {
92
- display: none !important;
93
- }
94
- }
95
  #query-monitor-main,
96
  #query-monitor-main dl,
97
  #query-monitor-main dt,
@@ -141,6 +139,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
141
  text-transform: none !important;
142
  transition: none !important;
143
  vertical-align: baseline !important;
 
144
  word-break: normal !important;
145
  word-wrap: normal !important;
146
  }
@@ -296,19 +295,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
296
  #query-monitor-main #qm-title .dashicons {
297
  transition: none !important;
298
  }
299
- #query-monitor-main #qm-title .qm-button-container-settings .dashicons {
300
- font-size: 17px !important;
301
- margin: 4px 0 2px !important;
302
- }
303
- #query-monitor-main #qm-title .qm-button-container-position .dashicons {
304
- font-size: 15px !important;
305
- margin: 2px -1px 3px 4px !important;
306
- transform: scaleX(-1) rotate(90deg) !important;
307
- }
308
- #query-monitor-main.qm-show-right #qm-title .qm-button-container-position .dashicons {
309
- margin: 4px 1px 0px 1px !important;
310
- transform: none !important;
311
- }
312
  #query-monitor-main #qm-title .qm-button-container-close {
313
  margin-right: 10px !important;
314
  }
@@ -340,6 +326,19 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
340
  #query-monitor-main #qm-title button.qm-button-active {
341
  color: #3879d9 !important;
342
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  #query-monitor-main .qm {
344
  display: none !important;
345
  }
@@ -378,15 +377,28 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
378
  }
379
  #query-monitor-main #qm-panel-menu li button:focus,
380
  #query-monitor-main #qm-panel-menu li button:hover {
381
- background: #def !important;
382
- color: #222 !important;
383
  }
384
  #query-monitor-main #qm-panel-menu li button:focus {
385
  text-decoration: underline !important;
386
  }
387
  #query-monitor-main #qm-panel-menu li.qm-current-menu button {
388
- background: #def !important;
389
- color: #222 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  }
391
  #query-monitor-main #qm-panel-menu li button[aria-selected="true"] {
392
  background: #0073aa !important;
@@ -397,6 +409,10 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
397
  background: #0084c4 !important;
398
  color: #fff !important;
399
  }
 
 
 
 
400
  #query-monitor-main #qm-panel-menu li button[aria-selected="true"]:after {
401
  border: solid 8px transparent;
402
  border-right-color: #23282d;
@@ -422,9 +438,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
422
  outline: 0 !important;
423
  /* @TODO might not need this any more */
424
  }
425
- #query-monitor-main .qm-non-tabular {
426
- padding: 10px 20px !important;
427
- }
428
  #query-monitor-main .qm-boxed {
429
  display: flex !important;
430
  flex-wrap: wrap !important;
@@ -514,6 +527,11 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
514
  #query-monitor-main .qm td.qm-num {
515
  text-align: right !important;
516
  }
 
 
 
 
 
517
  #query-monitor-main .qm td.qm-row-sql {
518
  min-width: 25em !important;
519
  }
@@ -536,7 +554,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
536
  #query-monitor-main .qm .qm-inner-toggle {
537
  padding: 4px 6px !important;
538
  }
539
- #query-monitor-main .qm-has-inner .qm-toggled > table {
540
  border-bottom: none !important;
541
  border-top: 1px solid #23282d !important;
542
  }
@@ -552,6 +570,9 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
552
  border-top: 1px solid #23282d !important;
553
  margin-bottom: 20px !important;
554
  }
 
 
 
555
  #query-monitor-main .qm-non-tabular h3 {
556
  font-size: 14px !important;
557
  margin: 0 0 15px 0 !important;
@@ -579,13 +600,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
579
  flex: 1 0 calc(100% - 10px - 16em);
580
  padding: 10px 0 !important;
581
  }
582
- #query-monitor-main .qm-non-tabular h3 a {
583
- float: right !important;
584
- }
585
- #query-monitor-main #qm-conditionals li {
586
- display: inline-block !important;
587
- margin: 0 20px 5px 0 !important;
588
- }
589
  #query-monitor-main .qm-non-tabular section,
590
  #query-monitor-main .qm-non-tabular .qm-section {
591
  margin: 0 0 30px 0 !important;
@@ -605,6 +619,10 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
605
  #query-monitor-main .qm-non-tabular table {
606
  border-bottom-color: #23282d !important;
607
  }
 
 
 
 
608
  #query-monitor-main .qm ol,
609
  #query-monitor-main .qm ul {
610
  list-style: none !important;
@@ -616,13 +634,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
616
  #query-monitor-main .qm li::before {
617
  content: '' !important;
618
  }
619
- #query-monitor-main .qm .qm-has-toggle ol.qm-numbered li {
620
- list-style: none !important;
621
- }
622
- #query-monitor-main .qm .qm-toggled-on ol.qm-numbered li,
623
- #query-monitor-main .qm ol.qm-numbered li {
624
- list-style: decimal inside !important;
625
- }
626
  #query-monitor-main .qm code,
627
  #query-monitor-main .qm pre {
628
  font-family: Menlo, Monaco, Consolas, monospace !important;
@@ -752,8 +763,8 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
752
  color: #fff0f0 !important;
753
  }
754
  #query-monitor-main .qm .qm-notice {
755
- background: #def !important;
756
- border: 1px solid #aad5ff !important;
757
  margin: 0 0 10px 0 !important;
758
  padding: 10px 20px 0 !important;
759
  }
@@ -935,6 +946,12 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
935
  margin: 0 !important;
936
  width: 16px !important;
937
  }
 
 
 
 
 
 
938
  #query-monitor-main .qm .qm-sorted-desc .qm-sort-arrow,
939
  #query-monitor-main .qm .qm-sorted-asc .qm-sort-arrow {
940
  color: #bbc8d4 !important;
@@ -942,12 +959,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
942
  #query-monitor-main .qm thead th.qm-sortable-column:hover .qm-sort-arrow {
943
  color: #0073aa !important;
944
  }
945
- #query-monitor-main .qm .qm-sortable-column .qm-sort-arrow::before {
946
- content: "\f140" !important;
947
- position: absolute !important;
948
- right: 0 !important;
949
- top: 4px !important;
950
- }
951
  #query-monitor-main .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
952
  content: "\f142" !important;
953
  }
43
  #wpadminbar .qm-error {
44
  background-color: #c00;
45
  }
46
+ #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
47
+ color: #aaa !important;
48
+ display: none !important;
49
+ font: 18px/44px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
50
+ padding: 0 10px !important;
51
+ width: auto !important;
52
+ }
53
+ @media screen and (max-width: 782px) {
54
+ #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
55
+ display: block !important;
56
+ }
57
+ #wpadminbar #wp-admin-bar-query-monitor .ab-label {
58
+ display: none !important;
59
+ }
60
+ }
61
 
62
  #wp-admin-bar-query-monitor *,
63
  #wp-admin-bar-query-monitor {
90
  display: none;
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  #query-monitor-main,
94
  #query-monitor-main dl,
95
  #query-monitor-main dt,
139
  text-transform: none !important;
140
  transition: none !important;
141
  vertical-align: baseline !important;
142
+ width: auto !important;
143
  word-break: normal !important;
144
  word-wrap: normal !important;
145
  }
295
  #query-monitor-main #qm-title .dashicons {
296
  transition: none !important;
297
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  #query-monitor-main #qm-title .qm-button-container-close {
299
  margin-right: 10px !important;
300
  }
326
  #query-monitor-main #qm-title button.qm-button-active {
327
  color: #3879d9 !important;
328
  }
329
+ #query-monitor-main #qm-title .qm-button-container-settings .dashicons {
330
+ font-size: 17px !important;
331
+ margin: 4px 0 2px !important;
332
+ }
333
+ #query-monitor-main #qm-title .qm-button-container-position .dashicons {
334
+ font-size: 15px !important;
335
+ margin: 2px -1px 3px 4px !important;
336
+ transform: scaleX(-1) rotate(90deg) !important;
337
+ }
338
+ #query-monitor-main.qm-show-right #qm-title .qm-button-container-position .dashicons {
339
+ margin: 4px 1px 0px 1px !important;
340
+ transform: none !important;
341
+ }
342
  #query-monitor-main .qm {
343
  display: none !important;
344
  }
377
  }
378
  #query-monitor-main #qm-panel-menu li button:focus,
379
  #query-monitor-main #qm-panel-menu li button:hover {
380
+ background: #3e444a !important;
381
+ color: #bbc8d4 !important;
382
  }
383
  #query-monitor-main #qm-panel-menu li button:focus {
384
  text-decoration: underline !important;
385
  }
386
  #query-monitor-main #qm-panel-menu li.qm-current-menu button {
387
+ background: #32373c !important;
388
+ color: #bbc8d4 !important;
389
+ }
390
+ #query-monitor-main #qm-panel-menu li.qm-current-menu button:focus {
391
+ background: #3e444a !important;
392
+ color: #bbc8d4 !important;
393
+ }
394
+ #query-monitor-main #qm-panel-menu li.qm-current-menu button:hover {
395
+ background: #3e444a !important;
396
+ color: #bbc8d4 !important;
397
+ }
398
+ #query-monitor-main #qm-panel-menu li li button::before {
399
+ content: "\2514" !important;
400
+ display: inline-block !important;
401
+ margin-right: 5px !important;
402
  }
403
  #query-monitor-main #qm-panel-menu li button[aria-selected="true"] {
404
  background: #0073aa !important;
409
  background: #0084c4 !important;
410
  color: #fff !important;
411
  }
412
+ #query-monitor-main #qm-panel-menu li button[aria-selected="true"]:hover {
413
+ background: #0073aa !important;
414
+ color: #fff !important;
415
+ }
416
  #query-monitor-main #qm-panel-menu li button[aria-selected="true"]:after {
417
  border: solid 8px transparent;
418
  border-right-color: #23282d;
438
  outline: 0 !important;
439
  /* @TODO might not need this any more */
440
  }
 
 
 
441
  #query-monitor-main .qm-boxed {
442
  display: flex !important;
443
  flex-wrap: wrap !important;
527
  #query-monitor-main .qm td.qm-num {
528
  text-align: right !important;
529
  }
530
+ #query-monitor-main .qm td.qm-num {
531
+ font-family: Menlo, Monaco, Consolas, monospace !important;
532
+ font-size: 11px !important;
533
+ line-height: 18px !important;
534
+ }
535
  #query-monitor-main .qm td.qm-row-sql {
536
  min-width: 25em !important;
537
  }
554
  #query-monitor-main .qm .qm-inner-toggle {
555
  padding: 4px 6px !important;
556
  }
557
+ #query-monitor-main .qm .qm-has-inner .qm-toggled > table {
558
  border-bottom: none !important;
559
  border-top: 1px solid #23282d !important;
560
  }
570
  border-top: 1px solid #23282d !important;
571
  margin-bottom: 20px !important;
572
  }
573
+ #query-monitor-main .qm-non-tabular {
574
+ padding: 10px 20px !important;
575
+ }
576
  #query-monitor-main .qm-non-tabular h3 {
577
  font-size: 14px !important;
578
  margin: 0 0 15px 0 !important;
600
  flex: 1 0 calc(100% - 10px - 16em);
601
  padding: 10px 0 !important;
602
  }
 
 
 
 
 
 
 
603
  #query-monitor-main .qm-non-tabular section,
604
  #query-monitor-main .qm-non-tabular .qm-section {
605
  margin: 0 0 30px 0 !important;
619
  #query-monitor-main .qm-non-tabular table {
620
  border-bottom-color: #23282d !important;
621
  }
622
+ #query-monitor-main #qm-conditionals li {
623
+ display: inline-block !important;
624
+ margin: 0 20px 5px 0 !important;
625
+ }
626
  #query-monitor-main .qm ol,
627
  #query-monitor-main .qm ul {
628
  list-style: none !important;
634
  #query-monitor-main .qm li::before {
635
  content: '' !important;
636
  }
 
 
 
 
 
 
 
637
  #query-monitor-main .qm code,
638
  #query-monitor-main .qm pre {
639
  font-family: Menlo, Monaco, Consolas, monospace !important;
763
  color: #fff0f0 !important;
764
  }
765
  #query-monitor-main .qm .qm-notice {
766
+ background: #3e444a !important;
767
+ border: 1px solid #262a2e !important;
768
  margin: 0 0 10px 0 !important;
769
  padding: 10px 20px 0 !important;
770
  }
946
  margin: 0 !important;
947
  width: 16px !important;
948
  }
949
+ #query-monitor-main .qm .qm-sortable-column .qm-sort-arrow::before {
950
+ content: "\f140" !important;
951
+ position: absolute !important;
952
+ right: 0 !important;
953
+ top: 4px !important;
954
+ }
955
  #query-monitor-main .qm .qm-sorted-desc .qm-sort-arrow,
956
  #query-monitor-main .qm .qm-sorted-asc .qm-sort-arrow {
957
  color: #bbc8d4 !important;
959
  #query-monitor-main .qm thead th.qm-sortable-column:hover .qm-sort-arrow {
960
  color: #0073aa !important;
961
  }
 
 
 
 
 
 
962
  #query-monitor-main .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
963
  content: "\f142" !important;
964
  }
assets/query-monitor.css CHANGED
@@ -43,6 +43,21 @@
43
  #wpadminbar .qm-error {
44
  background-color: #c00;
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  #wp-admin-bar-query-monitor *,
48
  #wp-admin-bar-query-monitor {
@@ -75,23 +90,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
75
  display: none;
76
  }
77
 
78
- #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
79
- color: #aaa !important;
80
- display: none !important;
81
- font: 18px/44px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
82
- padding: 0 10px !important;
83
- width: auto !important;
84
- }
85
-
86
- @media screen and (max-width: 782px) {
87
- #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
88
- display: block !important;
89
- }
90
-
91
- #wpadminbar #wp-admin-bar-query-monitor .ab-label {
92
- display: none !important;
93
- }
94
- }
95
  #query-monitor-main,
96
  #query-monitor-main dl,
97
  #query-monitor-main dt,
@@ -141,6 +139,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
141
  text-transform: none !important;
142
  transition: none !important;
143
  vertical-align: baseline !important;
 
144
  word-break: normal !important;
145
  word-wrap: normal !important;
146
  }
@@ -296,19 +295,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
296
  #query-monitor-main #qm-title .dashicons {
297
  transition: none !important;
298
  }
299
- #query-monitor-main #qm-title .qm-button-container-settings .dashicons {
300
- font-size: 17px !important;
301
- margin: 4px 0 2px !important;
302
- }
303
- #query-monitor-main #qm-title .qm-button-container-position .dashicons {
304
- font-size: 15px !important;
305
- margin: 2px -1px 3px 4px !important;
306
- transform: scaleX(-1) rotate(90deg) !important;
307
- }
308
- #query-monitor-main.qm-show-right #qm-title .qm-button-container-position .dashicons {
309
- margin: 4px 1px 0px 1px !important;
310
- transform: none !important;
311
- }
312
  #query-monitor-main #qm-title .qm-button-container-close {
313
  margin-right: 10px !important;
314
  }
@@ -340,6 +326,19 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
340
  #query-monitor-main #qm-title button.qm-button-active {
341
  color: #3879d9 !important;
342
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  #query-monitor-main .qm {
344
  display: none !important;
345
  }
@@ -378,7 +377,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
378
  }
379
  #query-monitor-main #qm-panel-menu li button:focus,
380
  #query-monitor-main #qm-panel-menu li button:hover {
381
- background: #def !important;
382
  color: #222 !important;
383
  }
384
  #query-monitor-main #qm-panel-menu li button:focus {
@@ -388,6 +387,19 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
388
  background: #def !important;
389
  color: #222 !important;
390
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  #query-monitor-main #qm-panel-menu li button[aria-selected="true"] {
392
  background: #0073aa !important;
393
  color: #fff !important;
@@ -397,6 +409,10 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
397
  background: #0084c4 !important;
398
  color: #fff !important;
399
  }
 
 
 
 
400
  #query-monitor-main #qm-panel-menu li button[aria-selected="true"]:after {
401
  border: solid 8px transparent;
402
  border-right-color: #fff;
@@ -422,9 +438,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
422
  outline: 0 !important;
423
  /* @TODO might not need this any more */
424
  }
425
- #query-monitor-main .qm-non-tabular {
426
- padding: 10px 20px !important;
427
- }
428
  #query-monitor-main .qm-boxed {
429
  display: flex !important;
430
  flex-wrap: wrap !important;
@@ -514,6 +527,11 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
514
  #query-monitor-main .qm td.qm-num {
515
  text-align: right !important;
516
  }
 
 
 
 
 
517
  #query-monitor-main .qm td.qm-row-sql {
518
  min-width: 25em !important;
519
  }
@@ -536,7 +554,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
536
  #query-monitor-main .qm .qm-inner-toggle {
537
  padding: 4px 6px !important;
538
  }
539
- #query-monitor-main .qm-has-inner .qm-toggled > table {
540
  border-bottom: none !important;
541
  border-top: 1px solid #e0e0e0 !important;
542
  }
@@ -552,6 +570,9 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
552
  border-top: 1px solid #e0e0e0 !important;
553
  margin-bottom: 20px !important;
554
  }
 
 
 
555
  #query-monitor-main .qm-non-tabular h3 {
556
  font-size: 14px !important;
557
  margin: 0 0 15px 0 !important;
@@ -579,13 +600,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
579
  flex: 1 0 calc(100% - 10px - 16em);
580
  padding: 10px 0 !important;
581
  }
582
- #query-monitor-main .qm-non-tabular h3 a {
583
- float: right !important;
584
- }
585
- #query-monitor-main #qm-conditionals li {
586
- display: inline-block !important;
587
- margin: 0 20px 5px 0 !important;
588
- }
589
  #query-monitor-main .qm-non-tabular section,
590
  #query-monitor-main .qm-non-tabular .qm-section {
591
  margin: 0 0 30px 0 !important;
@@ -605,6 +619,10 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
605
  #query-monitor-main .qm-non-tabular table {
606
  border-bottom-color: #e0e0e0 !important;
607
  }
 
 
 
 
608
  #query-monitor-main .qm ol,
609
  #query-monitor-main .qm ul {
610
  list-style: none !important;
@@ -616,13 +634,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
616
  #query-monitor-main .qm li::before {
617
  content: '' !important;
618
  }
619
- #query-monitor-main .qm .qm-has-toggle ol.qm-numbered li {
620
- list-style: none !important;
621
- }
622
- #query-monitor-main .qm .qm-toggled-on ol.qm-numbered li,
623
- #query-monitor-main .qm ol.qm-numbered li {
624
- list-style: decimal inside !important;
625
- }
626
  #query-monitor-main .qm code,
627
  #query-monitor-main .qm pre {
628
  font-family: Menlo, Monaco, Consolas, monospace !important;
@@ -752,8 +763,8 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
752
  color: #a00 !important;
753
  }
754
  #query-monitor-main .qm .qm-notice {
755
- background: #def !important;
756
- border: 1px solid #aad5ff !important;
757
  margin: 0 0 10px 0 !important;
758
  padding: 10px 20px 0 !important;
759
  }
@@ -935,6 +946,12 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
935
  margin: 0 !important;
936
  width: 16px !important;
937
  }
 
 
 
 
 
 
938
  #query-monitor-main .qm .qm-sorted-desc .qm-sort-arrow,
939
  #query-monitor-main .qm .qm-sorted-asc .qm-sort-arrow {
940
  color: #222 !important;
@@ -942,12 +959,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
942
  #query-monitor-main .qm thead th.qm-sortable-column:hover .qm-sort-arrow {
943
  color: #0073aa !important;
944
  }
945
- #query-monitor-main .qm .qm-sortable-column .qm-sort-arrow::before {
946
- content: "\f140" !important;
947
- position: absolute !important;
948
- right: 0 !important;
949
- top: 4px !important;
950
- }
951
  #query-monitor-main .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
952
  content: "\f142" !important;
953
  }
43
  #wpadminbar .qm-error {
44
  background-color: #c00;
45
  }
46
+ #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
47
+ color: #aaa !important;
48
+ display: none !important;
49
+ font: 18px/44px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
50
+ padding: 0 10px !important;
51
+ width: auto !important;
52
+ }
53
+ @media screen and (max-width: 782px) {
54
+ #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
55
+ display: block !important;
56
+ }
57
+ #wpadminbar #wp-admin-bar-query-monitor .ab-label {
58
+ display: none !important;
59
+ }
60
+ }
61
 
62
  #wp-admin-bar-query-monitor *,
63
  #wp-admin-bar-query-monitor {
90
  display: none;
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  #query-monitor-main,
94
  #query-monitor-main dl,
95
  #query-monitor-main dt,
139
  text-transform: none !important;
140
  transition: none !important;
141
  vertical-align: baseline !important;
142
+ width: auto !important;
143
  word-break: normal !important;
144
  word-wrap: normal !important;
145
  }
295
  #query-monitor-main #qm-title .dashicons {
296
  transition: none !important;
297
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
298
  #query-monitor-main #qm-title .qm-button-container-close {
299
  margin-right: 10px !important;
300
  }
326
  #query-monitor-main #qm-title button.qm-button-active {
327
  color: #3879d9 !important;
328
  }
329
+ #query-monitor-main #qm-title .qm-button-container-settings .dashicons {
330
+ font-size: 17px !important;
331
+ margin: 4px 0 2px !important;
332
+ }
333
+ #query-monitor-main #qm-title .qm-button-container-position .dashicons {
334
+ font-size: 15px !important;
335
+ margin: 2px -1px 3px 4px !important;
336
+ transform: scaleX(-1) rotate(90deg) !important;
337
+ }
338
+ #query-monitor-main.qm-show-right #qm-title .qm-button-container-position .dashicons {
339
+ margin: 4px 1px 0px 1px !important;
340
+ transform: none !important;
341
+ }
342
  #query-monitor-main .qm {
343
  display: none !important;
344
  }
377
  }
378
  #query-monitor-main #qm-panel-menu li button:focus,
379
  #query-monitor-main #qm-panel-menu li button:hover {
380
+ background: #cde !important;
381
  color: #222 !important;
382
  }
383
  #query-monitor-main #qm-panel-menu li button:focus {
387
  background: #def !important;
388
  color: #222 !important;
389
  }
390
+ #query-monitor-main #qm-panel-menu li.qm-current-menu button:focus {
391
+ background: #f7fbff !important;
392
+ color: #222 !important;
393
+ }
394
+ #query-monitor-main #qm-panel-menu li.qm-current-menu button:hover {
395
+ background: #cde !important;
396
+ color: #222 !important;
397
+ }
398
+ #query-monitor-main #qm-panel-menu li li button::before {
399
+ content: "\2514" !important;
400
+ display: inline-block !important;
401
+ margin-right: 5px !important;
402
+ }
403
  #query-monitor-main #qm-panel-menu li button[aria-selected="true"] {
404
  background: #0073aa !important;
405
  color: #fff !important;
409
  background: #0084c4 !important;
410
  color: #fff !important;
411
  }
412
+ #query-monitor-main #qm-panel-menu li button[aria-selected="true"]:hover {
413
+ background: #0073aa !important;
414
+ color: #fff !important;
415
+ }
416
  #query-monitor-main #qm-panel-menu li button[aria-selected="true"]:after {
417
  border: solid 8px transparent;
418
  border-right-color: #fff;
438
  outline: 0 !important;
439
  /* @TODO might not need this any more */
440
  }
 
 
 
441
  #query-monitor-main .qm-boxed {
442
  display: flex !important;
443
  flex-wrap: wrap !important;
527
  #query-monitor-main .qm td.qm-num {
528
  text-align: right !important;
529
  }
530
+ #query-monitor-main .qm td.qm-num {
531
+ font-family: Menlo, Monaco, Consolas, monospace !important;
532
+ font-size: 11px !important;
533
+ line-height: 18px !important;
534
+ }
535
  #query-monitor-main .qm td.qm-row-sql {
536
  min-width: 25em !important;
537
  }
554
  #query-monitor-main .qm .qm-inner-toggle {
555
  padding: 4px 6px !important;
556
  }
557
+ #query-monitor-main .qm .qm-has-inner .qm-toggled > table {
558
  border-bottom: none !important;
559
  border-top: 1px solid #e0e0e0 !important;
560
  }
570
  border-top: 1px solid #e0e0e0 !important;
571
  margin-bottom: 20px !important;
572
  }
573
+ #query-monitor-main .qm-non-tabular {
574
+ padding: 10px 20px !important;
575
+ }
576
  #query-monitor-main .qm-non-tabular h3 {
577
  font-size: 14px !important;
578
  margin: 0 0 15px 0 !important;
600
  flex: 1 0 calc(100% - 10px - 16em);
601
  padding: 10px 0 !important;
602
  }
 
 
 
 
 
 
 
603
  #query-monitor-main .qm-non-tabular section,
604
  #query-monitor-main .qm-non-tabular .qm-section {
605
  margin: 0 0 30px 0 !important;
619
  #query-monitor-main .qm-non-tabular table {
620
  border-bottom-color: #e0e0e0 !important;
621
  }
622
+ #query-monitor-main #qm-conditionals li {
623
+ display: inline-block !important;
624
+ margin: 0 20px 5px 0 !important;
625
+ }
626
  #query-monitor-main .qm ol,
627
  #query-monitor-main .qm ul {
628
  list-style: none !important;
634
  #query-monitor-main .qm li::before {
635
  content: '' !important;
636
  }
 
 
 
 
 
 
 
637
  #query-monitor-main .qm code,
638
  #query-monitor-main .qm pre {
639
  font-family: Menlo, Monaco, Consolas, monospace !important;
763
  color: #a00 !important;
764
  }
765
  #query-monitor-main .qm .qm-notice {
766
+ background: #cde !important;
767
+ border: 1px solid #a6c4e1 !important;
768
  margin: 0 0 10px 0 !important;
769
  padding: 10px 20px 0 !important;
770
  }
946
  margin: 0 !important;
947
  width: 16px !important;
948
  }
949
+ #query-monitor-main .qm .qm-sortable-column .qm-sort-arrow::before {
950
+ content: "\f140" !important;
951
+ position: absolute !important;
952
+ right: 0 !important;
953
+ top: 4px !important;
954
+ }
955
  #query-monitor-main .qm .qm-sorted-desc .qm-sort-arrow,
956
  #query-monitor-main .qm .qm-sorted-asc .qm-sort-arrow {
957
  color: #222 !important;
959
  #query-monitor-main .qm thead th.qm-sortable-column:hover .qm-sort-arrow {
960
  color: #0073aa !important;
961
  }
 
 
 
 
 
 
962
  #query-monitor-main .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
963
  content: "\f142" !important;
964
  }
assets/query-monitor.js CHANGED
@@ -55,7 +55,7 @@ if ( window.jQuery ) {
55
  var maxwidth = $(window).width();
56
  var container = $('#query-monitor-main');
57
  var container_height_key = 'qm-container-height';
58
- var container_pinned_key = 'qm-container-pinned';
59
  var container_position_key = 'qm-container-position';
60
  var container_width_key = 'qm-container-width';
61
 
@@ -414,14 +414,16 @@ if ( window.jQuery ) {
414
  var h = localStorage.getItem( container_height_key );
415
  var w = localStorage.getItem( container_width_key );
416
  if ( ! container.hasClass('qm-peek') ) {
417
- if ( p === 'right' && w !== null ) {
418
- if ( w < minwidth ) {
419
- w = minwidth;
420
- }
421
- if ( w > maxwidth ) {
422
- w = maxwidth;
 
 
 
423
  }
424
- container.width( w );
425
  container.addClass('qm-show-right');
426
  } else if ( p !== 'right' && h !== null ) {
427
  if ( h < minheight ) {
55
  var maxwidth = $(window).width();
56
  var container = $('#query-monitor-main');
57
  var container_height_key = 'qm-container-height';
58
+ var container_pinned_key = 'qm-' + ( $('body').hasClass('wp-admin') ? 'admin' : 'front' ) + '-container-pinned';
59
  var container_position_key = 'qm-container-position';
60
  var container_width_key = 'qm-container-width';
61
 
414
  var h = localStorage.getItem( container_height_key );
415
  var w = localStorage.getItem( container_width_key );
416
  if ( ! container.hasClass('qm-peek') ) {
417
+ if ( p === 'right' ) {
418
+ if ( w !== null ) {
419
+ if ( w < minwidth ) {
420
+ w = minwidth;
421
+ }
422
+ if ( w > maxwidth ) {
423
+ w = maxwidth;
424
+ }
425
+ container.width( w );
426
  }
 
427
  container.addClass('qm-show-right');
428
  } else if ( p !== 'right' && h !== null ) {
429
  if ( h < minheight ) {
classes/Backtrace.php CHANGED
@@ -179,7 +179,7 @@ class QM_Backtrace {
179
  }
180
 
181
  public function get_display_trace() {
182
- return array_reverse( $this->get_filtered_trace() );
183
  }
184
 
185
  public function get_filtered_trace() {
179
  }
180
 
181
  public function get_display_trace() {
182
+ return $this->get_filtered_trace();
183
  }
184
 
185
  public function get_filtered_trace() {
classes/Collectors.php CHANGED
@@ -21,12 +21,18 @@ class QM_Collectors implements IteratorAggregate {
21
  $collectors->items[ $collector->id ] = $collector;
22
  }
23
 
 
 
 
 
 
 
24
  public static function get( $id ) {
25
  $collectors = self::init();
26
  if ( isset( $collectors->items[ $id ] ) ) {
27
  return $collectors->items[ $id ];
28
  }
29
- return false;
30
  }
31
 
32
  public static function init() {
21
  $collectors->items[ $collector->id ] = $collector;
22
  }
23
 
24
+ /**
25
+ * Fetches a collector instance.
26
+ *
27
+ * @param string $id The collector ID.
28
+ * @return QM_Collector|null The collector object.
29
+ */
30
  public static function get( $id ) {
31
  $collectors = self::init();
32
  if ( isset( $collectors->items[ $id ] ) ) {
33
  return $collectors->items[ $id ];
34
  }
35
+ return null;
36
  }
37
 
38
  public static function init() {
classes/Dispatcher.php CHANGED
@@ -8,6 +8,20 @@
8
  if ( ! class_exists( 'QM_Dispatcher' ) ) {
9
  abstract class QM_Dispatcher {
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  public function __construct( QM_Plugin $qm ) {
12
  $this->qm = $qm;
13
 
@@ -47,6 +61,12 @@ abstract class QM_Dispatcher {
47
 
48
  }
49
 
 
 
 
 
 
 
50
  public function get_outputters( $outputter_id ) {
51
  $collectors = QM_Collectors::init();
52
  $collectors->process();
8
  if ( ! class_exists( 'QM_Dispatcher' ) ) {
9
  abstract class QM_Dispatcher {
10
 
11
+ /**
12
+ * Outputter instances.
13
+ *
14
+ * @var QM_Output[] Array of outputters.
15
+ */
16
+ protected $outputters = array();
17
+
18
+ /**
19
+ * Query Monitor plugin instance.
20
+ *
21
+ * @var QM_Plugin Plugin instance.
22
+ */
23
+ protected $qm;
24
+
25
  public function __construct( QM_Plugin $qm ) {
26
  $this->qm = $qm;
27
 
61
 
62
  }
63
 
64
+ /**
65
+ * Processes and fetches the outputters for this dispatcher.
66
+ *
67
+ * @param string $outputter_id The outputter ID.
68
+ * @return QM_Output[] Array of outputters.
69
+ */
70
  public function get_outputters( $outputter_id ) {
71
  $collectors = QM_Collectors::init();
72
  $collectors->process();
classes/Output.php CHANGED
@@ -8,7 +8,18 @@
8
  if ( ! class_exists( 'QM_Output' ) ) {
9
  abstract class QM_Output {
10
 
 
 
 
 
 
11
  protected $collector;
 
 
 
 
 
 
12
  protected $timer;
13
 
14
  public function __construct( QM_Collector $collector ) {
8
  if ( ! class_exists( 'QM_Output' ) ) {
9
  abstract class QM_Output {
10
 
11
+ /**
12
+ * Collector instance.
13
+ *
14
+ * @var QM_Collector Collector.
15
+ */
16
  protected $collector;
17
+
18
+ /**
19
+ * Timer instance.
20
+ *
21
+ * @var QM_Timer Timer.
22
+ */
23
  protected $timer;
24
 
25
  public function __construct( QM_Collector $collector ) {
classes/Timer.php CHANGED
@@ -82,6 +82,22 @@ class QM_Timer {
82
  return $this->end['memory'] - $this->start['memory'];
83
  }
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  public function get_trace() {
86
  return $this->trace;
87
  }
82
  return $this->end['memory'] - $this->start['memory'];
83
  }
84
 
85
+ public function get_start_time() {
86
+ return $this->start['time'];
87
+ }
88
+
89
+ public function get_start_memory() {
90
+ return $this->start['memory'];
91
+ }
92
+
93
+ public function get_end_time() {
94
+ return $this->end['time'];
95
+ }
96
+
97
+ public function get_end_memory() {
98
+ return $this->end['memory'];
99
+ }
100
+
101
  public function get_trace() {
102
  return $this->trace;
103
  }
collectors/admin.php CHANGED
@@ -53,6 +53,9 @@ class QM_Collector_Admin extends QM_Collector {
53
  }
54
 
55
  $this->data['pagenow'] = $pagenow;
 
 
 
56
  $this->data['current_screen'] = ( $current_screen ) ? get_object_vars( $current_screen ) : null;
57
 
58
  $screens = array(
53
  }
54
 
55
  $this->data['pagenow'] = $pagenow;
56
+ $this->data['typenow'] = isset( $GLOBALS['typenow'] ) ? $GLOBALS['typenow'] : '';
57
+ $this->data['taxnow'] = isset( $GLOBALS['taxnow'] ) ? $GLOBALS['taxnow'] : '';
58
+ $this->data['hook_suffix'] = isset( $GLOBALS['hook_suffix'] ) ? $GLOBALS['hook_suffix'] : '';
59
  $this->data['current_screen'] = ( $current_screen ) ? get_object_vars( $current_screen ) : null;
60
 
61
  $screens = array(
collectors/cache.php CHANGED
@@ -67,8 +67,13 @@ class QM_Collector_Cache extends QM_Collector {
67
  }
68
  }
69
 
70
- if ( isset( $this->data['stats']['cache_hits'] ) && isset( $this->data['stats']['cache_misses'] ) ) {
71
- $total = $this->data['stats']['cache_misses'] + $this->data['stats']['cache_hits'];
 
 
 
 
 
72
  $this->data['cache_hit_percentage'] = ( 100 / $total ) * $this->data['stats']['cache_hits'];
73
  }
74
 
67
  }
68
  }
69
 
70
+ if ( ! empty( $this->data['stats']['cache_hits'] ) ) {
71
+ $total = $this->data['stats']['cache_hits'];
72
+
73
+ if ( ! empty( $this->data['stats']['cache_misses'] ) ) {
74
+ $total += $this->data['stats']['cache_misses'];
75
+ }
76
+
77
  $this->data['cache_hit_percentage'] = ( 100 / $total ) * $this->data['stats']['cache_hits'];
78
  }
79
 
collectors/db_queries.php CHANGED
@@ -44,11 +44,6 @@ class QM_Collector_DB_Queries extends QM_Collector {
44
  }
45
 
46
  public function process() {
47
-
48
- if ( ! SAVEQUERIES ) {
49
- return;
50
- }
51
-
52
  $this->data['total_qs'] = 0;
53
  $this->data['total_time'] = 0;
54
  $this->data['errors'] = array();
@@ -99,6 +94,12 @@ class QM_Collector_DB_Queries extends QM_Collector {
99
  public function process_db_object( $id, wpdb $db ) {
100
  global $EZSQL_ERROR, $wp_the_query;
101
 
 
 
 
 
 
 
102
  $rows = array();
103
  $types = array();
104
  $total_time = 0;
44
  }
45
 
46
  public function process() {
 
 
 
 
 
47
  $this->data['total_qs'] = 0;
48
  $this->data['total_time'] = 0;
49
  $this->data['errors'] = array();
94
  public function process_db_object( $id, wpdb $db ) {
95
  global $EZSQL_ERROR, $wp_the_query;
96
 
97
+ // With SAVEQUERIES defined as false, `wpdb::queries` is empty but `wpdb::num_queries` is not.
98
+ if ( empty( $db->queries ) ) {
99
+ $this->data['total_qs'] += $db->num_queries;
100
+ return;
101
+ }
102
+
103
  $rows = array();
104
  $types = array();
105
  $total_time = 0;
collectors/environment.php CHANGED
@@ -204,8 +204,8 @@ class QM_Collector_Environment extends QM_Collector {
204
  $this->data['wp']['constants']['SUNRISE'] = self::format_bool_constant( 'SUNRISE' );
205
  }
206
 
207
- if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) { // WPCS: input var ok
208
- $server = explode( ' ', wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ); // WPCS: sanitization ok, input var ok
209
  $server = explode( '/', reset( $server ) );
210
  } else {
211
  $server = array( '' );
@@ -217,8 +217,8 @@ class QM_Collector_Environment extends QM_Collector {
217
  $server_version = null;
218
  }
219
 
220
- if ( isset( $_SERVER['SERVER_ADDR'] ) ) { // WPCS: input var ok
221
- $address = wp_unslash( $_SERVER['SERVER_ADDR'] ); // WPCS: sanitization ok, input var ok
222
  } else {
223
  $address = null;
224
  }
@@ -241,7 +241,7 @@ class QM_Collector_Environment extends QM_Collector {
241
  public function get_extension_version( $extension ) {
242
  // Nothing is simple in PHP. The exif and mysqlnd extensions (and probably others) add a bunch of
243
  // crap to their version number, so we need to pluck out the first numeric value in the string.
244
- $version = phpversion( $extension );
245
 
246
  if ( ! $version ) {
247
  return $version;
@@ -250,7 +250,7 @@ class QM_Collector_Environment extends QM_Collector {
250
  $parts = explode( ' ', $version );
251
 
252
  foreach ( $parts as $part ) {
253
- if ( is_numeric( $part[0] ) ) {
254
  $version = $part;
255
  break;
256
  }
@@ -276,8 +276,8 @@ class QM_Collector_Environment extends QM_Collector {
276
  }
277
  }
278
 
279
- if ( empty( $php_u ) && isset( $_SERVER['USER'] ) ) { // WPCS: input var ok
280
- $php_u = wp_unslash( $_SERVER['USER'] ); // WPCS: sanitization ok, input var ok
281
  }
282
 
283
  if ( empty( $php_u ) && function_exists( 'exec' ) ) {
204
  $this->data['wp']['constants']['SUNRISE'] = self::format_bool_constant( 'SUNRISE' );
205
  }
206
 
207
+ if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) {
208
+ $server = explode( ' ', wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) );
209
  $server = explode( '/', reset( $server ) );
210
  } else {
211
  $server = array( '' );
217
  $server_version = null;
218
  }
219
 
220
+ if ( isset( $_SERVER['SERVER_ADDR'] ) ) {
221
+ $address = wp_unslash( $_SERVER['SERVER_ADDR'] );
222
  } else {
223
  $address = null;
224
  }
241
  public function get_extension_version( $extension ) {
242
  // Nothing is simple in PHP. The exif and mysqlnd extensions (and probably others) add a bunch of
243
  // crap to their version number, so we need to pluck out the first numeric value in the string.
244
+ $version = trim( phpversion( $extension ) );
245
 
246
  if ( ! $version ) {
247
  return $version;
250
  $parts = explode( ' ', $version );
251
 
252
  foreach ( $parts as $part ) {
253
+ if ( $part && is_numeric( $part[0] ) ) {
254
  $version = $part;
255
  break;
256
  }
276
  }
277
  }
278
 
279
+ if ( empty( $php_u ) && isset( $_SERVER['USER'] ) ) {
280
+ $php_u = wp_unslash( $_SERVER['USER'] );
281
  }
282
 
283
  if ( empty( $php_u ) && function_exists( 'exec' ) ) {
collectors/php_errors.php CHANGED
@@ -13,6 +13,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
13
  public $types = array();
14
  private $error_reporting = null;
15
  private $display_errors = null;
 
16
  private static $unexpected_error;
17
 
18
  public function name() {
@@ -26,12 +27,66 @@ class QM_Collector_PHP_Errors extends QM_Collector {
26
 
27
  parent::__construct();
28
  set_error_handler( array( $this, 'error_handler' ), ( E_ALL ^ QM_ERROR_FATALS ) );
29
- register_shutdown_function( array( $this, 'shutdown_handler' ) );
 
 
 
 
30
 
31
  $this->error_reporting = error_reporting();
32
  $this->display_errors = ini_get( 'display_errors' );
33
  ini_set( 'display_errors', 0 );
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
 
37
  public function error_handler( $errno, $message, $file = null, $line = null, $context = null ) {
@@ -138,6 +193,9 @@ class QM_Collector_PHP_Errors extends QM_Collector {
138
 
139
  }
140
 
 
 
 
141
  public function shutdown_handler() {
142
 
143
  $e = error_get_last();
@@ -156,19 +214,21 @@ class QM_Collector_PHP_Errors extends QM_Collector {
156
  $error = 'Fatal error';
157
  }
158
 
159
- printf( // WPCS: XSS ok.
 
160
  '<br><b>%1$s</b>: %2$s in <b>%3$s</b> on line <b>%4$d</b><br>',
161
- htmlentities( $error ),
162
- nl2br( htmlentities( $e['message'] ), false ),
163
- htmlentities( $e['file'] ),
164
  intval( $e['line'] )
165
  );
166
-
167
  }
168
 
169
  public function post_process() {
170
  ini_set( 'display_errors', $this->display_errors );
171
  restore_error_handler();
 
172
  }
173
 
174
  /**
13
  public $types = array();
14
  private $error_reporting = null;
15
  private $display_errors = null;
16
+ private $exception_handler = null;
17
  private static $unexpected_error;
18
 
19
  public function name() {
27
 
28
  parent::__construct();
29
  set_error_handler( array( $this, 'error_handler' ), ( E_ALL ^ QM_ERROR_FATALS ) );
30
+
31
+ if ( ! interface_exists( 'Throwable' ) ) {
32
+ // PHP < 7 fatal error handler.
33
+ register_shutdown_function( array( $this, 'shutdown_handler' ) );
34
+ }
35
 
36
  $this->error_reporting = error_reporting();
37
  $this->display_errors = ini_get( 'display_errors' );
38
  ini_set( 'display_errors', 0 );
39
 
40
+ $this->exception_handler = set_exception_handler( array( $this, 'exception_handler' ) );
41
+ }
42
+
43
+ /**
44
+ * Uncaught exception handler.
45
+ *
46
+ * In PHP >= 7 this will receive a Throwable object.
47
+ * In PHP < 7 it will receive an Exception object.
48
+ *
49
+ * @param Throwable|Exception $e The error or exception.
50
+ */
51
+ public function exception_handler( $e ) {
52
+ require_once __DIR__ . '/../output/Html.php';
53
+
54
+ if ( is_a( $e, 'Exception' ) ) {
55
+ $error = 'Uncaught Exception';
56
+ } else {
57
+ $error = 'Uncaught Error';
58
+ }
59
+
60
+ // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
61
+ printf(
62
+ '<br><b>%1$s</b>: %2$s in <b>%3$s</b> on line <b>%4$d</b><br>',
63
+ htmlentities( $error, ENT_COMPAT, 'UTF-8' ),
64
+ nl2br( htmlentities( $e->getMessage(), ENT_COMPAT, 'UTF-8' ), false ),
65
+ htmlentities( $e->getFile(), ENT_COMPAT, 'UTF-8' ),
66
+ intval( $e->getLine() )
67
+ );
68
+ // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
69
+
70
+ echo '<ul>';
71
+ foreach ( $e->getTrace() as $frame ) {
72
+ $callback = QM_Util::populate_callback( $frame );
73
+
74
+ printf(
75
+ '<li>%s</li>',
76
+ QM_Output_Html::output_filename( $callback['name'], $frame['file'], $frame['line'], true )
77
+ ); // WPCS: XSS ok.
78
+ }
79
+ echo '</ul>';
80
+
81
+ // The exception must be re-thrown or passed to the previously registered exception handler so that the error
82
+ // is logged appropriately instead of discarded silently.
83
+ if ( $this->exception_handler ) {
84
+ call_user_func( $this->exception_handler, $e );
85
+ } else {
86
+ throw new Exception( $e->getMessage(), $e->getCode(), $e );
87
+ }
88
+
89
+ exit( 1 );
90
  }
91
 
92
  public function error_handler( $errno, $message, $file = null, $line = null, $context = null ) {
193
 
194
  }
195
 
196
+ /**
197
+ * Displays fatal error output for sites running PHP < 7.
198
+ */
199
  public function shutdown_handler() {
200
 
201
  $e = error_get_last();
214
  $error = 'Fatal error';
215
  }
216
 
217
+ // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
218
+ printf(
219
  '<br><b>%1$s</b>: %2$s in <b>%3$s</b> on line <b>%4$d</b><br>',
220
+ htmlentities( $error, ENT_COMPAT, 'UTF-8' ),
221
+ nl2br( htmlentities( $e['message'], ENT_COMPAT, 'UTF-8' ), false ),
222
+ htmlentities( $e['file'], ENT_COMPAT, 'UTF-8' ),
223
  intval( $e['line'] )
224
  );
225
+ // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
226
  }
227
 
228
  public function post_process() {
229
  ini_set( 'display_errors', $this->display_errors );
230
  restore_error_handler();
231
+ restore_exception_handler();
232
  }
233
 
234
  /**
collectors/raw_request.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class QM_Collector_Raw_Request extends QM_Collector {
4
+
5
+ public $id = 'raw_request';
6
+
7
+ /**
8
+ * Collector name.
9
+ *
10
+ * This is unused.
11
+ *
12
+ * @return string
13
+ */
14
+ public function name() {
15
+ return __( 'Request Data', 'query-monitor' );
16
+ }
17
+
18
+ /**
19
+ * Extracts headers from a PHP-style $_SERVER array.
20
+ *
21
+ * From WP_REST_Server::get_headers()
22
+ *
23
+ * @param array $server Associative array similar to `$_SERVER`.
24
+ * @return array Headers extracted from the input.
25
+ */
26
+ protected function get_headers( array $server ) {
27
+ $headers = array();
28
+
29
+ // CONTENT_* headers are not prefixed with HTTP_.
30
+ $additional = array(
31
+ 'CONTENT_LENGTH' => true,
32
+ 'CONTENT_MD5' => true,
33
+ 'CONTENT_TYPE' => true,
34
+ );
35
+
36
+ foreach ( $server as $key => $value ) {
37
+ if ( strpos( $key, 'HTTP_' ) === 0 ) {
38
+ $headers[ substr( $key, 5 ) ] = $value;
39
+ } elseif ( isset( $additional[ $key ] ) ) {
40
+ $headers[ $key ] = $value;
41
+ }
42
+ }
43
+
44
+ return $headers;
45
+ }
46
+
47
+ /**
48
+ * Process request and response data.
49
+ */
50
+ public function process() {
51
+ $request = array(
52
+ 'ip' => $_SERVER['REMOTE_ADDR'],
53
+ 'method' => strtoupper( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ),
54
+ 'scheme' => is_ssl() ? 'https' : 'http',
55
+ 'host' => wp_unslash( $_SERVER['HTTP_HOST'] ),
56
+ 'path' => isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '/',
57
+ 'query' => isset( $_SERVER['QUERY_STRING'] ) ? wp_unslash( $_SERVER['QUERY_STRING'] ) : '',
58
+ 'headers' => $this->get_headers( wp_unslash( $_SERVER ) ),
59
+ );
60
+
61
+ ksort( $request['headers'] );
62
+
63
+ $request['url'] = sprintf( '%s://%s%s', $request['scheme'], $request['host'], $request['path'] );
64
+
65
+ $this->data['request'] = $request;
66
+
67
+ $headers = array();
68
+ $raw_headers = headers_list();
69
+ foreach ( $raw_headers as $row ) {
70
+ list( $key, $value ) = explode( ':', $row, 2 );
71
+ $headers[ trim( $key ) ] = trim( $value );
72
+ }
73
+
74
+ ksort( $headers );
75
+
76
+ $response = array(
77
+ 'status' => self::http_response_code(),
78
+ 'headers' => $headers,
79
+ );
80
+
81
+ $this->data['response'] = $response;
82
+ }
83
+
84
+ public static function http_response_code() {
85
+ if ( is_callable( 'http_response_code' ) ) {
86
+ // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.http_response_codeFound
87
+ return http_response_code();
88
+ }
89
+
90
+ return __( 'Unknown HTTP Response Code', 'query-monitor' );
91
+ }
92
+ }
93
+
94
+ function register_qm_collector_raw_request( array $collectors, QueryMonitor $qm ) {
95
+ $collectors['raw_request'] = new QM_Collector_Raw_Request();
96
+ return $collectors;
97
+ }
98
+
99
+ add_filter( 'qm/collectors', 'register_qm_collector_raw_request', 10, 2 );
collectors/request.php CHANGED
@@ -23,6 +23,7 @@ class QM_Collector_Request extends QM_Collector {
23
  'parse_request',
24
  'parse_tax_query',
25
  'pre_get_posts',
 
26
  'the_post',
27
  'wp',
28
  );
@@ -57,6 +58,7 @@ class QM_Collector_Request extends QM_Collector {
57
  'query_vars',
58
  'redirect_canonical',
59
  'request',
 
60
  );
61
 
62
  foreach ( $wp_rewrite->extra_permastructs as $permastructname => $struct ) {
23
  'parse_request',
24
  'parse_tax_query',
25
  'pre_get_posts',
26
+ 'send_headers',
27
  'the_post',
28
  'wp',
29
  );
58
  'query_vars',
59
  'redirect_canonical',
60
  'request',
61
+ 'wp_headers',
62
  );
63
 
64
  foreach ( $wp_rewrite->extra_permastructs as $permastructname => $struct ) {
collectors/timing.php CHANGED
@@ -11,7 +11,6 @@ class QM_Collector_Timing extends QM_Collector {
11
  private $track_timer = array();
12
  private $start = array();
13
  private $stop = array();
14
- private $laps = array();
15
 
16
  public function name() {
17
  return __( 'Timing', 'query-monitor' );
@@ -61,6 +60,8 @@ class QM_Collector_Timing extends QM_Collector {
61
  $function_time = $this->track_timer[ $function ]->get_time();
62
  $function_memory = $this->track_timer[ $function ]->get_memory();
63
  $function_laps = $this->track_timer[ $function ]->get_laps();
 
 
64
 
65
  $this->data['timing'][] = array(
66
  'function' => $function,
@@ -68,6 +69,8 @@ class QM_Collector_Timing extends QM_Collector {
68
  'function_memory' => $function_memory,
69
  'laps' => $function_laps,
70
  'trace' => $trace,
 
 
71
  );
72
  }
73
 
@@ -82,6 +85,18 @@ class QM_Collector_Timing extends QM_Collector {
82
  );
83
  }
84
  }
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
  }
11
  private $track_timer = array();
12
  private $start = array();
13
  private $stop = array();
 
14
 
15
  public function name() {
16
  return __( 'Timing', 'query-monitor' );
60
  $function_time = $this->track_timer[ $function ]->get_time();
61
  $function_memory = $this->track_timer[ $function ]->get_memory();
62
  $function_laps = $this->track_timer[ $function ]->get_laps();
63
+ $start_time = $this->track_timer[ $function ]->get_start_time();
64
+ $end_time = $this->track_timer[ $function ]->get_end_time();
65
 
66
  $this->data['timing'][] = array(
67
  'function' => $function,
69
  'function_memory' => $function_memory,
70
  'laps' => $function_laps,
71
  'trace' => $trace,
72
+ 'start_time' => ( $start_time - $GLOBALS['timestart'] ),
73
+ 'end_time' => ( $end_time - $GLOBALS['timestart'] ),
74
  );
75
  }
76
 
85
  );
86
  }
87
  }
88
+
89
+ if ( ! empty( $this->data['timing'] ) ) {
90
+ usort( $this->data['timing'], array( $this, 'sort_by_start_time' ) );
91
+ }
92
+ }
93
+
94
+ public function sort_by_start_time( array $a, array $b ) {
95
+ if ( $a['start_time'] === $b['start_time'] ) {
96
+ return 0;
97
+ } else {
98
+ return ( $a['start_time'] > $b['start_time'] ) ? 1 : -1;
99
+ }
100
  }
101
 
102
  }
composer.json CHANGED
@@ -43,10 +43,10 @@
43
  "@php -r \"! file_exists( 'tests/.env' ) && copy( 'tests/.env.dist', 'tests/.env' );\""
44
  ],
45
  "test:cs": [
46
- "vendor/bin/phpcs -nps --colors --report-code --report-summary --report-width=80 ."
47
  ],
48
  "test:ut": [
49
- "vendor/bin/wp db reset --yes --path=tests/wordpress",
50
  "export WP_MULTISITE=0 && vendor/bin/phpunit --verbose --colors=always --exclude-group=ms-required",
51
  "export WP_MULTISITE=1 && vendor/bin/phpunit --verbose --colors=always --exclude-group=ms-excluded"
52
  ],
43
  "@php -r \"! file_exists( 'tests/.env' ) && copy( 'tests/.env.dist', 'tests/.env' );\""
44
  ],
45
  "test:cs": [
46
+ "vendor/bin/phpcs -nps --colors --report-code --report-summary --report-width=80 --cache=tests/cache/phpcs ."
47
  ],
48
  "test:ut": [
49
+ "vendor/bin/wp db reset --yes --path=$(npm run --silent jq '.extra .\"wordpress-install-dir\"' composer.json -- -r) #",
50
  "export WP_MULTISITE=0 && vendor/bin/phpunit --verbose --colors=always --exclude-group=ms-required",
51
  "export WP_MULTISITE=1 && vendor/bin/phpunit --verbose --colors=always --exclude-group=ms-excluded"
52
  ],
dispatchers/AJAX.php CHANGED
@@ -37,7 +37,6 @@ class QM_Dispatcher_AJAX extends QM_Dispatcher {
37
 
38
  $this->before_output();
39
 
40
- /* @var QM_Output_Headers[] */
41
  foreach ( $this->get_outputters( 'headers' ) as $id => $output ) {
42
  $output->output();
43
  }
37
 
38
  $this->before_output();
39
 
 
40
  foreach ( $this->get_outputters( 'headers' ) as $id => $output ) {
41
  $output->output();
42
  }
dispatchers/Html.php CHANGED
@@ -7,10 +7,16 @@
7
 
8
  class QM_Dispatcher_Html extends QM_Dispatcher {
9
 
 
 
 
 
 
 
 
10
  public $id = 'html';
11
  public $did_footer = false;
12
 
13
- protected $outputters = array();
14
  protected $admin_bar_menu = array();
15
  protected $panel_menu = array();
16
 
@@ -141,6 +147,8 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
141
  if ( Dark_Mode::is_using_dark_mode() ) {
142
  $css .= '-dark';
143
  }
 
 
144
  }
145
 
146
  wp_enqueue_style(
@@ -185,7 +193,6 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
185
 
186
  $this->before_output();
187
 
188
- /* @var QM_Output_Html[] */
189
  foreach ( $this->outputters as $id => $output ) {
190
  $timer = new QM_Timer();
191
  $timer->start();
@@ -235,7 +242,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
235
  *
236
  * @since 3.0.0
237
  *
238
- * @param array $admin_bar_men Array of menus.
239
  */
240
  $this->panel_menu = apply_filters( 'qm/output/panel_menus', $this->admin_bar_menu );
241
 
@@ -245,7 +252,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
245
  if ( ( ! empty( $collector->concerned_filters ) || ! empty( $collector->concerned_actions ) ) && isset( $this->panel_menu[ 'qm-' . $output_id ] ) ) {
246
  $this->panel_menu[ 'qm-' . $output_id ]['children'][ 'qm-' . $output_id . '-concerned_hooks' ] = array(
247
  'href' => esc_attr( '#' . $collector->id() . '-concerned_hooks' ),
248
- 'title' => '└ ' . __( 'Hooks in Use', 'query-monitor' ),
249
  );
250
  }
251
  }
@@ -295,7 +302,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
295
  if ( ! empty( $menu['children'] ) ) {
296
  foreach ( $menu['children'] as $child ) {
297
  printf(
298
- '<option value="%1$s">%2$s</option>',
299
  esc_attr( $child['href'] ),
300
  esc_html( $child['title'] )
301
  );
@@ -382,9 +389,12 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
382
 
383
  echo '<div class="qm-boxed">';
384
  $constants = array(
 
 
 
 
385
  'QM_DB_EXPENSIVE' => array(
386
- /* translators: %s: The default value for a PHP constant */
387
- 'label' => __( 'If an individual database query takes longer than this time to execute, it\'s considered "slow" and triggers a warning. Default value: %s.', 'query-monitor' ),
388
  'default' => 0.05,
389
  ),
390
  'QM_DISABLED' => array(
@@ -437,6 +447,19 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
437
  '<code>' . esc_html( $constant['default'] ) . '</code>'
438
  );
439
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
  if ( defined( $name ) ) {
441
  $current_value = constant( $name );
442
  if ( is_bool( $current_value ) ) {
@@ -469,7 +492,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
469
  * @since 3.1.0
470
  *
471
  * @param QM_Dispatcher_Html $this The HTML dispatcher instance.
472
- * @param QM_Output[] $this->outputters Array of outputters.
473
  */
474
  do_action( 'qm/output/after', $this, $this->outputters );
475
 
@@ -555,7 +578,10 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
555
 
556
  $admin_bar_menu = array(
557
  'top' => array(
558
- 'title' => sprintf( '<span class="ab-icon">QM</span><span class="ab-label">%s</span>', $title ),
 
 
 
559
  'classname' => $class,
560
  ),
561
  'sub' => array(),
7
 
8
  class QM_Dispatcher_Html extends QM_Dispatcher {
9
 
10
+ /**
11
+ * Outputter instances.
12
+ *
13
+ * @var QM_Output_html[] Array of outputters.
14
+ */
15
+ protected $outputters = array();
16
+
17
  public $id = 'html';
18
  public $did_footer = false;
19
 
 
20
  protected $admin_bar_menu = array();
21
  protected $panel_menu = array();
22
 
147
  if ( Dark_Mode::is_using_dark_mode() ) {
148
  $css .= '-dark';
149
  }
150
+ } elseif ( defined( 'QM_DARK_MODE' ) && QM_DARK_MODE ) {
151
+ $css .= '-dark';
152
  }
153
 
154
  wp_enqueue_style(
193
 
194
  $this->before_output();
195
 
 
196
  foreach ( $this->outputters as $id => $output ) {
197
  $timer = new QM_Timer();
198
  $timer->start();
242
  *
243
  * @since 3.0.0
244
  *
245
+ * @param array $admin_bar_menu Array of menus.
246
  */
247
  $this->panel_menu = apply_filters( 'qm/output/panel_menus', $this->admin_bar_menu );
248
 
252
  if ( ( ! empty( $collector->concerned_filters ) || ! empty( $collector->concerned_actions ) ) && isset( $this->panel_menu[ 'qm-' . $output_id ] ) ) {
253
  $this->panel_menu[ 'qm-' . $output_id ]['children'][ 'qm-' . $output_id . '-concerned_hooks' ] = array(
254
  'href' => esc_attr( '#' . $collector->id() . '-concerned_hooks' ),
255
+ 'title' => __( 'Hooks in Use', 'query-monitor' ),
256
  );
257
  }
258
  }
302
  if ( ! empty( $menu['children'] ) ) {
303
  foreach ( $menu['children'] as $child ) {
304
  printf(
305
+ '<option value="%1$s">└ %2$s</option>',
306
  esc_attr( $child['href'] ),
307
  esc_html( $child['title'] )
308
  );
389
 
390
  echo '<div class="qm-boxed">';
391
  $constants = array(
392
+ 'QM_DARK_MODE' => array(
393
+ 'label' => __( 'Enable dark mode for Query Monitor\'s interface.', 'query-monitor' ),
394
+ 'default' => false,
395
+ ),
396
  'QM_DB_EXPENSIVE' => array(
397
+ 'label' => __( 'If an individual database query takes longer than this time to execute, it\'s considered "slow" and triggers a warning.', 'query-monitor' ),
 
398
  'default' => 0.05,
399
  ),
400
  'QM_DISABLED' => array(
447
  '<code>' . esc_html( $constant['default'] ) . '</code>'
448
  );
449
 
450
+ $default_value = $constant['default'];
451
+ if ( is_bool( $default_value ) ) {
452
+ $default_value = ( $default_value ? 'true' : 'false' );
453
+ }
454
+
455
+ echo '<br><span class="qm-info">';
456
+ printf(
457
+ /* translators: %s: Default value for a PHP constant */
458
+ esc_html__( 'Default value: %s', 'query-monitor' ),
459
+ '<code>' . esc_html( $default_value ) . '</code>'
460
+ );
461
+ echo '</span>';
462
+
463
  if ( defined( $name ) ) {
464
  $current_value = constant( $name );
465
  if ( is_bool( $current_value ) ) {
492
  * @since 3.1.0
493
  *
494
  * @param QM_Dispatcher_Html $this The HTML dispatcher instance.
495
+ * @param QM_Output_Html[] $this->outputters Array of outputters.
496
  */
497
  do_action( 'qm/output/after', $this, $this->outputters );
498
 
578
 
579
  $admin_bar_menu = array(
580
  'top' => array(
581
+ 'title' => sprintf(
582
+ '<span class="ab-icon">QM</span><span class="ab-label">%s</span>',
583
+ $title
584
+ ),
585
  'classname' => $class,
586
  ),
587
  'sub' => array(),
dispatchers/WP_Die.php CHANGED
@@ -40,7 +40,7 @@ class QM_Dispatcher_WP_Die extends QM_Dispatcher {
40
  $filtered_trace = $this->trace->get_display_trace();
41
 
42
  // Ignore the `apply_filters('wp_die_handler')` stack frame:
43
- array_pop( $filtered_trace );
44
 
45
  foreach ( $filtered_trace as $i => $item ) {
46
  $stack[] = QM_Output_Html::output_filename( $item['display'], $item['file'], $item['line'] );
@@ -81,11 +81,12 @@ class QM_Dispatcher_WP_Die extends QM_Dispatcher {
81
  }
82
 
83
  #query-monitor ol {
84
- padding: 0 0 1em 2em;
85
  }
86
 
87
  #query-monitor li {
88
  margin: 0 0 0.5em;
 
89
  }
90
 
91
  #query-monitor .qm-info {
40
  $filtered_trace = $this->trace->get_display_trace();
41
 
42
  // Ignore the `apply_filters('wp_die_handler')` stack frame:
43
+ array_shift( $filtered_trace );
44
 
45
  foreach ( $filtered_trace as $i => $item ) {
46
  $stack[] = QM_Output_Html::output_filename( $item['display'], $item['file'], $item['line'] );
81
  }
82
 
83
  #query-monitor ol {
84
+ padding: 0 0 1em 1em;
85
  }
86
 
87
  #query-monitor li {
88
  margin: 0 0 0.5em;
89
+ list-style: none;
90
  }
91
 
92
  #query-monitor .qm-info {
output/Html.php CHANGED
@@ -121,7 +121,7 @@ abstract class QM_Output_Html extends QM_Output {
121
  esc_attr( $this->current_id . '-concerned_hooks' ),
122
  sprintf(
123
  /* translators: %s: Panel name */
124
- esc_html__( '%s: Hooks in Use', 'query-monitor' ),
125
  esc_html( $this->collector->name() )
126
  )
127
  );
121
  esc_attr( $this->current_id . '-concerned_hooks' ),
122
  sprintf(
123
  /* translators: %s: Panel name */
124
+ esc_html__( '%s: Related Hooks with Filters or Actions Attached', 'query-monitor' ),
125
  esc_html( $this->collector->name() )
126
  )
127
  );
output/headers/overview.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Headers_Overview extends QM_Output_Headers {
9
 
 
 
 
 
 
 
 
10
  public function get_output() {
11
 
12
  $data = $this->collector->get_data();
7
 
8
  class QM_Output_Headers_Overview extends QM_Output_Headers {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Overview Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function get_output() {
18
 
19
  $data = $this->collector->get_data();
output/headers/php_errors.php CHANGED
@@ -6,6 +6,13 @@
6
  */
7
  class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
8
 
 
 
 
 
 
 
 
9
  public function get_output() {
10
 
11
  $data = $this->collector->get_data();
@@ -42,12 +49,11 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
42
  }
43
 
44
  return array_merge(
45
- array(
46
- 'error-count' => $count,
47
- ),
48
  $headers
49
- );
50
-
51
  }
52
 
53
  }
6
  */
7
  class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
8
 
9
+ /**
10
+ * Collector instance.
11
+ *
12
+ * @var QM_Collector_PHP_Errors Collector.
13
+ */
14
+ protected $collector;
15
+
16
  public function get_output() {
17
 
18
  $data = $this->collector->get_data();
49
  }
50
 
51
  return array_merge(
52
+ array(
53
+ 'error-count' => $count,
54
+ ),
55
  $headers
56
+ );
 
57
  }
58
 
59
  }
output/headers/redirects.php CHANGED
@@ -6,6 +6,13 @@
6
  */
7
  class QM_Output_Headers_Redirects extends QM_Output_Headers {
8
 
 
 
 
 
 
 
 
9
  public function get_output() {
10
 
11
  $data = $this->collector->get_data();
6
  */
7
  class QM_Output_Headers_Redirects extends QM_Output_Headers {
8
 
9
+ /**
10
+ * Collector instance.
11
+ *
12
+ * @var QM_Collector_Redirects Collector.
13
+ */
14
+ protected $collector;
15
+
16
  public function get_output() {
17
 
18
  $data = $this->collector->get_data();
output/html/admin.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Admin extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 60 );
@@ -46,8 +53,32 @@ class QM_Output_Html_Admin extends QM_Output_Html {
46
  echo '</section>';
47
 
48
  echo '<section>';
49
- echo '<h3>$pagenow</h3>';
50
- echo '<p>' . esc_html( $data['pagenow'] ) . '</p>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  echo '</section>';
52
 
53
  if ( ! empty( $data['list_table'] ) ) {
7
 
8
  class QM_Output_Html_Admin extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Admin Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 60 );
53
  echo '</section>';
54
 
55
  echo '<section>';
56
+ echo '<h3>' . esc_html__( 'Globals', 'query-monitor' ) . '</h3>';
57
+ echo '<table>';
58
+ echo '<thead class="qm-screen-reader-text">';
59
+ echo '<tr>';
60
+ echo '<th scope="col">' . esc_html__( 'Global Variable', 'query-monitor' ) . '</th>';
61
+ echo '<th scope="col">' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
62
+ echo '</tr>';
63
+ echo '</thead>';
64
+ echo '<tbody>';
65
+
66
+ $admin_globals = array(
67
+ 'pagenow',
68
+ 'typenow',
69
+ 'taxnow',
70
+ 'hook_suffix',
71
+ );
72
+
73
+ foreach ( $admin_globals as $key ) {
74
+ echo '<tr>';
75
+ echo '<th scope="row">$' . esc_html( $key ) . '</th>';
76
+ echo '<td>' . esc_html( $data[ $key ] ) . '</td>';
77
+ echo '</tr>';
78
+ }
79
+
80
+ echo '</tbody>';
81
+ echo '</table>';
82
  echo '</section>';
83
 
84
  if ( ! empty( $data['list_table'] ) ) {
output/html/assets.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  abstract class QM_Output_Html_Assets extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 70 );
@@ -81,7 +88,7 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
81
  printf(
82
  '<td colspan="7">%1$s</td>',
83
  sprintf(
84
- esc_html( $type_label['total'] ),
85
  '<span class="qm-items-number">' . esc_html( number_format_i18n( $data['counts']['total'] ) ) . '</span>'
86
  )
87
  );
@@ -92,8 +99,6 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
92
  }
93
 
94
  protected function dependency_row( $handle, array $asset, $label ) {
95
- $data = $this->collector->get_data();
96
-
97
  $highlight_deps = array_map( array( $this, '_prefix_type' ), $asset['dependencies'] );
98
  $highlight_dependents = array_map( array( $this, '_prefix_type' ), $asset['dependents'] );
99
 
@@ -118,8 +123,19 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
118
  echo esc_html( $label );
119
  echo '</td>';
120
 
 
 
 
 
 
 
 
 
 
 
 
121
  echo '<td class="qm-nowrap qm-ltr">' . esc_html( $handle ) . '</td>';
122
- echo '<td class="qm-nowrap qm-ltr">' . esc_html( $asset['host'] ) . '</td>';
123
  echo '<td class="qm-ltr">';
124
  if ( is_wp_error( $asset['source'] ) ) {
125
  $error_data = $asset['source']->get_error_data();
@@ -175,7 +191,10 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
175
  }
176
 
177
  $type_label = $this->get_type_labels();
178
- $label = sprintf( $type_label['count'], number_format_i18n( $data['counts']['total'] ) );
 
 
 
179
 
180
  $args = array(
181
  'title' => esc_html( $label ),
7
 
8
  abstract class QM_Output_Html_Assets extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Assets Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 70 );
88
  printf(
89
  '<td colspan="7">%1$s</td>',
90
  sprintf(
91
+ esc_html( translate_nooped_plural( $type_label['total'], $data['counts']['total'], 'query-monitor' ) ),
92
  '<span class="qm-items-number">' . esc_html( number_format_i18n( $data['counts']['total'] ) ) . '</span>'
93
  )
94
  );
99
  }
100
 
101
  protected function dependency_row( $handle, array $asset, $label ) {
 
 
102
  $highlight_deps = array_map( array( $this, '_prefix_type' ), $asset['dependencies'] );
103
  $highlight_dependents = array_map( array( $this, '_prefix_type' ), $asset['dependents'] );
104
 
123
  echo esc_html( $label );
124
  echo '</td>';
125
 
126
+ $host = $asset['host'];
127
+ $parts = explode( '.', $host );
128
+
129
+ foreach ( $parts as $k => $part ) {
130
+ if ( strlen( $part ) > 16 ) {
131
+ $parts[ $k ] = substr( $parts[ $k ], 0, 6 ) . '&hellip;' . substr( $parts[ $k ], -6 );
132
+ }
133
+ }
134
+
135
+ $host = implode( '.', $parts );
136
+
137
  echo '<td class="qm-nowrap qm-ltr">' . esc_html( $handle ) . '</td>';
138
+ echo '<td class="qm-nowrap qm-ltr">' . esc_html( $host ) . '</td>';
139
  echo '<td class="qm-ltr">';
140
  if ( is_wp_error( $asset['source'] ) ) {
141
  $error_data = $asset['source']->get_error_data();
191
  }
192
 
193
  $type_label = $this->get_type_labels();
194
+ $label = sprintf(
195
+ translate_nooped_plural( $type_label['count'], $data['counts']['total'], 'query-monitor' ),
196
+ number_format_i18n( $data['counts']['total'] )
197
+ );
198
 
199
  $args = array(
200
  'title' => esc_html( $label ),
output/html/assets_scripts.php CHANGED
@@ -7,13 +7,20 @@
7
 
8
  class QM_Output_Html_Assets_Scripts extends QM_Output_Html_Assets {
9
 
 
 
 
 
 
 
 
10
  public function get_type_labels() {
11
  return array(
12
  /* translators: %s: Total number of enqueued scripts */
13
- 'total' => _x( 'Total: %s', 'Enqueued scripts', 'query-monitor' ),
14
  'plural' => __( 'Scripts', 'query-monitor' ),
15
  /* translators: %s: Total number of enqueued scripts */
16
- 'count' => _x( 'Scripts (%s)', 'Enqueued scripts', 'query-monitor' ),
17
  );
18
  }
19
 
7
 
8
  class QM_Output_Html_Assets_Scripts extends QM_Output_Html_Assets {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Assets_Scripts Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function get_type_labels() {
18
  return array(
19
  /* translators: %s: Total number of enqueued scripts */
20
+ 'total' => _nx_noop( 'Total: %s', 'Total: %s', 'Enqueued scripts', 'query-monitor' ),
21
  'plural' => __( 'Scripts', 'query-monitor' ),
22
  /* translators: %s: Total number of enqueued scripts */
23
+ 'count' => _nx_noop( 'Scripts (%s)', 'Scripts (%s)', 'Enqueued scripts', 'query-monitor' ),
24
  );
25
  }
26
 
output/html/assets_styles.php CHANGED
@@ -7,13 +7,20 @@
7
 
8
  class QM_Output_Html_Assets_Styles extends QM_Output_Html_Assets {
9
 
 
 
 
 
 
 
 
10
  public function get_type_labels() {
11
  return array(
12
  /* translators: %s: Total number of enqueued styles */
13
- 'total' => _x( 'Total: %s', 'Enqueued styles', 'query-monitor' ),
14
  'plural' => __( 'Styles', 'query-monitor' ),
15
  /* translators: %s: Total number of enqueued styles */
16
- 'count' => _x( 'Styles (%s)', 'Enqueued styles', 'query-monitor' ),
17
  );
18
  }
19
 
7
 
8
  class QM_Output_Html_Assets_Styles extends QM_Output_Html_Assets {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Assets_Styles Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function get_type_labels() {
18
  return array(
19
  /* translators: %s: Total number of enqueued styles */
20
+ 'total' => _nx_noop( 'Total: %s', 'Total: %s', 'Enqueued styles', 'query-monitor' ),
21
  'plural' => __( 'Styles', 'query-monitor' ),
22
  /* translators: %s: Total number of enqueued styles */
23
+ 'count' => _nx_noop( 'Styles (%s)', 'Styles (%s)', 'Enqueued styles', 'query-monitor' ),
24
  );
25
  }
26
 
output/html/block_editor.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Block_Editor extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 55 );
@@ -58,10 +65,10 @@ class QM_Output_Html_Block_Editor extends QM_Output_Html {
58
  echo '<tfoot>';
59
  echo '<tr>';
60
  printf(
61
- '<td colspan="6">%1$s</td>',
62
  sprintf(
63
  /* translators: %s: Total number of content blocks used */
64
- esc_html_x( 'Total: %s', 'Content blocks used', 'query-monitor' ),
65
  '<span class="qm-items-number">' . esc_html( number_format_i18n( $data['total_blocks'] ) ) . '</span>'
66
  )
67
  );
7
 
8
  class QM_Output_Html_Block_Editor extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Block_Editor Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 55 );
65
  echo '<tfoot>';
66
  echo '<tr>';
67
  printf(
68
+ '<td colspan="6">%s</td>',
69
  sprintf(
70
  /* translators: %s: Total number of content blocks used */
71
+ esc_html( _nx( 'Total: %s', 'Total: %s', $data['total_blocks'], 'Content blocks used', 'query-monitor' ) ),
72
  '<span class="qm-items-number">' . esc_html( number_format_i18n( $data['total_blocks'] ) ) . '</span>'
73
  )
74
  );
output/html/caps.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Caps extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 105 );
@@ -138,11 +145,11 @@ class QM_Output_Html_Caps extends QM_Output_Html {
138
 
139
  $last = end( $filtered_trace );
140
  if ( isset( $last['function'] ) && 'map_meta_cap' === $last['function'] ) {
141
- array_pop( $filtered_trace ); // remove the map_meta_cap() call
142
  }
143
 
144
- array_pop( $filtered_trace ); // remove the WP_User->has_cap() call
145
- array_pop( $filtered_trace ); // remove the *_user_can() call
146
 
147
  if ( ! count( $filtered_trace ) ) {
148
  $responsible_name = QM_Util::standard_dir( $trace[1]['file'], '' ) . ':' . $trace[1]['line'];
@@ -160,14 +167,15 @@ class QM_Output_Html_Caps extends QM_Output_Html {
160
 
161
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
162
 
163
- $caller = array_pop( $stack );
 
 
164
 
165
  if ( ! empty( $stack ) ) {
166
  echo self::build_toggler(); // WPCS: XSS ok;
167
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
168
  }
169
 
170
- echo "<li>{$caller}</li>"; // WPCS: XSS ok.
171
  echo '</ol></td>';
172
 
173
  printf(
@@ -184,13 +192,14 @@ class QM_Output_Html_Caps extends QM_Output_Html {
184
  echo '<tfoot>';
185
 
186
  $colspan = ( $show_user ) ? 5 : 4;
 
187
 
188
  echo '<tr>';
189
  echo '<td colspan="' . intval( $colspan ) . '">';
190
  printf(
191
  /* translators: %s: Number of user capability checks */
192
- esc_html_x( 'Total: %s', 'User capability checks', 'query-monitor' ),
193
- '<span class="qm-items-number">' . esc_html( number_format_i18n( count( $data['caps'] ) ) ) . '</span>'
194
  );
195
  echo '</td>';
196
  echo '</tr>';
7
 
8
  class QM_Output_Html_Caps extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Caps Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 105 );
145
 
146
  $last = end( $filtered_trace );
147
  if ( isset( $last['function'] ) && 'map_meta_cap' === $last['function'] ) {
148
+ array_shift( $filtered_trace ); // remove the map_meta_cap() call
149
  }
150
 
151
+ array_shift( $filtered_trace ); // remove the WP_User->has_cap() call
152
+ array_shift( $filtered_trace ); // remove the *_user_can() call
153
 
154
  if ( ! count( $filtered_trace ) ) {
155
  $responsible_name = QM_Util::standard_dir( $trace[1]['file'], '' ) . ':' . $trace[1]['line'];
167
 
168
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
169
 
170
+ $caller = array_shift( $stack );
171
+
172
+ echo "<li>{$caller}</li>"; // WPCS: XSS ok.
173
 
174
  if ( ! empty( $stack ) ) {
175
  echo self::build_toggler(); // WPCS: XSS ok;
176
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
177
  }
178
 
 
179
  echo '</ol></td>';
180
 
181
  printf(
192
  echo '<tfoot>';
193
 
194
  $colspan = ( $show_user ) ? 5 : 4;
195
+ $count = count( $data['caps'] );
196
 
197
  echo '<tr>';
198
  echo '<td colspan="' . intval( $colspan ) . '">';
199
  printf(
200
  /* translators: %s: Number of user capability checks */
201
+ esc_html( _nx( 'Total: %s', 'Total: %s', $count, 'User capability checks', 'query-monitor' ) ),
202
+ '<span class="qm-items-number">' . esc_html( number_format_i18n( $count ) ) . '</span>'
203
  );
204
  echo '</td>';
205
  echo '</tr>';
output/html/conditionals.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Conditionals extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 1000 );
7
 
8
  class QM_Output_Html_Conditionals extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Conditionals Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 1000 );
output/html/db_callers.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_DB_Callers extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 30 );
@@ -99,7 +106,7 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
99
  $dbq_data = $dbq->get_data();
100
  if ( isset( $dbq_data['times'] ) ) {
101
  $menu['qm-db_queries-$wpdb']['children'][] = $this->menu( array(
102
- 'title' => '└ ' . esc_html__( 'Queries by Caller', 'query-monitor' ),
103
  ) );
104
  }
105
  }
7
 
8
  class QM_Output_Html_DB_Callers extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_DB_Callers Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 30 );
106
  $dbq_data = $dbq->get_data();
107
  if ( isset( $dbq_data['times'] ) ) {
108
  $menu['qm-db_queries-$wpdb']['children'][] = $this->menu( array(
109
+ 'title' => esc_html__( 'Queries by Caller', 'query-monitor' ),
110
  ) );
111
  }
112
  }
output/html/db_components.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_DB_Components extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 40 );
@@ -96,7 +103,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
96
  $dbq_data = $dbq->get_data();
97
  if ( isset( $dbq_data['component_times'] ) ) {
98
  $menu['qm-db_queries-$wpdb']['children'][] = $this->menu( array(
99
- 'title' => '└ ' . esc_html__( 'Queries by Component', 'query-monitor' ),
100
  ) );
101
  }
102
  }
7
 
8
  class QM_Output_Html_DB_Components extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_DB_Components Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 40 );
103
  $dbq_data = $dbq->get_data();
104
  if ( isset( $dbq_data['component_times'] ) ) {
105
  $menu['qm-db_queries-$wpdb']['children'][] = $this->menu( array(
106
+ 'title' => esc_html__( 'Queries by Component', 'query-monitor' ),
107
  ) );
108
  }
109
  }
output/html/db_dupes.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_DB_Dupes extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 45 );
@@ -111,11 +118,12 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
111
  if ( $dbq ) {
112
  $dbq_data = $dbq->get_data();
113
  if ( isset( $dbq_data['dupes'] ) && count( $dbq_data['dupes'] ) ) {
 
114
  $menu[ $this->collector->id() ] = $this->menu( array(
115
  'title' => esc_html( sprintf(
116
  /* translators: %s: Number of duplicate database queries */
117
- __( 'Duplicate Queries (%s)', 'query-monitor' ),
118
- count( $dbq_data['dupes'] )
119
  ) ),
120
  ) );
121
  }
@@ -127,7 +135,7 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
127
  public function panel_menu( array $menu ) {
128
  $id = $this->collector->id();
129
  if ( isset( $menu[ $id ] ) ) {
130
- $menu[ $id ]['title'] = '└ ' . $menu[ $id ]['title'];
131
 
132
  $menu['qm-db_queries-$wpdb']['children'][] = $menu[ $id ];
133
  unset( $menu[ $id ] );
7
 
8
  class QM_Output_Html_DB_Dupes extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_DB_Dupes Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 45 );
118
  if ( $dbq ) {
119
  $dbq_data = $dbq->get_data();
120
  if ( isset( $dbq_data['dupes'] ) && count( $dbq_data['dupes'] ) ) {
121
+ $count = count( $dbq_data['dupes'] );
122
  $menu[ $this->collector->id() ] = $this->menu( array(
123
  'title' => esc_html( sprintf(
124
  /* translators: %s: Number of duplicate database queries */
125
+ _n( 'Duplicate Queries (%s)', 'Duplicate Queries (%s)', $count, 'query-monitor' ),
126
+ number_format_i18n( $count )
127
  ) ),
128
  ) );
129
  }
135
  public function panel_menu( array $menu ) {
136
  $id = $this->collector->id();
137
  if ( isset( $menu[ $id ] ) ) {
138
+ $menu[ $id ]['title'] = $menu[ $id ]['title'];
139
 
140
  $menu['qm-db_queries-$wpdb']['children'][] = $menu[ $id ];
141
  unset( $menu[ $id ] );
output/html/db_queries.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_DB_Queries extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public $query_row = 0;
11
 
12
  public function __construct( QM_Collector $collector ) {
@@ -86,7 +93,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
86
  }
87
 
88
  protected function output_expensive_queries( array $expensive ) {
89
- $dp = strlen( substr( strrchr( QM_DB_EXPENSIVE, '.' ), 1 ) );
90
 
91
  $panel_name = sprintf(
92
  /* translators: %s: Database query time in seconds */
@@ -262,7 +269,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
262
  echo '<td colspan="' . intval( $span - 1 ) . '">';
263
  printf(
264
  /* translators: %s: Number of database queries */
265
- esc_html_x( 'Total: %s', 'Database queries', 'query-monitor' ),
266
  '<span class="qm-items-number">' . esc_html( number_format_i18n( $db->total_qs ) ) . '</span>'
267
  );
268
  echo '</td>';
@@ -306,7 +313,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
306
  $caller_name = self::output_filename( $row['caller'], $caller['calling_file'], $caller['calling_line'] );
307
  $stack = array();
308
  $filtered_trace = $row['trace']->get_display_trace();
309
- array_pop( $filtered_trace );
310
 
311
  foreach ( $filtered_trace as $item ) {
312
  $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
@@ -372,15 +379,15 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
372
  }
373
 
374
  if ( isset( $cols['caller'] ) ) {
375
- echo "<td class='qm-row-caller qm-ltr qm-has-toggle qm-nowrap'><ol class='qm-toggler qm-numbered'>";
 
 
376
  echo self::build_toggler(); // WPCS: XSS ok;
377
 
378
  if ( ! empty( $stack ) ) {
379
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
380
  }
381
 
382
- echo "<li>{$caller_name}</li>"; // WPCS: XSS ok.
383
-
384
  echo '</ol>';
385
  if ( $row['is_main_query'] ) {
386
  printf(
@@ -446,16 +453,22 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
446
  foreach ( $data['dbs'] as $key => $db ) {
447
  $title[] = sprintf(
448
  /* translators: %s: Database query time in seconds */
449
- '%s' . esc_html_x( '%s S', 'Query time', 'query-monitor' ),
450
  ( count( $data['dbs'] ) > 1 ? '&bull;&nbsp;&nbsp;&nbsp;' : '' ),
451
  number_format_i18n( $db->total_time, 4 )
452
  );
453
  $title[] = sprintf(
454
  /* translators: %s: Number of database queries */
455
- esc_html_x( '%s Q', 'Query count', 'query-monitor' ),
456
  number_format_i18n( $db->total_qs )
457
  );
458
  }
 
 
 
 
 
 
459
  }
460
 
461
  foreach ( $title as &$t ) {
@@ -507,25 +520,28 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
507
 
508
  if ( $errors ) {
509
  $id = $this->collector->id() . '-errors';
 
510
  $menu[ $id ] = $this->menu( array(
511
  'id' => 'query-monitor-errors',
512
  'href' => '#qm-query-errors',
513
  'title' => esc_html( sprintf(
514
  /* translators: %s: Number of database errors */
515
- __( 'Database Errors (%s)', 'query-monitor' ),
516
- number_format_i18n( count( $errors ) )
517
  ) ),
518
  ) );
519
  }
 
520
  if ( $expensive ) {
521
  $id = $this->collector->id() . '-expensive';
 
522
  $menu[ $id ] = $this->menu( array(
523
  'id' => 'query-monitor-expensive',
524
  'href' => '#qm-query-expensive',
525
  'title' => esc_html( sprintf(
526
  /* translators: %s: Number of slow database queries */
527
- __( 'Slow Queries (%s)', 'query-monitor' ),
528
- number_format_i18n( count( $expensive ) )
529
  ) ),
530
  ) );
531
  }
@@ -538,7 +554,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
538
  foreach ( array( 'errors', 'expensive' ) as $sub ) {
539
  $id = $this->collector->id() . '-' . $sub;
540
  if ( isset( $menu[ $id ] ) ) {
541
- $menu[ $id ]['title'] = '└ ' . $menu[ $id ]['title'];
542
 
543
  $menu['qm-db_queries-$wpdb']['children'][] = $menu[ $id ];
544
  unset( $menu[ $id ] );
7
 
8
  class QM_Output_Html_DB_Queries extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_DB_Queries Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public $query_row = 0;
18
 
19
  public function __construct( QM_Collector $collector ) {
93
  }
94
 
95
  protected function output_expensive_queries( array $expensive ) {
96
+ $dp = strlen( substr( strrchr( (string) QM_DB_EXPENSIVE, '.' ), 1 ) );
97
 
98
  $panel_name = sprintf(
99
  /* translators: %s: Database query time in seconds */
269
  echo '<td colspan="' . intval( $span - 1 ) . '">';
270
  printf(
271
  /* translators: %s: Number of database queries */
272
+ esc_html( _nx( 'Total: %s', 'Total: %s', $db->total_qs, 'Query count', 'query-monitor' ) ),
273
  '<span class="qm-items-number">' . esc_html( number_format_i18n( $db->total_qs ) ) . '</span>'
274
  );
275
  echo '</td>';
313
  $caller_name = self::output_filename( $row['caller'], $caller['calling_file'], $caller['calling_line'] );
314
  $stack = array();
315
  $filtered_trace = $row['trace']->get_display_trace();
316
+ array_shift( $filtered_trace );
317
 
318
  foreach ( $filtered_trace as $item ) {
319
  $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
379
  }
380
 
381
  if ( isset( $cols['caller'] ) ) {
382
+ echo '<td class="qm-row-caller qm-ltr qm-has-toggle qm-nowrap"><ol class="qm-toggler qm-numbered">';
383
+ echo "<li>{$caller_name}</li>"; // WPCS: XSS ok.
384
+
385
  echo self::build_toggler(); // WPCS: XSS ok;
386
 
387
  if ( ! empty( $stack ) ) {
388
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
389
  }
390
 
 
 
391
  echo '</ol>';
392
  if ( $row['is_main_query'] ) {
393
  printf(
453
  foreach ( $data['dbs'] as $key => $db ) {
454
  $title[] = sprintf(
455
  /* translators: %s: Database query time in seconds */
456
+ '%s' . esc_html( _nx( '%s S', '%s S', $db->total_time, 'Query time', 'query-monitor' ) ),
457
  ( count( $data['dbs'] ) > 1 ? '&bull;&nbsp;&nbsp;&nbsp;' : '' ),
458
  number_format_i18n( $db->total_time, 4 )
459
  );
460
  $title[] = sprintf(
461
  /* translators: %s: Number of database queries */
462
+ esc_html( _nx( '%s Q', '%s Q', $db->total_qs, 'Query count', 'query-monitor' ) ),
463
  number_format_i18n( $db->total_qs )
464
  );
465
  }
466
+ } elseif ( isset( $data['total_qs'] ) ) {
467
+ $title[] = sprintf(
468
+ /* translators: %s: Number of database queries */
469
+ esc_html( _nx( '%s Q', '%s Q', $data['total_qs'], 'Query count', 'query-monitor' ) ),
470
+ number_format_i18n( $data['total_qs'] )
471
+ );
472
  }
473
 
474
  foreach ( $title as &$t ) {
520
 
521
  if ( $errors ) {
522
  $id = $this->collector->id() . '-errors';
523
+ $count = count( $errors );
524
  $menu[ $id ] = $this->menu( array(
525
  'id' => 'query-monitor-errors',
526
  'href' => '#qm-query-errors',
527
  'title' => esc_html( sprintf(
528
  /* translators: %s: Number of database errors */
529
+ _n( 'Database Errors (%s)', 'Database Errors (%s)', $count, 'query-monitor' ),
530
+ number_format_i18n( $count )
531
  ) ),
532
  ) );
533
  }
534
+
535
  if ( $expensive ) {
536
  $id = $this->collector->id() . '-expensive';
537
+ $count = count( $expensive );
538
  $menu[ $id ] = $this->menu( array(
539
  'id' => 'query-monitor-expensive',
540
  'href' => '#qm-query-expensive',
541
  'title' => esc_html( sprintf(
542
  /* translators: %s: Number of slow database queries */
543
+ _n( 'Slow Queries (%s)', 'Slow Queries (%s)', $count, 'query-monitor' ),
544
+ number_format_i18n( $count )
545
  ) ),
546
  ) );
547
  }
554
  foreach ( array( 'errors', 'expensive' ) as $sub ) {
555
  $id = $this->collector->id() . '-' . $sub;
556
  if ( isset( $menu[ $id ] ) ) {
557
+ $menu[ $id ]['title'] = $menu[ $id ]['title'];
558
 
559
  $menu['qm-db_queries-$wpdb']['children'][] = $menu[ $id ];
560
  unset( $menu[ $id ] );
output/html/debug_bar.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Debug_Bar extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 200 );
7
 
8
  class QM_Output_Html_Debug_Bar extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Debug_Bar Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 200 );
output/html/environment.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Environment extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 110 );
7
 
8
  class QM_Output_Html_Environment extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Environment Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 110 );
output/html/headers.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Request and response headers output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
7
+
8
+ class QM_Output_Html_Headers extends QM_Output_Html {
9
+
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Raw_Request Collector.
14
+ */
15
+ protected $collector;
16
+
17
+ public function __construct( QM_Collector $collector ) {
18
+ parent::__construct( $collector );
19
+ add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 20 );
20
+ }
21
+
22
+ public function output() {
23
+ $this->output_request();
24
+ $this->output_response();
25
+ }
26
+
27
+ public function output_request() {
28
+ $data = $this->collector->get_data();
29
+
30
+ $this->before_tabular_output();
31
+
32
+ $this->output_header_table( $data['request']['headers'], __( 'Request Header Name', 'query-monitor' ) );
33
+
34
+ $this->after_tabular_output();
35
+ }
36
+
37
+ public function output_response() {
38
+ $data = $this->collector->get_data();
39
+ $id = sprintf( 'qm-%s-response', $this->collector->id );
40
+
41
+ $this->before_tabular_output( $id );
42
+
43
+ $this->output_header_table( $data['response']['headers'], __( 'Response Header Name', 'query-monitor' ) );
44
+
45
+ $this->after_tabular_output();
46
+ }
47
+
48
+ protected function output_header_table( array $headers, $title ) {
49
+ echo '<thead>';
50
+ echo '<tr>';
51
+ echo '<th>';
52
+ echo esc_html( $title );
53
+ echo '</th><th>';
54
+ esc_html_e( 'Value', 'query-monitor' );
55
+ echo '</th></tr>';
56
+ echo '<tbody>';
57
+
58
+ foreach ( $headers as $name => $value ) {
59
+ echo '<tr>';
60
+ $formatted = str_replace( ' ', '-', ucwords( strtolower( str_replace( array( '-', '_' ), ' ', $name ) ) ) );
61
+ printf( '<th scope="row"><code>%s</code></th>', esc_html( $formatted ) );
62
+ printf( '<td><pre class="qm-pre-wrap"><code>%s</code></pre></td>', esc_html( $value ) );
63
+ echo '</tr>';
64
+ }
65
+
66
+ echo '</tbody>';
67
+
68
+ echo '<tfoot>';
69
+ echo '<tr>';
70
+ echo '<td colspan="2">';
71
+ esc_html_e( 'Note that header names are not case-sensitive.', 'query-monitor' );
72
+ echo '</td>';
73
+ echo '</tr>';
74
+ echo '</tfoot>';
75
+ }
76
+
77
+ public function panel_menu( array $menu ) {
78
+ if ( ! isset( $menu['qm-request'] ) ) {
79
+ return $menu;
80
+ }
81
+
82
+ $ids = array(
83
+ $this->collector->id() => __( 'Request Headers', 'query-monitor' ),
84
+ $this->collector->id() . '-response' => __( 'Response Headers', 'query-monitor' ),
85
+ );
86
+ foreach ( $ids as $id => $title ) {
87
+ $menu['qm-request']['children'][] = array(
88
+ 'id' => $id,
89
+ 'href' => '#' . $id,
90
+ 'title' => esc_html( $title ),
91
+ );
92
+ }
93
+
94
+ return $menu;
95
+ }
96
+ }
97
+
98
+ function register_qm_output_html_headers( array $output, QM_Collectors $collectors ) {
99
+ $collector = QM_Collectors::get( 'raw_request' );
100
+ if ( $collector ) {
101
+ $output['raw_request'] = new QM_Output_Html_Headers( $collector );
102
+ }
103
+ return $output;
104
+ }
105
+
106
+ add_filter( 'qm/outputter/html', 'register_qm_output_html_headers', 100, 2 );
output/html/hooks.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Hooks extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public $id = 'hooks';
11
 
12
  public function __construct( QM_Collector $collector ) {
@@ -32,7 +39,9 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
32
  echo '<th scope="col">' . esc_html__( 'Priority', 'query-monitor' ) . '</th>';
33
  echo '<th scope="col">' . esc_html__( 'Action', 'query-monitor' ) . '</th>';
34
  echo '<th scope="col" class="qm-filterable-column">';
35
- echo $this->build_filter( 'component', $data['components'], __( 'Component', 'query-monitor' ), 'subject' ); // WPCS: XSS ok.
 
 
36
  echo '</th>';
37
  echo '</tr>';
38
  echo '</thead>';
7
 
8
  class QM_Output_Html_Hooks extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Hooks Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public $id = 'hooks';
18
 
19
  public function __construct( QM_Collector $collector ) {
39
  echo '<th scope="col">' . esc_html__( 'Priority', 'query-monitor' ) . '</th>';
40
  echo '<th scope="col">' . esc_html__( 'Action', 'query-monitor' ) . '</th>';
41
  echo '<th scope="col" class="qm-filterable-column">';
42
+ echo $this->build_filter( 'component', $data['components'], __( 'Component', 'query-monitor' ), array(
43
+ 'highlight' => 'subject',
44
+ ) ); // WPCS: XSS ok.
45
  echo '</th>';
46
  echo '</tr>';
47
  echo '</thead>';
output/html/http.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_HTTP extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 90 );
@@ -249,14 +256,15 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
249
 
250
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
251
 
252
- $caller = array_pop( $stack );
 
 
253
 
254
  if ( ! empty( $stack ) ) {
255
  echo self::build_toggler(); // WPCS: XSS ok;
256
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
257
  }
258
 
259
- echo "<li>{$caller}</li>"; // WPCS: XSS ok.
260
  echo '</ol></td>';
261
 
262
  printf(
@@ -285,14 +293,15 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
285
  echo '<tfoot>';
286
 
287
  $total_stime = number_format_i18n( $data['ltime'], 4 );
 
288
 
289
  echo '<tr>';
290
  printf(
291
  '<td colspan="6">%s</td>',
292
  sprintf(
293
  /* translators: %s: Number of HTTP API requests */
294
- esc_html_x( 'Total: %s', 'HTTP API calls', 'query-monitor' ),
295
- '<span class="qm-items-number">' . esc_html( number_format_i18n( count( $data['http'] ) ) ) . '</span>'
296
  )
297
  );
298
  echo '<td class="qm-num qm-items-time">' . esc_html( $total_stime ) . '</td>';
@@ -334,7 +343,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
334
  $title = ( empty( $count ) )
335
  ? __( 'HTTP API Calls', 'query-monitor' )
336
  /* translators: %s: Number of calls to the HTTP API */
337
- : __( 'HTTP API Calls (%s)', 'query-monitor' );
338
 
339
  $args = array(
340
  'title' => esc_html( sprintf(
7
 
8
  class QM_Output_Html_HTTP extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_HTTP Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 90 );
256
 
257
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
258
 
259
+ $caller = array_shift( $stack );
260
+
261
+ echo "<li>{$caller}</li>"; // WPCS: XSS ok.
262
 
263
  if ( ! empty( $stack ) ) {
264
  echo self::build_toggler(); // WPCS: XSS ok;
265
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
266
  }
267
 
 
268
  echo '</ol></td>';
269
 
270
  printf(
293
  echo '<tfoot>';
294
 
295
  $total_stime = number_format_i18n( $data['ltime'], 4 );
296
+ $count = count( $data['http'] );
297
 
298
  echo '<tr>';
299
  printf(
300
  '<td colspan="6">%s</td>',
301
  sprintf(
302
  /* translators: %s: Number of HTTP API requests */
303
+ esc_html( _nx( 'Total: %s', 'Total: %s', $count, 'HTTP API calls', 'query-monitor' ) ),
304
+ '<span class="qm-items-number">' . esc_html( number_format_i18n( $count ) ) . '</span>'
305
  )
306
  );
307
  echo '<td class="qm-num qm-items-time">' . esc_html( $total_stime ) . '</td>';
343
  $title = ( empty( $count ) )
344
  ? __( 'HTTP API Calls', 'query-monitor' )
345
  /* translators: %s: Number of calls to the HTTP API */
346
+ : _n( 'HTTP API Calls (%s)', 'HTTP API Calls (%s)', $count, 'query-monitor' );
347
 
348
  $args = array(
349
  'title' => esc_html( sprintf(
output/html/languages.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Languages extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public $id = 'languages';
11
 
12
  public function __construct( QM_Collector $collector ) {
@@ -40,7 +47,11 @@ class QM_Output_Html_Languages extends QM_Output_Html {
40
  foreach ( $mofiles as $mofile ) {
41
  echo '<tr>';
42
 
43
- echo '<td class="qm-ltr">' . esc_html( $mofile['domain'] ) . '</td>';
 
 
 
 
44
 
45
  echo '<td>' . esc_html( $mofile['type'] ) . '</td>';
46
 
7
 
8
  class QM_Output_Html_Languages extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Languages Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public $id = 'languages';
18
 
19
  public function __construct( QM_Collector $collector ) {
47
  foreach ( $mofiles as $mofile ) {
48
  echo '<tr>';
49
 
50
+ if ( $mofile['handle'] ) {
51
+ echo '<td class="qm-ltr">' . esc_html( $mofile['domain'] ) . ' (' . esc_html( $mofile['handle'] ) . ')</td>';
52
+ } else {
53
+ echo '<td class="qm-ltr">' . esc_html( $mofile['domain'] ) . '</td>';
54
+ }
55
 
56
  echo '<td>' . esc_html( $mofile['type'] ) . '</td>';
57
 
output/html/logger.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Logger extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 12 );
@@ -88,14 +95,15 @@ class QM_Output_Html_Logger extends QM_Output_Html {
88
 
89
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
90
 
91
- $caller = array_pop( $stack );
 
 
92
 
93
  if ( ! empty( $stack ) ) {
94
  echo self::build_toggler(); // WPCS: XSS ok;
95
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
96
  }
97
 
98
- echo "<li>{$caller}</li>"; // WPCS: XSS ok.
99
  echo '</ol></td>';
100
 
101
  printf(
7
 
8
  class QM_Output_Html_Logger extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Logger Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 12 );
95
 
96
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
97
 
98
+ $caller = array_shift( $stack );
99
+
100
+ echo "<li>{$caller}</li>"; // WPCS: XSS ok.
101
 
102
  if ( ! empty( $stack ) ) {
103
  echo self::build_toggler(); // WPCS: XSS ok;
104
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
105
  }
106
 
 
107
  echo '</ol></td>';
108
 
109
  printf(
output/html/overview.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Overview extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/title', array( $this, 'admin_title' ), 10 );
@@ -23,9 +30,11 @@ class QM_Output_Html_Overview extends QM_Output_Html {
23
  $db_queries_data = $db_queries->get_data();
24
  if ( isset( $db_queries_data['types'] ) && isset( $db_queries_data['total_time'] ) ) {
25
  $db_query_num = $db_queries_data['types'];
 
26
  }
27
  }
28
 
 
29
  $cache = QM_Collectors::get( 'cache' );
30
 
31
  $qm_broken = __( 'A JavaScript problem on the page is preventing Query Monitor from working correctly. jQuery may have been blocked from loading.', 'query-monitor' );
@@ -41,6 +50,18 @@ class QM_Output_Html_Overview extends QM_Output_Html {
41
  echo '<p class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $ajax_errors ) . '</p>';
42
  echo '</section>';
43
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  echo '</div>';
45
  echo '<div class="qm-boxed">';
46
 
@@ -116,14 +137,16 @@ class QM_Output_Html_Overview extends QM_Output_Html {
116
  echo '</p>';
117
  echo '</section>';
118
 
119
- if ( isset( $db_query_num ) ) {
120
  echo '<section>';
121
  echo '<h3>' . esc_html__( 'Database Query Time', 'query-monitor' ) . '</h3>';
122
  echo '<p>';
123
  echo esc_html( number_format_i18n( $db_queries_data['total_time'], 4 ) );
124
  echo '</p>';
125
  echo '</section>';
 
126
 
 
127
  echo '<section>';
128
  echo '<h3>' . esc_html__( 'Database Queries', 'query-monitor' ) . '</h3>';
129
  echo '<p>';
@@ -141,7 +164,7 @@ class QM_Output_Html_Overview extends QM_Output_Html {
141
 
142
  echo esc_html( sprintf(
143
  /* translators: %s: Total number of database queries */
144
- _x( 'Total: %s', 'database queries', 'query-monitor' ),
145
  number_format_i18n( $db_queries_data['total_qs'] )
146
  ) );
147
 
@@ -233,7 +256,7 @@ class QM_Output_Html_Overview extends QM_Output_Html {
233
  }
234
 
235
  $title[] = sprintf(
236
- /* translators: %s: Page load time in seconds */
237
  esc_html_x( '%s S', 'Page load time', 'query-monitor' ),
238
  number_format_i18n( $data['time_taken'], 2 )
239
  );
7
 
8
  class QM_Output_Html_Overview extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Overview Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/title', array( $this, 'admin_title' ), 10 );
30
  $db_queries_data = $db_queries->get_data();
31
  if ( isset( $db_queries_data['types'] ) && isset( $db_queries_data['total_time'] ) ) {
32
  $db_query_num = $db_queries_data['types'];
33
+ $db_query_time = $db_queries_data['total_time'];
34
  }
35
  }
36
 
37
+ $raw_request = QM_Collectors::get( 'raw_request' );
38
  $cache = QM_Collectors::get( 'cache' );
39
 
40
  $qm_broken = __( 'A JavaScript problem on the page is preventing Query Monitor from working correctly. jQuery may have been blocked from loading.', 'query-monitor' );
50
  echo '<p class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $ajax_errors ) . '</p>';
51
  echo '</section>';
52
 
53
+ if ( $raw_request ) {
54
+ echo '<section id="qm-overview-raw-request">';
55
+ $raw_data = $raw_request->get_data();
56
+ printf(
57
+ '<h2>%1$s %2$s → %3$s</h2>',
58
+ esc_html( $raw_data['request']['method'] ),
59
+ esc_html( $raw_data['request']['url'] ),
60
+ esc_html( $raw_data['response']['status'] )
61
+ );
62
+ echo '</section>';
63
+ }
64
+
65
  echo '</div>';
66
  echo '<div class="qm-boxed">';
67
 
137
  echo '</p>';
138
  echo '</section>';
139
 
140
+ if ( isset( $db_queries_data ) ) {
141
  echo '<section>';
142
  echo '<h3>' . esc_html__( 'Database Query Time', 'query-monitor' ) . '</h3>';
143
  echo '<p>';
144
  echo esc_html( number_format_i18n( $db_queries_data['total_time'], 4 ) );
145
  echo '</p>';
146
  echo '</section>';
147
+ }
148
 
149
+ if ( isset( $db_query_num ) && isset( $db_queries_data ) ) {
150
  echo '<section>';
151
  echo '<h3>' . esc_html__( 'Database Queries', 'query-monitor' ) . '</h3>';
152
  echo '<p>';
164
 
165
  echo esc_html( sprintf(
166
  /* translators: %s: Total number of database queries */
167
+ _nx( 'Total: %s', 'Total: %s', $db_queries_data['total_qs'], 'database queries', 'query-monitor' ),
168
  number_format_i18n( $db_queries_data['total_qs'] )
169
  ) );
170
 
256
  }
257
 
258
  $title[] = sprintf(
259
+ /* translators: %s: Page load time in seconds with a decimal fraction */
260
  esc_html_x( '%s S', 'Page load time', 'query-monitor' ),
261
  number_format_i18n( $data['time_taken'], 2 )
262
  );
output/html/php_errors.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_PHP_Errors extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 10 );
@@ -117,14 +124,15 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
117
  echo '<td class="qm-row-caller qm-row-stack qm-nowrap qm-ltr qm-has-toggle"><ol class="qm-toggler qm-numbered">';
118
 
119
  echo self::build_toggler(); // WPCS: XSS ok;
120
- if ( ! empty( $stack ) ) {
121
- echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
122
- }
123
 
124
  echo '<li>';
125
  echo self::output_filename( $error['filename'] . ':' . $error['line'], $error['file'], $error['line'], true ); // WPCS: XSS ok.
126
  echo '</li>';
127
 
 
 
 
 
128
  echo '</ol></td>';
129
 
130
  if ( $component ) {
@@ -216,7 +224,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
216
  return $menu;
217
  }
218
 
219
- /* translators: %s: Number of PHP errors */
220
  $title = __( 'PHP Errors (%s)', 'query-monitor' );
221
 
222
  /* translators: used between list items, there is a space after the comma */
7
 
8
  class QM_Output_Html_PHP_Errors extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_PHP_Errors Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 10 );
124
  echo '<td class="qm-row-caller qm-row-stack qm-nowrap qm-ltr qm-has-toggle"><ol class="qm-toggler qm-numbered">';
125
 
126
  echo self::build_toggler(); // WPCS: XSS ok;
 
 
 
127
 
128
  echo '<li>';
129
  echo self::output_filename( $error['filename'] . ':' . $error['line'], $error['file'], $error['line'], true ); // WPCS: XSS ok.
130
  echo '</li>';
131
 
132
+ if ( ! empty( $stack ) ) {
133
+ echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
134
+ }
135
+
136
  echo '</ol></td>';
137
 
138
  if ( $component ) {
224
  return $menu;
225
  }
226
 
227
+ /* translators: %s: List of PHP error types */
228
  $title = __( 'PHP Errors (%s)', 'query-monitor' );
229
 
230
  /* translators: used between list items, there is a space after the comma */
output/html/request.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Request extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 50 );
@@ -17,6 +24,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
17
  $data = $this->collector->get_data();
18
 
19
  $db_queries = QM_Collectors::get( 'db_queries' );
 
20
 
21
  $this->before_non_tabular_output();
22
 
@@ -140,7 +148,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
140
 
141
  if ( ! empty( $data['user']['data'] ) ) {
142
  printf( // WPCS: XSS ok.
143
- '<p>%1$s</p>',
144
  esc_html( $data['user']['title'] )
145
  );
146
  } else {
@@ -155,7 +163,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
155
 
156
  foreach ( $data['multisite'] as $var => $value ) {
157
  printf( // WPCS: XSS ok.
158
- '<p>%1$s</p>',
159
  esc_html( $value['title'] )
160
  );
161
  }
@@ -163,6 +171,28 @@ class QM_Output_Html_Request extends QM_Output_Html {
163
  echo '</section>';
164
  }
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  $this->after_non_tabular_output();
167
  }
168
 
7
 
8
  class QM_Output_Html_Request extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Request Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 50 );
24
  $data = $this->collector->get_data();
25
 
26
  $db_queries = QM_Collectors::get( 'db_queries' );
27
+ $raw_request = QM_Collectors::get( 'raw_request' );
28
 
29
  $this->before_non_tabular_output();
30
 
148
 
149
  if ( ! empty( $data['user']['data'] ) ) {
150
  printf( // WPCS: XSS ok.
151
+ '<p>%s</p>',
152
  esc_html( $data['user']['title'] )
153
  );
154
  } else {
163
 
164
  foreach ( $data['multisite'] as $var => $value ) {
165
  printf( // WPCS: XSS ok.
166
+ '<p>%s</p>',
167
  esc_html( $value['title'] )
168
  );
169
  }
171
  echo '</section>';
172
  }
173
 
174
+ if ( ! empty( $raw_request ) ) {
175
+ $raw_data = $raw_request->get_data();
176
+ echo '<section>';
177
+ echo '<h3>' . esc_html__( 'Request Data', 'query-monitor' ) . '</h3>';
178
+ echo '<table>';
179
+
180
+ foreach ( array(
181
+ 'ip' => __( 'Remote IP', 'query-monitor' ),
182
+ 'method' => __( 'HTTP method', 'query-monitor' ),
183
+ 'url' => __( 'Requested URL', 'query-monitor' ),
184
+ ) as $item => $name ) {
185
+ echo '<tr>';
186
+ echo '<th scope="row">' . esc_html( $name ) . '</td>';
187
+ echo '<td class="qm-ltr qm-wrap">' . esc_html( $raw_data['request'][ $item ] ) . '</td>';
188
+ echo '</tr>';
189
+ }
190
+
191
+ echo '</table>';
192
+
193
+ echo '</section>';
194
+ }
195
+
196
  $this->after_non_tabular_output();
197
  }
198
 
output/html/theme.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Theme extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 60 );
7
 
8
  class QM_Output_Html_Theme extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Theme Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 60 );
output/html/timing.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Timing extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 15 );
@@ -25,6 +32,8 @@ class QM_Output_Html_Timing extends QM_Output_Html {
25
  echo '<thead>';
26
  echo '<tr>';
27
  echo '<th scope="col">' . esc_html__( 'Tracked Function', 'query-monitor' ) . '</th>';
 
 
28
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Time', 'query-monitor' ) . '</th>';
29
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Memory', 'query-monitor' ) . '</th>';
30
  echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
@@ -54,6 +63,16 @@ class QM_Output_Html_Timing extends QM_Output_Html {
54
  echo '</ol></td>';
55
  }
56
 
 
 
 
 
 
 
 
 
 
 
57
  printf(
58
  '<td class="qm-num">%s</td>',
59
  esc_html( number_format_i18n( $row['function_time'], 4 ) )
@@ -83,6 +102,9 @@ class QM_Output_Html_Timing extends QM_Output_Html {
83
  echo esc_html( $row['function'] . ': ' . $lap_id );
84
  echo '</code></td>';
85
 
 
 
 
86
  printf(
87
  '<td class="qm-num">%s</td>',
88
  esc_html( number_format_i18n( $lap['time_used'], 4 ) )
@@ -125,7 +147,7 @@ class QM_Output_Html_Timing extends QM_Output_Html {
125
  }
126
 
127
  printf(
128
- '<td colspan="2"><span class="dashicons dashicons-warning" aria-hidden="true"></span>%s</td>',
129
  esc_html( $row['message'] )
130
  );
131
 
7
 
8
  class QM_Output_Html_Timing extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Timing Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 15 );
32
  echo '<thead>';
33
  echo '<tr>';
34
  echo '<th scope="col">' . esc_html__( 'Tracked Function', 'query-monitor' ) . '</th>';
35
+ echo '<th scope="col" class="qm-num">' . esc_html__( 'Started', 'query-monitor' ) . '</th>';
36
+ echo '<th scope="col" class="qm-num">' . esc_html__( 'Stopped', 'query-monitor' ) . '</th>';
37
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Time', 'query-monitor' ) . '</th>';
38
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Memory', 'query-monitor' ) . '</th>';
39
  echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
63
  echo '</ol></td>';
64
  }
65
 
66
+ printf(
67
+ '<td class="qm-num">%s</td>',
68
+ esc_html( number_format_i18n( $row['start_time'], 4 ) )
69
+ );
70
+
71
+ printf(
72
+ '<td class="qm-num">%s</td>',
73
+ esc_html( number_format_i18n( $row['end_time'], 4 ) )
74
+ );
75
+
76
  printf(
77
  '<td class="qm-num">%s</td>',
78
  esc_html( number_format_i18n( $row['function_time'], 4 ) )
102
  echo esc_html( $row['function'] . ': ' . $lap_id );
103
  echo '</code></td>';
104
 
105
+ echo '<td class="qm-num"></td>';
106
+ echo '<td class="qm-num"></td>';
107
+
108
  printf(
109
  '<td class="qm-num">%s</td>',
110
  esc_html( number_format_i18n( $lap['time_used'], 4 ) )
147
  }
148
 
149
  printf(
150
+ '<td colspan="4"><span class="dashicons dashicons-warning" aria-hidden="true"></span>%s</td>',
151
  esc_html( $row['message'] )
152
  );
153
 
output/html/transients.php CHANGED
@@ -7,6 +7,13 @@
7
 
8
  class QM_Output_Html_Transients extends QM_Output_Html {
9
 
 
 
 
 
 
 
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 100 );
@@ -75,8 +82,8 @@ class QM_Output_Html_Transients extends QM_Output_Html {
75
 
76
  $stack = array();
77
  $filtered_trace = $row['trace']->get_display_trace();
78
- array_pop( $filtered_trace ); // remove do_action('setted_(site_)?transient')
79
- array_pop( $filtered_trace ); // remove set_(site_)?transient()
80
 
81
  foreach ( $filtered_trace as $item ) {
82
  $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
@@ -84,14 +91,15 @@ class QM_Output_Html_Transients extends QM_Output_Html {
84
 
85
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
86
 
87
- $caller = array_pop( $stack );
 
 
88
 
89
  if ( ! empty( $stack ) ) {
90
  echo self::build_toggler(); // WPCS: XSS ok;
91
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
92
  }
93
 
94
- echo "<li>{$caller}</li>"; // WPCS: XSS ok.
95
  echo '</ol></td>';
96
 
97
  printf(
@@ -122,7 +130,7 @@ class QM_Output_Html_Transients extends QM_Output_Html {
122
  $title = ( empty( $count ) )
123
  ? __( 'Transient Updates', 'query-monitor' )
124
  /* translators: %s: Number of transient values that were updated */
125
- : __( 'Transient Updates (%s)', 'query-monitor' );
126
 
127
  $menu[ $this->collector->id() ] = $this->menu( array(
128
  'title' => esc_html( sprintf(
7
 
8
  class QM_Output_Html_Transients extends QM_Output_Html {
9
 
10
+ /**
11
+ * Collector instance.
12
+ *
13
+ * @var QM_Collector_Transients Collector.
14
+ */
15
+ protected $collector;
16
+
17
  public function __construct( QM_Collector $collector ) {
18
  parent::__construct( $collector );
19
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 100 );
82
 
83
  $stack = array();
84
  $filtered_trace = $row['trace']->get_display_trace();
85
+ array_shift( $filtered_trace ); // remove do_action('setted_(site_)?transient')
86
+ array_shift( $filtered_trace ); // remove set_(site_)?transient()
87
 
88
  foreach ( $filtered_trace as $item ) {
89
  $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
91
 
92
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
93
 
94
+ $caller = array_shift( $stack );
95
+
96
+ echo "<li>{$caller}</li>"; // WPCS: XSS ok.
97
 
98
  if ( ! empty( $stack ) ) {
99
  echo self::build_toggler(); // WPCS: XSS ok;
100
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
101
  }
102
 
 
103
  echo '</ol></td>';
104
 
105
  printf(
130
  $title = ( empty( $count ) )
131
  ? __( 'Transient Updates', 'query-monitor' )
132
  /* translators: %s: Number of transient values that were updated */
133
+ : _n( 'Transient Updates (%s)', 'Transient Updates (%s)', $count, 'query-monitor' );
134
 
135
  $menu[ $this->collector->id() ] = $this->menu( array(
136
  'title' => esc_html( sprintf(
query-monitor.php CHANGED
@@ -10,7 +10,7 @@
10
  *
11
  * Plugin Name: Query Monitor
12
  * Description: The Developer Tools Panel for WordPress.
13
- * Version: 3.3.7
14
  * Plugin URI: https://querymonitor.com/
15
  * Author: John Blackbourn
16
  * Author URI: https://querymonitor.com/
10
  *
11
  * Plugin Name: Query Monitor
12
  * Description: The Developer Tools Panel for WordPress.
13
+ * Version: 3.4.0
14
  * Plugin URI: https://querymonitor.com/
15
  * Author: John Blackbourn
16
  * Author URI: https://querymonitor.com/
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: johnbillion
3
  Tags: debug, debug-bar, debugging, development, developer, performance, profiler, queries, query monitor, rest-api
4
  Requires at least: 3.7
5
  Tested up to: 5.2
6
- Stable tag: 3.3.7
7
  License: GPLv2 or later
8
  Requires PHP: 5.3
9
 
3
  Tags: debug, debug-bar, debugging, development, developer, performance, profiler, queries, query monitor, rest-api
4
  Requires at least: 3.7
5
  Tested up to: 5.2
6
+ Stable tag: 3.4.0
7
  License: GPLv2 or later
8
  Requires PHP: 5.3
9