Query Monitor - Version 3.2.0

Version Description

Download this release

Release Info

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

Code changes from version 3.1.1 to 3.2.0

Files changed (63) hide show
  1. assets/query-monitor-dark.css +80 -11
  2. assets/query-monitor.css +73 -11
  3. assets/query-monitor.js +24 -43
  4. classes/Backtrace.php +41 -3
  5. classes/Collectors.php +4 -3
  6. classes/Dispatcher.php +29 -4
  7. classes/Dispatchers.php +2 -2
  8. classes/QM.php +64 -0
  9. classes/QueryMonitor.php +33 -3
  10. classes/Timer.php +1 -1
  11. classes/Util.php +7 -7
  12. classes/debug_bar.php +15 -1
  13. classes/debug_bar_panel.php +2 -2
  14. collectors/admin.php +4 -4
  15. collectors/assets.php +6 -4
  16. collectors/block_editor.php +83 -0
  17. collectors/cache.php +3 -3
  18. collectors/caps.php +13 -13
  19. collectors/conditionals.php +17 -2
  20. collectors/db_callers.php +1 -1
  21. collectors/db_components.php +1 -1
  22. collectors/db_dupes.php +1 -1
  23. collectors/db_queries.php +20 -11
  24. collectors/debug_bar.php +3 -3
  25. collectors/environment.php +14 -17
  26. collectors/hooks.php +7 -7
  27. collectors/http.php +16 -9
  28. collectors/languages.php +2 -2
  29. collectors/logger.php +2 -2
  30. collectors/overview.php +1 -1
  31. collectors/php_errors.php +36 -13
  32. collectors/redirects.php +2 -2
  33. collectors/request.php +4 -3
  34. collectors/theme.php +40 -34
  35. collectors/timing.php +19 -19
  36. collectors/transients.php +1 -1
  37. composer.json +3 -2
  38. dispatchers/AJAX.php +1 -0
  39. dispatchers/Html.php +60 -27
  40. output/Html.php +19 -5
  41. output/headers/overview.php +1 -1
  42. output/headers/php_errors.php +9 -6
  43. output/headers/redirects.php +1 -1
  44. output/html/admin.php +6 -6
  45. output/html/assets.php +65 -17
  46. output/html/block_editor.php +199 -0
  47. output/html/caps.php +6 -6
  48. output/html/conditionals.php +4 -4
  49. output/html/db_callers.php +3 -3
  50. output/html/db_components.php +3 -3
  51. output/html/db_queries.php +3 -1
  52. output/html/debug_bar.php +1 -1
  53. output/html/environment.php +33 -14
  54. output/html/hooks.php +20 -15
  55. output/html/http.php +5 -3
  56. output/html/logger.php +1 -1
  57. output/html/overview.php +27 -17
  58. output/html/php_errors.php +11 -11
  59. output/html/request.php +13 -13
  60. output/html/theme.php +58 -31
  61. query-monitor.php +7 -7
  62. readme.txt +3 -3
  63. wp-content/db.php +5 -4
assets/query-monitor-dark.css CHANGED
@@ -3,6 +3,13 @@
3
  *
4
  * @package query-monitor
5
  */
 
 
 
 
 
 
 
6
  /* === Admin Toolbar === */
7
  #wpadminbar .quicklinks .menupop ul li.qm-true > a {
8
  color: #8c8 !important;
@@ -118,6 +125,8 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
118
  #query-monitor h4,
119
  #query-monitor h5,
120
  #query-monitor h6,
 
 
121
  #query-monitor p {
122
  /* reset */
123
  background: transparent !important;
@@ -135,6 +144,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
135
  vertical-align: baseline !important;
136
  text-shadow: none !important;
137
  text-transform: none !important;
 
138
  -webkit-font-smoothing: auto !important;
139
  letter-spacing: normal !important;
140
  border-radius: 0 !important;
@@ -144,6 +154,57 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
144
  outline: none !important;
145
  box-shadow: none !important;
146
  text-indent: 0 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
 
149
  #query-monitor {
@@ -160,6 +221,10 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
160
  width: 100% !important;
161
  direction: ltr !important;
162
  }
 
 
 
 
163
 
164
  #query-monitor.qm-show,
165
  #query-monitor.qm-peek {
@@ -195,7 +260,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
195
  #query-monitor #qm-title .qm-title-heading {
196
  flex-grow: 1 !important;
197
  border-right: 1px solid #bbb !important;
198
- margin-right: 8px !important;
199
  }
200
  #query-monitor #qm-title div.qm-title-heading {
201
  display: none;
@@ -206,8 +271,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
206
  #query-monitor #qm-title .dashicons {
207
  transition: none !important;
208
  }
209
- #query-monitor #qm-title .qm-button-container-settings .dashicons,
210
- #query-monitor #qm-title .qm-button-container-pin .dashicons {
211
  font-size: 17px !important;
212
  margin: 3px 0 2px !important;
213
  }
@@ -221,6 +285,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
221
  margin: 0 0 0 0px !important;
222
  display: inline-block !important;
223
  padding: 0px 4px !important;
 
224
  }
225
  #query-monitor #qm-title button:focus,
226
  #query-monitor #qm-title button:hover {
@@ -233,12 +298,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
233
  #query-monitor #qm-title button.qm-button-active {
234
  color: #3879d9 !important;
235
  }
236
- #query-monitor #qm-title .qm-button-container-pin.qm-button-active .dashicons {
237
- transform: rotate(-45deg) !important;
238
- }
239
- #query-monitor #qm-title .qm-button-container-pin.qm-button-active .dashicons:before {
240
- margin-left: 2px !important;
241
- }
242
  #query-monitor .qm {
243
  display: none !important;
244
  }
@@ -409,6 +468,9 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
409
  #query-monitor .qm td.qm-row-sql {
410
  min-width: 25em !important;
411
  }
 
 
 
412
  #query-monitor .qm tr.qm-warn td.qm-col-status,
413
  #query-monitor .qm td.qm-url,
414
  #query-monitor .qm th.qm-col-message,
@@ -463,14 +525,17 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
463
  display: inline-block !important;
464
  margin: 0 20px 5px 0 !important;
465
  }
 
466
  #query-monitor .qm-non-tabular .qm-section {
467
  margin: 0 0 30px 0 !important;
468
  }
 
469
  #query-monitor .qm-non-tabular .qm-boxed .qm-section {
470
  margin: 0 20px 10px 0 !important;
471
  border-right: 1px solid #bbc8d4 !important;
472
  padding: 10px 20px 10px 0 !important;
473
  }
 
474
  #query-monitor .qm-non-tabular .qm-boxed .qm-section:last-child {
475
  margin-right: 0 !important;
476
  border-right: none !important;
@@ -787,6 +852,10 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
787
  }
788
 
789
  .qm-hide,
 
 
 
 
790
  .qm-hide-scripts-host,
791
  .qm-hide-styles-host,
792
  .qm-hide-user,
@@ -835,14 +904,14 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
835
  color: #0073aa !important;
836
  }
837
 
838
- #query-monitor .qm .qm-sortable-column .qm-sort-arrow:before {
839
  content: "\f140" !important;
840
  top: 4px !important;
841
  right: 0 !important;
842
  position: absolute !important;
843
  }
844
 
845
- #query-monitor .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow:before {
846
  content: "\f142" !important;
847
  }
848
 
3
  *
4
  * @package query-monitor
5
  */
6
+ /**
7
+ * Dark Mode Colours
8
+ */
9
+ /**
10
+ * The colours below are loosely based on the WordPress branding colours.
11
+ * https://make.wordpress.org/design/handbook/design-guide/foundations/colors/
12
+ */
13
  /* === Admin Toolbar === */
14
  #wpadminbar .quicklinks .menupop ul li.qm-true > a {
15
  color: #8c8 !important;
125
  #query-monitor h4,
126
  #query-monitor h5,
127
  #query-monitor h6,
128
+ #query-monitor section,
129
+ #query-monitor nav,
130
  #query-monitor p {
131
  /* reset */
132
  background: transparent !important;
144
  vertical-align: baseline !important;
145
  text-shadow: none !important;
146
  text-transform: none !important;
147
+ text-decoration: none !important;
148
  -webkit-font-smoothing: auto !important;
149
  letter-spacing: normal !important;
150
  border-radius: 0 !important;
154
  outline: none !important;
155
  box-shadow: none !important;
156
  text-indent: 0 !important;
157
+ float: none !important;
158
+ clear: both !important;
159
+ }
160
+ #query-monitor::before, #query-monitor::after,
161
+ #query-monitor dl::before,
162
+ #query-monitor dl::after,
163
+ #query-monitor dt::before,
164
+ #query-monitor dt::after,
165
+ #query-monitor dd::before,
166
+ #query-monitor dd::after,
167
+ #query-monitor button::before,
168
+ #query-monitor button::after,
169
+ #query-monitor label::before,
170
+ #query-monitor label::after,
171
+ #query-monitor select::before,
172
+ #query-monitor select::after,
173
+ #query-monitor table::before,
174
+ #query-monitor table::after,
175
+ #query-monitor td::before,
176
+ #query-monitor td::after,
177
+ #query-monitor th::before,
178
+ #query-monitor th::after,
179
+ #query-monitor ul::before,
180
+ #query-monitor ul::after,
181
+ #query-monitor ol::before,
182
+ #query-monitor ol::after,
183
+ #query-monitor li::before,
184
+ #query-monitor li::after,
185
+ #query-monitor code::before,
186
+ #query-monitor code::after,
187
+ #query-monitor a::before,
188
+ #query-monitor a::after,
189
+ #query-monitor h1::before,
190
+ #query-monitor h1::after,
191
+ #query-monitor h2::before,
192
+ #query-monitor h2::after,
193
+ #query-monitor h3::before,
194
+ #query-monitor h3::after,
195
+ #query-monitor h4::before,
196
+ #query-monitor h4::after,
197
+ #query-monitor h5::before,
198
+ #query-monitor h5::after,
199
+ #query-monitor h6::before,
200
+ #query-monitor h6::after,
201
+ #query-monitor section::before,
202
+ #query-monitor section::after,
203
+ #query-monitor nav::before,
204
+ #query-monitor nav::after,
205
+ #query-monitor p::before,
206
+ #query-monitor p::after {
207
+ display: none !important;
208
  }
209
 
210
  #query-monitor {
221
  width: 100% !important;
222
  direction: ltr !important;
223
  }
224
+ #query-monitor ::selection {
225
+ background-color: #B9D6FB !important;
226
+ color: #bbc8d4 !important;
227
+ }
228
 
229
  #query-monitor.qm-show,
230
  #query-monitor.qm-peek {
260
  #query-monitor #qm-title .qm-title-heading {
261
  flex-grow: 1 !important;
262
  border-right: 1px solid #bbb !important;
263
+ margin-right: 6px !important;
264
  }
265
  #query-monitor #qm-title div.qm-title-heading {
266
  display: none;
271
  #query-monitor #qm-title .dashicons {
272
  transition: none !important;
273
  }
274
+ #query-monitor #qm-title .qm-button-container-settings .dashicons {
 
275
  font-size: 17px !important;
276
  margin: 3px 0 2px !important;
277
  }
285
  margin: 0 0 0 0px !important;
286
  display: inline-block !important;
287
  padding: 0px 4px !important;
288
+ min-width: auto !important;
289
  }
290
  #query-monitor #qm-title button:focus,
291
  #query-monitor #qm-title button:hover {
298
  #query-monitor #qm-title button.qm-button-active {
299
  color: #3879d9 !important;
300
  }
 
 
 
 
 
 
301
  #query-monitor .qm {
302
  display: none !important;
303
  }
468
  #query-monitor .qm td.qm-row-sql {
469
  min-width: 25em !important;
470
  }
471
+ #query-monitor .qm td.qm-row-block-html {
472
+ max-width: 25em !important;
473
+ }
474
  #query-monitor .qm tr.qm-warn td.qm-col-status,
475
  #query-monitor .qm td.qm-url,
476
  #query-monitor .qm th.qm-col-message,
525
  display: inline-block !important;
526
  margin: 0 20px 5px 0 !important;
527
  }
528
+ #query-monitor .qm-non-tabular section,
529
  #query-monitor .qm-non-tabular .qm-section {
530
  margin: 0 0 30px 0 !important;
531
  }
532
+ #query-monitor .qm-non-tabular .qm-boxed section,
533
  #query-monitor .qm-non-tabular .qm-boxed .qm-section {
534
  margin: 0 20px 10px 0 !important;
535
  border-right: 1px solid #bbc8d4 !important;
536
  padding: 10px 20px 10px 0 !important;
537
  }
538
+ #query-monitor .qm-non-tabular .qm-boxed section:last-child,
539
  #query-monitor .qm-non-tabular .qm-boxed .qm-section:last-child {
540
  margin-right: 0 !important;
541
  border-right: none !important;
852
  }
853
 
854
  .qm-hide,
855
+ .qm-hide-scripts-dependencies,
856
+ .qm-hide-styles-dependencies,
857
+ .qm-hide-scripts-dependents,
858
+ .qm-hide-styles-dependents,
859
  .qm-hide-scripts-host,
860
  .qm-hide-styles-host,
861
  .qm-hide-user,
904
  color: #0073aa !important;
905
  }
906
 
907
+ #query-monitor .qm .qm-sortable-column .qm-sort-arrow::before {
908
  content: "\f140" !important;
909
  top: 4px !important;
910
  right: 0 !important;
911
  position: absolute !important;
912
  }
913
 
914
+ #query-monitor .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
915
  content: "\f142" !important;
916
  }
917
 
assets/query-monitor.css CHANGED
@@ -118,6 +118,8 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
118
  #query-monitor h4,
119
  #query-monitor h5,
120
  #query-monitor h6,
 
 
121
  #query-monitor p {
122
  /* reset */
123
  background: transparent !important;
@@ -135,6 +137,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
135
  vertical-align: baseline !important;
136
  text-shadow: none !important;
137
  text-transform: none !important;
 
138
  -webkit-font-smoothing: auto !important;
139
  letter-spacing: normal !important;
140
  border-radius: 0 !important;
@@ -144,6 +147,57 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
144
  outline: none !important;
145
  box-shadow: none !important;
146
  text-indent: 0 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  }
148
 
149
  #query-monitor {
@@ -160,6 +214,10 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
160
  width: 100% !important;
161
  direction: ltr !important;
162
  }
 
 
 
 
163
 
164
  #query-monitor.qm-show,
165
  #query-monitor.qm-peek {
@@ -195,7 +253,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
195
  #query-monitor #qm-title .qm-title-heading {
196
  flex-grow: 1 !important;
197
  border-right: 1px solid #bbb !important;
198
- margin-right: 8px !important;
199
  }
200
  #query-monitor #qm-title div.qm-title-heading {
201
  display: none;
@@ -206,8 +264,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
206
  #query-monitor #qm-title .dashicons {
207
  transition: none !important;
208
  }
209
- #query-monitor #qm-title .qm-button-container-settings .dashicons,
210
- #query-monitor #qm-title .qm-button-container-pin .dashicons {
211
  font-size: 17px !important;
212
  margin: 3px 0 2px !important;
213
  }
@@ -221,6 +278,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
221
  margin: 0 0 0 0px !important;
222
  display: inline-block !important;
223
  padding: 0px 4px !important;
 
224
  }
225
  #query-monitor #qm-title button:focus,
226
  #query-monitor #qm-title button:hover {
@@ -233,12 +291,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
233
  #query-monitor #qm-title button.qm-button-active {
234
  color: #3879d9 !important;
235
  }
236
- #query-monitor #qm-title .qm-button-container-pin.qm-button-active .dashicons {
237
- transform: rotate(-45deg) !important;
238
- }
239
- #query-monitor #qm-title .qm-button-container-pin.qm-button-active .dashicons:before {
240
- margin-left: 2px !important;
241
- }
242
  #query-monitor .qm {
243
  display: none !important;
244
  }
@@ -409,6 +461,9 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
409
  #query-monitor .qm td.qm-row-sql {
410
  min-width: 25em !important;
411
  }
 
 
 
412
  #query-monitor .qm tr.qm-warn td.qm-col-status,
413
  #query-monitor .qm td.qm-url,
414
  #query-monitor .qm th.qm-col-message,
@@ -463,14 +518,17 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
463
  display: inline-block !important;
464
  margin: 0 20px 5px 0 !important;
465
  }
 
466
  #query-monitor .qm-non-tabular .qm-section {
467
  margin: 0 0 30px 0 !important;
468
  }
 
469
  #query-monitor .qm-non-tabular .qm-boxed .qm-section {
470
  margin: 0 20px 10px 0 !important;
471
  border-right: 1px solid #ddd !important;
472
  padding: 10px 20px 10px 0 !important;
473
  }
 
474
  #query-monitor .qm-non-tabular .qm-boxed .qm-section:last-child {
475
  margin-right: 0 !important;
476
  border-right: none !important;
@@ -787,6 +845,10 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
787
  }
788
 
789
  .qm-hide,
 
 
 
 
790
  .qm-hide-scripts-host,
791
  .qm-hide-styles-host,
792
  .qm-hide-user,
@@ -835,14 +897,14 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
835
  color: #0073aa !important;
836
  }
837
 
838
- #query-monitor .qm .qm-sortable-column .qm-sort-arrow:before {
839
  content: "\f140" !important;
840
  top: 4px !important;
841
  right: 0 !important;
842
  position: absolute !important;
843
  }
844
 
845
- #query-monitor .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow:before {
846
  content: "\f142" !important;
847
  }
848
 
118
  #query-monitor h4,
119
  #query-monitor h5,
120
  #query-monitor h6,
121
+ #query-monitor section,
122
+ #query-monitor nav,
123
  #query-monitor p {
124
  /* reset */
125
  background: transparent !important;
137
  vertical-align: baseline !important;
138
  text-shadow: none !important;
139
  text-transform: none !important;
140
+ text-decoration: none !important;
141
  -webkit-font-smoothing: auto !important;
142
  letter-spacing: normal !important;
143
  border-radius: 0 !important;
147
  outline: none !important;
148
  box-shadow: none !important;
149
  text-indent: 0 !important;
150
+ float: none !important;
151
+ clear: both !important;
152
+ }
153
+ #query-monitor::before, #query-monitor::after,
154
+ #query-monitor dl::before,
155
+ #query-monitor dl::after,
156
+ #query-monitor dt::before,
157
+ #query-monitor dt::after,
158
+ #query-monitor dd::before,
159
+ #query-monitor dd::after,
160
+ #query-monitor button::before,
161
+ #query-monitor button::after,
162
+ #query-monitor label::before,
163
+ #query-monitor label::after,
164
+ #query-monitor select::before,
165
+ #query-monitor select::after,
166
+ #query-monitor table::before,
167
+ #query-monitor table::after,
168
+ #query-monitor td::before,
169
+ #query-monitor td::after,
170
+ #query-monitor th::before,
171
+ #query-monitor th::after,
172
+ #query-monitor ul::before,
173
+ #query-monitor ul::after,
174
+ #query-monitor ol::before,
175
+ #query-monitor ol::after,
176
+ #query-monitor li::before,
177
+ #query-monitor li::after,
178
+ #query-monitor code::before,
179
+ #query-monitor code::after,
180
+ #query-monitor a::before,
181
+ #query-monitor a::after,
182
+ #query-monitor h1::before,
183
+ #query-monitor h1::after,
184
+ #query-monitor h2::before,
185
+ #query-monitor h2::after,
186
+ #query-monitor h3::before,
187
+ #query-monitor h3::after,
188
+ #query-monitor h4::before,
189
+ #query-monitor h4::after,
190
+ #query-monitor h5::before,
191
+ #query-monitor h5::after,
192
+ #query-monitor h6::before,
193
+ #query-monitor h6::after,
194
+ #query-monitor section::before,
195
+ #query-monitor section::after,
196
+ #query-monitor nav::before,
197
+ #query-monitor nav::after,
198
+ #query-monitor p::before,
199
+ #query-monitor p::after {
200
+ display: none !important;
201
  }
202
 
203
  #query-monitor {
214
  width: 100% !important;
215
  direction: ltr !important;
216
  }
217
+ #query-monitor ::selection {
218
+ background-color: #B9D6FB !important;
219
+ color: #222 !important;
220
+ }
221
 
222
  #query-monitor.qm-show,
223
  #query-monitor.qm-peek {
253
  #query-monitor #qm-title .qm-title-heading {
254
  flex-grow: 1 !important;
255
  border-right: 1px solid #bbb !important;
256
+ margin-right: 6px !important;
257
  }
258
  #query-monitor #qm-title div.qm-title-heading {
259
  display: none;
264
  #query-monitor #qm-title .dashicons {
265
  transition: none !important;
266
  }
267
+ #query-monitor #qm-title .qm-button-container-settings .dashicons {
 
268
  font-size: 17px !important;
269
  margin: 3px 0 2px !important;
270
  }
278
  margin: 0 0 0 0px !important;
279
  display: inline-block !important;
280
  padding: 0px 4px !important;
281
+ min-width: auto !important;
282
  }
283
  #query-monitor #qm-title button:focus,
284
  #query-monitor #qm-title button:hover {
291
  #query-monitor #qm-title button.qm-button-active {
292
  color: #3879d9 !important;
293
  }
 
 
 
 
 
 
294
  #query-monitor .qm {
295
  display: none !important;
296
  }
461
  #query-monitor .qm td.qm-row-sql {
462
  min-width: 25em !important;
463
  }
464
+ #query-monitor .qm td.qm-row-block-html {
465
+ max-width: 25em !important;
466
+ }
467
  #query-monitor .qm tr.qm-warn td.qm-col-status,
468
  #query-monitor .qm td.qm-url,
469
  #query-monitor .qm th.qm-col-message,
518
  display: inline-block !important;
519
  margin: 0 20px 5px 0 !important;
520
  }
521
+ #query-monitor .qm-non-tabular section,
522
  #query-monitor .qm-non-tabular .qm-section {
523
  margin: 0 0 30px 0 !important;
524
  }
525
+ #query-monitor .qm-non-tabular .qm-boxed section,
526
  #query-monitor .qm-non-tabular .qm-boxed .qm-section {
527
  margin: 0 20px 10px 0 !important;
528
  border-right: 1px solid #ddd !important;
529
  padding: 10px 20px 10px 0 !important;
530
  }
531
+ #query-monitor .qm-non-tabular .qm-boxed section:last-child,
532
  #query-monitor .qm-non-tabular .qm-boxed .qm-section:last-child {
533
  margin-right: 0 !important;
534
  border-right: none !important;
845
  }
846
 
847
  .qm-hide,
848
+ .qm-hide-scripts-dependencies,
849
+ .qm-hide-styles-dependencies,
850
+ .qm-hide-scripts-dependents,
851
+ .qm-hide-styles-dependents,
852
  .qm-hide-scripts-host,
853
  .qm-hide-styles-host,
854
  .qm-hide-user,
897
  color: #0073aa !important;
898
  }
899
 
900
+ #query-monitor .qm .qm-sortable-column .qm-sort-arrow::before {
901
  content: "\f140" !important;
902
  top: 4px !important;
903
  right: 0 !important;
904
  position: absolute !important;
905
  }
906
 
907
+ #query-monitor .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
908
  content: "\f142" !important;
909
  }
910
 
assets/query-monitor.js CHANGED
@@ -24,7 +24,7 @@ var QM_i18n = {
24
  num_int = Math.floor( number ),
25
  num_str = num_int.toString(),
26
  fraction = num_float.substring( num_float.indexOf( '.' ) + 1, num_float.length ),
27
- o = '';
28
 
29
  if ( num_str.length > 3 ) {
30
  for ( i = num_str.length; i > 3; i -= 3 ) {
@@ -48,11 +48,11 @@ var QM_i18n = {
48
  if ( window.jQuery ) {
49
 
50
  jQuery( function($) {
51
- var minheight = 100;
52
- var maxheight = ( $(window).height() - 50 );
53
- var container = $('#query-monitor');
54
  var container_storage_key = 'qm-container-height';
55
- var container_pinned_key = 'qm-container-pinned';
56
 
57
  if ( $('#query-monitor').hasClass('qm-peek') ) {
58
  minheight = 27;
@@ -89,8 +89,8 @@ if ( window.jQuery ) {
89
 
90
  if ( selected_menu.length ) {
91
  var selected_menu_pos = selected_menu.position();
92
- var menu_height = $('#qm-panel-menu').height();
93
- var menu_scroll = $('#qm-panel-menu').scrollTop();
94
 
95
  if ( ( selected_menu_pos.top > ( menu_height + menu_scroll ) ) || ( selected_menu_pos.top < menu_scroll ) ) {
96
  $('#qm-panel-menu').scrollTop( selected_menu_pos.top - ( menu_height / 2 ) );
@@ -99,9 +99,7 @@ if ( window.jQuery ) {
99
 
100
  $('.qm-title-heading select').val(panel);
101
 
102
- if ( localStorage.getItem( container_pinned_key ) ) {
103
- localStorage.setItem( container_pinned_key, panel );
104
- }
105
 
106
  var filters = $( panel ).find('.qm-filter');
107
 
@@ -122,20 +120,17 @@ if ( window.jQuery ) {
122
  .addClass(qm.menu.top.classname)
123
  .attr('dir','ltr')
124
  .find('a').eq(0)
125
- .html(qm.menu.top.title)
126
- ;
127
 
128
  $.each( qm.menu.sub, function( i, el ) {
129
 
130
  var new_menu = $('#wp-admin-bar-query-monitor-placeholder')
131
  .clone()
132
- .attr('id','wp-admin-bar-' + el.id)
133
- ;
134
  new_menu
135
  .find('a').eq(0)
136
  .html(el.title)
137
- .attr('href',el.href)
138
- ;
139
 
140
  if ( ( typeof el.meta != 'undefined' ) && ( typeof el.meta.classname != 'undefined' ) ) {
141
  new_menu.addClass(el.meta.classname);
@@ -215,7 +210,7 @@ if ( window.jQuery ) {
215
  });
216
 
217
  $('#query-monitor').find('.qm-filter').each(function () {
218
- var key = $(this).attr('id');
219
  var value = localStorage.getItem( key );
220
  if ( value !== null ) {
221
  // Escape the following chars with a backslash before passing into jQ selectors: [ ] ( ) ' " \
@@ -239,9 +234,9 @@ if ( window.jQuery ) {
239
  });
240
 
241
  $('#query-monitor').find('.qm-toggle').on('click',function(e){
242
- var el = $(this);
243
  var currentState = el.attr('aria-expanded');
244
- var newState = 'true';
245
  if (currentState === 'true') {
246
  newState = 'false';
247
  }
@@ -323,8 +318,7 @@ if ( window.jQuery ) {
323
  if ( ! qm.ajax_errors[error.type] ) {
324
  $('#wp-admin-bar-query-monitor')
325
  .addClass('qm-' + error.type)
326
- .find('a').first().append('<span class="ab-label qm-ajax-' + error.type + '"> &nbsp; Ajax: ' + error.type + '</span>')
327
- ;
328
  }
329
  }
330
 
@@ -343,7 +337,7 @@ if ( window.jQuery ) {
343
  } );
344
 
345
  $('.qm-auth').on('click',function(e){
346
- var state = $('#qm-settings').data('qm-state');
347
  var action = ( 'off' === state ? 'on' : 'off' );
348
 
349
  $.ajax(qm_l10n.ajaxurl,{
@@ -407,7 +401,7 @@ if ( window.jQuery ) {
407
 
408
  $(window).on('resize', function(){
409
  var maxheight = ( $(window).height() - toolbarHeight );
410
- var h = container.height();
411
 
412
  if ( h < minheight ) {
413
  container.height( minheight );
@@ -421,20 +415,9 @@ if ( window.jQuery ) {
421
  $('.qm-button-container-close').click(function(){
422
  $('#query-monitor').removeClass('qm-show').height('');
423
  localStorage.removeItem( container_pinned_key );
424
- $('.qm-button-container-pin').removeClass( 'qm-button-active' );
425
- });
426
-
427
- $('.qm-button-container-pin').click(function(){
428
- if ( $(this).hasClass( 'qm-button-active' ) ) {
429
- localStorage.removeItem( container_pinned_key );
430
- } else {
431
- localStorage.setItem( container_pinned_key, '#' + $('.qm-panel-show').first().attr('id') );
432
- }
433
-
434
- $(this).toggleClass( 'qm-button-active' );
435
  });
436
 
437
- $('.qm-button-container-settings').click(function(){
438
  show_panel( '#qm-settings' );
439
  $('#qm-settings').focus();
440
  });
@@ -442,8 +425,6 @@ if ( window.jQuery ) {
442
  var pinned = localStorage.getItem( container_pinned_key );
443
  if ( pinned && $( pinned ).length ) {
444
  show_panel( pinned );
445
- // Don't auto-focus the pinned QM panel
446
- $('.qm-button-container-pin').addClass( 'qm-button-active' );
447
  }
448
 
449
  $('.qm-title-heading select').change(function(){
@@ -465,11 +446,11 @@ if ( window.jQuery ) {
465
  * Author: Gajus Kuizinas <g.kuizinas@anuary.com>
466
  */
467
  (function ($) {
468
- $.qm = $.qm || {};
469
  $.qm.tableSort = function (settings) {
470
  // @param object columns NodeList table colums.
471
  // @param integer row_width defines the number of columns per row.
472
- var table_to_array = function (columns, row_width) {
473
  columns = Array.prototype.slice.call(columns, 0);
474
 
475
  var rows = [];
@@ -479,7 +460,7 @@ if ( window.jQuery ) {
479
  var row = [];
480
 
481
  for (var k = 0; k < row_width; k++) {
482
- var e = columns[i + k];
483
  var data = e.dataset.qmSortWeight;
484
 
485
  if (data === undefined) {
@@ -507,7 +488,7 @@ if ( window.jQuery ) {
507
  var table = $(this);
508
 
509
  table.find('.qm-sortable-column').on('click', function (e) {
510
- var desc = ! $(this).hasClass('qm-sorted-desc');
511
  var index = $(this).index();
512
 
513
  table.find('thead th').removeClass('qm-sorted-asc qm-sorted-desc').attr('aria-sort','none');
@@ -519,8 +500,8 @@ if ( window.jQuery ) {
519
  }
520
 
521
  table.find('tbody').each(function () {
522
- var tbody = $(this);
523
- var rows = this.rows;
524
  var columns = this.querySelectorAll('th,td');
525
 
526
  if (this.data_matrix === undefined) {
24
  num_int = Math.floor( number ),
25
  num_str = num_int.toString(),
26
  fraction = num_float.substring( num_float.indexOf( '.' ) + 1, num_float.length ),
27
+ o = '';
28
 
29
  if ( num_str.length > 3 ) {
30
  for ( i = num_str.length; i > 3; i -= 3 ) {
48
  if ( window.jQuery ) {
49
 
50
  jQuery( function($) {
51
+ var minheight = 100;
52
+ var maxheight = ( $(window).height() - 50 );
53
+ var container = $('#query-monitor');
54
  var container_storage_key = 'qm-container-height';
55
+ var container_pinned_key = 'qm-container-pinned';
56
 
57
  if ( $('#query-monitor').hasClass('qm-peek') ) {
58
  minheight = 27;
89
 
90
  if ( selected_menu.length ) {
91
  var selected_menu_pos = selected_menu.position();
92
+ var menu_height = $('#qm-panel-menu').height();
93
+ var menu_scroll = $('#qm-panel-menu').scrollTop();
94
 
95
  if ( ( selected_menu_pos.top > ( menu_height + menu_scroll ) ) || ( selected_menu_pos.top < menu_scroll ) ) {
96
  $('#qm-panel-menu').scrollTop( selected_menu_pos.top - ( menu_height / 2 ) );
99
 
100
  $('.qm-title-heading select').val(panel);
101
 
102
+ localStorage.setItem( container_pinned_key, panel );
 
 
103
 
104
  var filters = $( panel ).find('.qm-filter');
105
 
120
  .addClass(qm.menu.top.classname)
121
  .attr('dir','ltr')
122
  .find('a').eq(0)
123
+ .html(qm.menu.top.title);
 
124
 
125
  $.each( qm.menu.sub, function( i, el ) {
126
 
127
  var new_menu = $('#wp-admin-bar-query-monitor-placeholder')
128
  .clone()
129
+ .attr('id','wp-admin-bar-' + el.id);
 
130
  new_menu
131
  .find('a').eq(0)
132
  .html(el.title)
133
+ .attr('href',el.href);
 
134
 
135
  if ( ( typeof el.meta != 'undefined' ) && ( typeof el.meta.classname != 'undefined' ) ) {
136
  new_menu.addClass(el.meta.classname);
210
  });
211
 
212
  $('#query-monitor').find('.qm-filter').each(function () {
213
+ var key = $(this).attr('id');
214
  var value = localStorage.getItem( key );
215
  if ( value !== null ) {
216
  // Escape the following chars with a backslash before passing into jQ selectors: [ ] ( ) ' " \
234
  });
235
 
236
  $('#query-monitor').find('.qm-toggle').on('click',function(e){
237
+ var el = $(this);
238
  var currentState = el.attr('aria-expanded');
239
+ var newState = 'true';
240
  if (currentState === 'true') {
241
  newState = 'false';
242
  }
318
  if ( ! qm.ajax_errors[error.type] ) {
319
  $('#wp-admin-bar-query-monitor')
320
  .addClass('qm-' + error.type)
321
+ .find('a').first().append('<span class="ab-label qm-ajax-' + error.type + '"> &nbsp; Ajax: ' + error.type + '</span>');
 
322
  }
323
  }
324
 
337
  } );
338
 
339
  $('.qm-auth').on('click',function(e){
340
+ var state = $('#qm-settings').data('qm-state');
341
  var action = ( 'off' === state ? 'on' : 'off' );
342
 
343
  $.ajax(qm_l10n.ajaxurl,{
401
 
402
  $(window).on('resize', function(){
403
  var maxheight = ( $(window).height() - toolbarHeight );
404
+ var h = container.height();
405
 
406
  if ( h < minheight ) {
407
  container.height( minheight );
415
  $('.qm-button-container-close').click(function(){
416
  $('#query-monitor').removeClass('qm-show').height('');
417
  localStorage.removeItem( container_pinned_key );
 
 
 
 
 
 
 
 
 
 
 
418
  });
419
 
420
+ $('.qm-button-container-settings,a[href="#qm-settings"]').click(function(){
421
  show_panel( '#qm-settings' );
422
  $('#qm-settings').focus();
423
  });
425
  var pinned = localStorage.getItem( container_pinned_key );
426
  if ( pinned && $( pinned ).length ) {
427
  show_panel( pinned );
 
 
428
  }
429
 
430
  $('.qm-title-heading select').change(function(){
446
  * Author: Gajus Kuizinas <g.kuizinas@anuary.com>
447
  */
448
  (function ($) {
449
+ $.qm = $.qm || {};
450
  $.qm.tableSort = function (settings) {
451
  // @param object columns NodeList table colums.
452
  // @param integer row_width defines the number of columns per row.
453
+ var table_to_array = function (columns, row_width) {
454
  columns = Array.prototype.slice.call(columns, 0);
455
 
456
  var rows = [];
460
  var row = [];
461
 
462
  for (var k = 0; k < row_width; k++) {
463
+ var e = columns[i + k];
464
  var data = e.dataset.qmSortWeight;
465
 
466
  if (data === undefined) {
488
  var table = $(this);
489
 
490
  table.find('.qm-sortable-column').on('click', function (e) {
491
+ var desc = ! $(this).hasClass('qm-sorted-desc');
492
  var index = $(this).index();
493
 
494
  table.find('thead th').removeClass('qm-sorted-asc qm-sorted-desc').attr('aria-sort','none');
500
  }
501
 
502
  table.find('tbody').each(function () {
503
+ var tbody = $(this);
504
+ var rows = this.rows;
505
  var columns = this.querySelectorAll('th,td');
506
 
507
  if (this.data_matrix === undefined) {
classes/Backtrace.php CHANGED
@@ -149,6 +149,7 @@ class QM_Backtrace {
149
  // so short-circuit and return early.
150
  return $comp;
151
  }
 
152
  } catch ( ReflectionException $e ) {
153
  # nothing
154
  }
@@ -209,7 +210,7 @@ class QM_Backtrace {
209
 
210
  public function ignore_current_filter() {
211
 
212
- if ( isset( $this->trace[2] ) and isset( $this->trace[2]['function'] ) ) {
213
  if ( in_array( $this->trace[2]['function'], array( 'apply_filters', 'do_action' ), true ) ) {
214
  $this->ignore( 3 ); # Ignore filter and action callbacks
215
  }
@@ -219,13 +220,50 @@ class QM_Backtrace {
219
 
220
  public function filter_trace( array $trace ) {
221
 
222
- if ( ! self::$filtered and function_exists( 'did_action' ) and did_action( 'plugins_loaded' ) ) {
223
 
224
- # Only run apply_filters on these once
 
 
 
 
 
 
 
225
  self::$ignore_class = apply_filters( 'qm/trace/ignore_class', self::$ignore_class );
 
 
 
 
 
 
 
 
 
226
  self::$ignore_method = apply_filters( 'qm/trace/ignore_method', self::$ignore_method );
 
 
 
 
 
 
 
 
 
227
  self::$ignore_func = apply_filters( 'qm/trace/ignore_func', self::$ignore_func );
 
 
 
 
 
 
 
 
 
 
 
228
  self::$show_args = apply_filters( 'qm/trace/show_args', self::$show_args );
 
229
  self::$filtered = true;
230
 
231
  }
149
  // so short-circuit and return early.
150
  return $comp;
151
  }
152
+ // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
153
  } catch ( ReflectionException $e ) {
154
  # nothing
155
  }
210
 
211
  public function ignore_current_filter() {
212
 
213
+ if ( isset( $this->trace[2] ) && isset( $this->trace[2]['function'] ) ) {
214
  if ( in_array( $this->trace[2]['function'], array( 'apply_filters', 'do_action' ), true ) ) {
215
  $this->ignore( 3 ); # Ignore filter and action callbacks
216
  }
220
 
221
  public function filter_trace( array $trace ) {
222
 
223
+ if ( ! self::$filtered && function_exists( 'did_action' ) && did_action( 'plugins_loaded' ) ) {
224
 
225
+ /**
226
+ * Filters which classes to ignore when constructing user-facing call stacks.
227
+ *
228
+ * @since 2.7.0
229
+ *
230
+ * @param bool[] $ignore_class Array of class names to ignore. The array keys are class names to ignore,
231
+ * the array values are whether to ignore the class or not (usually true).
232
+ */
233
  self::$ignore_class = apply_filters( 'qm/trace/ignore_class', self::$ignore_class );
234
+
235
+ /**
236
+ * Filters which class methods to ignore when constructing user-facing call stacks.
237
+ *
238
+ * @since 2.7.0
239
+ *
240
+ * @param bool[] $ignore_method Array of method names to ignore. The array keys are method names to ignore,
241
+ * the array values are whether to ignore the method or not (usually true).
242
+ */
243
  self::$ignore_method = apply_filters( 'qm/trace/ignore_method', self::$ignore_method );
244
+
245
+ /**
246
+ * Filters which functions to ignore when constructing user-facing call stacks.
247
+ *
248
+ * @since 2.7.0
249
+ *
250
+ * @param bool[] $ignore_func Array of function names to ignore. The array keys are function names to ignore,
251
+ * the array values are whether to ignore the function or not (usually true).
252
+ */
253
  self::$ignore_func = apply_filters( 'qm/trace/ignore_func', self::$ignore_func );
254
+
255
+ /**
256
+ * Filters the number of argument values to show for the given function name when constructing user-facing
257
+ * call stacks.
258
+ *
259
+ * @since 2.7.0
260
+ *
261
+ * @param (int|string)[] $show_args The number of argument values to show for the given function name. The
262
+ * array keys are function names, the array values are either integers or
263
+ * "dir" to specifically treat the function argument as a directory path.
264
+ */
265
  self::$show_args = apply_filters( 'qm/trace/show_args', self::$show_args );
266
+
267
  self::$filtered = true;
268
 
269
  }
classes/Collectors.php CHANGED
@@ -8,7 +8,7 @@
8
  if ( ! class_exists( 'QM_Collectors' ) ) {
9
  class QM_Collectors implements IteratorAggregate {
10
 
11
- private $items = array();
12
  private $processed = false;
13
 
14
  public function getIterator() {
@@ -17,6 +17,7 @@ class QM_Collectors implements IteratorAggregate {
17
 
18
  public static function add( QM_Collector $collector ) {
19
  $collectors = self::init();
 
20
  $collectors->items[ $collector->id ] = $collector;
21
  }
22
 
@@ -32,7 +33,7 @@ class QM_Collectors implements IteratorAggregate {
32
  static $instance;
33
 
34
  if ( ! $instance ) {
35
- $instance = new QM_Collectors;
36
  }
37
 
38
  return $instance;
@@ -47,7 +48,7 @@ class QM_Collectors implements IteratorAggregate {
47
  foreach ( $this as $collector ) {
48
  $collector->tear_down();
49
 
50
- $timer = new QM_Timer;
51
  $timer->start();
52
 
53
  $collector->process();
8
  if ( ! class_exists( 'QM_Collectors' ) ) {
9
  class QM_Collectors implements IteratorAggregate {
10
 
11
+ private $items = array();
12
  private $processed = false;
13
 
14
  public function getIterator() {
17
 
18
  public static function add( QM_Collector $collector ) {
19
  $collectors = self::init();
20
+
21
  $collectors->items[ $collector->id ] = $collector;
22
  }
23
 
33
  static $instance;
34
 
35
  if ( ! $instance ) {
36
+ $instance = new QM_Collectors();
37
  }
38
 
39
  return $instance;
48
  foreach ( $this as $collector ) {
49
  $collector->tear_down();
50
 
51
+ $timer = new QM_Timer();
52
  $timer->start();
53
 
54
  $collector->process();
classes/Dispatcher.php CHANGED
@@ -26,11 +26,19 @@ abstract class QM_Dispatcher {
26
  $e = error_get_last();
27
 
28
  # Don't dispatch if a fatal has occurred:
29
- if ( ! empty( $e ) and ( $e['type'] & ( E_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR ) ) ) {
30
  return false;
31
  }
32
 
33
- # Allow users to disable this dispatcher
 
 
 
 
 
 
 
 
34
  if ( ! apply_filters( "qm/dispatch/{$this->id}", true ) ) {
35
  return false;
36
  }
@@ -43,14 +51,31 @@ abstract class QM_Dispatcher {
43
  $collectors = QM_Collectors::init();
44
  $collectors->process();
45
 
 
 
 
 
 
 
 
 
 
 
46
  $this->outputters = apply_filters( "qm/outputter/{$outputter_id}", array(), $collectors );
47
 
48
  return $this->outputters;
49
  }
50
 
51
  public function init() {
52
- // @TODO should be abstract?
53
- // nothing
 
 
 
 
 
 
 
54
  }
55
 
56
  protected function before_output() {
26
  $e = error_get_last();
27
 
28
  # Don't dispatch if a fatal has occurred:
29
+ if ( ! empty( $e ) && ( $e['type'] & ( E_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR ) ) ) {
30
  return false;
31
  }
32
 
33
+ /**
34
+ * Allows users to disable this dispatcher.
35
+ *
36
+ * The dynamic portion of the hook name, `$this->id`, refers to the dispatcher ID.
37
+ *
38
+ * @since 2.8.0
39
+ *
40
+ * @param bool $true Whether or not the dispatcher is enabled.
41
+ */
42
  if ( ! apply_filters( "qm/dispatch/{$this->id}", true ) ) {
43
  return false;
44
  }
51
  $collectors = QM_Collectors::init();
52
  $collectors->process();
53
 
54
+ /**
55
+ * Allows users to filter what outputs.
56
+ *
57
+ * The dynamic portion of the hook name, `$outputter_id`, refers to the outputter ID.
58
+ *
59
+ * @since 2.8.0
60
+ *
61
+ * @param QM_Output[] $outputters Array of outputters.
62
+ * @param QM_Collectors $collectors List of collectors.
63
+ */
64
  $this->outputters = apply_filters( "qm/outputter/{$outputter_id}", array(), $collectors );
65
 
66
  return $this->outputters;
67
  }
68
 
69
  public function init() {
70
+ if ( ! $this->user_can_view() ) {
71
+ return;
72
+ }
73
+
74
+ if ( ! defined( 'DONOTCACHEPAGE' ) ) {
75
+ define( 'DONOTCACHEPAGE', 1 );
76
+ }
77
+
78
+ add_action( 'send_headers', 'nocache_headers' );
79
  }
80
 
81
  protected function before_output() {
classes/Dispatchers.php CHANGED
@@ -14,7 +14,7 @@ class QM_Dispatchers implements IteratorAggregate {
14
  }
15
 
16
  public static function add( QM_Dispatcher $dispatcher ) {
17
- $dispatchers = self::init();
18
  $dispatchers->items[ $dispatcher->id ] = $dispatcher;
19
  }
20
 
@@ -30,7 +30,7 @@ class QM_Dispatchers implements IteratorAggregate {
30
  static $instance;
31
 
32
  if ( ! $instance ) {
33
- $instance = new QM_Dispatchers;
34
  }
35
 
36
  return $instance;
14
  }
15
 
16
  public static function add( QM_Dispatcher $dispatcher ) {
17
+ $dispatchers = self::init();
18
  $dispatchers->items[ $dispatcher->id ] = $dispatcher;
19
  }
20
 
30
  static $instance;
31
 
32
  if ( ! $instance ) {
33
+ $instance = new QM_Dispatchers();
34
  }
35
 
36
  return $instance;
classes/QM.php CHANGED
@@ -8,34 +8,98 @@
8
  class QM {
9
 
10
  public static function emergency( $message, array $context = array() ) {
 
 
 
 
 
 
 
 
11
  do_action( 'qm/emergency', $message, $context );
12
  }
13
 
14
  public static function alert( $message, array $context = array() ) {
 
 
 
 
 
 
 
 
15
  do_action( 'qm/alert', $message, $context );
16
  }
17
 
18
  public static function critical( $message, array $context = array() ) {
 
 
 
 
 
 
 
 
19
  do_action( 'qm/critical', $message, $context );
20
  }
21
 
22
  public static function error( $message, array $context = array() ) {
 
 
 
 
 
 
 
 
23
  do_action( 'qm/error', $message, $context );
24
  }
25
 
26
  public static function warning( $message, array $context = array() ) {
 
 
 
 
 
 
 
 
27
  do_action( 'qm/warning', $message, $context );
28
  }
29
 
30
  public static function notice( $message, array $context = array() ) {
 
 
 
 
 
 
 
 
31
  do_action( 'qm/notice', $message, $context );
32
  }
33
 
34
  public static function info( $message, array $context = array() ) {
 
 
 
 
 
 
 
 
35
  do_action( 'qm/info', $message, $context );
36
  }
37
 
38
  public static function debug( $message, array $context = array() ) {
 
 
 
 
 
 
 
 
39
  do_action( 'qm/debug', $message, $context );
40
  }
41
 
8
  class QM {
9
 
10
  public static function emergency( $message, array $context = array() ) {
11
+ /**
12
+ * Fires when an `emergency` level message is logged.
13
+ *
14
+ * @since 3.1.0
15
+ *
16
+ * @param string $message The message.
17
+ * @param array $context The context passed.
18
+ */
19
  do_action( 'qm/emergency', $message, $context );
20
  }
21
 
22
  public static function alert( $message, array $context = array() ) {
23
+ /**
24
+ * Fires when an `alert` level message is logged.
25
+ *
26
+ * @since 3.1.0
27
+ *
28
+ * @param string $message The message.
29
+ * @param array $context The context passed.
30
+ */
31
  do_action( 'qm/alert', $message, $context );
32
  }
33
 
34
  public static function critical( $message, array $context = array() ) {
35
+ /**
36
+ * Fires when a `critical` level message is logged.
37
+ *
38
+ * @since 3.1.0
39
+ *
40
+ * @param string $message The message.
41
+ * @param array $context The context passed.
42
+ */
43
  do_action( 'qm/critical', $message, $context );
44
  }
45
 
46
  public static function error( $message, array $context = array() ) {
47
+ /**
48
+ * Fires when an `error` level message is logged.
49
+ *
50
+ * @since 3.1.0
51
+ *
52
+ * @param string $message The message.
53
+ * @param array $context The context passed.
54
+ */
55
  do_action( 'qm/error', $message, $context );
56
  }
57
 
58
  public static function warning( $message, array $context = array() ) {
59
+ /**
60
+ * Fires when a `warning` level message is logged.
61
+ *
62
+ * @since 3.1.0
63
+ *
64
+ * @param string $message The message.
65
+ * @param array $context The context passed.
66
+ */
67
  do_action( 'qm/warning', $message, $context );
68
  }
69
 
70
  public static function notice( $message, array $context = array() ) {
71
+ /**
72
+ * Fires when a `notice` level message is logged.
73
+ *
74
+ * @since 3.1.0
75
+ *
76
+ * @param string $message The message.
77
+ * @param array $context The context passed.
78
+ */
79
  do_action( 'qm/notice', $message, $context );
80
  }
81
 
82
  public static function info( $message, array $context = array() ) {
83
+ /**
84
+ * Fires when an `info` level message is logged.
85
+ *
86
+ * @since 3.1.0
87
+ *
88
+ * @param string $message The message.
89
+ * @param array $context The context passed.
90
+ */
91
  do_action( 'qm/info', $message, $context );
92
  }
93
 
94
  public static function debug( $message, array $context = array() ) {
95
+ /**
96
+ * Fires when a `debug` level message is logged.
97
+ *
98
+ * @since 3.1.0
99
+ *
100
+ * @param string $message The message.
101
+ * @param array $context The context passed.
102
+ */
103
  do_action( 'qm/debug', $message, $context );
104
  }
105
 
classes/QueryMonitor.php CHANGED
@@ -19,6 +19,8 @@ class QueryMonitor extends QM_Plugin {
19
  add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 4 );
20
  add_filter( 'ure_built_in_wp_caps', array( $this, 'filter_ure_caps' ) );
21
  add_filter( 'ure_capabilities_groups_tree', array( $this, 'filter_ure_groups' ) );
 
 
22
 
23
  # Parent setup:
24
  parent::__construct( $file );
@@ -26,16 +28,30 @@ class QueryMonitor extends QM_Plugin {
26
  # Load and register built-in collectors:
27
  $collectors = array();
28
  foreach ( glob( $this->plugin_path( 'collectors/*.php' ) ) as $file ) {
29
- $key = basename( $file, '.php' );
30
  $collectors[ $key ] = $file;
31
  }
32
 
 
 
 
 
 
 
 
33
  foreach ( apply_filters( 'qm/built-in-collectors', $collectors ) as $file ) {
34
  include $file;
35
  }
36
 
37
  }
38
 
 
 
 
 
 
 
 
39
  /**
40
  * Filter a user's capabilities so they can be altered at runtime.
41
  *
@@ -75,7 +91,14 @@ class QueryMonitor extends QM_Plugin {
75
 
76
  public function action_plugins_loaded() {
77
 
78
- # Register additional collectors:
 
 
 
 
 
 
 
79
  foreach ( apply_filters( 'qm/collectors', array(), $this ) as $collector ) {
80
  QM_Collectors::add( $collector );
81
  }
@@ -85,7 +108,14 @@ class QueryMonitor extends QM_Plugin {
85
  include $file;
86
  }
87
 
88
- # Register built-in and additional dispatchers:
 
 
 
 
 
 
 
89
  foreach ( apply_filters( 'qm/dispatchers', array(), $this ) as $dispatcher ) {
90
  QM_Dispatchers::add( $dispatcher );
91
  }
19
  add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 4 );
20
  add_filter( 'ure_built_in_wp_caps', array( $this, 'filter_ure_caps' ) );
21
  add_filter( 'ure_capabilities_groups_tree', array( $this, 'filter_ure_groups' ) );
22
+ add_filter( 'network_admin_plugin_action_links_query-monitor/query-monitor.php', array( $this, 'filter_plugin_action_links' ) );
23
+ add_filter( 'plugin_action_links_query-monitor/query-monitor.php', array( $this, 'filter_plugin_action_links' ) );
24
 
25
  # Parent setup:
26
  parent::__construct( $file );
28
  # Load and register built-in collectors:
29
  $collectors = array();
30
  foreach ( glob( $this->plugin_path( 'collectors/*.php' ) ) as $file ) {
31
+ $key = basename( $file, '.php' );
32
  $collectors[ $key ] = $file;
33
  }
34
 
35
+ /**
36
+ * Allow filtering of built-in collector files.
37
+ *
38
+ * @since 2.14.0
39
+ *
40
+ * @param string[] $collectors Array of file paths to be loaded.
41
+ */
42
  foreach ( apply_filters( 'qm/built-in-collectors', $collectors ) as $file ) {
43
  include $file;
44
  }
45
 
46
  }
47
 
48
+ public function filter_plugin_action_links( array $actions ) {
49
+ return array_merge( array(
50
+ 'settings' => '<a href="#qm-settings">' . esc_html__( 'Settings', 'query-monitor' ) . '</a>',
51
+ 'add-ons' => '<a href="https://github.com/johnbillion/query-monitor/wiki/Query-Monitor-Add-on-Plugins">' . esc_html__( 'Add-ons', 'query-monitor' ) . '</a>',
52
+ ), $actions );
53
+ }
54
+
55
  /**
56
  * Filter a user's capabilities so they can be altered at runtime.
57
  *
91
 
92
  public function action_plugins_loaded() {
93
 
94
+ /**
95
+ * Filters the collectors that are being added.
96
+ *
97
+ * @since 2.11.2
98
+ *
99
+ * @param QM_Collector[] $collectors Array of collecter instances.
100
+ * @param QueryMonitor $this QueryMonitor instance.
101
+ */
102
  foreach ( apply_filters( 'qm/collectors', array(), $this ) as $collector ) {
103
  QM_Collectors::add( $collector );
104
  }
108
  include $file;
109
  }
110
 
111
+ /**
112
+ * Filters the dispatchers that are being added.
113
+ *
114
+ * @since 2.11.2
115
+ *
116
+ * @param QM_Dispatcher[] $dispatchers Array of dispatcher instances.
117
+ * @param QueryMonitor $this QueryMonitor instance.
118
+ */
119
  foreach ( apply_filters( 'qm/dispatchers', array(), $this ) as $dispatcher ) {
120
  QM_Dispatchers::add( $dispatcher );
121
  }
classes/Timer.php CHANGED
@@ -13,7 +13,7 @@ class QM_Timer {
13
  protected $laps = array();
14
 
15
  public function start( array $data = null ) {
16
- $this->trace = new QM_Backtrace;
17
  $this->start = array(
18
  'time' => microtime( true ),
19
  'memory' => memory_get_usage(),
13
  protected $laps = array();
14
 
15
  public function start( array $data = null ) {
16
+ $this->trace = new QM_Backtrace();
17
  $this->start = array(
18
  'time' => microtime( true ),
19
  'memory' => memory_get_usage(),
classes/Util.php CHANGED
@@ -185,7 +185,7 @@ class QM_Util {
185
 
186
  public static function populate_callback( array $callback ) {
187
 
188
- if ( is_string( $callback['function'] ) and ( false !== strpos( $callback['function'], '::' ) ) ) {
189
  $callback['function'] = explode( '::', $callback['function'] );
190
  }
191
 
@@ -200,12 +200,12 @@ class QM_Util {
200
  $access = '::';
201
  }
202
 
203
- $callback['name'] = QM_Util::shorten_fqn( $class . $access . $callback['function'][1] ) . '()';
204
  $ref = new ReflectionMethod( $class, $callback['function'][1] );
205
  } elseif ( is_object( $callback['function'] ) ) {
206
  if ( is_a( $callback['function'], 'Closure' ) ) {
207
  $ref = new ReflectionFunction( $callback['function'] );
208
- $file = QM_Util::standard_dir( $ref->getFileName(), '' );
209
  if ( 0 === strpos( $file, '/' ) ) {
210
  $file = basename( $ref->getFileName() );
211
  }
@@ -214,11 +214,11 @@ class QM_Util {
214
  } else {
215
  // the object should have a __invoke() method
216
  $class = get_class( $callback['function'] );
217
- $callback['name'] = QM_Util::shorten_fqn( $class ) . '->__invoke()';
218
  $ref = new ReflectionMethod( $class, '__invoke' );
219
  }
220
  } else {
221
- $callback['name'] = QM_Util::shorten_fqn( $callback['function'] ) . '()';
222
  $ref = new ReflectionFunction( $callback['function'] );
223
  }
224
 
@@ -232,7 +232,7 @@ class QM_Util {
232
  if ( preg_match( '|(?P<file>.*)\((?P<line>[0-9]+)\)|', $callback['file'], $matches ) ) {
233
  $callback['file'] = $matches['file'];
234
  $callback['line'] = $matches['line'];
235
- $file = trim( QM_Util::standard_dir( $callback['file'], '' ), '/' );
236
  /* translators: 1: Line number, 2: File name */
237
  $callback['name'] = sprintf( __( 'Anonymous function on line %1$d of %2$s', 'query-monitor' ), $callback['line'], $file );
238
  } else {
@@ -263,7 +263,7 @@ class QM_Util {
263
  }
264
 
265
  public static function is_ajax() {
266
- if ( defined( 'DOING_AJAX' ) and DOING_AJAX ) {
267
  return true;
268
  }
269
  return false;
185
 
186
  public static function populate_callback( array $callback ) {
187
 
188
+ if ( is_string( $callback['function'] ) && ( false !== strpos( $callback['function'], '::' ) ) ) {
189
  $callback['function'] = explode( '::', $callback['function'] );
190
  }
191
 
200
  $access = '::';
201
  }
202
 
203
+ $callback['name'] = self::shorten_fqn( $class . $access . $callback['function'][1] ) . '()';
204
  $ref = new ReflectionMethod( $class, $callback['function'][1] );
205
  } elseif ( is_object( $callback['function'] ) ) {
206
  if ( is_a( $callback['function'], 'Closure' ) ) {
207
  $ref = new ReflectionFunction( $callback['function'] );
208
+ $file = self::standard_dir( $ref->getFileName(), '' );
209
  if ( 0 === strpos( $file, '/' ) ) {
210
  $file = basename( $ref->getFileName() );
211
  }
214
  } else {
215
  // the object should have a __invoke() method
216
  $class = get_class( $callback['function'] );
217
+ $callback['name'] = self::shorten_fqn( $class ) . '->__invoke()';
218
  $ref = new ReflectionMethod( $class, '__invoke' );
219
  }
220
  } else {
221
+ $callback['name'] = self::shorten_fqn( $callback['function'] ) . '()';
222
  $ref = new ReflectionFunction( $callback['function'] );
223
  }
224
 
232
  if ( preg_match( '|(?P<file>.*)\((?P<line>[0-9]+)\)|', $callback['file'], $matches ) ) {
233
  $callback['file'] = $matches['file'];
234
  $callback['line'] = $matches['line'];
235
+ $file = trim( self::standard_dir( $callback['file'], '' ), '/' );
236
  /* translators: 1: Line number, 2: File name */
237
  $callback['name'] = sprintf( __( 'Anonymous function on line %1$d of %2$s', 'query-monitor' ), $callback['line'], $file );
238
  } else {
263
  }
264
 
265
  public static function is_ajax() {
266
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
267
  return true;
268
  }
269
  return false;
classes/debug_bar.php CHANGED
@@ -16,19 +16,33 @@ class Debug_Bar {
16
  }
17
 
18
  public function enqueue() {
 
19
  wp_register_style( 'debug-bar', false, array(
20
  'query-monitor',
21
  ) );
 
22
  wp_register_script( 'debug-bar', false, array(
23
  'query-monitor',
24
  ) );
25
 
 
 
 
 
 
26
  do_action( 'debug_bar_enqueue_scripts' );
27
  }
28
 
29
  public function init_panels() {
30
  require_once 'debug_bar_panel.php';
31
 
 
 
 
 
 
 
 
32
  $this->panels = apply_filters( 'debug_bar_panels', array() );
33
  }
34
 
@@ -41,7 +55,7 @@ class Debug_Bar {
41
  }
42
 
43
  public function Debug_Bar() {
44
- Debug_Bar::__construct();
45
  }
46
 
47
  }
16
  }
17
 
18
  public function enqueue() {
19
+ // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
20
  wp_register_style( 'debug-bar', false, array(
21
  'query-monitor',
22
  ) );
23
+ // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
24
  wp_register_script( 'debug-bar', false, array(
25
  'query-monitor',
26
  ) );
27
 
28
+ /**
29
+ * Fires after scripts have been enqueued. This mimics the same action fired in the Debug Bar plugin.
30
+ *
31
+ * @since 2.7.0
32
+ */
33
  do_action( 'debug_bar_enqueue_scripts' );
34
  }
35
 
36
  public function init_panels() {
37
  require_once 'debug_bar_panel.php';
38
 
39
+ /**
40
+ * Filters the debug bar panel list. This mimics the same filter called in the Debug Bar plugin.
41
+ *
42
+ * @since 2.7.0
43
+ *
44
+ * @param Debug_Bar_Panel[] $panels Array of Debug Bar panel instances.
45
+ */
46
  $this->panels = apply_filters( 'debug_bar_panels', array() );
47
  }
48
 
55
  }
56
 
57
  public function Debug_Bar() {
58
+ self::__construct();
59
  }
60
 
61
  }
classes/debug_bar_panel.php CHANGED
@@ -7,7 +7,7 @@
7
 
8
  abstract class Debug_Bar_Panel {
9
 
10
- public $_title = '';
11
  public $_visible = true;
12
 
13
  public function __construct( $title = '' ) {
@@ -54,7 +54,7 @@ abstract class Debug_Bar_Panel {
54
  }
55
 
56
  public function Debug_Bar_Panel( $title = '' ) {
57
- Debug_Bar_Panel::__construct( $title );
58
  }
59
 
60
  }
7
 
8
  abstract class Debug_Bar_Panel {
9
 
10
+ public $_title = '';
11
  public $_visible = true;
12
 
13
  public function __construct( $title = '' ) {
54
  }
55
 
56
  public function Debug_Bar_Panel( $title = '' ) {
57
+ self::__construct( $title );
58
  }
59
 
60
  }
collectors/admin.php CHANGED
@@ -25,7 +25,7 @@ class QM_Collector_Admin extends QM_Collector {
25
  $this->data['base'] = $pagenow;
26
  }
27
 
28
- $this->data['pagenow'] = $pagenow;
29
  $this->data['current_screen'] = ( $current_screen ) ? get_object_vars( $current_screen ) : null;
30
 
31
  $screens = array(
@@ -42,7 +42,7 @@ class QM_Collector_Admin extends QM_Collector {
42
  'users-network' => true,
43
  );
44
 
45
- if ( ! empty( $this->data['current_screen'] ) and isset( $screens[ $this->data['current_screen']['base'] ] ) ) {
46
 
47
  $list_table = array();
48
 
@@ -56,7 +56,7 @@ class QM_Collector_Admin extends QM_Collector {
56
  $list_table['column'] = $this->data['current_screen']['base'];
57
  }
58
 
59
- if ( ! empty( $this->data['current_screen']['post_type'] ) and empty( $this->data['current_screen']['taxonomy'] ) ) {
60
  $list_table['columns'] = $this->data['current_screen']['post_type'] . '_posts';
61
  } else {
62
  $list_table['columns'] = $this->data['current_screen']['id'];
@@ -88,7 +88,7 @@ class QM_Collector_Admin extends QM_Collector {
88
  }
89
 
90
  function register_qm_collector_admin( array $collectors, QueryMonitor $qm ) {
91
- $collectors['response'] = new QM_Collector_Admin;
92
  return $collectors;
93
  }
94
 
25
  $this->data['base'] = $pagenow;
26
  }
27
 
28
+ $this->data['pagenow'] = $pagenow;
29
  $this->data['current_screen'] = ( $current_screen ) ? get_object_vars( $current_screen ) : null;
30
 
31
  $screens = array(
42
  'users-network' => true,
43
  );
44
 
45
+ if ( ! empty( $this->data['current_screen'] ) && isset( $screens[ $this->data['current_screen']['base'] ] ) ) {
46
 
47
  $list_table = array();
48
 
56
  $list_table['column'] = $this->data['current_screen']['base'];
57
  }
58
 
59
+ if ( ! empty( $this->data['current_screen']['post_type'] ) && empty( $this->data['current_screen']['taxonomy'] ) ) {
60
  $list_table['columns'] = $this->data['current_screen']['post_type'] . '_posts';
61
  } else {
62
  $list_table['columns'] = $this->data['current_screen']['id'];
88
  }
89
 
90
  function register_qm_collector_admin( array $collectors, QueryMonitor $qm ) {
91
+ $collectors['response'] = new QM_Collector_Admin();
92
  return $collectors;
93
  }
94
 
collectors/assets.php CHANGED
@@ -22,7 +22,7 @@ class QM_Collector_Assets extends QM_Collector {
22
  public function action_head() {
23
  global $wp_scripts, $wp_styles;
24
 
25
- $this->data['header']['styles'] = $wp_styles->done;
26
  $this->data['header']['scripts'] = $wp_scripts->done;
27
 
28
  }
@@ -48,14 +48,16 @@ class QM_Collector_Assets extends QM_Collector {
48
  return;
49
  }
50
 
 
 
51
  foreach ( array( 'scripts', 'styles' ) as $type ) {
52
  foreach ( array( 'header', 'footer' ) as $position ) {
53
  if ( empty( $this->data[ $position ][ $type ] ) ) {
54
  $this->data[ $position ][ $type ] = array();
55
  }
56
  }
57
- $raw = $this->data['raw'][ $type ];
58
- $broken = array_values( array_diff( $raw->queue, $raw->done ) );
59
  $missing = array_values( array_diff( $raw->queue, array_keys( $raw->registered ) ) );
60
 
61
  if ( ! empty( $broken ) ) {
@@ -123,7 +125,7 @@ class QM_Collector_Assets extends QM_Collector {
123
  }
124
 
125
  function register_qm_collector_assets( array $collectors, QueryMonitor $qm ) {
126
- $collectors['assets'] = new QM_Collector_Assets;
127
  return $collectors;
128
  }
129
 
22
  public function action_head() {
23
  global $wp_scripts, $wp_styles;
24
 
25
+ $this->data['header']['styles'] = $wp_styles->done;
26
  $this->data['header']['scripts'] = $wp_scripts->done;
27
 
28
  }
48
  return;
49
  }
50
 
51
+ $this->data['is_ssl'] = is_ssl();
52
+
53
  foreach ( array( 'scripts', 'styles' ) as $type ) {
54
  foreach ( array( 'header', 'footer' ) as $position ) {
55
  if ( empty( $this->data[ $position ][ $type ] ) ) {
56
  $this->data[ $position ][ $type ] = array();
57
  }
58
  }
59
+ $raw = $this->data['raw'][ $type ];
60
+ $broken = array_values( array_diff( $raw->queue, $raw->done ) );
61
  $missing = array_values( array_diff( $raw->queue, array_keys( $raw->registered ) ) );
62
 
63
  if ( ! empty( $broken ) ) {
125
  }
126
 
127
  function register_qm_collector_assets( array $collectors, QueryMonitor $qm ) {
128
+ $collectors['assets'] = new QM_Collector_Assets();
129
  return $collectors;
130
  }
131
 
collectors/block_editor.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Block editor (née Gutenberg) collector.
4
+ *
5
+ * @package query-monitor
6
+ */
7
+
8
+ class QM_Collector_Block_Editor extends QM_Collector {
9
+
10
+ public $id = 'block_editor';
11
+
12
+ public function name() {
13
+ return __( 'Blocks', 'query-monitor' );
14
+ }
15
+
16
+ public function process() {
17
+ $this->data['block_editor_enabled'] = self::wp_block_editor_enabled();
18
+
19
+ if ( ! is_singular() ) {
20
+ return;
21
+ }
22
+
23
+ $block_type_registry = WP_Block_Type_Registry::get_instance();
24
+
25
+ $this->data['post_has_blocks'] = self::wp_has_blocks( get_post()->post_content );
26
+ $this->data['post_blocks'] = self::wp_parse_blocks( get_post()->post_content );
27
+ $this->data['all_dynamic_blocks'] = self::wp_get_dynamic_block_names();
28
+
29
+ if ( $this->data['post_has_blocks'] ) {
30
+ foreach ( $this->data['post_blocks'] as $i => $block ) {
31
+ $block_type = $block_type_registry->get_registered( $block['blockName'] );
32
+ $dynamic = false;
33
+ $callback = null;
34
+
35
+ if ( $block_type && $block_type->is_dynamic() ) {
36
+ $dynamic = true;
37
+ $callback = QM_Util::populate_callback( array(
38
+ 'function' => $block_type->render_callback,
39
+ ) );
40
+ }
41
+
42
+ $this->data['post_blocks'][ $i ]['dynamic'] = $dynamic;
43
+ $this->data['post_blocks'][ $i ]['callback'] = $callback;
44
+ }
45
+ }
46
+ }
47
+
48
+ protected static function wp_block_editor_enabled() {
49
+ return ( function_exists( 'parse_blocks' ) || function_exists( 'gutenberg_parse_blocks' ) );
50
+ }
51
+
52
+ protected static function wp_has_blocks( $content ) {
53
+ if ( function_exists( 'has_blocks' ) ) {
54
+ return has_blocks( $content );
55
+ } elseif ( function_exists( 'gutenberg_has_blocks' ) ) {
56
+ return gutenberg_has_blocks( $content );
57
+ }
58
+
59
+ return false;
60
+ }
61
+
62
+ protected static function wp_parse_blocks( $content ) {
63
+ if ( function_exists( 'parse_blocks' ) ) {
64
+ return parse_blocks( $content );
65
+ } elseif ( function_exists( 'gutenberg_parse_blocks' ) ) {
66
+ return gutenberg_parse_blocks( $content );
67
+ }
68
+
69
+ return null;
70
+ }
71
+
72
+ protected static function wp_get_dynamic_block_names() {
73
+ return get_dynamic_block_names();
74
+ }
75
+
76
+ }
77
+
78
+ function register_qm_collector_block_editor( array $collectors, QueryMonitor $qm ) {
79
+ $collectors['block_editor'] = new QM_Collector_Block_Editor();
80
+ return $collectors;
81
+ }
82
+
83
+ add_filter( 'qm/collectors', 'register_qm_collector_block_editor', 10, 2 );
collectors/cache.php CHANGED
@@ -16,7 +16,7 @@ class QM_Collector_Cache extends QM_Collector {
16
  public function process() {
17
  global $wp_object_cache;
18
 
19
- $this->data['ext_object_cache'] = (bool) wp_using_ext_object_cache();
20
  $this->data['cache_hit_percentage'] = 0;
21
 
22
  if ( is_object( $wp_object_cache ) ) {
@@ -66,7 +66,7 @@ class QM_Collector_Cache extends QM_Collector {
66
  }
67
 
68
  if ( isset( $this->data['stats']['cache_hits'] ) && isset( $this->data['stats']['cache_misses'] ) ) {
69
- $total = $this->data['stats']['cache_misses'] + $this->data['stats']['cache_hits'];
70
  $this->data['cache_hit_percentage'] = ( 100 / $total ) * $this->data['stats']['cache_hits'];
71
  }
72
 
@@ -89,7 +89,7 @@ class QM_Collector_Cache extends QM_Collector {
89
  }
90
 
91
  function register_qm_collector_cache( array $collectors, QueryMonitor $qm ) {
92
- $collectors['cache'] = new QM_Collector_Cache;
93
  return $collectors;
94
  }
95
 
16
  public function process() {
17
  global $wp_object_cache;
18
 
19
+ $this->data['ext_object_cache'] = (bool) wp_using_ext_object_cache();
20
  $this->data['cache_hit_percentage'] = 0;
21
 
22
  if ( is_object( $wp_object_cache ) ) {
66
  }
67
 
68
  if ( isset( $this->data['stats']['cache_hits'] ) && isset( $this->data['stats']['cache_misses'] ) ) {
69
+ $total = $this->data['stats']['cache_misses'] + $this->data['stats']['cache_hits'];
70
  $this->data['cache_hit_percentage'] = ( 100 / $total ) * $this->data['stats']['cache_hits'];
71
  }
72
 
89
  }
90
 
91
  function register_qm_collector_cache( array $collectors, QueryMonitor $qm ) {
92
+ $collectors['cache'] = new QM_Collector_Cache();
93
  return $collectors;
94
  }
95
 
collectors/caps.php CHANGED
@@ -44,7 +44,7 @@ class QM_Collector_Caps extends QM_Collector {
44
  * @return bool[] Concerned user's capabilities.
45
  */
46
  public function filter_user_has_cap( array $user_caps, array $caps, array $args ) {
47
- $trace = new QM_Backtrace;
48
  $result = true;
49
 
50
  foreach ( $caps as $cap ) {
@@ -87,7 +87,7 @@ class QM_Collector_Caps extends QM_Collector {
87
  return $required_caps;
88
  }
89
 
90
- $trace = new QM_Backtrace;
91
  $result = ( ! in_array( 'do_not_allow', $required_caps, true ) );
92
 
93
  array_unshift( $args, $user_id );
@@ -107,8 +107,8 @@ class QM_Collector_Caps extends QM_Collector {
107
  return;
108
  }
109
 
110
- $all_parts = array();
111
- $all_users = array();
112
  $components = array();
113
 
114
  $this->data['caps'] = array_filter( $this->data['caps'], array( $this, 'filter_remove_noise' ) );
@@ -124,26 +124,26 @@ class QM_Collector_Caps extends QM_Collector {
124
  $name = '';
125
  }
126
 
127
- $parts = array_filter( preg_split( '#[_/-]#', $name ) );
128
  $this->data['caps'][ $i ]['parts'] = $parts;
129
  $this->data['caps'][ $i ]['name'] = $name;
130
  $this->data['caps'][ $i ]['user'] = $cap['args'][1];
131
  $this->data['caps'][ $i ]['args'] = array_slice( $cap['args'], 2 );
132
- $all_parts = array_merge( $all_parts, $parts );
133
- $all_users[] = $cap['args'][1];
134
- $component = $cap['trace']->get_component();
135
- $components[ $component->name ] = $component->name;
136
  }
137
 
138
- $this->data['parts'] = array_unique( array_filter( $all_parts ) );
139
- $this->data['users'] = array_unique( array_filter( $all_users ) );
140
  $this->data['components'] = $components;
141
  }
142
 
143
  public function filter_remove_noise( array $cap ) {
144
  $trace = $cap['trace']->get_trace();
145
 
146
- $exclude_files = array(
147
  ABSPATH . 'wp-admin/menu.php',
148
  ABSPATH . 'wp-admin/includes/menu.php',
149
  );
@@ -167,7 +167,7 @@ class QM_Collector_Caps extends QM_Collector {
167
  }
168
 
169
  function register_qm_collector_caps( array $collectors, QueryMonitor $qm ) {
170
- $collectors['caps'] = new QM_Collector_Caps;
171
  return $collectors;
172
  }
173
 
44
  * @return bool[] Concerned user's capabilities.
45
  */
46
  public function filter_user_has_cap( array $user_caps, array $caps, array $args ) {
47
+ $trace = new QM_Backtrace();
48
  $result = true;
49
 
50
  foreach ( $caps as $cap ) {
87
  return $required_caps;
88
  }
89
 
90
+ $trace = new QM_Backtrace();
91
  $result = ( ! in_array( 'do_not_allow', $required_caps, true ) );
92
 
93
  array_unshift( $args, $user_id );
107
  return;
108
  }
109
 
110
+ $all_parts = array();
111
+ $all_users = array();
112
  $components = array();
113
 
114
  $this->data['caps'] = array_filter( $this->data['caps'], array( $this, 'filter_remove_noise' ) );
124
  $name = '';
125
  }
126
 
127
+ $parts = array_filter( preg_split( '#[_/-]#', $name ) );
128
  $this->data['caps'][ $i ]['parts'] = $parts;
129
  $this->data['caps'][ $i ]['name'] = $name;
130
  $this->data['caps'][ $i ]['user'] = $cap['args'][1];
131
  $this->data['caps'][ $i ]['args'] = array_slice( $cap['args'], 2 );
132
+ $all_parts = array_merge( $all_parts, $parts );
133
+ $all_users[] = $cap['args'][1];
134
+ $component = $cap['trace']->get_component();
135
+ $components[ $component->name ] = $component->name;
136
  }
137
 
138
+ $this->data['parts'] = array_unique( array_filter( $all_parts ) );
139
+ $this->data['users'] = array_unique( array_filter( $all_users ) );
140
  $this->data['components'] = $components;
141
  }
142
 
143
  public function filter_remove_noise( array $cap ) {
144
  $trace = $cap['trace']->get_trace();
145
 
146
+ $exclude_files = array(
147
  ABSPATH . 'wp-admin/menu.php',
148
  ABSPATH . 'wp-admin/includes/menu.php',
149
  );
167
  }
168
 
169
  function register_qm_collector_caps( array $collectors, QueryMonitor $qm ) {
170
+ $collectors['caps'] = new QM_Collector_Caps();
171
  return $collectors;
172
  }
173
 
collectors/conditionals.php CHANGED
@@ -15,6 +15,13 @@ class QM_Collector_Conditionals extends QM_Collector {
15
 
16
  public function process() {
17
 
 
 
 
 
 
 
 
18
  $conds = apply_filters( 'qm/collect/conditionals', array(
19
  'is_404',
20
  'is_admin',
@@ -54,13 +61,21 @@ class QM_Collector_Conditionals extends QM_Collector {
54
  'is_user_admin',
55
  'is_year',
56
  ) );
 
 
 
 
 
 
 
 
57
  $conds = apply_filters( 'query_monitor_conditionals', $conds );
58
 
59
  $true = $false = $na = array();
60
 
61
  foreach ( $conds as $cond ) {
62
  if ( function_exists( $cond ) ) {
63
- if ( ( 'is_sticky' === $cond ) and ! get_post( $id = null ) ) {
64
  # Special case for is_sticky to prevent PHP notices
65
  $false[] = $cond;
66
  } elseif ( ! is_multisite() && in_array( $cond, array( 'is_main_network', 'is_main_site' ), true ) ) {
@@ -84,7 +99,7 @@ class QM_Collector_Conditionals extends QM_Collector {
84
  }
85
 
86
  function register_qm_collector_conditionals( array $collectors, QueryMonitor $qm ) {
87
- $collectors['conditionals'] = new QM_Collector_Conditionals;
88
  return $collectors;
89
  }
90
 
15
 
16
  public function process() {
17
 
18
+ /**
19
+ * Allows users to filter the names of conditional functions that are exposed by QM.
20
+ *
21
+ * @since 2.7.0
22
+ *
23
+ * @param string[] $conditionals The list of conditional function names.
24
+ */
25
  $conds = apply_filters( 'qm/collect/conditionals', array(
26
  'is_404',
27
  'is_admin',
61
  'is_user_admin',
62
  'is_year',
63
  ) );
64
+
65
+ /**
66
+ * This filter is deprecated. Please use `qm/collect/conditionals` instead.
67
+ *
68
+ * @since 2.7.0
69
+ *
70
+ * @param string[] $conditionals The list of conditional function names.
71
+ */
72
  $conds = apply_filters( 'query_monitor_conditionals', $conds );
73
 
74
  $true = $false = $na = array();
75
 
76
  foreach ( $conds as $cond ) {
77
  if ( function_exists( $cond ) ) {
78
+ if ( ( 'is_sticky' === $cond ) && ! get_post( $id = null ) ) {
79
  # Special case for is_sticky to prevent PHP notices
80
  $false[] = $cond;
81
  } elseif ( ! is_multisite() && in_array( $cond, array( 'is_main_network', 'is_main_site' ), true ) ) {
99
  }
100
 
101
  function register_qm_collector_conditionals( array $collectors, QueryMonitor $qm ) {
102
+ $collectors['conditionals'] = new QM_Collector_Conditionals();
103
  return $collectors;
104
  }
105
 
collectors/db_callers.php CHANGED
@@ -30,7 +30,7 @@ class QM_Collector_DB_Callers extends QM_Collector {
30
  }
31
 
32
  function register_qm_collector_db_callers( array $collectors, QueryMonitor $qm ) {
33
- $collectors['db_callers'] = new QM_Collector_DB_Callers;
34
  return $collectors;
35
  }
36
 
30
  }
31
 
32
  function register_qm_collector_db_callers( array $collectors, QueryMonitor $qm ) {
33
+ $collectors['db_callers'] = new QM_Collector_DB_Callers();
34
  return $collectors;
35
  }
36
 
collectors/db_components.php CHANGED
@@ -30,7 +30,7 @@ class QM_Collector_DB_Components extends QM_Collector {
30
  }
31
 
32
  function register_qm_collector_db_components( array $collectors, QueryMonitor $qm ) {
33
- $collectors['db_components'] = new QM_Collector_DB_Components;
34
  return $collectors;
35
  }
36
 
30
  }
31
 
32
  function register_qm_collector_db_components( array $collectors, QueryMonitor $qm ) {
33
+ $collectors['db_components'] = new QM_Collector_DB_Components();
34
  return $collectors;
35
  }
36
 
collectors/db_dupes.php CHANGED
@@ -99,7 +99,7 @@ class QM_Collector_DB_Dupes extends QM_Collector {
99
  }
100
 
101
  function register_qm_collector_db_dupes( array $collectors, QueryMonitor $qm ) {
102
- $collectors['db_dupes'] = new QM_Collector_DB_Dupes;
103
  return $collectors;
104
  }
105
 
99
  }
100
 
101
  function register_qm_collector_db_dupes( array $collectors, QueryMonitor $qm ) {
102
+ $collectors['db_dupes'] = new QM_Collector_DB_Dupes();
103
  return $collectors;
104
  }
105
 
collectors/db_queries.php CHANGED
@@ -18,7 +18,7 @@ if ( SAVEQUERIES && property_exists( $GLOBALS['wpdb'], 'save_queries' ) ) {
18
 
19
  class QM_Collector_DB_Queries extends QM_Collector {
20
 
21
- public $id = 'db_queries';
22
  public $db_objects = array();
23
 
24
  public function name() {
@@ -53,6 +53,15 @@ class QM_Collector_DB_Queries extends QM_Collector {
53
  $this->data['total_time'] = 0;
54
  $this->data['errors'] = array();
55
 
 
 
 
 
 
 
 
 
 
56
  $this->db_objects = apply_filters( 'qm/collect/db_objects', array(
57
  '$wpdb' => $GLOBALS['wpdb'],
58
  ) );
@@ -72,8 +81,8 @@ class QM_Collector_DB_Queries extends QM_Collector {
72
  if ( ! isset( $this->data['times'][ $caller ] ) ) {
73
  $this->data['times'][ $caller ] = array(
74
  'caller' => $caller,
75
- 'ltime' => 0,
76
- 'types' => array(),
77
  );
78
  }
79
 
@@ -109,12 +118,12 @@ class QM_Collector_DB_Queries extends QM_Collector {
109
  continue;
110
  }
111
 
112
- $sql = $query[0];
113
- $ltime = $query[1];
114
- $stack = $query[2];
115
- $has_start = isset( $query[3] );
116
- $has_trace = isset( $query['trace'] );
117
- $has_result = isset( $query['result'] );
118
 
119
  if ( $has_result ) {
120
  $result = $query['result'];
@@ -212,7 +221,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
212
 
213
  $total_qs = count( $rows );
214
 
215
- $this->data['total_qs'] += $total_qs;
216
  $this->data['total_time'] += $total_time;
217
 
218
  $has_main_query = wp_list_filter( $rows, array(
@@ -228,7 +237,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
228
  }
229
 
230
  function register_qm_collector_db_queries( array $collectors, QueryMonitor $qm ) {
231
- $collectors['db_queries'] = new QM_Collector_DB_Queries;
232
  return $collectors;
233
  }
234
 
18
 
19
  class QM_Collector_DB_Queries extends QM_Collector {
20
 
21
+ public $id = 'db_queries';
22
  public $db_objects = array();
23
 
24
  public function name() {
53
  $this->data['total_time'] = 0;
54
  $this->data['errors'] = array();
55
 
56
+ /**
57
+ * Filters the `wpdb` instances that are exposed to QM.
58
+ *
59
+ * This allows Query Monitor to display multiple instances of `wpdb` on one page load.
60
+ *
61
+ * @since 2.7.0
62
+ *
63
+ * @param wpdb[] $db_objects Array of `wpdb` instances, keyed by their name.
64
+ */
65
  $this->db_objects = apply_filters( 'qm/collect/db_objects', array(
66
  '$wpdb' => $GLOBALS['wpdb'],
67
  ) );
81
  if ( ! isset( $this->data['times'][ $caller ] ) ) {
82
  $this->data['times'][ $caller ] = array(
83
  'caller' => $caller,
84
+ 'ltime' => 0,
85
+ 'types' => array(),
86
  );
87
  }
88
 
118
  continue;
119
  }
120
 
121
+ $sql = $query[0];
122
+ $ltime = $query[1];
123
+ $stack = $query[2];
124
+ $has_start = isset( $query[3] );
125
+ $has_trace = isset( $query['trace'] );
126
+ $has_result = isset( $query['result'] );
127
 
128
  if ( $has_result ) {
129
  $result = $query['result'];
221
 
222
  $total_qs = count( $rows );
223
 
224
+ $this->data['total_qs'] += $total_qs;
225
  $this->data['total_time'] += $total_time;
226
 
227
  $has_main_query = wp_list_filter( $rows, array(
237
  }
238
 
239
  function register_qm_collector_db_queries( array $collectors, QueryMonitor $qm ) {
240
+ $collectors['db_queries'] = new QM_Collector_DB_Queries();
241
  return $collectors;
242
  }
243
 
collectors/debug_bar.php CHANGED
@@ -54,11 +54,11 @@ function register_qm_collectors_debug_bar() {
54
  }
55
 
56
  $collectors = QM_Collectors::init();
57
- $qm = QueryMonitor::init();
58
 
59
  require_once $qm->plugin_path( 'classes/debug_bar.php' );
60
 
61
- $debug_bar = new Debug_Bar;
62
  $redundant = array(
63
  'debug_bar_actions_addon_panel', // Debug Bar Actions and Filters Addon
64
  'debug_bar_remote_requests_panel', // Debug Bar Remote Requests
@@ -73,7 +73,7 @@ function register_qm_collectors_debug_bar() {
73
  continue;
74
  }
75
 
76
- $collector = new QM_Collector_Debug_Bar;
77
  $collector->set_id( "debug_bar_{$panel_id}" );
78
  $collector->set_panel( $panel );
79
 
54
  }
55
 
56
  $collectors = QM_Collectors::init();
57
+ $qm = QueryMonitor::init();
58
 
59
  require_once $qm->plugin_path( 'classes/debug_bar.php' );
60
 
61
+ $debug_bar = new Debug_Bar();
62
  $redundant = array(
63
  'debug_bar_actions_addon_panel', // Debug Bar Actions and Filters Addon
64
  'debug_bar_remote_requests_panel', // Debug Bar Remote Requests
73
  continue;
74
  }
75
 
76
+ $collector = new QM_Collector_Debug_Bar();
77
  $collector->set_id( "debug_bar_{$panel_id}" );
78
  $collector->set_panel( $panel );
79
 
collectors/environment.php CHANGED
@@ -7,7 +7,7 @@
7
 
8
  class QM_Collector_Environment extends QM_Collector {
9
 
10
- public $id = 'environment';
11
  protected $php_vars = array(
12
  'max_execution_time',
13
  'memory_limit',
@@ -31,7 +31,7 @@ class QM_Collector_Environment extends QM_Collector {
31
  # caught early before any plugins had a chance to alter them
32
 
33
  foreach ( $this->php_vars as $setting ) {
34
- if ( isset( $wpdb->qm_php_vars ) and isset( $wpdb->qm_php_vars[ $setting ] ) ) {
35
  $val = $wpdb->qm_php_vars[ $setting ];
36
  } else {
37
  $val = ini_get( $setting );
@@ -128,11 +128,7 @@ class QM_Collector_Environment extends QM_Collector {
128
  $info = mysql_get_server_info( $db->dbh );
129
  }
130
 
131
- if ( false !== strpos( $info, 'MariaDB' ) ) {
132
- $rdbms = 'MariaDB';
133
- } else {
134
- $rdbms = 'MySQL';
135
- }
136
 
137
  if ( $client ) {
138
  $client_version = implode( '.', QM_Util::get_client_version( $client ) );
@@ -163,14 +159,14 @@ class QM_Collector_Environment extends QM_Collector {
163
  $this->data['php']['version'] = phpversion();
164
  $this->data['php']['sapi'] = php_sapi_name();
165
  $this->data['php']['user'] = self::get_current_user();
166
- $this->data['php']['old'] = version_compare( $this->data['php']['version'], 7, '<' );
167
 
168
  foreach ( $this->php_vars as $setting ) {
169
  $this->data['php']['variables'][ $setting ]['after'] = ini_get( $setting );
170
  }
171
 
172
  if ( defined( 'SORT_FLAG_CASE' ) ) {
173
- // phpcs:ignore PHPCompatibility.PHP.NewConstants
174
  $sort_flags = SORT_STRING | SORT_FLAG_CASE;
175
  } else {
176
  $sort_flags = SORT_STRING;
@@ -188,7 +184,7 @@ class QM_Collector_Environment extends QM_Collector {
188
  $this->data['php']['error_levels'] = self::get_error_levels( $this->data['php']['error_reporting'] );
189
 
190
  $this->data['wp']['version'] = $wp_version;
191
- $this->data['wp']['constants'] = array(
192
  'WP_DEBUG' => self::format_bool_constant( 'WP_DEBUG' ),
193
  'WP_DEBUG_DISPLAY' => self::format_bool_constant( 'WP_DEBUG_DISPLAY' ),
194
  'WP_DEBUG_LOG' => self::format_bool_constant( 'WP_DEBUG_LOG' ),
@@ -199,6 +195,7 @@ class QM_Collector_Environment extends QM_Collector {
199
  'COMPRESS_CSS' => self::format_bool_constant( 'COMPRESS_CSS' ),
200
  'WP_LOCAL_DEV' => self::format_bool_constant( 'WP_LOCAL_DEV' ),
201
  );
 
202
 
203
  if ( is_multisite() ) {
204
  $this->data['wp']['constants']['SUNRISE'] = self::format_bool_constant( 'SUNRISE' );
@@ -264,27 +261,27 @@ class QM_Collector_Environment extends QM_Collector {
264
  $php_u = null;
265
 
266
  if ( function_exists( 'posix_getpwuid' ) ) {
267
- $u = posix_getpwuid( posix_getuid() );
268
- $g = posix_getgrgid( $u['gid'] );
269
  $php_u = $u['name'] . ':' . $g['name'];
270
  }
271
 
272
- if ( empty( $php_u ) and isset( $_ENV['APACHE_RUN_USER'] ) ) {
273
  $php_u = $_ENV['APACHE_RUN_USER'];
274
  if ( isset( $_ENV['APACHE_RUN_GROUP'] ) ) {
275
  $php_u .= ':' . $_ENV['APACHE_RUN_GROUP'];
276
  }
277
  }
278
 
279
- if ( empty( $php_u ) and 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 ) and function_exists( 'exec' ) ) {
284
  $php_u = exec( 'whoami' ); // @codingStandardsIgnoreLine
285
  }
286
 
287
- if ( empty( $php_u ) and function_exists( 'getenv' ) ) {
288
  $php_u = getenv( 'USERNAME' );
289
  }
290
 
@@ -295,7 +292,7 @@ class QM_Collector_Environment extends QM_Collector {
295
  }
296
 
297
  function register_qm_collector_environment( array $collectors, QueryMonitor $qm ) {
298
- $collectors['environment'] = new QM_Collector_Environment;
299
  return $collectors;
300
  }
301
 
7
 
8
  class QM_Collector_Environment extends QM_Collector {
9
 
10
+ public $id = 'environment';
11
  protected $php_vars = array(
12
  'max_execution_time',
13
  'memory_limit',
31
  # caught early before any plugins had a chance to alter them
32
 
33
  foreach ( $this->php_vars as $setting ) {
34
+ if ( isset( $wpdb->qm_php_vars ) && isset( $wpdb->qm_php_vars[ $setting ] ) ) {
35
  $val = $wpdb->qm_php_vars[ $setting ];
36
  } else {
37
  $val = ini_get( $setting );
128
  $info = mysql_get_server_info( $db->dbh );
129
  }
130
 
131
+ $rdbms = trim( preg_replace( '#[^a-zA-Z ]#', '', $info ) );
 
 
 
 
132
 
133
  if ( $client ) {
134
  $client_version = implode( '.', QM_Util::get_client_version( $client ) );
159
  $this->data['php']['version'] = phpversion();
160
  $this->data['php']['sapi'] = php_sapi_name();
161
  $this->data['php']['user'] = self::get_current_user();
162
+ $this->data['php']['old'] = version_compare( $this->data['php']['version'], 7.1, '<' );
163
 
164
  foreach ( $this->php_vars as $setting ) {
165
  $this->data['php']['variables'][ $setting ]['after'] = ini_get( $setting );
166
  }
167
 
168
  if ( defined( 'SORT_FLAG_CASE' ) ) {
169
+ // phpcs:ignore PHPCompatibility.Constants.NewConstants
170
  $sort_flags = SORT_STRING | SORT_FLAG_CASE;
171
  } else {
172
  $sort_flags = SORT_STRING;
184
  $this->data['php']['error_levels'] = self::get_error_levels( $this->data['php']['error_reporting'] );
185
 
186
  $this->data['wp']['version'] = $wp_version;
187
+ $constants = array(
188
  'WP_DEBUG' => self::format_bool_constant( 'WP_DEBUG' ),
189
  'WP_DEBUG_DISPLAY' => self::format_bool_constant( 'WP_DEBUG_DISPLAY' ),
190
  'WP_DEBUG_LOG' => self::format_bool_constant( 'WP_DEBUG_LOG' ),
195
  'COMPRESS_CSS' => self::format_bool_constant( 'COMPRESS_CSS' ),
196
  'WP_LOCAL_DEV' => self::format_bool_constant( 'WP_LOCAL_DEV' ),
197
  );
198
+ $this->data['wp']['constants'] = apply_filters( 'qm/environment-constants', $constants );
199
 
200
  if ( is_multisite() ) {
201
  $this->data['wp']['constants']['SUNRISE'] = self::format_bool_constant( 'SUNRISE' );
261
  $php_u = null;
262
 
263
  if ( function_exists( 'posix_getpwuid' ) ) {
264
+ $u = posix_getpwuid( posix_getuid() );
265
+ $g = posix_getgrgid( $u['gid'] );
266
  $php_u = $u['name'] . ':' . $g['name'];
267
  }
268
 
269
+ if ( empty( $php_u ) && isset( $_ENV['APACHE_RUN_USER'] ) ) {
270
  $php_u = $_ENV['APACHE_RUN_USER'];
271
  if ( isset( $_ENV['APACHE_RUN_GROUP'] ) ) {
272
  $php_u .= ':' . $_ENV['APACHE_RUN_GROUP'];
273
  }
274
  }
275
 
276
+ if ( empty( $php_u ) && isset( $_SERVER['USER'] ) ) { // WPCS: input var ok
277
  $php_u = wp_unslash( $_SERVER['USER'] ); // WPCS: sanitization ok, input var ok
278
  }
279
 
280
+ if ( empty( $php_u ) && function_exists( 'exec' ) ) {
281
  $php_u = exec( 'whoami' ); // @codingStandardsIgnoreLine
282
  }
283
 
284
+ if ( empty( $php_u ) && function_exists( 'getenv' ) ) {
285
  $php_u = getenv( 'USERNAME' );
286
  }
287
 
292
  }
293
 
294
  function register_qm_collector_environment( array $collectors, QueryMonitor $qm ) {
295
+ $collectors['environment'] = new QM_Collector_Environment();
296
  return $collectors;
297
  }
298
 
collectors/hooks.php CHANGED
@@ -39,13 +39,13 @@ class QM_Collector_Hooks extends QM_Collector {
39
 
40
  $hooks[ $name ] = self::process_action( $name, $wp_filter, self::$hide_qm, self::$hide_core );
41
 
42
- $all_parts = array_merge( $all_parts, $hooks[ $name ]['parts'] );
43
- $components = array_merge( $components, $hooks[ $name ]['components'] );
44
 
45
  }
46
 
47
- $this->data['hooks'] = $hooks;
48
- $this->data['parts'] = array_unique( array_filter( $all_parts ) );
49
  $this->data['components'] = array_unique( array_filter( $components ) );
50
 
51
  }
@@ -90,8 +90,8 @@ class QM_Collector_Hooks extends QM_Collector {
90
  unset( $callback['function'] );
91
 
92
  $actions[] = array(
93
- 'priority' => $priority,
94
- 'callback' => $callback,
95
  );
96
 
97
  }
@@ -112,4 +112,4 @@ class QM_Collector_Hooks extends QM_Collector {
112
  }
113
 
114
  # Load early to catch all hooks
115
- QM_Collectors::add( new QM_Collector_Hooks );
39
 
40
  $hooks[ $name ] = self::process_action( $name, $wp_filter, self::$hide_qm, self::$hide_core );
41
 
42
+ $all_parts = array_merge( $all_parts, $hooks[ $name ]['parts'] );
43
+ $components = array_merge( $components, $hooks[ $name ]['components'] );
44
 
45
  }
46
 
47
+ $this->data['hooks'] = $hooks;
48
+ $this->data['parts'] = array_unique( array_filter( $all_parts ) );
49
  $this->data['components'] = array_unique( array_filter( $components ) );
50
 
51
  }
90
  unset( $callback['function'] );
91
 
92
  $actions[] = array(
93
+ 'priority' => $priority,
94
+ 'callback' => $callback,
95
  );
96
 
97
  }
112
  }
113
 
114
  # Load early to catch all hooks
115
+ QM_Collectors::add( new QM_Collector_Hooks() );
collectors/http.php CHANGED
@@ -7,9 +7,9 @@
7
 
8
  class QM_Collector_HTTP extends QM_Collector {
9
 
10
- public $id = 'http';
11
  private $transport = null;
12
- private $info = null;
13
 
14
  public function name() {
15
  return __( 'HTTP API Requests', 'query-monitor' );
@@ -40,23 +40,23 @@ class QM_Collector_HTTP extends QM_Collector {
40
  * @return array HTTP request arguments.
41
  */
42
  public function filter_http_request_args( array $args, $url ) {
43
- $trace = new QM_Backtrace;
44
  if ( isset( $args['_qm_key'] ) ) {
45
  // Something has triggered another HTTP request from within the `pre_http_request` filter
46
  // (eg. WordPress Beta Tester does this). This allows for one level of nested queries.
47
  $args['_qm_original_key'] = $args['_qm_key'];
48
- $start = $this->data['http'][ $args['_qm_key'] ]['start'];
49
  } else {
50
  $start = microtime( true );
51
  }
52
- $key = microtime( true ) . $url;
53
  $this->data['http'][ $key ] = array(
54
  'url' => $url,
55
  'args' => $args,
56
  'start' => $start,
57
  'trace' => $trace,
58
  );
59
- $args['_qm_key'] = $key;
60
  return $args;
61
  }
62
 
@@ -155,7 +155,7 @@ class QM_Collector_HTTP extends QM_Collector {
155
 
156
  $this->data['http'][ $args['_qm_key'] ]['info'] = $this->info;
157
  $this->data['http'][ $args['_qm_key'] ]['transport'] = $this->transport;
158
- $this->info = null;
159
  $this->transport = null;
160
  }
161
 
@@ -170,7 +170,7 @@ class QM_Collector_HTTP extends QM_Collector {
170
  'WP_HTTP_BLOCK_EXTERNAL',
171
  'WP_ACCESSIBLE_HOSTS',
172
  ) as $var ) {
173
- if ( defined( $var ) and constant( $var ) ) {
174
  $val = constant( $var );
175
  if ( true === $val ) {
176
  # @TODO this transformation should happen in the output, not the collector
@@ -186,6 +186,13 @@ class QM_Collector_HTTP extends QM_Collector {
186
  return;
187
  }
188
 
 
 
 
 
 
 
 
189
  $silent = apply_filters( 'qm/collect/silent_http_errors', array(
190
  'http_request_not_executed',
191
  'airplane_mode_enabled',
@@ -242,4 +249,4 @@ class QM_Collector_HTTP extends QM_Collector {
242
  }
243
 
244
  # Load early in case a plugin is doing an HTTP request when it initialises instead of after the `plugins_loaded` hook
245
- QM_Collectors::add( new QM_Collector_HTTP );
7
 
8
  class QM_Collector_HTTP extends QM_Collector {
9
 
10
+ public $id = 'http';
11
  private $transport = null;
12
+ private $info = null;
13
 
14
  public function name() {
15
  return __( 'HTTP API Requests', 'query-monitor' );
40
  * @return array HTTP request arguments.
41
  */
42
  public function filter_http_request_args( array $args, $url ) {
43
+ $trace = new QM_Backtrace();
44
  if ( isset( $args['_qm_key'] ) ) {
45
  // Something has triggered another HTTP request from within the `pre_http_request` filter
46
  // (eg. WordPress Beta Tester does this). This allows for one level of nested queries.
47
  $args['_qm_original_key'] = $args['_qm_key'];
48
+ $start = $this->data['http'][ $args['_qm_key'] ]['start'];
49
  } else {
50
  $start = microtime( true );
51
  }
52
+ $key = microtime( true ) . $url;
53
  $this->data['http'][ $key ] = array(
54
  'url' => $url,
55
  'args' => $args,
56
  'start' => $start,
57
  'trace' => $trace,
58
  );
59
+ $args['_qm_key'] = $key;
60
  return $args;
61
  }
62
 
155
 
156
  $this->data['http'][ $args['_qm_key'] ]['info'] = $this->info;
157
  $this->data['http'][ $args['_qm_key'] ]['transport'] = $this->transport;
158
+ $this->info = null;
159
  $this->transport = null;
160
  }
161
 
170
  'WP_HTTP_BLOCK_EXTERNAL',
171
  'WP_ACCESSIBLE_HOSTS',
172
  ) as $var ) {
173
+ if ( defined( $var ) && constant( $var ) ) {
174
  $val = constant( $var );
175
  if ( true === $val ) {
176
  # @TODO this transformation should happen in the output, not the collector
186
  return;
187
  }
188
 
189
+ /**
190
+ * List of HTTP API error codes to ignore.
191
+ *
192
+ * @since 2.7.0
193
+ *
194
+ * @param array $http_errors Array of HTTP errors.
195
+ */
196
  $silent = apply_filters( 'qm/collect/silent_http_errors', array(
197
  'http_request_not_executed',
198
  'airplane_mode_enabled',
249
  }
250
 
251
  # Load early in case a plugin is doing an HTTP request when it initialises instead of after the `plugins_loaded` hook
252
+ QM_Collectors::add( new QM_Collector_HTTP() );
collectors/languages.php CHANGED
@@ -40,7 +40,7 @@ class QM_Collector_Languages extends QM_Collector {
40
  return $override;
41
  }
42
 
43
- $trace = new QM_Backtrace;
44
  $filtered = $trace->get_filtered_trace();
45
  $caller = array();
46
 
@@ -89,4 +89,4 @@ class QM_Collector_Languages extends QM_Collector {
89
  }
90
 
91
  # Load early to catch early errors
92
- QM_Collectors::add( new QM_Collector_Languages );
40
  return $override;
41
  }
42
 
43
+ $trace = new QM_Backtrace();
44
  $filtered = $trace->get_filtered_trace();
45
  $caller = array();
46
 
89
  }
90
 
91
  # Load early to catch early errors
92
+ QM_Collectors::add( new QM_Collector_Languages() );
collectors/logger.php CHANGED
@@ -119,7 +119,7 @@ class QM_Collector_Logger extends QM_Collector {
119
  $components = array();
120
 
121
  foreach ( $this->data['logs'] as $row ) {
122
- $component = $row['trace']->get_component();
123
  $components[ $component->name ] = $component->name;
124
  }
125
 
@@ -152,4 +152,4 @@ class QM_Collector_Logger extends QM_Collector {
152
  }
153
 
154
  # Load early in case a plugin wants to log a message early in the bootstrap process
155
- QM_Collectors::add( new QM_Collector_Logger );
119
  $components = array();
120
 
121
  foreach ( $this->data['logs'] as $row ) {
122
+ $component = $row['trace']->get_component();
123
  $components[ $component->name ] = $component->name;
124
  }
125
 
152
  }
153
 
154
  # Load early in case a plugin wants to log a message early in the bootstrap process
155
+ QM_Collectors::add( new QM_Collector_Logger() );
collectors/overview.php CHANGED
@@ -62,7 +62,7 @@ class QM_Collector_Overview extends QM_Collector {
62
  }
63
 
64
  function register_qm_collector_overview( array $collectors, QueryMonitor $qm ) {
65
- $collectors['overview'] = new QM_Collector_Overview;
66
  return $collectors;
67
  }
68
 
62
  }
63
 
64
  function register_qm_collector_overview( array $collectors, QueryMonitor $qm ) {
65
+ $collectors['overview'] = new QM_Collector_Overview();
66
  return $collectors;
67
  }
68
 
collectors/php_errors.php CHANGED
@@ -7,10 +7,10 @@
7
 
8
  class QM_Collector_PHP_Errors extends QM_Collector {
9
 
10
- public $id = 'php_errors';
11
- public $types = array();
12
  private $error_reporting = null;
13
- private $display_errors = null;
14
  private static $unexpected_error;
15
  private static $wordpress_couldnt;
16
 
@@ -19,7 +19,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
19
  }
20
 
21
  public function __construct() {
22
- if ( defined( 'QM_DISABLE_ERROR_HANDLER' ) and QM_DISABLE_ERROR_HANDLER ) {
23
  return;
24
  }
25
 
@@ -28,13 +28,24 @@ class QM_Collector_PHP_Errors extends QM_Collector {
28
  register_shutdown_function( array( $this, 'shutdown_handler' ) );
29
 
30
  $this->error_reporting = error_reporting();
31
- $this->display_errors = ini_get( 'display_errors' );
32
  ini_set( 'display_errors', 0 );
33
 
34
  }
35
 
36
  public function error_handler( $errno, $message, $file = null, $line = null, $context = null ) {
37
 
 
 
 
 
 
 
 
 
 
 
 
38
  do_action( 'qm/collect/new_php_error', $errno, $message, $file, $line, $context );
39
 
40
  switch ( $errno ) {
@@ -78,8 +89,8 @@ class QM_Collector_PHP_Errors extends QM_Collector {
78
  if ( ! isset( self::$unexpected_error ) ) {
79
  // These strings are from core. They're passed through `__()` as variables so they get translated at runtime
80
  // but do not get seen by GlotPress when it populates its database of translatable strings for QM.
81
- $unexpected_error = 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.';
82
- $wordpress_couldnt = '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)';
83
  self::$unexpected_error = call_user_func( '__', $unexpected_error );
84
  self::$wordpress_couldnt = call_user_func( '__', $wordpress_couldnt );
85
  }
@@ -114,6 +125,14 @@ class QM_Collector_PHP_Errors extends QM_Collector {
114
  );
115
  }
116
 
 
 
 
 
 
 
 
 
117
  return apply_filters( 'qm/collect/php_errors_return_value', false );
118
 
119
  }
@@ -126,7 +145,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
126
  return;
127
  }
128
 
129
- if ( empty( $e ) or ! ( $e['type'] & ( E_ERROR | E_PARSE | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_RECOVERABLE_ERROR ) ) ) {
130
  return;
131
  }
132
 
@@ -176,7 +195,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
176
  */
177
  public function process() {
178
  $this->types = array(
179
- 'errors' => array(
180
  'warning' => _x( 'Warning', 'PHP error level', 'query-monitor' ),
181
  'notice' => _x( 'Notice', 'PHP error level', 'query-monitor' ),
182
  'strict' => _x( 'Strict', 'PHP error level', 'query-monitor' ),
@@ -188,14 +207,14 @@ class QM_Collector_PHP_Errors extends QM_Collector {
188
  'strict' => _x( 'Strict (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
189
  'deprecated' => _x( 'Deprecated (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
190
  ),
191
- 'silenced' => array(
192
  'warning' => _x( 'Warning (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
193
  'notice' => _x( 'Notice (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
194
  'strict' => _x( 'Strict (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
195
  'deprecated' => _x( 'Deprecated (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
196
  ),
197
  );
198
- $components = array();
199
 
200
  if ( ! empty( $this->data ) && ! empty( $this->data['errors'] ) ) {
201
  /**
@@ -232,6 +251,8 @@ class QM_Collector_PHP_Errors extends QM_Collector {
232
  * to silence all errors from a component. See the PHP documentation on error
233
  * reporting for more info: http://php.net/manual/en/function.error-reporting.php
234
  *
 
 
235
  * @param int[] $levels The error levels used for each component.
236
  */
237
  $levels = apply_filters( 'qm/collect/php_error_levels', array() );
@@ -243,6 +264,8 @@ class QM_Collector_PHP_Errors extends QM_Collector {
243
  *
244
  * add_filter( 'qm/collect/hide_silenced_php_errors', '__return_true' );
245
  *
 
 
246
  * @param bool $hide Whether to hide silenced PHP errors. Default false.
247
  */
248
  $this->hide_silenced_php_errors = apply_filters( 'qm/collect/hide_silenced_php_errors', false );
@@ -253,7 +276,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
253
  foreach ( $error_types as $type => $title ) {
254
  if ( isset( $this->data[ $error_group ][ $type ] ) ) {
255
  foreach ( $this->data[ $error_group ][ $type ] as $error ) {
256
- $component = $error['trace']->get_component();
257
  $components[ $component->name ] = $component->name;
258
  }
259
  }
@@ -355,4 +378,4 @@ class QM_Collector_PHP_Errors extends QM_Collector {
355
  }
356
 
357
  # Load early to catch early errors
358
- QM_Collectors::add( new QM_Collector_PHP_Errors );
7
 
8
  class QM_Collector_PHP_Errors extends QM_Collector {
9
 
10
+ public $id = 'php_errors';
11
+ public $types = array();
12
  private $error_reporting = null;
13
+ private $display_errors = null;
14
  private static $unexpected_error;
15
  private static $wordpress_couldnt;
16
 
19
  }
20
 
21
  public function __construct() {
22
+ if ( defined( 'QM_DISABLE_ERROR_HANDLER' ) && QM_DISABLE_ERROR_HANDLER ) {
23
  return;
24
  }
25
 
28
  register_shutdown_function( array( $this, 'shutdown_handler' ) );
29
 
30
  $this->error_reporting = error_reporting();
31
+ $this->display_errors = ini_get( 'display_errors' );
32
  ini_set( 'display_errors', 0 );
33
 
34
  }
35
 
36
  public function error_handler( $errno, $message, $file = null, $line = null, $context = null ) {
37
 
38
+ /**
39
+ * Fires before logging the PHP error in Query Monitor.
40
+ *
41
+ * @since 2.7.0
42
+ *
43
+ * @param int $errno The error number.
44
+ * @param string $message The error message.
45
+ * @param string $file The file location.
46
+ * @param string $line The line number.
47
+ * @param string $context The context being passed.
48
+ */
49
  do_action( 'qm/collect/new_php_error', $errno, $message, $file, $line, $context );
50
 
51
  switch ( $errno ) {
89
  if ( ! isset( self::$unexpected_error ) ) {
90
  // These strings are from core. They're passed through `__()` as variables so they get translated at runtime
91
  // but do not get seen by GlotPress when it populates its database of translatable strings for QM.
92
+ $unexpected_error = 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.';
93
+ $wordpress_couldnt = '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)';
94
  self::$unexpected_error = call_user_func( '__', $unexpected_error );
95
  self::$wordpress_couldnt = call_user_func( '__', $wordpress_couldnt );
96
  }
125
  );
126
  }
127
 
128
+ /**
129
+ * Filters the PHP error handler return value. This can be used to control whether or not additional error
130
+ * handlers are called after Query Monitor's.
131
+ *
132
+ * @since 2.7.0
133
+ *
134
+ * @param bool $return_value Error handler return value. Default true.
135
+ */
136
  return apply_filters( 'qm/collect/php_errors_return_value', false );
137
 
138
  }
145
  return;
146
  }
147
 
148
+ if ( empty( $e ) || ! ( $e['type'] & ( E_ERROR | E_PARSE | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_RECOVERABLE_ERROR ) ) ) {
149
  return;
150
  }
151
 
195
  */
196
  public function process() {
197
  $this->types = array(
198
+ 'errors' => array(
199
  'warning' => _x( 'Warning', 'PHP error level', 'query-monitor' ),
200
  'notice' => _x( 'Notice', 'PHP error level', 'query-monitor' ),
201
  'strict' => _x( 'Strict', 'PHP error level', 'query-monitor' ),
207
  'strict' => _x( 'Strict (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
208
  'deprecated' => _x( 'Deprecated (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
209
  ),
210
+ 'silenced' => array(
211
  'warning' => _x( 'Warning (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
212
  'notice' => _x( 'Notice (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
213
  'strict' => _x( 'Strict (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
214
  'deprecated' => _x( 'Deprecated (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
215
  ),
216
  );
217
+ $components = array();
218
 
219
  if ( ! empty( $this->data ) && ! empty( $this->data['errors'] ) ) {
220
  /**
251
  * to silence all errors from a component. See the PHP documentation on error
252
  * reporting for more info: http://php.net/manual/en/function.error-reporting.php
253
  *
254
+ * @since 2.7.0
255
+ *
256
  * @param int[] $levels The error levels used for each component.
257
  */
258
  $levels = apply_filters( 'qm/collect/php_error_levels', array() );
264
  *
265
  * add_filter( 'qm/collect/hide_silenced_php_errors', '__return_true' );
266
  *
267
+ * @since 2.7.0
268
+ *
269
  * @param bool $hide Whether to hide silenced PHP errors. Default false.
270
  */
271
  $this->hide_silenced_php_errors = apply_filters( 'qm/collect/hide_silenced_php_errors', false );
276
  foreach ( $error_types as $type => $title ) {
277
  if ( isset( $this->data[ $error_group ][ $type ] ) ) {
278
  foreach ( $this->data[ $error_group ][ $type ] as $error ) {
279
+ $component = $error['trace']->get_component();
280
  $components[ $component->name ] = $component->name;
281
  }
282
  }
378
  }
379
 
380
  # Load early to catch early errors
381
+ QM_Collectors::add( new QM_Collector_PHP_Errors() );
collectors/redirects.php CHANGED
@@ -24,7 +24,7 @@ class QM_Collector_Redirects extends QM_Collector {
24
  return $location;
25
  }
26
 
27
- $trace = new QM_Backtrace;
28
 
29
  $this->data['trace'] = $trace;
30
  $this->data['location'] = $location;
@@ -37,4 +37,4 @@ class QM_Collector_Redirects extends QM_Collector {
37
  }
38
 
39
  # Load early in case a plugin is doing a redirect when it initialises instead of after the `plugins_loaded` hook
40
- QM_Collectors::add( new QM_Collector_Redirects );
24
  return $location;
25
  }
26
 
27
+ $trace = new QM_Backtrace();
28
 
29
  $this->data['trace'] = $trace;
30
  $this->data['location'] = $location;
37
  }
38
 
39
  # Load early in case a plugin is doing a redirect when it initialises instead of after the `plugins_loaded` hook
40
+ QM_Collectors::add( new QM_Collector_Redirects() );
collectors/request.php CHANGED
@@ -17,7 +17,7 @@ class QM_Collector_Request extends QM_Collector {
17
 
18
  global $wp, $wp_query, $current_blog, $current_site, $wp_rewrite;
19
 
20
- $qo = get_queried_object();
21
  $user = wp_get_current_user();
22
 
23
  if ( $user->exists() ) {
@@ -76,6 +76,7 @@ class QM_Collector_Request extends QM_Collector {
76
  }
77
  }
78
 
 
79
  $plugin_qvars = array_flip( apply_filters( 'query_vars', array() ) );
80
  $qvars = $wp_query->query_vars;
81
  $query_vars = array();
@@ -97,7 +98,7 @@ class QM_Collector_Request extends QM_Collector {
97
  # First add plugin vars to $this->data['qvars']:
98
  foreach ( $query_vars as $k => $v ) {
99
  if ( isset( $plugin_qvars[ $k ] ) ) {
100
- $this->data['qvars'][ $k ] = $v;
101
  $this->data['plugin_qvars'][ $k ] = $v;
102
  }
103
  }
@@ -189,7 +190,7 @@ class QM_Collector_Request extends QM_Collector {
189
  }
190
 
191
  function register_qm_collector_request( array $collectors, QueryMonitor $qm ) {
192
- $collectors['request'] = new QM_Collector_Request;
193
  return $collectors;
194
  }
195
 
17
 
18
  global $wp, $wp_query, $current_blog, $current_site, $wp_rewrite;
19
 
20
+ $qo = get_queried_object();
21
  $user = wp_get_current_user();
22
 
23
  if ( $user->exists() ) {
76
  }
77
  }
78
 
79
+ /** This filter is documented in wp-includes/class-wp.php */
80
  $plugin_qvars = array_flip( apply_filters( 'query_vars', array() ) );
81
  $qvars = $wp_query->query_vars;
82
  $query_vars = array();
98
  # First add plugin vars to $this->data['qvars']:
99
  foreach ( $query_vars as $k => $v ) {
100
  if ( isset( $plugin_qvars[ $k ] ) ) {
101
+ $this->data['qvars'][ $k ] = $v;
102
  $this->data['plugin_qvars'][ $k ] = $v;
103
  }
104
  }
190
  }
191
 
192
  function register_qm_collector_request( array $collectors, QueryMonitor $qm ) {
193
+ $collectors['request'] = new QM_Collector_Request();
194
  return $collectors;
195
  }
196
 
collectors/theme.php CHANGED
@@ -7,7 +7,7 @@
7
 
8
  class QM_Collector_Theme extends QM_Collector {
9
 
10
- public $id = 'response';
11
  protected $got_theme_compat = false;
12
 
13
  public function name() {
@@ -103,13 +103,43 @@ class QM_Collector_Theme extends QM_Collector {
103
 
104
  public function process() {
105
 
106
- if ( ! empty( $this->data['template_path'] ) ) {
 
 
107
 
108
- $template_path = QM_Util::standard_dir( $this->data['template_path'] );
109
- $stylesheet_directory = QM_Util::standard_dir( get_stylesheet_directory() );
110
- $template_directory = QM_Util::standard_dir( get_template_directory() );
111
- $theme_directory = QM_Util::standard_dir( get_theme_root() );
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  $template_file = str_replace( array( $stylesheet_directory, $template_directory, ABSPATH ), '', $template_path );
114
  $template_file = ltrim( $template_file, '/' );
115
  $theme_template_file = str_replace( array( $theme_directory, ABSPATH ), '', $template_path );
@@ -118,35 +148,11 @@ class QM_Collector_Theme extends QM_Collector {
118
  $this->data['template_path'] = $template_path;
119
  $this->data['template_file'] = $template_file;
120
  $this->data['theme_template_file'] = $theme_template_file;
121
- $this->data['template_hierarchy'] = array_unique( $this->data['template_hierarchy'] );
122
-
123
- foreach ( get_included_files() as $file ) {
124
- $file = QM_Util::standard_dir( $file );
125
- $filename = str_replace( array(
126
- $stylesheet_directory,
127
- $template_directory,
128
- ), '', $file );
129
- if ( $filename !== $file ) {
130
- $slug = trim( str_replace( '.php', '', $filename ), '/' );
131
- $display = trim( $filename, '/' );
132
- $theme_display = trim( str_replace( $theme_directory, '', $file ), '/' );
133
- if ( did_action( "get_template_part_{$slug}" ) ) {
134
- $this->data['template_parts'][ $file ] = $display;
135
- $this->data['theme_template_parts'][ $file ] = $theme_display;
136
- } else {
137
- $slug = trim( preg_replace( '|\-[^\-]+$|', '', $slug ), '/' );
138
- if ( did_action( "get_template_part_{$slug}" ) ) {
139
- $this->data['template_parts'][ $file ] = $display;
140
- $this->data['theme_template_parts'][ $file ] = $theme_display;
141
- }
142
- }
143
- }
144
- }
145
  }
146
 
147
- $this->data['stylesheet'] = get_stylesheet();
148
- $this->data['template'] = get_template();
149
- $this->data['is_child_theme'] = ( $this->data['stylesheet'] !== $this->data['template'] );
150
 
151
  if ( isset( $this->data['body_class'] ) ) {
152
  asort( $this->data['body_class'] );
@@ -157,7 +163,7 @@ class QM_Collector_Theme extends QM_Collector {
157
  }
158
 
159
  function register_qm_collector_theme( array $collectors, QueryMonitor $qm ) {
160
- $collectors['response'] = new QM_Collector_Theme;
161
  return $collectors;
162
  }
163
 
7
 
8
  class QM_Collector_Theme extends QM_Collector {
9
 
10
+ public $id = 'response';
11
  protected $got_theme_compat = false;
12
 
13
  public function name() {
103
 
104
  public function process() {
105
 
106
+ $stylesheet_directory = QM_Util::standard_dir( get_stylesheet_directory() );
107
+ $template_directory = QM_Util::standard_dir( get_template_directory() );
108
+ $theme_directory = QM_Util::standard_dir( get_theme_root() );
109
 
110
+ if ( isset( $this->data['template_hierarchy'] ) ) {
111
+ $this->data['template_hierarchy'] = array_unique( $this->data['template_hierarchy'] );
112
+ }
 
113
 
114
+ foreach ( get_included_files() as $file ) {
115
+ $file = QM_Util::standard_dir( $file );
116
+ $filename = str_replace( array(
117
+ $stylesheet_directory,
118
+ $template_directory,
119
+ ), '', $file );
120
+ if ( $filename !== $file ) {
121
+ $slug = trim( str_replace( '.php', '', $filename ), '/' );
122
+ $display = trim( $filename, '/' );
123
+ $theme_display = trim( str_replace( $theme_directory, '', $file ), '/' );
124
+ $count = did_action( "get_template_part_{$slug}" );
125
+ if ( $count ) {
126
+ $this->data['template_parts'][ $file ] = $display;
127
+ $this->data['theme_template_parts'][ $file ] = $theme_display;
128
+ $this->data['count_template_parts'][ $file ] = $count;
129
+ } else {
130
+ $slug = trim( preg_replace( '|\-[^\-]+$|', '', $slug ), '/' );
131
+ $count = did_action( "get_template_part_{$slug}" );
132
+ if ( $count ) {
133
+ $this->data['template_parts'][ $file ] = $display;
134
+ $this->data['theme_template_parts'][ $file ] = $theme_display;
135
+ $this->data['count_template_parts'][ $file ] = $count;
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ if ( ! empty( $this->data['template_path'] ) ) {
142
+ $template_path = QM_Util::standard_dir( $this->data['template_path'] );
143
  $template_file = str_replace( array( $stylesheet_directory, $template_directory, ABSPATH ), '', $template_path );
144
  $template_file = ltrim( $template_file, '/' );
145
  $theme_template_file = str_replace( array( $theme_directory, ABSPATH ), '', $template_path );
148
  $this->data['template_path'] = $template_path;
149
  $this->data['template_file'] = $template_file;
150
  $this->data['theme_template_file'] = $theme_template_file;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
152
 
153
+ $this->data['stylesheet'] = get_stylesheet();
154
+ $this->data['template'] = get_template();
155
+ $this->data['is_child_theme'] = ( $this->data['stylesheet'] !== $this->data['template'] );
156
 
157
  if ( isset( $this->data['body_class'] ) ) {
158
  asort( $this->data['body_class'] );
163
  }
164
 
165
  function register_qm_collector_theme( array $collectors, QueryMonitor $qm ) {
166
+ $collectors['response'] = new QM_Collector_Theme();
167
  return $collectors;
168
  }
169
 
collectors/timing.php CHANGED
@@ -7,11 +7,11 @@
7
 
8
  class QM_Collector_Timing extends QM_Collector {
9
 
10
- public $id = 'timing';
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' );
@@ -25,17 +25,17 @@ class QM_Collector_Timing extends QM_Collector {
25
  }
26
 
27
  public function action_function_time_start( $function ) {
28
- $this->track_timer[ $function ] = new QM_Timer;
29
- $this->start[ $function ] = $this->track_timer[ $function ]->start();
30
  }
31
 
32
  public function action_function_time_stop( $function ) {
33
  if ( ! isset( $this->track_timer[ $function ] ) ) {
34
- $trace = new QM_Backtrace;
35
  $this->data['warning'][] = array(
36
- 'function' => $function,
37
- 'message' => __( 'Timer not started', 'query-monitor' ),
38
- 'trace' => $trace,
39
  );
40
  return;
41
  }
@@ -45,11 +45,11 @@ class QM_Collector_Timing extends QM_Collector {
45
 
46
  public function action_function_time_lap( $function, $name = null ) {
47
  if ( ! isset( $this->track_timer[ $function ] ) ) {
48
- $trace = new QM_Backtrace;
49
  $this->data['warning'][] = array(
50
- 'function' => $function,
51
- 'message' => __( 'Timer not started', 'query-monitor' ),
52
- 'trace' => $trace,
53
  );
54
  return;
55
  }
@@ -74,11 +74,11 @@ class QM_Collector_Timing extends QM_Collector {
74
  public function process() {
75
  foreach ( $this->start as $function => $value ) {
76
  if ( ! isset( $this->stop[ $function ] ) ) {
77
- $trace = $this->track_timer[ $function ]->get_trace();
78
  $this->data['warning'][] = array(
79
- 'function' => $function,
80
- 'message' => __( 'Timer not stopped', 'query-monitor' ),
81
- 'trace' => $trace,
82
  );
83
  }
84
  }
@@ -87,4 +87,4 @@ class QM_Collector_Timing extends QM_Collector {
87
  }
88
 
89
  # Load early in case a plugin is setting the function to be checked when it initialises instead of after the `plugins_loaded` hook
90
- QM_Collectors::add( new QM_Collector_Timing );
7
 
8
  class QM_Collector_Timing extends QM_Collector {
9
 
10
+ public $id = 'timing';
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' );
25
  }
26
 
27
  public function action_function_time_start( $function ) {
28
+ $this->track_timer[ $function ] = new QM_Timer();
29
+ $this->start[ $function ] = $this->track_timer[ $function ]->start();
30
  }
31
 
32
  public function action_function_time_stop( $function ) {
33
  if ( ! isset( $this->track_timer[ $function ] ) ) {
34
+ $trace = new QM_Backtrace();
35
  $this->data['warning'][] = array(
36
+ 'function' => $function,
37
+ 'message' => __( 'Timer not started', 'query-monitor' ),
38
+ 'trace' => $trace,
39
  );
40
  return;
41
  }
45
 
46
  public function action_function_time_lap( $function, $name = null ) {
47
  if ( ! isset( $this->track_timer[ $function ] ) ) {
48
+ $trace = new QM_Backtrace();
49
  $this->data['warning'][] = array(
50
+ 'function' => $function,
51
+ 'message' => __( 'Timer not started', 'query-monitor' ),
52
+ 'trace' => $trace,
53
  );
54
  return;
55
  }
74
  public function process() {
75
  foreach ( $this->start as $function => $value ) {
76
  if ( ! isset( $this->stop[ $function ] ) ) {
77
+ $trace = $this->track_timer[ $function ]->get_trace();
78
  $this->data['warning'][] = array(
79
+ 'function' => $function,
80
+ 'message' => __( 'Timer not stopped', 'query-monitor' ),
81
+ 'trace' => $trace,
82
  );
83
  }
84
  }
87
  }
88
 
89
  # Load early in case a plugin is setting the function to be checked when it initialises instead of after the `plugins_loaded` hook
90
+ QM_Collectors::add( new QM_Collector_Timing() );
collectors/transients.php CHANGED
@@ -50,4 +50,4 @@ class QM_Collector_Transients extends QM_Collector {
50
  }
51
 
52
  # Load early in case a plugin is setting transients when it initialises instead of after the `plugins_loaded` hook
53
- QM_Collectors::add( new QM_Collector_Transients );
50
  }
51
 
52
  # Load early in case a plugin is setting transients when it initialises instead of after the `plugins_loaded` hook
53
+ QM_Collectors::add( new QM_Collector_Transients() );
composer.json CHANGED
@@ -38,10 +38,11 @@
38
  "composer/installers": "~1.0"
39
  },
40
  "require-dev" : {
 
41
  "squizlabs/php_codesniffer": "^3.2",
42
- "phpcompatibility/php-compatibility": "~8.2",
43
  "danieltj27/dark-mode": "3.1.1",
44
- "wp-coding-standards/wpcs": "0.13",
45
  "phpunit/phpunit": "^5"
46
  }
47
  }
38
  "composer/installers": "~1.0"
39
  },
40
  "require-dev" : {
41
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
42
  "squizlabs/php_codesniffer": "^3.2",
43
+ "phpcompatibility/phpcompatibility-wp": "^2.0",
44
  "danieltj27/dark-mode": "3.1.1",
45
+ "wp-coding-standards/wpcs": "^1.2",
46
  "phpunit/phpunit": "^5"
47
  }
48
  }
dispatchers/AJAX.php CHANGED
@@ -26,6 +26,7 @@ class QM_Dispatcher_AJAX extends QM_Dispatcher {
26
  ob_start();
27
  }
28
 
 
29
  }
30
 
31
  public function dispatch() {
26
  ob_start();
27
  }
28
 
29
+ parent::init();
30
  }
31
 
32
  public function dispatch() {
dispatchers/Html.php CHANGED
@@ -7,7 +7,7 @@
7
 
8
  class QM_Dispatcher_Html extends QM_Dispatcher {
9
 
10
- public $id = 'html';
11
  public $did_footer = false;
12
 
13
  protected $outputters = array();
@@ -43,12 +43,12 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
43
  * @return bool Should the authentication cookie be secure?
44
  */
45
  public static function secure_cookie() {
46
- return ( is_ssl() and ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) ) );
47
  }
48
 
49
  public function ajax_on() {
50
 
51
- if ( ! current_user_can( 'view_query_monitor' ) or ! check_ajax_referer( 'qm-auth-on', 'nonce', false ) ) {
52
  wp_send_json_error();
53
  }
54
 
@@ -64,7 +64,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
64
 
65
  public function ajax_off() {
66
 
67
- if ( ! self::user_verified() or ! check_ajax_referer( 'qm-auth-off', 'nonce', false ) ) {
68
  wp_send_json_error();
69
  }
70
 
@@ -105,18 +105,14 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
105
  return;
106
  }
107
 
108
- if ( ! defined( 'DONOTCACHEPAGE' ) ) {
109
- define( 'DONOTCACHEPAGE', 1 );
110
- }
111
-
112
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
113
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
114
  add_action( 'login_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
115
  add_action( 'enqueue_embed_scripts', array( $this, 'enqueue_assets' ), -999 );
116
- add_action( 'send_headers', 'nocache_headers' );
117
 
118
  add_action( 'gp_head', array( $this, 'manually_print_assets' ), 11 );
119
 
 
120
  }
121
 
122
  public function manually_print_assets() {
@@ -191,7 +187,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
191
 
192
  /* @var QM_Output_Html[] */
193
  foreach ( $this->outputters as $id => $output ) {
194
- $timer = new QM_Timer;
195
  $timer->start();
196
 
197
  printf(
@@ -223,9 +219,25 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
223
  require_once $file;
224
  }
225
 
226
- $this->outputters = $this->get_outputters( 'html' );
 
 
 
 
 
 
 
 
227
  $this->admin_bar_menu = apply_filters( 'qm/output/menus', array() );
228
- $this->panel_menu = apply_filters( 'qm/output/panel_menus', $this->admin_bar_menu );
 
 
 
 
 
 
 
 
229
 
230
  $class = array(
231
  'qm-no-js',
@@ -276,12 +288,11 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
276
 
277
  echo '</div>';
278
  echo '<div class="qm-title-button"><button class="qm-button-container-settings"><span class="screen-reader-text">' . esc_html__( 'Settings', 'query-monitor' ) . '</span><span class="dashicons dashicons-admin-generic" aria-hidden="true"></span></button></div>';
279
- echo '<div class="qm-title-button"><button class="qm-button-container-pin"><span class="screen-reader-text">' . esc_html__( 'Pin Panel Open', 'query-monitor' ) . '</span><span class="dashicons dashicons-admin-post" aria-hidden="true"></span></button></div>';
280
  echo '<div class="qm-title-button"><button class="qm-button-container-close"><span class="screen-reader-text">' . esc_html__( 'Close Panel', 'query-monitor' ) . '</span><span class="dashicons dashicons-no-alt" aria-hidden="true"></span></button></div>';
281
  echo '</div>'; // #qm-title
282
 
283
  echo '<div id="qm-wrapper">';
284
- echo '<div id="qm-panel-menu" role="navigation" aria-labelledby="qm-panel-menu-caption">';
285
  echo '<h2 class="qm-screen-reader-text" id="qm-panel-menu-caption">' . esc_html__( 'Query Monitor Menu', 'query-monitor' ) . '</h2>';
286
  echo '<ul>';
287
 
@@ -300,7 +311,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
300
  }
301
 
302
  echo '</ul>';
303
- echo '</div>'; // #qm-panel-menu
304
 
305
  echo '<div id="qm-panels">';
306
 
@@ -318,7 +329,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
318
  echo '<h2 class="qm-screen-reader-text">' . esc_html__( 'Settings', 'query-monitor' ) . '</h2>';
319
 
320
  echo '<div class="qm-boxed">';
321
- echo '<div class="qm-section">';
322
  echo '<h3>' . esc_html__( 'Authentication', 'query-monitor' ) . '</h3>';
323
 
324
  echo '<p>' . esc_html__( 'You can set an authentication cookie which allows you to view Query Monitor output when you&rsquo;re not logged in, or when you&rsquo;re logged in as a different user.', 'query-monitor' ) . '</p>';
@@ -326,15 +337,15 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
326
  echo '<p data-qm-state-visibility="on"><span class="dashicons dashicons-yes qm-dashicons-yes"></span> ' . esc_html__( 'Authentication cookie is set', 'query-monitor' ) . '</p>';
327
 
328
  echo '<p><button class="qm-auth qm-button" data-qm-text-on="' . esc_attr( $text['on'] ) . '" data-qm-text-off="' . esc_attr( $text['off'] ) . '">' . esc_html( $text[ $state ] ) . '</button></p>';
329
- echo '</div>';
330
 
331
  $constants = array(
332
- 'QM_DB_EXPENSIVE' => array(
333
  /* translators: %s: The default value for a PHP constant */
334
  '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' ),
335
  'default' => 0.05,
336
  ),
337
- 'QM_DISABLED' => array(
338
  'label' => __( 'Disable Query Monitor entirely.', 'query-monitor' ),
339
  'default' => false,
340
  ),
@@ -342,29 +353,29 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
342
  'label' => __( 'Disable the handling of PHP errors.', 'query-monitor' ),
343
  'default' => false,
344
  ),
345
- 'QM_ENABLE_CAPS_PANEL' => array(
346
  'label' => __( 'Enable the Capability Checks panel.', 'query-monitor' ),
347
  'default' => false,
348
  ),
349
- 'QM_HIDE_CORE_ACTIONS' => array(
350
  'label' => __( 'Hide WordPress core on the Hooks & Actions panel.', 'query-monitor' ),
351
  'default' => false,
352
  ),
353
- 'QM_HIDE_SELF' => array(
354
  'label' => __( 'Hide Query Monitor itself from various panels.', 'query-monitor' ),
355
  'default' => false,
356
  ),
357
- 'QM_NO_JQUERY' => array(
358
  'label' => __( 'Don\'t specify jQuery as a dependency of Query Monitor. If jQuery isn\'t enqueued then Query Monitor will still operate, but with some reduced functionality.', 'query-monitor' ),
359
  'default' => false,
360
  ),
361
- 'QM_SHOW_ALL_HOOKS' => array(
362
  'label' => __( 'In the Hooks & Actions panel, show every hook that has an action or filter attached (instead of every action hook that fired during the request).', 'query-monitor' ),
363
  'default' => false,
364
  ),
365
  );
366
 
367
- echo '<div class="qm-section">';
368
  echo '<h3>' . esc_html__( 'Configuration', 'query-monitor' ) . '</h3>';
369
  echo '<p>';
370
  printf(
@@ -404,12 +415,20 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
404
  }
405
 
406
  echo '</dl>';
407
- echo '</div>';
408
 
409
  echo '</div>';
410
 
411
  echo '</div>'; // #qm-settings
412
 
 
 
 
 
 
 
 
 
413
  do_action( 'qm/output/after', $this, $this->outputters );
414
 
415
  echo '</div>'; // #qm-panels
@@ -466,12 +485,26 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
466
 
467
  public function js_admin_bar_menu() {
468
 
 
 
 
 
 
 
 
469
  $class = implode( ' ', apply_filters( 'qm/output/menu_class', array() ) );
470
 
471
  if ( false === strpos( $class, 'qm-' ) ) {
472
  $class .= ' qm-all-clear';
473
  }
474
 
 
 
 
 
 
 
 
475
  $title = implode( '&nbsp;&nbsp;&nbsp;', apply_filters( 'qm/output/title', array() ) );
476
 
477
  if ( empty( $title ) ) {
@@ -520,7 +553,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
520
  }
521
  }
522
 
523
- # Back-compat filter. Please use `qm/dispatch/html` instead
524
  if ( ! apply_filters( 'qm/process', true, is_admin_bar_showing() ) ) {
525
  return false;
526
  }
7
 
8
  class QM_Dispatcher_Html extends QM_Dispatcher {
9
 
10
+ public $id = 'html';
11
  public $did_footer = false;
12
 
13
  protected $outputters = array();
43
  * @return bool Should the authentication cookie be secure?
44
  */
45
  public static function secure_cookie() {
46
+ return ( is_ssl() && ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) ) );
47
  }
48
 
49
  public function ajax_on() {
50
 
51
+ if ( ! current_user_can( 'view_query_monitor' ) || ! check_ajax_referer( 'qm-auth-on', 'nonce', false ) ) {
52
  wp_send_json_error();
53
  }
54
 
64
 
65
  public function ajax_off() {
66
 
67
+ if ( ! self::user_verified() || ! check_ajax_referer( 'qm-auth-off', 'nonce', false ) ) {
68
  wp_send_json_error();
69
  }
70
 
105
  return;
106
  }
107
 
 
 
 
 
108
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
109
  add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
110
  add_action( 'login_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
111
  add_action( 'enqueue_embed_scripts', array( $this, 'enqueue_assets' ), -999 );
 
112
 
113
  add_action( 'gp_head', array( $this, 'manually_print_assets' ), 11 );
114
 
115
+ parent::init();
116
  }
117
 
118
  public function manually_print_assets() {
187
 
188
  /* @var QM_Output_Html[] */
189
  foreach ( $this->outputters as $id => $output ) {
190
+ $timer = new QM_Timer();
191
  $timer->start();
192
 
193
  printf(
219
  require_once $file;
220
  }
221
 
222
+ $this->outputters = $this->get_outputters( 'html' );
223
+
224
+ /**
225
+ * Filters the menu items shown in Query Monitor's admin toolbar menu.
226
+ *
227
+ * @since 3.0.0
228
+ *
229
+ * @param array $menus Array of menus.
230
+ */
231
  $this->admin_bar_menu = apply_filters( 'qm/output/menus', array() );
232
+
233
+ /**
234
+ * Filters the menu items shown in the panel navigation menu in Query Monitor's output.
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
 
242
  $class = array(
243
  'qm-no-js',
288
 
289
  echo '</div>';
290
  echo '<div class="qm-title-button"><button class="qm-button-container-settings"><span class="screen-reader-text">' . esc_html__( 'Settings', 'query-monitor' ) . '</span><span class="dashicons dashicons-admin-generic" aria-hidden="true"></span></button></div>';
 
291
  echo '<div class="qm-title-button"><button class="qm-button-container-close"><span class="screen-reader-text">' . esc_html__( 'Close Panel', 'query-monitor' ) . '</span><span class="dashicons dashicons-no-alt" aria-hidden="true"></span></button></div>';
292
  echo '</div>'; // #qm-title
293
 
294
  echo '<div id="qm-wrapper">';
295
+ echo '<nav id="qm-panel-menu" aria-labelledby="qm-panel-menu-caption">';
296
  echo '<h2 class="qm-screen-reader-text" id="qm-panel-menu-caption">' . esc_html__( 'Query Monitor Menu', 'query-monitor' ) . '</h2>';
297
  echo '<ul>';
298
 
311
  }
312
 
313
  echo '</ul>';
314
+ echo '</nav>'; // #qm-panel-menu
315
 
316
  echo '<div id="qm-panels">';
317
 
329
  echo '<h2 class="qm-screen-reader-text">' . esc_html__( 'Settings', 'query-monitor' ) . '</h2>';
330
 
331
  echo '<div class="qm-boxed">';
332
+ echo '<section>';
333
  echo '<h3>' . esc_html__( 'Authentication', 'query-monitor' ) . '</h3>';
334
 
335
  echo '<p>' . esc_html__( 'You can set an authentication cookie which allows you to view Query Monitor output when you&rsquo;re not logged in, or when you&rsquo;re logged in as a different user.', 'query-monitor' ) . '</p>';
337
  echo '<p data-qm-state-visibility="on"><span class="dashicons dashicons-yes qm-dashicons-yes"></span> ' . esc_html__( 'Authentication cookie is set', 'query-monitor' ) . '</p>';
338
 
339
  echo '<p><button class="qm-auth qm-button" data-qm-text-on="' . esc_attr( $text['on'] ) . '" data-qm-text-off="' . esc_attr( $text['off'] ) . '">' . esc_html( $text[ $state ] ) . '</button></p>';
340
+ echo '</section>';
341
 
342
  $constants = array(
343
+ 'QM_DB_EXPENSIVE' => array(
344
  /* translators: %s: The default value for a PHP constant */
345
  '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' ),
346
  'default' => 0.05,
347
  ),
348
+ 'QM_DISABLED' => array(
349
  'label' => __( 'Disable Query Monitor entirely.', 'query-monitor' ),
350
  'default' => false,
351
  ),
353
  'label' => __( 'Disable the handling of PHP errors.', 'query-monitor' ),
354
  'default' => false,
355
  ),
356
+ 'QM_ENABLE_CAPS_PANEL' => array(
357
  'label' => __( 'Enable the Capability Checks panel.', 'query-monitor' ),
358
  'default' => false,
359
  ),
360
+ 'QM_HIDE_CORE_ACTIONS' => array(
361
  'label' => __( 'Hide WordPress core on the Hooks & Actions panel.', 'query-monitor' ),
362
  'default' => false,
363
  ),
364
+ 'QM_HIDE_SELF' => array(
365
  'label' => __( 'Hide Query Monitor itself from various panels.', 'query-monitor' ),
366
  'default' => false,
367
  ),
368
+ 'QM_NO_JQUERY' => array(
369
  'label' => __( 'Don\'t specify jQuery as a dependency of Query Monitor. If jQuery isn\'t enqueued then Query Monitor will still operate, but with some reduced functionality.', 'query-monitor' ),
370
  'default' => false,
371
  ),
372
+ 'QM_SHOW_ALL_HOOKS' => array(
373
  'label' => __( 'In the Hooks & Actions panel, show every hook that has an action or filter attached (instead of every action hook that fired during the request).', 'query-monitor' ),
374
  'default' => false,
375
  ),
376
  );
377
 
378
+ echo '<section>';
379
  echo '<h3>' . esc_html__( 'Configuration', 'query-monitor' ) . '</h3>';
380
  echo '<p>';
381
  printf(
415
  }
416
 
417
  echo '</dl>';
418
+ echo '</section>';
419
 
420
  echo '</div>';
421
 
422
  echo '</div>'; // #qm-settings
423
 
424
+ /**
425
+ * Fires after settings but before the panel closing tag.
426
+ *
427
+ * @since 3.1.0
428
+ *
429
+ * @param QM_Dispatcher_Html $this The HTML dispatcher instance.
430
+ * @param QM_Output[] $this->outputters Array of outputters.
431
+ */
432
  do_action( 'qm/output/after', $this, $this->outputters );
433
 
434
  echo '</div>'; // #qm-panels
485
 
486
  public function js_admin_bar_menu() {
487
 
488
+ /**
489
+ * Filters the CSS class names used on Query Monitor's admin toolbar menu.
490
+ *
491
+ * @since 2.7.0
492
+ *
493
+ * @param array $menu_classes Array of menu classes.
494
+ */
495
  $class = implode( ' ', apply_filters( 'qm/output/menu_class', array() ) );
496
 
497
  if ( false === strpos( $class, 'qm-' ) ) {
498
  $class .= ' qm-all-clear';
499
  }
500
 
501
+ /**
502
+ * Filters the title used in Query Monitor's admin toolbar menu.
503
+ *
504
+ * @since 2.7.0
505
+ *
506
+ * @param array $output_title List of titles.
507
+ */
508
  $title = implode( '&nbsp;&nbsp;&nbsp;', apply_filters( 'qm/output/title', array() ) );
509
 
510
  if ( empty( $title ) ) {
553
  }
554
  }
555
 
556
+ /** Back-compat filter. Please use `qm/dispatch/html` instead */
557
  if ( ! apply_filters( 'qm/process', true, is_admin_bar_showing() ) ) {
558
  return false;
559
  }
output/Html.php CHANGED
@@ -105,13 +105,13 @@ abstract class QM_Output_Html extends QM_Output {
105
  }
106
 
107
  protected function build_notice( $notice ) {
108
- $return = '<div class="qm-section">';
109
  $return .= '<div class="qm-notice">';
110
  $return .= '<p>';
111
  $return .= $notice;
112
  $return .= '</p>';
113
  $return .= '</div>';
114
- $return .= '</div>';
115
 
116
  return $return;
117
  }
@@ -265,10 +265,10 @@ abstract class QM_Output_Html extends QM_Output {
265
  $sql = trim( $sql );
266
 
267
  $regex = 'ADD|AFTER|ALTER|AND|BEGIN|COMMIT|CREATE|DELETE|DESCRIBE|DO|DROP|ELSE|END|EXCEPT|EXPLAIN|FROM|GROUP|HAVING|INNER|INSERT|INTERSECT|LEFT|LIMIT|ON|OR|ORDER|OUTER|RENAME|REPLACE|RIGHT|ROLLBACK|SELECT|SET|SHOW|START|THEN|TRUNCATE|UNION|UPDATE|USE|USING|VALUES|WHEN|WHERE|XOR';
268
- $sql = preg_replace( '# (' . $regex . ') #', '<br> $1 ', $sql );
269
 
270
  $keywords = '\b(?:ACTION|ADD|AFTER|ALTER|AND|ASC|AS|AUTO_INCREMENT|BEGIN|BETWEEN|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOOL|BREAK|BY|CASE|COLLATE|COLUMNS?|COMMIT|CONTINUE|CREATE|DATA(?:BASES?)?|DATE(?:TIME)?|DECIMAL|DECLARE|DEC|DEFAULT|DELAYED|DELETE|DESCRIBE|DESC|DISTINCT|DOUBLE|DO|DROP|DUPLICATE|ELSE|END|ENUM|EXCEPT|EXISTS|EXPLAIN|FIELDS|FLOAT|FOREIGN|FOR|FROM|FULL|FUNCTION|GROUP|HAVING|IF|IGNORE|INDEX|INNER|INSERT|INTEGER|INTERSECT|INTERVAL|INTO|INT|IN|IS|JOIN|KEYS?|LEFT|LIKE|LIMIT|LONG(?:BLOB|TEXT)|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|NOT|NO|NULLIF|ON|ORDER|OR|OUTER|PRIMARY|PROC(?:EDURE)?|REGEXP|RENAME|REPLACE|RIGHT|RLIKE|ROLLBACK|SCHEMA|SELECT|SET|SHOW|SMALLINT|START|TABLES?|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TRUNCATE|UNION|UNIQUE|UNSIGNED|UPDATE|USE|USING|VALUES?|VAR(?:BINARY|CHAR)|WHEN|WHERE|WHILE|XOR)\b';
271
- $sql = preg_replace( '#' . $keywords . '#', '<b>$0</b>', $sql );
272
 
273
  return '<code>' . $sql . '</code>';
274
 
@@ -373,6 +373,14 @@ abstract class QM_Output_Html extends QM_Output {
373
  public static function get_file_link_format() {
374
  if ( ! isset( self::$file_link_format ) ) {
375
  $format = ini_get( 'xdebug.file_link_format' );
 
 
 
 
 
 
 
 
376
  $format = apply_filters( 'qm/output/file_link_format', $format );
377
  if ( empty( $format ) ) {
378
  self::$file_link_format = false;
@@ -385,7 +393,13 @@ abstract class QM_Output_Html extends QM_Output {
385
  }
386
 
387
  public static function get_file_path_map() {
388
- // @TODO document this!
 
 
 
 
 
 
389
  return apply_filters( 'qm/output/file_path_map', array() );
390
  }
391
 
105
  }
106
 
107
  protected function build_notice( $notice ) {
108
+ $return = '<section>';
109
  $return .= '<div class="qm-notice">';
110
  $return .= '<p>';
111
  $return .= $notice;
112
  $return .= '</p>';
113
  $return .= '</div>';
114
+ $return .= '</section>';
115
 
116
  return $return;
117
  }
265
  $sql = trim( $sql );
266
 
267
  $regex = 'ADD|AFTER|ALTER|AND|BEGIN|COMMIT|CREATE|DELETE|DESCRIBE|DO|DROP|ELSE|END|EXCEPT|EXPLAIN|FROM|GROUP|HAVING|INNER|INSERT|INTERSECT|LEFT|LIMIT|ON|OR|ORDER|OUTER|RENAME|REPLACE|RIGHT|ROLLBACK|SELECT|SET|SHOW|START|THEN|TRUNCATE|UNION|UPDATE|USE|USING|VALUES|WHEN|WHERE|XOR';
268
+ $sql = preg_replace( '# (' . $regex . ') #', '<br> $1 ', $sql );
269
 
270
  $keywords = '\b(?:ACTION|ADD|AFTER|ALTER|AND|ASC|AS|AUTO_INCREMENT|BEGIN|BETWEEN|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOOL|BREAK|BY|CASE|COLLATE|COLUMNS?|COMMIT|CONTINUE|CREATE|DATA(?:BASES?)?|DATE(?:TIME)?|DECIMAL|DECLARE|DEC|DEFAULT|DELAYED|DELETE|DESCRIBE|DESC|DISTINCT|DOUBLE|DO|DROP|DUPLICATE|ELSE|END|ENUM|EXCEPT|EXISTS|EXPLAIN|FIELDS|FLOAT|FOREIGN|FOR|FROM|FULL|FUNCTION|GROUP|HAVING|IF|IGNORE|INDEX|INNER|INSERT|INTEGER|INTERSECT|INTERVAL|INTO|INT|IN|IS|JOIN|KEYS?|LEFT|LIKE|LIMIT|LONG(?:BLOB|TEXT)|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|NOT|NO|NULLIF|ON|ORDER|OR|OUTER|PRIMARY|PROC(?:EDURE)?|REGEXP|RENAME|REPLACE|RIGHT|RLIKE|ROLLBACK|SCHEMA|SELECT|SET|SHOW|SMALLINT|START|TABLES?|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TRUNCATE|UNION|UNIQUE|UNSIGNED|UPDATE|USE|USING|VALUES?|VAR(?:BINARY|CHAR)|WHEN|WHERE|WHILE|XOR)\b';
271
+ $sql = preg_replace( '#' . $keywords . '#', '<b>$0</b>', $sql );
272
 
273
  return '<code>' . $sql . '</code>';
274
 
373
  public static function get_file_link_format() {
374
  if ( ! isset( self::$file_link_format ) ) {
375
  $format = ini_get( 'xdebug.file_link_format' );
376
+
377
+ /**
378
+ * Filters the file link format.
379
+ *
380
+ * @since 3.0.0
381
+ *
382
+ * @param string $format The format of the file link.
383
+ */
384
  $format = apply_filters( 'qm/output/file_link_format', $format );
385
  if ( empty( $format ) ) {
386
  self::$file_link_format = false;
393
  }
394
 
395
  public static function get_file_path_map() {
396
+ /**
397
+ * The file path map.
398
+ *
399
+ * @since 3.0.0
400
+ *
401
+ * @param array $file_map Array of file paths.
402
+ */
403
  return apply_filters( 'qm/output/file_path_map', array() );
404
  }
405
 
output/headers/overview.php CHANGED
@@ -9,7 +9,7 @@ class QM_Output_Headers_Overview extends QM_Output_Headers {
9
 
10
  public function get_output() {
11
 
12
- $data = $this->collector->get_data();
13
  $headers = array();
14
 
15
  $headers['time_taken'] = number_format_i18n( $data['time_taken'], 4 );
9
 
10
  public function get_output() {
11
 
12
+ $data = $this->collector->get_data();
13
  $headers = array();
14
 
15
  $headers['time_taken'] = number_format_i18n( $data['time_taken'], 4 );
output/headers/php_errors.php CHANGED
@@ -8,7 +8,7 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
8
 
9
  public function get_output() {
10
 
11
- $data = $this->collector->get_data();
12
  $headers = array();
13
 
14
  if ( empty( $data['errors'] ) ) {
@@ -25,7 +25,7 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
25
 
26
  # @TODO we should calculate the component during process() so we don't need to do it
27
  # separately in each output.
28
- $component = $error['trace']->get_component();
29
  $output_error = array(
30
  'type' => $error['type'],
31
  'message' => $error['message'],
@@ -35,15 +35,18 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
35
  'component' => $component->name,
36
  );
37
 
38
- $key = sprintf( 'error-%d', $count );
39
  $headers[ $key ] = json_encode( $output_error );
40
 
41
  }
42
  }
43
 
44
- return array_merge( array(
45
- 'error-count' => $count,
46
- ), $headers );
 
 
 
47
 
48
  }
49
 
8
 
9
  public function get_output() {
10
 
11
+ $data = $this->collector->get_data();
12
  $headers = array();
13
 
14
  if ( empty( $data['errors'] ) ) {
25
 
26
  # @TODO we should calculate the component during process() so we don't need to do it
27
  # separately in each output.
28
+ $component = $error['trace']->get_component();
29
  $output_error = array(
30
  'type' => $error['type'],
31
  'message' => $error['message'],
35
  'component' => $component->name,
36
  );
37
 
38
+ $key = sprintf( 'error-%d', $count );
39
  $headers[ $key ] = json_encode( $output_error );
40
 
41
  }
42
  }
43
 
44
+ return array_merge(
45
+ array(
46
+ 'error-count' => $count,
47
+ ),
48
+ $headers
49
+ );
50
 
51
  }
52
 
output/headers/redirects.php CHANGED
@@ -8,7 +8,7 @@ class QM_Output_Headers_Redirects extends QM_Output_Headers {
8
 
9
  public function get_output() {
10
 
11
- $data = $this->collector->get_data();
12
  $headers = array();
13
 
14
  if ( empty( $data['trace'] ) ) {
8
 
9
  public function get_output() {
10
 
11
+ $data = $this->collector->get_data();
12
  $headers = array();
13
 
14
  if ( empty( $data['trace'] ) ) {
output/html/admin.php CHANGED
@@ -22,7 +22,7 @@ class QM_Output_Html_Admin extends QM_Output_Html {
22
 
23
  $this->before_non_tabular_output();
24
 
25
- echo '<div class="qm-section">';
26
  echo '<h3>get_current_screen()</h3>';
27
 
28
  echo '<table>';
@@ -43,16 +43,16 @@ class QM_Output_Html_Admin extends QM_Output_Html {
43
 
44
  echo '</tbody>';
45
  echo '</table>';
46
- echo '</div>';
47
 
48
- echo '<div class="qm-section">';
49
  echo '<h3>$pagenow</h3>';
50
  echo '<p>' . esc_html( $data['pagenow'] ) . '</p>';
51
- echo '</div>';
52
 
53
  if ( ! empty( $data['list_table'] ) ) {
54
 
55
- echo '<div class="qm-section">';
56
  echo '<h3>' . esc_html__( 'List Table', 'query-monitor' ) . '</h3>';
57
 
58
  if ( ! empty( $data['list_table']['class_name'] ) ) {
@@ -65,7 +65,7 @@ class QM_Output_Html_Admin extends QM_Output_Html {
65
  echo '<p><code>' . esc_html( $data['list_table']['sortables_filter'] ) . '</code></p>';
66
  echo '<h4>' . esc_html__( 'Column Action:', 'query-monitor' ) . '</h4>';
67
  echo '<p><code>' . esc_html( $data['list_table']['column_action'] ) . '</code></p>';
68
- echo '</div>';
69
 
70
  }
71
 
22
 
23
  $this->before_non_tabular_output();
24
 
25
+ echo '<section>';
26
  echo '<h3>get_current_screen()</h3>';
27
 
28
  echo '<table>';
43
 
44
  echo '</tbody>';
45
  echo '</table>';
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'] ) ) {
54
 
55
+ echo '<section>';
56
  echo '<h3>' . esc_html__( 'List Table', 'query-monitor' ) . '</h3>';
57
 
58
  if ( ! empty( $data['list_table']['class_name'] ) ) {
65
  echo '<p><code>' . esc_html( $data['list_table']['sortables_filter'] ) . '</code></p>';
66
  echo '<h4>' . esc_html__( 'Column Action:', 'query-monitor' ) . '</h4>';
67
  echo '<p><code>' . esc_html( $data['list_table']['column_action'] ) . '</code></p>';
68
+ echo '</section>';
69
 
70
  }
71
 
output/html/assets.php CHANGED
@@ -31,25 +31,48 @@ class QM_Output_Html_Assets extends QM_Output_Html {
31
  $type_labels = array(
32
  'scripts' => array(
33
  /* translators: %s: Total number of enqueued scripts */
34
- 'total' => _x( 'Total: %s', 'Enqueued scripts', 'query-monitor' ),
35
- 'plural' => __( 'Scripts', 'query-monitor' ),
36
  ),
37
- 'styles' => array(
38
  /* translators: %s: Total number of enqueued styles */
39
- 'total' => _x( 'Total: %s', 'Enqueued styles', 'query-monitor' ),
40
- 'plural' => __( 'Styles', 'query-monitor' ),
41
  ),
42
  );
43
 
44
  foreach ( $type_labels as $type => $type_label ) {
45
 
46
- $types = array();
 
 
47
 
48
  foreach ( $position_labels as $position => $label ) {
49
  if ( ! empty( $data[ $position ][ $type ] ) ) {
50
  $types[ $position ] = $label;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
  }
 
 
 
 
 
53
 
54
  $hosts = array(
55
  __( 'Other', 'query-monitor' ),
@@ -77,8 +100,12 @@ class QM_Output_Html_Assets extends QM_Output_Html {
77
  echo $this->build_filter( $type . '-host', $hosts, __( 'Host', 'query-monitor' ), $args ); // WPCS: XSS ok.
78
  echo '</th>';
79
  echo '<th scope="col">' . esc_html__( 'Source', 'query-monitor' ) . '</th>';
80
- echo '<th scope="col">' . esc_html__( 'Dependencies', 'query-monitor' ) . '</th>';
81
- echo '<th scope="col">' . esc_html__( 'Dependents', 'query-monitor' ) . '</th>';
 
 
 
 
82
  echo '<th scope="col">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
83
  echo '</tr>';
84
  echo '</thead>';
@@ -121,13 +148,21 @@ class QM_Output_Html_Assets extends QM_Output_Html {
121
 
122
  list( $src, $host, $source, $local ) = $this->get_dependency_data( $dependency, $dependencies, $type );
123
 
 
 
 
 
 
 
 
 
124
  $qm_host = ( $local ) ? 'local' : __( 'Other', 'query-monitor' );
125
 
126
  if ( in_array( $handle, $dependencies->done, true ) ) {
127
- echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" data-qm-' . esc_attr( $type ) . '-host="' . esc_attr( $qm_host ) . '">';
128
  echo '<td class="qm-nowrap">' . esc_html( $label ) . '</td>';
129
  } else {
130
- echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" data-qm-' . esc_attr( $type ) . '-host="' . esc_attr( $qm_host ) . '" class="qm-warn">';
131
  echo '<td class="qm-nowrap"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $label ) . '</td>';
132
  }
133
 
@@ -138,6 +173,8 @@ class QM_Output_Html_Assets extends QM_Output_Html {
138
  }
139
 
140
  protected function get_dependency_data( _WP_Dependency $dependency, WP_Dependencies $dependencies, $type ) {
 
 
141
  $loader = rtrim( $type, 's' );
142
 
143
  /**
@@ -145,12 +182,15 @@ class QM_Output_Html_Assets extends QM_Output_Html {
145
  *
146
  * The variable {$loader} can be either 'script' or 'style'.
147
  *
 
 
148
  * @param string $src Script or style loader source path.
149
  * @param string $handle Script or style handle.
150
  */
151
  $source = apply_filters( "{$loader}_loader_src", $dependency->src, $dependency->handle );
152
 
153
- $host = (string) wp_parse_url( $source, PHP_URL_HOST );
 
154
  // phpcs:ignore WordPress.VIP.ValidatedSanitizedInput
155
  $http_host = wp_unslash( $_SERVER['HTTP_HOST'] );
156
 
@@ -158,6 +198,14 @@ class QM_Output_Html_Assets extends QM_Output_Html {
158
  $host = $http_host;
159
  }
160
 
 
 
 
 
 
 
 
 
161
  if ( is_wp_error( $source ) ) {
162
  $src = $source->get_error_message();
163
  if ( ( $error_data = $source->get_error_data() ) && isset( $error_data['src'] ) ) {
@@ -165,7 +213,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
165
  $host = (string) wp_parse_url( $error_data['src'], PHP_URL_HOST );
166
  }
167
  } elseif ( empty( $source ) ) {
168
- $src = '';
169
  $host = '';
170
  } else {
171
  $src = $source;
@@ -187,7 +235,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
187
  list( $src, $host, $source, $local ) = $this->get_dependency_data( $dependency, $dependencies, $type );
188
 
189
  $dependents = $this->collector->get_dependents( $dependency, $dependencies );
190
- $deps = $dependency->deps;
191
  sort( $deps );
192
 
193
  foreach ( $deps as & $dep ) {
@@ -214,7 +262,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
214
  printf(
215
  '<a href="%s" class="qm-link">%s</a>',
216
  esc_attr( $src ),
217
- esc_html( $src )
218
  );
219
  }
220
  echo '</td>';
@@ -232,7 +280,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
232
 
233
  $data = $this->collector->get_data();
234
 
235
- if ( ! empty( $data['broken'] ) or ! empty( $data['missing'] ) ) {
236
  $class[] = 'qm-error';
237
  }
238
 
@@ -242,7 +290,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
242
 
243
  public function admin_menu( array $menu ) {
244
 
245
- $data = $this->collector->get_data();
246
  $labels = array(
247
  'scripts' => __( 'Scripts', 'query-monitor' ),
248
  'styles' => __( 'Styles', 'query-monitor' ),
@@ -255,7 +303,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
255
  'href' => esc_attr( '#' . $this->collector->id() . '-' . $type ),
256
  );
257
 
258
- if ( ! empty( $data['broken'][ $type ] ) or ! empty( $data['missing'][ $type ] ) ) {
259
  $args['meta']['classname'] = 'qm-error';
260
  }
261
 
31
  $type_labels = array(
32
  'scripts' => array(
33
  /* translators: %s: Total number of enqueued scripts */
34
+ 'total' => _x( 'Total: %s', 'Enqueued scripts', 'query-monitor' ),
35
+ 'plural' => __( 'Scripts', 'query-monitor' ),
36
  ),
37
+ 'styles' => array(
38
  /* translators: %s: Total number of enqueued styles */
39
+ 'total' => _x( 'Total: %s', 'Enqueued styles', 'query-monitor' ),
40
+ 'plural' => __( 'Styles', 'query-monitor' ),
41
  ),
42
  );
43
 
44
  foreach ( $type_labels as $type => $type_label ) {
45
 
46
+ $types = array();
47
+ $all_dependencies = array();
48
+ $all_dependents = array();
49
 
50
  foreach ( $position_labels as $position => $label ) {
51
  if ( ! empty( $data[ $position ][ $type ] ) ) {
52
  $types[ $position ] = $label;
53
+
54
+ $handles = $data[ $position ][ $type ];
55
+
56
+ foreach ( $handles as $handle ) {
57
+ $dependency = $data['raw'][ $type ]->query( $handle );
58
+
59
+ if ( ! $dependency ) {
60
+ continue;
61
+ }
62
+
63
+ $dependencies = $dependency->deps;
64
+ $all_dependencies = array_merge( $all_dependencies, $dependencies );
65
+
66
+ $dependents = $this->collector->get_dependents( $dependency, $data['raw'][ $type ] );
67
+ $all_dependents = array_merge( $all_dependents, $dependents );
68
+ }
69
  }
70
  }
71
+ $all_dependencies = array_unique( $all_dependencies );
72
+ sort( $all_dependencies );
73
+
74
+ $all_dependents = array_unique( $all_dependents );
75
+ sort( $all_dependents );
76
 
77
  $hosts = array(
78
  __( 'Other', 'query-monitor' ),
100
  echo $this->build_filter( $type . '-host', $hosts, __( 'Host', 'query-monitor' ), $args ); // WPCS: XSS ok.
101
  echo '</th>';
102
  echo '<th scope="col">' . esc_html__( 'Source', 'query-monitor' ) . '</th>';
103
+ echo '<th scope="col" class="qm-filterable-column">';
104
+ echo $this->build_filter( $type . '-dependencies', $all_dependencies, __( 'Dependencies', 'query-monitor' ) ); // WPCS: XSS ok.
105
+ echo '</th>';
106
+ echo '<th scope="col" class="qm-filterable-column">';
107
+ echo $this->build_filter( $type . '-dependents', $all_dependents, __( 'Dependents', 'query-monitor' ) ); // WPCS: XSS ok.
108
+ echo '</th>';
109
  echo '<th scope="col">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
110
  echo '</tr>';
111
  echo '</thead>';
148
 
149
  list( $src, $host, $source, $local ) = $this->get_dependency_data( $dependency, $dependencies, $type );
150
 
151
+ $dependencies_list = $dependency->deps;
152
+ // $dependencies_list[] = $handle;
153
+ $dependencies_list = implode( ' ', $dependencies_list );
154
+
155
+ $dependents_list = $this->collector->get_dependents( $dependency, $dependencies );
156
+ // $dependents_list[] = $handle;
157
+ $dependents_list = implode( ' ', $dependents_list );
158
+
159
  $qm_host = ( $local ) ? 'local' : __( 'Other', 'query-monitor' );
160
 
161
  if ( in_array( $handle, $dependencies->done, true ) ) {
162
+ echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" data-qm-' . esc_attr( $type ) . '-host="' . esc_attr( $qm_host ) . '" data-qm-' . esc_attr( $type ) . '-dependents="' . esc_attr( $dependents_list ) . '" data-qm-' . esc_attr( $type ) . '-dependencies="' . esc_attr( $dependencies_list ) . '">';
163
  echo '<td class="qm-nowrap">' . esc_html( $label ) . '</td>';
164
  } else {
165
+ echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" data-qm-' . esc_attr( $type ) . '-host="' . esc_attr( $qm_host ) . '" data-qm-' . esc_attr( $type ) . '-dependents="' . esc_attr( $dependents_list ) . '" data-qm-' . esc_attr( $type ) . '-dependencies="' . esc_attr( $dependencies_list ) . '" class="qm-warn">';
166
  echo '<td class="qm-nowrap"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $label ) . '</td>';
167
  }
168
 
173
  }
174
 
175
  protected function get_dependency_data( _WP_Dependency $dependency, WP_Dependencies $dependencies, $type ) {
176
+ $data = $this->collector->get_data();
177
+
178
  $loader = rtrim( $type, 's' );
179
 
180
  /**
182
  *
183
  * The variable {$loader} can be either 'script' or 'style'.
184
  *
185
+ * @since 2.9.0
186
+ *
187
  * @param string $src Script or style loader source path.
188
  * @param string $handle Script or style handle.
189
  */
190
  $source = apply_filters( "{$loader}_loader_src", $dependency->src, $dependency->handle );
191
 
192
+ $host = (string) wp_parse_url( $source, PHP_URL_HOST );
193
+ $scheme = (string) wp_parse_url( $source, PHP_URL_SCHEME );
194
  // phpcs:ignore WordPress.VIP.ValidatedSanitizedInput
195
  $http_host = wp_unslash( $_SERVER['HTTP_HOST'] );
196
 
198
  $host = $http_host;
199
  }
200
 
201
+ $insecure = ( $scheme && $data['is_ssl'] && ( 'https' !== $scheme ) );
202
+
203
+ if ( $insecure ) {
204
+ $source = new WP_Error( 'insecure_content', __( 'Insecure content', 'query-monitor' ), array(
205
+ 'src' => $source,
206
+ ) );
207
+ }
208
+
209
  if ( is_wp_error( $source ) ) {
210
  $src = $source->get_error_message();
211
  if ( ( $error_data = $source->get_error_data() ) && isset( $error_data['src'] ) ) {
213
  $host = (string) wp_parse_url( $error_data['src'], PHP_URL_HOST );
214
  }
215
  } elseif ( empty( $source ) ) {
216
+ $src = '';
217
  $host = '';
218
  } else {
219
  $src = $source;
235
  list( $src, $host, $source, $local ) = $this->get_dependency_data( $dependency, $dependencies, $type );
236
 
237
  $dependents = $this->collector->get_dependents( $dependency, $dependencies );
238
+ $deps = $dependency->deps;
239
  sort( $deps );
240
 
241
  foreach ( $deps as & $dep ) {
262
  printf(
263
  '<a href="%s" class="qm-link">%s</a>',
264
  esc_attr( $src ),
265
+ esc_html( ltrim( str_replace( home_url(), '', $src ), '/' ) )
266
  );
267
  }
268
  echo '</td>';
280
 
281
  $data = $this->collector->get_data();
282
 
283
+ if ( ! empty( $data['broken'] ) || ! empty( $data['missing'] ) ) {
284
  $class[] = 'qm-error';
285
  }
286
 
290
 
291
  public function admin_menu( array $menu ) {
292
 
293
+ $data = $this->collector->get_data();
294
  $labels = array(
295
  'scripts' => __( 'Scripts', 'query-monitor' ),
296
  'styles' => __( 'Styles', 'query-monitor' ),
303
  'href' => esc_attr( '#' . $this->collector->id() . '-' . $type ),
304
  );
305
 
306
+ if ( ! empty( $data['broken'][ $type ] ) || ! empty( $data['missing'][ $type ] ) ) {
307
  $args['meta']['classname'] = 'qm-error';
308
  }
309
 
output/html/block_editor.php ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Block editor data output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
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 );
13
+ }
14
+
15
+ public function output() {
16
+ $data = $this->collector->get_data();
17
+ $i = 0;
18
+
19
+ if ( empty( $data['block_editor_enabled'] ) || empty( $data['post_blocks'] ) ) {
20
+ return;
21
+ }
22
+
23
+ if ( ! $data['post_has_blocks'] ) {
24
+ $this->before_non_tabular_output();
25
+
26
+ $notice = __( 'This post contains no blocks.', 'query-monitor' );
27
+ echo $this->build_notice( $notice ); // WPCS: XSS ok.
28
+
29
+ $this->after_non_tabular_output();
30
+
31
+ return;
32
+ }
33
+
34
+ $this->before_tabular_output();
35
+
36
+ echo '<thead>';
37
+ echo '<tr>';
38
+ echo '<th scope="col">#</th>';
39
+ echo '<th scope="col">' . esc_html__( 'Block Name', 'query-monitor' ) . '</th>';
40
+ echo '<th scope="col">' . esc_html__( 'Attributes', 'query-monitor' ) . '</th>';
41
+ echo '<th scope="col">' . esc_html__( 'Render Callback', 'query-monitor' ) . '</th>';
42
+ echo '<th scope="col">' . esc_html__( 'Inner HTML', 'query-monitor' ) . '</th>';
43
+ echo '</tr>';
44
+ echo '</thead>';
45
+
46
+ echo '<tbody>';
47
+
48
+ foreach ( $data['post_blocks'] as $block ) {
49
+ $inner_html = trim( $block['innerHTML'] );
50
+
51
+ // Don't display empty blocks caused by two consecutive line breaks in content
52
+ if ( ! $block['blockName'] && ! $inner_html ) {
53
+ continue;
54
+ }
55
+
56
+ $block_error = ( empty( $block['blockName'] ) && ! empty( $inner_html ) );
57
+ $row_class = '';
58
+ $reused_post = null;
59
+ $reused_type = null;
60
+ $reused_pto = null;
61
+ $error_message = null;
62
+
63
+ if ( 'core/block' === $block['blockName'] && ! empty( $block['attrs']['ref'] ) ) {
64
+ $reused_post = get_post( $block['attrs']['ref'] );
65
+
66
+ if ( ! $reused_post ) {
67
+ $block_error = true;
68
+ $error_message = esc_html__( 'Referenced block does not exist.', 'query-monitor' );
69
+ } else {
70
+ $reused_type = get_post( $block['attrs']['ref'] )->post_type;
71
+ $reused_pto = get_post_type_object( $reused_type );
72
+ if ( 'wp_block' !== $reused_type ) {
73
+ $block_error = true;
74
+ $error_message = sprintf(
75
+ /* translators: %1$s: Erroneous post type name, %2$s: WordPress block post type name */
76
+ esc_html__( 'Referenced post is of type %1$s instead of %2$s.', 'query-monitor' ),
77
+ '<code>' . esc_html( $reused_type ) . '</code>',
78
+ '<code>wp_block</code>'
79
+ );
80
+ }
81
+ }
82
+ }
83
+
84
+ if ( $block_error ) {
85
+ $row_class = 'qm-warn';
86
+ }
87
+
88
+ echo '<tr class="' . esc_attr( $row_class ) . '">';
89
+
90
+ echo '<th scope="row" class="qm-row-num qm-num"><span class="qm-sticky">' . absint( ++$i ) . '</span></th>';
91
+
92
+ echo '<td class="qm-row-block-name"><span class="qm-sticky">';
93
+
94
+ if ( $block_error ) {
95
+ echo '<span class="dashicons dashicons-warning" aria-hidden="true"></span>';
96
+ }
97
+
98
+ if ( $block['blockName'] ) {
99
+ echo esc_html( $block['blockName'] );
100
+ } else {
101
+ echo '<em>' . esc_html__( 'None', 'query-monitor' ) . '</em>';
102
+ }
103
+
104
+ if ( $error_message ) {
105
+ echo '<br>';
106
+ echo $error_message; // WPCS: XSS ok;
107
+ }
108
+
109
+ if ( 'core/block' === $block['blockName'] && ! empty( $block['attrs']['ref'] ) && ! empty( $reused_pto ) ) {
110
+ echo '<br>';
111
+ echo '<a href="' . esc_url( get_edit_post_link( $block['attrs']['ref'] ) ) . '" class="qm-link">' . esc_html( $reused_pto->labels->edit_item ) . '</a>';
112
+ }
113
+
114
+ echo '</span></td>';
115
+
116
+ echo '<td class="qm-row-block-attrs">';
117
+ if ( $block['attrs'] ) {
118
+ $json = json_encode( $block['attrs'], JSON_PRETTY_PRINT );
119
+ echo '<pre>' . esc_html( $json ) . '</pre>';
120
+ }
121
+ echo '</td>';
122
+
123
+ if ( isset( $block['callback']['error'] ) ) {
124
+ $class = ' qm-warn';
125
+ } else {
126
+ $class = '';
127
+ }
128
+
129
+ if ( $block['dynamic'] ) {
130
+ if ( isset( $block['callback']['file'] ) ) {
131
+ if ( self::has_clickable_links() ) {
132
+ echo '<td class="qm-nowrap qm-ltr' . esc_attr( $class ) . '">';
133
+ echo self::output_filename( $block['callback']['name'], $block['callback']['file'], $block['callback']['line'] ); // WPCS: XSS ok.
134
+ echo '</td>';
135
+ } else {
136
+ echo '<td class="qm-nowrap qm-ltr qm-has-toggle' . esc_attr( $class ) . '"><ol class="qm-toggler">';
137
+ echo self::build_toggler(); // WPCS: XSS ok;
138
+ echo '<li>';
139
+ echo self::output_filename( $block['callback']['name'], $block['callback']['file'], $block['callback']['line'] ); // WPCS: XSS ok.
140
+ echo '</li>';
141
+ echo '</ol></td>';
142
+ }
143
+ } else {
144
+ echo '<td class="qm-ltr qm-nowrap' . esc_attr( $class ) . '">';
145
+ echo '<code>' . esc_html( $block['callback']['name'] ) . '</code>';
146
+
147
+ if ( isset( $block['callback']['error'] ) ) {
148
+ echo '<br>';
149
+ echo esc_html( sprintf(
150
+ /* translators: %s: Error message text */
151
+ __( 'Error: %s', 'query-monitor' ),
152
+ $block['callback']['error']->get_error_message()
153
+ ) );
154
+ }
155
+
156
+ echo '</td>';
157
+ }
158
+ } else {
159
+ echo '<td></td>';
160
+ }
161
+
162
+ echo '<td class="qm-row-block-html">';
163
+ if ( $block['innerHTML'] ) {
164
+ echo esc_html( $block['innerHTML'] );
165
+ }
166
+ echo '</td>';
167
+
168
+ echo '</tr>';
169
+ }
170
+
171
+ echo '</tbody>';
172
+
173
+ $this->after_tabular_output();
174
+ }
175
+
176
+ public function admin_menu( array $menu ) {
177
+ $data = $this->collector->get_data();
178
+
179
+ if ( empty( $data['block_editor_enabled'] ) || empty( $data['post_blocks'] ) ) {
180
+ return $menu;
181
+ }
182
+
183
+ $menu[] = $this->menu( array(
184
+ 'title' => esc_html__( 'Blocks', 'query-monitor' ),
185
+ ) );
186
+
187
+ return $menu;
188
+ }
189
+
190
+ }
191
+
192
+ function register_qm_output_html_block_editor( array $output, QM_Collectors $collectors ) {
193
+ if ( $collector = QM_Collectors::get( 'block_editor' ) ) {
194
+ $output['block_editor'] = new QM_Output_Html_Block_Editor( $collector );
195
+ }
196
+ return $output;
197
+ }
198
+
199
+ add_filter( 'qm/outputter/html', 'register_qm_output_html_block_editor', 60, 2 );
output/html/caps.php CHANGED
@@ -16,7 +16,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
16
  if ( ! defined( 'QM_ENABLE_CAPS_PANEL' ) || ! QM_ENABLE_CAPS_PANEL ) {
17
  $this->before_non_tabular_output();
18
 
19
- echo '<div class="qm-section">';
20
  echo '<div class="qm-notice">';
21
  echo '<p>';
22
  printf(
@@ -27,7 +27,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
27
  echo '</p>';
28
  echo "<p><code>define( 'QM_ENABLE_CAPS_PANEL', true );</code></p>";
29
  echo '</div>';
30
- echo '</div>';
31
 
32
  $this->after_non_tabular_output();
33
 
@@ -39,7 +39,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
39
  if ( ! empty( $data['caps'] ) ) {
40
  $this->before_tabular_output();
41
 
42
- $results = array(
43
  'true',
44
  'false',
45
  );
@@ -81,7 +81,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
81
  foreach ( $data['caps'] as $row ) {
82
  $component = $row['trace']->get_component();
83
 
84
- $row_attr = array();
85
  $row_attr['data-qm-name'] = implode( ' ', $row['parts'] );
86
  $row_attr['data-qm-user'] = $row['user'];
87
  $row_attr['data-qm-component'] = $component->name;
@@ -147,8 +147,8 @@ class QM_Output_Html_Caps extends QM_Output_Html {
147
  if ( ! count( $filtered_trace ) ) {
148
  $responsible_name = QM_Util::standard_dir( $trace[1]['file'], '' ) . ':' . $trace[1]['line'];
149
 
150
- $responsible_item = $trace[1];
151
- $responsible_item['display'] = $responsible_name;
152
  $responsible_item['calling_file'] = $trace[1]['file'];
153
  $responsible_item['calling_line'] = $trace[1]['line'];
154
  array_unshift( $filtered_trace, $responsible_item );
16
  if ( ! defined( 'QM_ENABLE_CAPS_PANEL' ) || ! QM_ENABLE_CAPS_PANEL ) {
17
  $this->before_non_tabular_output();
18
 
19
+ echo '<section>';
20
  echo '<div class="qm-notice">';
21
  echo '<p>';
22
  printf(
27
  echo '</p>';
28
  echo "<p><code>define( 'QM_ENABLE_CAPS_PANEL', true );</code></p>";
29
  echo '</div>';
30
+ echo '</section>';
31
 
32
  $this->after_non_tabular_output();
33
 
39
  if ( ! empty( $data['caps'] ) ) {
40
  $this->before_tabular_output();
41
 
42
+ $results = array(
43
  'true',
44
  'false',
45
  );
81
  foreach ( $data['caps'] as $row ) {
82
  $component = $row['trace']->get_component();
83
 
84
+ $row_attr = array();
85
  $row_attr['data-qm-name'] = implode( ' ', $row['parts'] );
86
  $row_attr['data-qm-user'] = $row['user'];
87
  $row_attr['data-qm-component'] = $component->name;
147
  if ( ! count( $filtered_trace ) ) {
148
  $responsible_name = QM_Util::standard_dir( $trace[1]['file'], '' ) . ':' . $trace[1]['line'];
149
 
150
+ $responsible_item = $trace[1];
151
+ $responsible_item['display'] = $responsible_name;
152
  $responsible_item['calling_file'] = $trace[1]['file'];
153
  $responsible_item['calling_line'] = $trace[1]['line'];
154
  array_unshift( $filtered_trace, $responsible_item );
output/html/conditionals.php CHANGED
@@ -18,22 +18,22 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
18
 
19
  $this->before_non_tabular_output();
20
 
21
- echo '<div class="qm-section">';
22
  echo '<h3>' . esc_html__( 'True Conditionals', 'query-monitor' ) . '</h3>';
23
 
24
  foreach ( $data['conds']['true'] as $cond ) {
25
  echo '<p class="qm-item qm-ltr qm-true"><code>' . esc_html( $cond ) . '()</code></p>';
26
  }
27
 
28
- echo '</div>';
29
- echo '<div class="qm-section">';
30
  echo '<h3>' . esc_html__( 'False Conditionals', 'query-monitor' ) . '</h3>';
31
 
32
  foreach ( $data['conds']['false'] as $cond ) {
33
  echo '<p class="qm-item qm-ltr qm-false"><code>' . esc_html( $cond ) . '()</code></p>';
34
  }
35
 
36
- echo '</div>';
37
 
38
  $this->after_non_tabular_output();
39
  }
18
 
19
  $this->before_non_tabular_output();
20
 
21
+ echo '<section>';
22
  echo '<h3>' . esc_html__( 'True Conditionals', 'query-monitor' ) . '</h3>';
23
 
24
  foreach ( $data['conds']['true'] as $cond ) {
25
  echo '<p class="qm-item qm-ltr qm-true"><code>' . esc_html( $cond ) . '()</code></p>';
26
  }
27
 
28
+ echo '</section>';
29
+ echo '<section>';
30
  echo '<h3>' . esc_html__( 'False Conditionals', 'query-monitor' ) . '</h3>';
31
 
32
  foreach ( $data['conds']['false'] as $cond ) {
33
  echo '<p class="qm-item qm-ltr qm-false"><code>' . esc_html( $cond ) . '()</code></p>';
34
  }
35
 
36
+ echo '</section>';
37
 
38
  $this->after_non_tabular_output();
39
  }
output/html/db_callers.php CHANGED
@@ -20,7 +20,7 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
20
  return;
21
  }
22
 
23
- $total_time = 0;
24
 
25
  if ( ! empty( $data['times'] ) ) {
26
  $this->before_tabular_output();
@@ -44,8 +44,8 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
44
  echo '<tbody>';
45
 
46
  foreach ( $data['times'] as $row ) {
47
- $total_time += $row['ltime'];
48
- $stime = number_format_i18n( $row['ltime'], 4 );
49
 
50
  echo '<tr>';
51
  echo '<td class="qm-ltr"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="' . esc_attr( $row['caller'] ) . '"><code>' . esc_html( $row['caller'] ) . '</code></a></td>';
20
  return;
21
  }
22
 
23
+ $total_time = 0;
24
 
25
  if ( ! empty( $data['times'] ) ) {
26
  $this->before_tabular_output();
44
  echo '<tbody>';
45
 
46
  foreach ( $data['times'] as $row ) {
47
+ $total_time += $row['ltime'];
48
+ $stime = number_format_i18n( $row['ltime'], 4 );
49
 
50
  echo '<tr>';
51
  echo '<td class="qm-ltr"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="' . esc_attr( $row['caller'] ) . '"><code>' . esc_html( $row['caller'] ) . '</code></a></td>';
output/html/db_components.php CHANGED
@@ -20,8 +20,8 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
20
  return;
21
  }
22
 
23
- $total_time = 0;
24
- $span = count( $data['types'] ) + 2;
25
 
26
  $this->before_tabular_output();
27
 
@@ -46,7 +46,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
46
  echo '<tbody>';
47
 
48
  foreach ( $data['times'] as $row ) {
49
- $total_time += $row['ltime'];
50
 
51
  echo '<tr>';
52
  echo '<td class="qm-row-component"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="component" data-qm-value="' . esc_attr( $row['component'] ) . '">' . esc_html( $row['component'] ) . '</a></td>';
20
  return;
21
  }
22
 
23
+ $total_time = 0;
24
+ $span = count( $data['types'] ) + 2;
25
 
26
  $this->before_tabular_output();
27
 
46
  echo '<tbody>';
47
 
48
  foreach ( $data['times'] as $row ) {
49
+ $total_time += $row['ltime'];
50
 
51
  echo '<tr>';
52
  echo '<td class="qm-row-component"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="component" data-qm-value="' . esc_attr( $row['component'] ) . '">' . esc_html( $row['component'] ) . '</a></td>';
output/html/db_queries.php CHANGED
@@ -154,6 +154,8 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
154
  * By default QM shows a prompt to install the QM db.php drop-in,
155
  * this filter allows a dev to choose not to show the prompt.
156
  *
 
 
157
  * @param bool $show_prompt Whether to show the prompt.
158
  */
159
  if ( apply_filters( 'qm/show_extended_query_prompt', true ) && ! $db->has_trace && ( '$wpdb' === $name ) ) {
@@ -492,7 +494,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
492
  ) );
493
  }
494
 
495
- if ( isset( $data['dbs'] ) and count( $data['dbs'] ) > 1 ) {
496
  foreach ( $data['dbs'] as $name => $db ) {
497
  $menu[] = $this->menu( array(
498
  'id' => esc_attr( sprintf( 'query-monitor-%s-db-%s', $this->collector->id(), sanitize_title_with_dashes( $name ) ) ),
154
  * By default QM shows a prompt to install the QM db.php drop-in,
155
  * this filter allows a dev to choose not to show the prompt.
156
  *
157
+ * @since 2.9.0
158
+ *
159
  * @param bool $show_prompt Whether to show the prompt.
160
  */
161
  if ( apply_filters( 'qm/show_extended_query_prompt', true ) && ! $db->has_trace && ( '$wpdb' === $name ) ) {
494
  ) );
495
  }
496
 
497
+ if ( isset( $data['dbs'] ) && count( $data['dbs'] ) > 1 ) {
498
  foreach ( $data['dbs'] as $name => $db ) {
499
  $menu[] = $this->menu( array(
500
  'id' => esc_attr( sprintf( 'query-monitor-%s-db-%s', $this->collector->id(), sanitize_title_with_dashes( $name ) ) ),
output/html/debug_bar.php CHANGED
@@ -63,7 +63,7 @@ function register_qm_output_html_debug_bar( array $output, QM_Collectors $collec
63
  $panel_id = strtolower( sanitize_html_class( get_class( $panel ) ) );
64
  $collector = QM_Collectors::get( "debug_bar_{$panel_id}" );
65
 
66
- if ( $collector and $collector->is_visible() ) {
67
  $output[ "debug_bar_{$panel_id}" ] = new QM_Output_Html_Debug_Bar( $collector );
68
  }
69
  }
63
  $panel_id = strtolower( sanitize_html_class( get_class( $panel ) ) );
64
  $collector = QM_Collectors::get( "debug_bar_{$panel_id}" );
65
 
66
+ if ( $collector && $collector->is_visible() ) {
67
  $output[ "debug_bar_{$panel_id}" ] = new QM_Output_Html_Debug_Bar( $collector );
68
  }
69
  }
output/html/environment.php CHANGED
@@ -18,7 +18,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
18
 
19
  $this->before_non_tabular_output();
20
 
21
- echo '<div class="qm-section">';
22
  echo '<h3>PHP</h3>';
23
 
24
  echo '<table>';
@@ -34,12 +34,17 @@ class QM_Output_Html_Environment extends QM_Output_Html {
34
  'https://wordpress.org/support/upgrade-php/',
35
  esc_html__( 'Help', 'query-monitor' )
36
  );
37
- $class = 'qm-warn';
38
  }
39
 
40
  echo '<tr class="' . esc_attr( $class ) . '">';
41
  echo '<th scope="row">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
42
  echo '<td>';
 
 
 
 
 
43
  echo esc_html( $data['php']['version'] );
44
  echo $append; // WPCS: XSS ok.
45
  echo '</td>';
@@ -60,10 +65,24 @@ class QM_Output_Html_Environment extends QM_Output_Html {
60
  echo '</tr>';
61
 
62
  foreach ( $data['php']['variables'] as $key => $val ) {
 
 
 
 
 
63
 
64
- echo '<tr>';
 
 
 
 
65
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
66
  echo '<td>';
 
 
 
 
 
67
  echo esc_html( $val['after'] );
68
 
69
  if ( $val['after'] !== $val['before'] ) {
@@ -129,7 +148,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
129
  echo '</tbody>';
130
  echo '</table>';
131
 
132
- echo '</div>';
133
 
134
  if ( isset( $data['db'] ) ) {
135
 
@@ -142,7 +161,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
142
  $name = sprintf( __( 'Database: %s', 'query-monitor' ), $id );
143
  }
144
 
145
- echo '<div class="qm-section">';
146
  echo '<h3>' . esc_html( $name ) . '</h3>';
147
 
148
  echo '<table>';
@@ -185,12 +204,12 @@ class QM_Output_Html_Environment extends QM_Output_Html {
185
  // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
186
  $val = $setting->Value;
187
 
188
- $append = '';
189
  $show_warning = false;
190
 
191
- if ( ( true === $db['vars'][ $key ] ) and empty( $val ) ) {
192
  $show_warning = true;
193
- } elseif ( is_string( $db['vars'][ $key ] ) and ( $val !== $db['vars'][ $key ] ) ) {
194
  $show_warning = true;
195
  }
196
 
@@ -202,7 +221,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
202
  );
203
  }
204
 
205
- if ( is_numeric( $val ) and ( $val >= ( 1024 * 1024 ) ) ) {
206
  $append .= sprintf(
207
  '&nbsp;<span class="qm-info">(~%s)</span>',
208
  esc_html( size_format( $val ) )
@@ -230,12 +249,12 @@ class QM_Output_Html_Environment extends QM_Output_Html {
230
  echo '</tbody>';
231
  echo '</table>';
232
 
233
- echo '</div>';
234
 
235
  }
236
  }
237
 
238
- echo '<div class="qm-section">';
239
  echo '<h3>WordPress</h3>';
240
 
241
  echo '<table>';
@@ -258,9 +277,9 @@ class QM_Output_Html_Environment extends QM_Output_Html {
258
  echo '</tbody>';
259
  echo '</table>';
260
 
261
- echo '</div>';
262
 
263
- echo '<div class="qm-section">';
264
  echo '<h3>' . esc_html__( 'Server', 'query-monitor' ) . '</h3>';
265
 
266
  $server = array(
@@ -287,7 +306,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
287
 
288
  echo '</tbody>';
289
  echo '</table>';
290
- echo '</div>';
291
 
292
  $this->after_non_tabular_output();
293
  }
18
 
19
  $this->before_non_tabular_output();
20
 
21
+ echo '<section>';
22
  echo '<h3>PHP</h3>';
23
 
24
  echo '<table>';
34
  'https://wordpress.org/support/upgrade-php/',
35
  esc_html__( 'Help', 'query-monitor' )
36
  );
37
+ $class = 'qm-warn';
38
  }
39
 
40
  echo '<tr class="' . esc_attr( $class ) . '">';
41
  echo '<th scope="row">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
42
  echo '<td>';
43
+
44
+ if ( $php_warning ) {
45
+ echo '<span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
46
+ }
47
+
48
  echo esc_html( $data['php']['version'] );
49
  echo $append; // WPCS: XSS ok.
50
  echo '</td>';
65
  echo '</tr>';
66
 
67
  foreach ( $data['php']['variables'] as $key => $val ) {
68
+ $class = '';
69
+ $warners = array(
70
+ 'max_execution_time',
71
+ 'memory_limit',
72
+ );
73
 
74
+ if ( ! $val && in_array( $key, $warners, true ) ) {
75
+ $class = 'qm-warn';
76
+ }
77
+
78
+ echo '<tr class="' . esc_attr( $class ) . '">';
79
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
80
  echo '<td>';
81
+
82
+ if ( 'qm-warn' === $class ) {
83
+ echo '<span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
84
+ }
85
+
86
  echo esc_html( $val['after'] );
87
 
88
  if ( $val['after'] !== $val['before'] ) {
148
  echo '</tbody>';
149
  echo '</table>';
150
 
151
+ echo '</section>';
152
 
153
  if ( isset( $data['db'] ) ) {
154
 
161
  $name = sprintf( __( 'Database: %s', 'query-monitor' ), $id );
162
  }
163
 
164
+ echo '<section>';
165
  echo '<h3>' . esc_html( $name ) . '</h3>';
166
 
167
  echo '<table>';
204
  // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
205
  $val = $setting->Value;
206
 
207
+ $append = '';
208
  $show_warning = false;
209
 
210
+ if ( ( true === $db['vars'][ $key ] ) && empty( $val ) ) {
211
  $show_warning = true;
212
+ } elseif ( is_string( $db['vars'][ $key ] ) && ( $val !== $db['vars'][ $key ] ) ) {
213
  $show_warning = true;
214
  }
215
 
221
  );
222
  }
223
 
224
+ if ( is_numeric( $val ) && ( $val >= ( 1024 * 1024 ) ) ) {
225
  $append .= sprintf(
226
  '&nbsp;<span class="qm-info">(~%s)</span>',
227
  esc_html( size_format( $val ) )
249
  echo '</tbody>';
250
  echo '</table>';
251
 
252
+ echo '</section>';
253
 
254
  }
255
  }
256
 
257
+ echo '<section>';
258
  echo '<h3>WordPress</h3>';
259
 
260
  echo '<table>';
277
  echo '</tbody>';
278
  echo '</table>';
279
 
280
+ echo '</section>';
281
 
282
+ echo '<section>';
283
  echo '<h3>' . esc_html__( 'Server', 'query-monitor' ) . '</h3>';
284
 
285
  $server = array(
306
 
307
  echo '</tbody>';
308
  echo '</table>';
309
+ echo '</section>';
310
 
311
  $this->after_non_tabular_output();
312
  }
output/html/hooks.php CHANGED
@@ -22,13 +22,13 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
22
  return;
23
  }
24
 
25
- if ( is_multisite() and is_network_admin() ) {
26
  $screen = preg_replace( '|-network$|', '', $data['screen'] );
27
  } else {
28
  $screen = $data['screen'];
29
  }
30
 
31
- $parts = $data['parts'];
32
  $components = $data['components'];
33
 
34
  usort( $parts, 'strcasecmp' );
@@ -70,7 +70,7 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
70
  $hook_name = esc_html( $hook['name'] );
71
  }
72
 
73
- $row_attr = array();
74
  $row_attr['data-qm-name'] = implode( ' ', $hook['parts'] );
75
  $row_attr['data-qm-component'] = implode( ' ', $hook['components'] );
76
 
@@ -97,14 +97,18 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
97
  foreach ( $hook['actions'] as $action ) {
98
 
99
  if ( isset( $action['callback']['component'] ) ) {
100
- $component = $action['callback']['component']->name;
101
  } else {
102
- $component = '';
 
 
 
 
103
  }
104
 
105
  printf( // WPCS: XSS ok.
106
  '<tr data-qm-subject="%s" %s>',
107
- esc_attr( $component ),
108
  $attr
109
  );
110
 
@@ -149,18 +153,19 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
149
  } else {
150
  echo '<td class="qm-ltr qm-nowrap' . esc_attr( $class ) . '">';
151
  echo '<code>' . esc_html( $action['callback']['name'] ) . '</code>';
152
- }
153
 
154
- if ( isset( $action['callback']['error'] ) ) {
155
- echo '<br>';
156
- echo esc_html( sprintf(
157
- /* translators: %s: Error message text */
158
- __( 'Error: %s', 'query-monitor' ),
159
- $action['callback']['error']->get_error_message()
160
- ) );
 
 
 
161
  }
162
 
163
- echo '</td>';
164
  echo '<td class="qm-nowrap' . esc_attr( $class ) . '">';
165
  echo esc_html( $component );
166
  echo '</td>';
22
  return;
23
  }
24
 
25
+ if ( is_multisite() && is_network_admin() ) {
26
  $screen = preg_replace( '|-network$|', '', $data['screen'] );
27
  } else {
28
  $screen = $data['screen'];
29
  }
30
 
31
+ $parts = $data['parts'];
32
  $components = $data['components'];
33
 
34
  usort( $parts, 'strcasecmp' );
70
  $hook_name = esc_html( $hook['name'] );
71
  }
72
 
73
+ $row_attr = array();
74
  $row_attr['data-qm-name'] = implode( ' ', $hook['parts'] );
75
  $row_attr['data-qm-component'] = implode( ' ', $hook['components'] );
76
 
97
  foreach ( $hook['actions'] as $action ) {
98
 
99
  if ( isset( $action['callback']['component'] ) ) {
100
+ $component = $subject = $action['callback']['component']->name;
101
  } else {
102
+ $component = $subject = '';
103
+ }
104
+
105
+ if ( __( 'Core', 'query-monitor' ) !== $component ) {
106
+ $subject .= ' non-core';
107
  }
108
 
109
  printf( // WPCS: XSS ok.
110
  '<tr data-qm-subject="%s" %s>',
111
+ esc_attr( $subject ),
112
  $attr
113
  );
114
 
153
  } else {
154
  echo '<td class="qm-ltr qm-nowrap' . esc_attr( $class ) . '">';
155
  echo '<code>' . esc_html( $action['callback']['name'] ) . '</code>';
 
156
 
157
+ if ( isset( $action['callback']['error'] ) ) {
158
+ echo '<br>';
159
+ echo esc_html( sprintf(
160
+ /* translators: %s: Error message text */
161
+ __( 'Error: %s', 'query-monitor' ),
162
+ $action['callback']['error']->get_error_message()
163
+ ) );
164
+ }
165
+
166
+ echo '</td>';
167
  }
168
 
 
169
  echo '<td class="qm-nowrap' . esc_attr( $class ) . '">';
170
  echo esc_html( $component );
171
  echo '</td>';
output/html/http.php CHANGED
@@ -69,8 +69,8 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
69
  /* translators: A non-blocking HTTP API request */
70
  $response = __( 'Non-blocking', 'query-monitor' );
71
  } else {
72
- $code = wp_remote_retrieve_response_code( $row['response'] );
73
- $msg = wp_remote_retrieve_response_message( $row['response'] );
74
 
75
  if ( intval( $code ) >= 400 ) {
76
  $is_error = true;
@@ -84,9 +84,11 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
84
  $css = 'qm-warn';
85
  }
86
 
87
- $url = self::format_url( $row['url'] );
88
  $info = '';
89
 
 
 
90
  if ( 'https' === parse_url( $row['url'], PHP_URL_SCHEME ) ) {
91
  if ( empty( $row['args']['sslverify'] ) && empty( $row['args']['local'] ) ) {
92
  $info .= '<span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( sprintf(
69
  /* translators: A non-blocking HTTP API request */
70
  $response = __( 'Non-blocking', 'query-monitor' );
71
  } else {
72
+ $code = wp_remote_retrieve_response_code( $row['response'] );
73
+ $msg = wp_remote_retrieve_response_message( $row['response'] );
74
 
75
  if ( intval( $code ) >= 400 ) {
76
  $is_error = true;
84
  $css = 'qm-warn';
85
  }
86
 
87
+ $url = self::format_url( $row['url'] );
88
  $info = '';
89
 
90
+ $url = preg_replace( '|^http:|', '<span class="qm-warn">http</span>:', $url );
91
+
92
  if ( 'https' === parse_url( $row['url'], PHP_URL_SCHEME ) ) {
93
  if ( empty( $row['args']['sslverify'] ) && empty( $row['args']['local'] ) ) {
94
  $info .= '<span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( sprintf(
output/html/logger.php CHANGED
@@ -43,7 +43,7 @@ class QM_Output_Html_Logger extends QM_Output_Html {
43
  foreach ( $data['logs'] as $row ) {
44
  $component = $row['trace']->get_component();
45
 
46
- $row_attr = array();
47
  $row_attr['data-qm-component'] = $component->name;
48
  $row_attr['data-qm-type'] = ucfirst( $row['level'] );
49
 
43
  foreach ( $data['logs'] as $row ) {
44
  $component = $row['trace']->get_component();
45
 
46
+ $row_attr = array();
47
  $row_attr['data-qm-component'] = $component->name;
48
  $row_attr['data-qm-type'] = ucfirst( $row['level'] );
49
 
output/html/overview.php CHANGED
@@ -36,23 +36,23 @@ class QM_Output_Html_Overview extends QM_Output_Html {
36
  }
37
  }
38
 
39
- $qm_broken = __( 'A JavaScript problem on the page is preventing Query Monitor from working correctly. jQuery may have been blocked from loading.', 'query-monitor' );
40
  $ajax_errors = __( 'PHP errors were triggered during an Ajax request. See your browser developer console for details.', 'query-monitor' );
41
 
42
  $this->before_non_tabular_output();
43
 
44
- echo '<div class="qm-section" id="qm-broken">';
45
  echo '<p class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $qm_broken ) . '</p>';
46
- echo '</div>';
47
 
48
- echo '<div class="qm-section" id="qm-ajax-errors">';
49
  echo '<p class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $ajax_errors ) . '</p>';
50
- echo '</div>';
51
 
52
  echo '</div>';
53
  echo '<div class="qm-boxed">';
54
 
55
- echo '<div class="qm-section">';
56
  echo '<h3>' . esc_html__( 'Page Generation Time', 'query-monitor' ) . '</h3>';
57
  echo '<p class="qm-item">';
58
  echo esc_html( number_format_i18n( $data['time_taken'], 4 ) );
@@ -72,13 +72,18 @@ class QM_Output_Html_Overview extends QM_Output_Html {
72
  echo '</span>';
73
  } else {
74
  echo '<br><span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
75
- esc_html_e( 'No execution time limit', 'query-monitor' );
 
 
 
 
 
76
  echo '</span>';
77
  }
78
  echo '</p>';
79
- echo '</div>';
80
 
81
- echo '<div class="qm-section">';
82
  echo '<h3>' . esc_html__( 'Peak Memory Usage', 'query-monitor' ) . '</h3>';
83
  echo '<p class="qm-item">';
84
 
@@ -106,23 +111,28 @@ class QM_Output_Html_Overview extends QM_Output_Html {
106
  echo '</span>';
107
  } else {
108
  echo '<br><span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
109
- esc_html_e( 'No memory limit', 'query-monitor' );
 
 
 
 
 
110
  echo '</span>';
111
  }
112
  }
113
 
114
  echo '</p>';
115
- echo '</div>';
116
 
117
  if ( isset( $db_query_num ) ) {
118
- echo '<div class="qm-section">';
119
  echo '<h3>' . esc_html__( 'Database Query Time', 'query-monitor' ) . '</h3>';
120
  echo '<p class="qm-item">';
121
  echo esc_html( number_format_i18n( $db_queries_data['total_time'], 4 ) );
122
  echo '</p>';
123
- echo '</div>';
124
 
125
- echo '<div class="qm-section">';
126
  echo '<h3>' . esc_html__( 'Database Queries', 'query-monitor' ) . '</h3>';
127
  echo '<p class="qm-item">';
128
 
@@ -140,10 +150,10 @@ class QM_Output_Html_Overview extends QM_Output_Html {
140
  echo esc_html__( 'Total', 'query-monitor' ) . ': ' . esc_html( number_format_i18n( $db_queries_data['total_qs'] ) );
141
 
142
  echo '</p>';
143
- echo '</div>';
144
  }
145
 
146
- echo '<div class="qm-section">';
147
  echo '<h3>' . esc_html__( 'Object Cache', 'query-monitor' ) . '</h3>';
148
  echo '<p class="qm-item">';
149
 
@@ -198,7 +208,7 @@ class QM_Output_Html_Overview extends QM_Output_Html {
198
  }
199
 
200
  echo '</p>';
201
- echo '</div>';
202
 
203
  $this->after_non_tabular_output();
204
  }
36
  }
37
  }
38
 
39
+ $qm_broken = __( 'A JavaScript problem on the page is preventing Query Monitor from working correctly. jQuery may have been blocked from loading.', 'query-monitor' );
40
  $ajax_errors = __( 'PHP errors were triggered during an Ajax request. See your browser developer console for details.', 'query-monitor' );
41
 
42
  $this->before_non_tabular_output();
43
 
44
+ echo '<section id="qm-broken">';
45
  echo '<p class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $qm_broken ) . '</p>';
46
+ echo '</section>';
47
 
48
+ echo '<section id="qm-ajax-errors">';
49
  echo '<p class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $ajax_errors ) . '</p>';
50
+ echo '</section>';
51
 
52
  echo '</div>';
53
  echo '<div class="qm-boxed">';
54
 
55
+ echo '<section>';
56
  echo '<h3>' . esc_html__( 'Page Generation Time', 'query-monitor' ) . '</h3>';
57
  echo '<p class="qm-item">';
58
  echo esc_html( number_format_i18n( $data['time_taken'], 4 ) );
72
  echo '</span>';
73
  } else {
74
  echo '<br><span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
75
+ printf(
76
+ /* translators: 1: Name of the PHP directive, 2: Value of the PHP directive */
77
+ esc_html__( 'No execution time limit. The %1$s PHP configuration directive is set to %2$s.', 'query-monitor' ),
78
+ '<code>max_execution_time</code>',
79
+ '0'
80
+ );
81
  echo '</span>';
82
  }
83
  echo '</p>';
84
+ echo '</section>';
85
 
86
+ echo '<section>';
87
  echo '<h3>' . esc_html__( 'Peak Memory Usage', 'query-monitor' ) . '</h3>';
88
  echo '<p class="qm-item">';
89
 
111
  echo '</span>';
112
  } else {
113
  echo '<br><span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
114
+ printf(
115
+ /* translators: 1: Name of the PHP directive, 2: Value of the PHP directive */
116
+ esc_html__( 'No memory limit. The %1$s PHP configuration directive is set to %2$s.', 'query-monitor' ),
117
+ '<code>memory_limit</code>',
118
+ '0'
119
+ );
120
  echo '</span>';
121
  }
122
  }
123
 
124
  echo '</p>';
125
+ echo '</section>';
126
 
127
  if ( isset( $db_query_num ) ) {
128
+ echo '<section>';
129
  echo '<h3>' . esc_html__( 'Database Query Time', 'query-monitor' ) . '</h3>';
130
  echo '<p class="qm-item">';
131
  echo esc_html( number_format_i18n( $db_queries_data['total_time'], 4 ) );
132
  echo '</p>';
133
+ echo '</section>';
134
 
135
+ echo '<section>';
136
  echo '<h3>' . esc_html__( 'Database Queries', 'query-monitor' ) . '</h3>';
137
  echo '<p class="qm-item">';
138
 
150
  echo esc_html__( 'Total', 'query-monitor' ) . ': ' . esc_html( number_format_i18n( $db_queries_data['total_qs'] ) );
151
 
152
  echo '</p>';
153
+ echo '</section>';
154
  }
155
 
156
+ echo '<section>';
157
  echo '<h3>' . esc_html__( 'Object Cache', 'query-monitor' ) . '</h3>';
158
  echo '<p class="qm-item">';
159
 
208
  }
209
 
210
  echo '</p>';
211
+ echo '</section>';
212
 
213
  $this->after_non_tabular_output();
214
  }
output/html/php_errors.php CHANGED
@@ -22,7 +22,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
22
  return;
23
  }
24
 
25
- $levels = array(
26
  'Warning',
27
  'Notice',
28
  'Strict',
@@ -59,8 +59,8 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
59
 
60
  foreach ( $data[ $error_group ][ $type ] as $error ) {
61
 
62
- $component = $error['trace']->get_component();
63
- $row_attr = array();
64
  $row_attr['data-qm-component'] = $component->name;
65
  $row_attr['data-qm-type'] = ucfirst( $type );
66
 
@@ -159,7 +159,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
159
 
160
  public function admin_menu( array $menu ) {
161
 
162
- $data = $this->collector->get_data();
163
  $menu_label = array();
164
 
165
  $types = array(
@@ -173,26 +173,26 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
173
  'warning' => _nx_noop( '%s Warning', '%s Warnings', 'PHP error level', 'query-monitor' ),
174
  );
175
 
176
- $key = 'quiet';
177
  $generic = false;
178
 
179
  foreach ( $types as $type => $label ) {
180
 
181
- $count = 0;
182
  $has_errors = false;
183
 
184
  if ( isset( $data['suppressed'][ $type ] ) ) {
185
  $has_errors = true;
186
- $generic = true;
187
  }
188
  if ( isset( $data['silenced'][ $type ] ) ) {
189
  $has_errors = true;
190
- $generic = true;
191
  }
192
  if ( isset( $data['errors'][ $type ] ) ) {
193
  $has_errors = true;
194
- $key = $type;
195
- $count += array_sum( wp_list_pluck( $data['errors'][ $type ], 'calls' ) );
196
  }
197
 
198
  if ( ! $has_errors ) {
@@ -200,7 +200,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
200
  }
201
 
202
  if ( $count ) {
203
- $label = sprintf(
204
  translate_nooped_plural(
205
  $label,
206
  $count,
22
  return;
23
  }
24
 
25
+ $levels = array(
26
  'Warning',
27
  'Notice',
28
  'Strict',
59
 
60
  foreach ( $data[ $error_group ][ $type ] as $error ) {
61
 
62
+ $component = $error['trace']->get_component();
63
+ $row_attr = array();
64
  $row_attr['data-qm-component'] = $component->name;
65
  $row_attr['data-qm-type'] = ucfirst( $type );
66
 
159
 
160
  public function admin_menu( array $menu ) {
161
 
162
+ $data = $this->collector->get_data();
163
  $menu_label = array();
164
 
165
  $types = array(
173
  'warning' => _nx_noop( '%s Warning', '%s Warnings', 'PHP error level', 'query-monitor' ),
174
  );
175
 
176
+ $key = 'quiet';
177
  $generic = false;
178
 
179
  foreach ( $types as $type => $label ) {
180
 
181
+ $count = 0;
182
  $has_errors = false;
183
 
184
  if ( isset( $data['suppressed'][ $type ] ) ) {
185
  $has_errors = true;
186
+ $generic = true;
187
  }
188
  if ( isset( $data['silenced'][ $type ] ) ) {
189
  $has_errors = true;
190
+ $generic = true;
191
  }
192
  if ( isset( $data['errors'][ $type ] ) ) {
193
  $has_errors = true;
194
+ $key = $type;
195
+ $count += array_sum( wp_list_pluck( $data['errors'][ $type ], 'calls' ) );
196
  }
197
 
198
  if ( ! $has_errors ) {
200
  }
201
 
202
  if ( $count ) {
203
+ $label = sprintf(
204
  translate_nooped_plural(
205
  $label,
206
  $count,
output/html/request.php CHANGED
@@ -40,10 +40,10 @@ class QM_Output_Html_Request extends QM_Output_Html {
40
  $value = '<em>' . esc_html__( 'none', 'query-monitor' ) . '</em>';
41
  }
42
 
43
- echo '<div class="qm-section">';
44
  echo '<h3>' . esc_html( $name ) . '</h3>';
45
  echo '<p class="qm-ltr"><code>' . $value . '</code></p>'; // WPCS: XSS ok.
46
- echo '</div>';
47
  }
48
 
49
  echo '</div>';
@@ -51,7 +51,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
51
  echo '<div class="qm-boxed qm-boxed-wrap">';
52
 
53
  if ( ! empty( $data['matching_rewrites'] ) ) {
54
- echo '<div class="qm-section">';
55
  echo '<h3>' . esc_html__( 'All Matching Rewrite Rules', 'query-monitor' ) . '</h3>';
56
  echo '<table>';
57
 
@@ -67,10 +67,10 @@ class QM_Output_Html_Request extends QM_Output_Html {
67
  }
68
 
69
  echo '</table>';
70
- echo '</div>';
71
  }
72
 
73
- echo '<div class="qm-section">';
74
  echo '<h3>';
75
  esc_html_e( 'Query Vars', 'query-monitor' );
76
  echo '</h3>';
@@ -99,7 +99,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
99
  echo '<th scope="row" class="qm-ltr">' . esc_html( $var ) . '</td>';
100
  }
101
 
102
- if ( is_array( $value ) or is_object( $value ) ) {
103
  echo '<td class="qm-ltr"><pre>';
104
  echo esc_html( print_r( $value, true ) );
105
  echo '</pre></td>';
@@ -118,9 +118,9 @@ class QM_Output_Html_Request extends QM_Output_Html {
118
 
119
  }
120
 
121
- echo '</div>';
122
 
123
- echo '<div class="qm-section">';
124
  echo '<h3>' . esc_html__( 'Queried Object', 'query-monitor' ) . '</h3>';
125
 
126
  if ( ! empty( $data['queried_object'] ) ) {
@@ -133,9 +133,9 @@ class QM_Output_Html_Request extends QM_Output_Html {
133
  echo '<p><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></p>';
134
  }
135
 
136
- echo '</div>';
137
 
138
- echo '<div class="qm-section">';
139
  echo '<h3>' . esc_html__( 'Current User', 'query-monitor' ) . '</h3>';
140
 
141
  if ( ! empty( $data['user']['data'] ) ) {
@@ -147,10 +147,10 @@ class QM_Output_Html_Request extends QM_Output_Html {
147
  echo '<p><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></p>';
148
  }
149
 
150
- echo '</div>';
151
 
152
  if ( ! empty( $data['multisite'] ) ) {
153
- echo '<div class="qm-section">';
154
  echo '<h3>' . esc_html__( 'Multisite', 'query-monitor' ) . '</h3>';
155
 
156
  foreach ( $data['multisite'] as $var => $value ) {
@@ -160,7 +160,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
160
  );
161
  }
162
 
163
- echo '</div>';
164
  }
165
 
166
  $this->after_non_tabular_output();
40
  $value = '<em>' . esc_html__( 'none', 'query-monitor' ) . '</em>';
41
  }
42
 
43
+ echo '<section>';
44
  echo '<h3>' . esc_html( $name ) . '</h3>';
45
  echo '<p class="qm-ltr"><code>' . $value . '</code></p>'; // WPCS: XSS ok.
46
+ echo '</section>';
47
  }
48
 
49
  echo '</div>';
51
  echo '<div class="qm-boxed qm-boxed-wrap">';
52
 
53
  if ( ! empty( $data['matching_rewrites'] ) ) {
54
+ echo '<section>';
55
  echo '<h3>' . esc_html__( 'All Matching Rewrite Rules', 'query-monitor' ) . '</h3>';
56
  echo '<table>';
57
 
67
  }
68
 
69
  echo '</table>';
70
+ echo '</section>';
71
  }
72
 
73
+ echo '<section>';
74
  echo '<h3>';
75
  esc_html_e( 'Query Vars', 'query-monitor' );
76
  echo '</h3>';
99
  echo '<th scope="row" class="qm-ltr">' . esc_html( $var ) . '</td>';
100
  }
101
 
102
+ if ( is_array( $value ) || is_object( $value ) ) {
103
  echo '<td class="qm-ltr"><pre>';
104
  echo esc_html( print_r( $value, true ) );
105
  echo '</pre></td>';
118
 
119
  }
120
 
121
+ echo '</section>';
122
 
123
+ echo '<section>';
124
  echo '<h3>' . esc_html__( 'Queried Object', 'query-monitor' ) . '</h3>';
125
 
126
  if ( ! empty( $data['queried_object'] ) ) {
133
  echo '<p><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></p>';
134
  }
135
 
136
+ echo '</section>';
137
 
138
+ echo '<section>';
139
  echo '<h3>' . esc_html__( 'Current User', 'query-monitor' ) . '</h3>';
140
 
141
  if ( ! empty( $data['user']['data'] ) ) {
147
  echo '<p><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></p>';
148
  }
149
 
150
+ echo '</section>';
151
 
152
  if ( ! empty( $data['multisite'] ) ) {
153
+ echo '<section>';
154
  echo '<h3>' . esc_html__( 'Multisite', 'query-monitor' ) . '</h3>';
155
 
156
  foreach ( $data['multisite'] as $var => $value ) {
160
  );
161
  }
162
 
163
+ echo '</section>';
164
  }
165
 
166
  $this->after_non_tabular_output();
output/html/theme.php CHANGED
@@ -22,29 +22,46 @@ class QM_Output_Html_Theme extends QM_Output_Html {
22
 
23
  $this->before_non_tabular_output();
24
 
25
- echo '<div class="qm-section">';
 
 
 
 
 
 
 
 
 
 
 
26
  echo '<h3>' . esc_html__( 'Template File', 'query-monitor' ) . '</h3>';
27
 
28
  if ( ! empty( $data['template_path'] ) ) {
29
  if ( $data['is_child_theme'] ) {
30
- echo '<p class="qm-ltr">' . self::output_filename( $data['theme_template_file'], $data['template_path'], 0, true ) . '</p>'; // WPCS: XSS ok.
31
  } else {
32
- echo '<p class="qm-ltr">' . self::output_filename( $data['template_file'], $data['template_path'], 0, true ) . '</p>'; // WPCS: XSS ok.
33
  }
 
 
 
 
 
 
34
  } else {
35
  echo '<p><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></p>';
36
  }
37
 
38
- echo '</div>';
39
 
40
  if ( ! empty( $data['template_hierarchy'] ) ) {
41
- echo '<div class="qm-section">';
42
  echo '<h3>' . esc_html__( 'Template Hierarchy', 'query-monitor' ) . '</h3>';
43
  echo '<ol class="qm-ltr qm-numbered"><li>' . implode( '</li><li>', array_map( 'esc_html', $data['template_hierarchy'] ) ) . '</li></ol>';
44
- echo '</div>';
45
  }
46
 
47
- echo '<div class="qm-section">';
48
  echo '<h3>' . esc_html__( 'Template Parts', 'query-monitor' ) . '</h3>';
49
 
50
  if ( ! empty( $data['template_parts'] ) ) {
@@ -58,7 +75,23 @@ class QM_Output_Html_Theme extends QM_Output_Html {
58
  echo '<ul class="qm-ltr">';
59
 
60
  foreach ( $parts as $filename => $display ) {
61
- echo '<li>' . self::output_filename( $display, $filename, 0, true ) . '</li>'; // WPCS: XSS ok.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }
63
 
64
  echo '</ul>';
@@ -67,10 +100,10 @@ class QM_Output_Html_Theme extends QM_Output_Html {
67
  echo '<p><em>' . esc_html__( 'None', 'query-monitor' ) . '</em></p>';
68
  }
69
 
70
- echo '</div>';
71
 
72
  if ( ! empty( $data['timber_files'] ) ) {
73
- echo '<div class="qm-section">';
74
  echo '<h3>' . esc_html__( 'Timber Files', 'query-monitor' ) . '</h3>';
75
  echo '<ul class="qm-ltr">';
76
 
@@ -79,22 +112,11 @@ class QM_Output_Html_Theme extends QM_Output_Html {
79
  }
80
 
81
  echo '</ul>';
82
- echo '</div>';
83
  }
84
 
85
- echo '<div class="qm-section">';
86
- echo '<h3>' . esc_html__( 'Theme', 'query-monitor' ) . '</h3>';
87
- echo '<p>' . esc_html( $data['stylesheet'] ) . '</p>';
88
-
89
- if ( $data['is_child_theme'] ) {
90
- echo '<h3>' . esc_html__( 'Parent Theme:', 'query-monitor' ) . '</h3>';
91
- echo '<p>' . esc_html( $data['template'] ) . '</p>';
92
- }
93
-
94
- echo '</div>';
95
-
96
  if ( ! empty( $data['body_class'] ) ) {
97
- echo '<div class="qm-section">';
98
 
99
  echo '<h3>' . esc_html__( 'Body Classes', 'query-monitor' ) . '</h3>';
100
  echo '<ul class="qm-ltr">';
@@ -104,7 +126,7 @@ class QM_Output_Html_Theme extends QM_Output_Html {
104
  }
105
 
106
  echo '</ul>';
107
- echo '</div>';
108
  }
109
 
110
  $this->after_non_tabular_output();
@@ -115,14 +137,19 @@ class QM_Output_Html_Theme extends QM_Output_Html {
115
  $data = $this->collector->get_data();
116
 
117
  if ( isset( $data['template_file'] ) ) {
118
- $menu['theme'] = $this->menu( array(
119
- 'title' => esc_html( sprintf(
120
- /* translators: %s: Template file name */
121
- __( 'Template: %s', 'query-monitor' ),
122
- ( $data['is_child_theme'] ? $data['theme_template_file'] : $data['template_file'] )
123
- ) ),
124
- ) );
125
  }
 
 
 
 
 
 
 
 
 
126
  return $menu;
127
 
128
  }
22
 
23
  $this->before_non_tabular_output();
24
 
25
+ echo '<section>';
26
+ echo '<h3>' . esc_html__( 'Theme', 'query-monitor' ) . '</h3>';
27
+ echo '<p>' . esc_html( $data['stylesheet'] ) . '</p>';
28
+
29
+ if ( $data['is_child_theme'] ) {
30
+ echo '<h3>' . esc_html__( 'Parent Theme:', 'query-monitor' ) . '</h3>';
31
+ echo '<p>' . esc_html( $data['template'] ) . '</p>';
32
+ }
33
+
34
+ echo '</section>';
35
+
36
+ echo '<section>';
37
  echo '<h3>' . esc_html__( 'Template File', 'query-monitor' ) . '</h3>';
38
 
39
  if ( ! empty( $data['template_path'] ) ) {
40
  if ( $data['is_child_theme'] ) {
41
+ $display = $data['theme_template_file'];
42
  } else {
43
+ $display = $data['template_file'];
44
  }
45
+ if ( self::has_clickable_links() ) {
46
+ $file = $data['template_path'];
47
+ } else {
48
+ $file = false;
49
+ }
50
+ echo '<p class="qm-ltr">' . self::output_filename( $display, $file, 0, true ) . '</p>'; // WPCS: XSS ok.
51
  } else {
52
  echo '<p><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></p>';
53
  }
54
 
55
+ echo '</section>';
56
 
57
  if ( ! empty( $data['template_hierarchy'] ) ) {
58
+ echo '<section>';
59
  echo '<h3>' . esc_html__( 'Template Hierarchy', 'query-monitor' ) . '</h3>';
60
  echo '<ol class="qm-ltr qm-numbered"><li>' . implode( '</li><li>', array_map( 'esc_html', $data['template_hierarchy'] ) ) . '</li></ol>';
61
+ echo '</section>';
62
  }
63
 
64
+ echo '<section>';
65
  echo '<h3>' . esc_html__( 'Template Parts', 'query-monitor' ) . '</h3>';
66
 
67
  if ( ! empty( $data['template_parts'] ) ) {
75
  echo '<ul class="qm-ltr">';
76
 
77
  foreach ( $parts as $filename => $display ) {
78
+ echo '<li>';
79
+
80
+ if ( self::has_clickable_links() ) {
81
+ echo self::output_filename( $display, $filename, 0, true ); // WPCS: XSS ok.
82
+ } else {
83
+ echo esc_html( $display );
84
+ }
85
+
86
+ if ( $data['count_template_parts'][ $filename ] > 1 ) {
87
+ $count = sprintf(
88
+ /* translators: %s: The number of times that a template part file was included in the page */
89
+ _nx( 'Included %s time', 'Included %s times', $data['count_template_parts'][ $filename ], 'template parts', 'query-monitor' ),
90
+ esc_html( number_format_i18n( $data['count_template_parts'][ $filename ] ) )
91
+ );
92
+ echo '<br><span class="qm-info qm-supplemental">' . esc_html( $count ) . '</span>';
93
+ }
94
+ echo '</li>';
95
  }
96
 
97
  echo '</ul>';
100
  echo '<p><em>' . esc_html__( 'None', 'query-monitor' ) . '</em></p>';
101
  }
102
 
103
+ echo '</section>';
104
 
105
  if ( ! empty( $data['timber_files'] ) ) {
106
+ echo '<section>';
107
  echo '<h3>' . esc_html__( 'Timber Files', 'query-monitor' ) . '</h3>';
108
  echo '<ul class="qm-ltr">';
109
 
112
  }
113
 
114
  echo '</ul>';
115
+ echo '</section>';
116
  }
117
 
 
 
 
 
 
 
 
 
 
 
 
118
  if ( ! empty( $data['body_class'] ) ) {
119
+ echo '<section>';
120
 
121
  echo '<h3>' . esc_html__( 'Body Classes', 'query-monitor' ) . '</h3>';
122
  echo '<ul class="qm-ltr">';
126
  }
127
 
128
  echo '</ul>';
129
+ echo '</section>';
130
  }
131
 
132
  $this->after_non_tabular_output();
137
  $data = $this->collector->get_data();
138
 
139
  if ( isset( $data['template_file'] ) ) {
140
+ $name = ( $data['is_child_theme'] ) ? $data['theme_template_file'] : $data['template_file'];
141
+ } else {
142
+ $name = __( 'Unknown', 'query-monitor' );
 
 
 
 
143
  }
144
+
145
+ $menu['theme'] = $this->menu( array(
146
+ 'title' => esc_html( sprintf(
147
+ /* translators: %s: Template file name */
148
+ __( 'Template: %s', 'query-monitor' ),
149
+ $name
150
+ ) ),
151
+ ) );
152
+
153
  return $menu;
154
 
155
  }
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.1.1
14
  * Plugin URI: https://querymonitor.com/
15
  * Author: John Blackbourn & contributors
16
  * Author URI: https://querymonitor.com/
@@ -29,12 +29,16 @@
29
  * GNU General Public License for more details.
30
  */
31
 
32
- defined( 'ABSPATH' ) or die();
33
 
34
  $qm_dir = dirname( __FILE__ );
35
 
36
  require_once "{$qm_dir}/classes/Plugin.php";
37
 
 
 
 
 
38
  # No autoloaders for us. See https://github.com/johnbillion/query-monitor/issues/7
39
  foreach ( array( 'Activation', 'Util', 'QM' ) as $qm_class ) {
40
  require_once "{$qm_dir}/classes/{$qm_class}.php";
@@ -42,11 +46,7 @@ foreach ( array( 'Activation', 'Util', 'QM' ) as $qm_class ) {
42
 
43
  QM_Activation::init( __FILE__ );
44
 
45
- if ( ! QM_Plugin::php_version_met() ) {
46
- return;
47
- }
48
-
49
- if ( defined( 'QM_DISABLED' ) and QM_DISABLED ) {
50
  return;
51
  }
52
 
10
  *
11
  * Plugin Name: Query Monitor
12
  * Description: The Developer Tools Panel for WordPress.
13
+ * Version: 3.2.0
14
  * Plugin URI: https://querymonitor.com/
15
  * Author: John Blackbourn & contributors
16
  * Author URI: https://querymonitor.com/
29
  * GNU General Public License for more details.
30
  */
31
 
32
+ defined( 'ABSPATH' ) || die();
33
 
34
  $qm_dir = dirname( __FILE__ );
35
 
36
  require_once "{$qm_dir}/classes/Plugin.php";
37
 
38
+ if ( ! QM_Plugin::php_version_met() ) {
39
+ return;
40
+ }
41
+
42
  # No autoloaders for us. See https://github.com/johnbillion/query-monitor/issues/7
43
  foreach ( array( 'Activation', 'Util', 'QM' ) as $qm_class ) {
44
  require_once "{$qm_dir}/classes/{$qm_class}.php";
46
 
47
  QM_Activation::init( __FILE__ );
48
 
49
+ if ( defined( 'QM_DISABLED' ) && QM_DISABLED ) {
 
 
 
 
50
  return;
51
  }
52
 
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  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: 4.9
6
- Stable tag: 3.1.1
7
  License: GPLv2 or later
8
  Requires PHP: 5.3
9
 
@@ -11,7 +11,7 @@ Query Monitor is the developer tools panel for WordPress.
11
 
12
  == Description ==
13
 
14
- Query Monitor is the developer tools panel for WordPress. It includes some advanced features such as Ajax and REST API debugging, and the ability to narrow down its output by plugin or theme.
15
 
16
  Query Monitor focuses heavily on presenting its information in a useful manner. For example, aggregate database query information is made available, allowing you to quickly determine poorly performing plugins, themes, or functions. It adds an admin toolbar menu showing an overview of the current page, with complete data shown in a panel once you select a menu item.
17
 
2
  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.0
6
+ Stable tag: 3.2.0
7
  License: GPLv2 or later
8
  Requires PHP: 5.3
9
 
11
 
12
  == Description ==
13
 
14
+ Query Monitor is the developer tools panel for WordPress. It includes some advanced features such as debugging of Ajax, REST API, and Gutenberg blocks, and the ability to narrow down its output by plugin or theme.
15
 
16
  Query Monitor focuses heavily on presenting its information in a useful manner. For example, aggregate database query information is made available, allowing you to quickly determine poorly performing plugins, themes, or functions. It adds an admin toolbar menu showing an overview of the current page, with complete data shown in a panel once you select a menu item.
17
 
wp-content/db.php CHANGED
@@ -12,9 +12,9 @@
12
  * @package query-monitor
13
  */
14
 
15
- defined( 'ABSPATH' ) or die();
16
 
17
- if ( defined( 'QM_DISABLED' ) and QM_DISABLED ) {
18
  return;
19
  }
20
 
@@ -66,7 +66,7 @@ class QM_DB extends wpdb {
66
  /**
67
  * Class constructor
68
  */
69
- function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
70
 
71
  foreach ( $this->qm_php_vars as $setting => &$val ) {
72
  $val = ini_get( $setting );
@@ -84,7 +84,7 @@ class QM_DB extends wpdb {
84
  * @param string $query Database query
85
  * @return int|false Number of rows affected/selected or false on error
86
  */
87
- function query( $query ) {
88
  if ( ! $this->ready ) {
89
  if ( isset( $this->check_current_query ) ) {
90
  // This property was introduced in WP 4.2
@@ -133,4 +133,5 @@ class QM_DB extends wpdb {
133
 
134
  }
135
 
 
136
  $wpdb = new QM_DB( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
12
  * @package query-monitor
13
  */
14
 
15
+ defined( 'ABSPATH' ) || die();
16
 
17
+ if ( defined( 'QM_DISABLED' ) && QM_DISABLED ) {
18
  return;
19
  }
20
 
66
  /**
67
  * Class constructor
68
  */
69
+ public function __construct( $dbuser, $dbpassword, $dbname, $dbhost ) {
70
 
71
  foreach ( $this->qm_php_vars as $setting => &$val ) {
72
  $val = ini_get( $setting );
84
  * @param string $query Database query
85
  * @return int|false Number of rows affected/selected or false on error
86
  */
87
+ public function query( $query ) {
88
  if ( ! $this->ready ) {
89
  if ( isset( $this->check_current_query ) ) {
90
  // This property was introduced in WP 4.2
133
 
134
  }
135
 
136
+ // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
137
  $wpdb = new QM_DB( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );