Query Monitor - Version 3.1.0

Version Description

Download this release

Release Info

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

Code changes from version 3.0.1 to 3.1.0

assets/compat.css DELETED
@@ -1,59 +0,0 @@
1
- /*
2
- Copyright 2009-2017 John Blackbourn
3
-
4
- This program is free software; you can redistribute it and/or modify
5
- it under the terms of the GNU General Public License as published by
6
- the Free Software Foundation; either version 2 of the License, or
7
- (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU General Public License for more details.
13
-
14
- */
15
-
16
- body:not(.mp6) #wpadminbar .quicklinks .menupop ul li.qm-true > a {
17
- color: #4a4 !important;
18
- }
19
-
20
- body:not(.mp6) #wp-admin-bar-query-monitor-deprecated,
21
- body:not(.mp6) #wp-admin-bar-query-monitor-stricts {
22
- background-color: #eee !important;
23
- }
24
-
25
- body:not(.mp6) #wpadminbar .qm-deprecated,
26
- body:not(.mp6) #wpadminbar .qm-strict {
27
- background-color: #000;
28
- }
29
-
30
- body:not(.mp6) #wp-admin-bar-query-monitor-deprecated a,
31
- body:not(.mp6) #wp-admin-bar-query-monitor-stricts a {
32
- color: #555 !important;
33
- }
34
-
35
- body:not(.mp6) #wp-admin-bar-query-monitor.hover a small,
36
- body:not(.mp6) #wp-admin-bar-query-monitor.hover a .ab-label {
37
- color: #333 !important;
38
- }
39
-
40
- /* for mp6 on 3.7, reduce the menu icon line height */
41
- body.mp6 #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
42
- line-height: 30px !important;
43
- }
44
-
45
- @media screen and (max-width: 782px) {
46
- /* for default 3.7, hide the menu icon */
47
- body:not(.mp6) #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
48
- display: none !important;
49
- }
50
- /* for default 3.7, show the menu text */
51
- body:not(.mp6) #wpadminbar #wp-admin-bar-query-monitor .ab-label {
52
- display: inline-block !important;
53
- }
54
- }
55
-
56
- /* remove the label margin */
57
- #wpadminbar #wp-admin-bar-query-monitor .ab-label {
58
- margin: 0 !important;
59
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/query-monitor.css CHANGED
@@ -1,82 +1,54 @@
1
- /*
2
- Copyright 2009-2017 John Blackbourn
3
-
4
- This program is free software; you can redistribute it and/or modify
5
- it under the terms of the GNU General Public License as published by
6
- the Free Software Foundation; either version 2 of the License, or
7
- (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU General Public License for more details.
13
-
14
- */
15
-
16
  /* === Admin Toolbar === */
17
-
18
  #wpadminbar .quicklinks .menupop ul li.qm-true > a {
19
- color: #8c8 !important;
20
  }
21
-
22
- #wpadminbar .quicklinks .menupop ul li.qm-true > a:focus,
23
- #wpadminbar .quicklinks .menupop ul li.qm-true > a:hover {
24
- color: #4a4 !important;
25
  }
26
-
27
  #wpadminbar .qm-alert {
28
- background-color: #f60;
29
- }
30
-
31
- #wp-admin-bar-query-monitor-deprecateds,
32
- #wp-admin-bar-query-monitor-stricts {
33
- background-color: #555 !important;
34
- }
35
-
36
- #wpadminbar .qm-deprecated,
37
- #wpadminbar .qm-strict {
38
- background-color: #3c3c3c;
39
- }
40
-
41
- #wp-admin-bar-query-monitor-notices {
42
- background-color: #740 !important;
43
  }
44
-
45
  #wpadminbar .qm-notice {
46
- background-color: #740;
47
  }
48
-
49
- #wp-admin-bar-query-monitor-expensive {
50
- background-color: #b60 !important;
51
  }
52
-
53
- #wpadminbar .qm-expensive {
54
- background-color: #b60;
55
  }
56
-
57
- #wp-admin-bar-query-monitor-warnings {
58
- background-color: #c00 !important;
59
  }
60
-
 
61
  #wpadminbar .qm-warning {
62
- background-color: #c00;
63
  }
64
-
65
- #wpadminbar .qm-warning > a {
66
- color: #fff !important;
67
- }
68
-
69
- #wp-admin-bar-query-monitor-errors {
70
- background-color: #c00 !important;
71
  }
72
-
73
  #wpadminbar .qm-error {
74
- background-color: #c00 !important;
75
  }
76
 
77
- #wpadminbar .qm-error > a,
78
- #wpadminbar .qm-alert > a {
79
- color: #fff !important;
 
80
  }
81
 
82
  body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover):not(.hover) .ab-label,
@@ -84,48 +56,51 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
84
  #wp-admin-bar-query-monitor-stricts a,
85
  #wp-admin-bar-query-monitor-notices a,
86
  #wp-admin-bar-query-monitor-expensive a,
 
87
  #wp-admin-bar-query-monitor-warnings a,
88
  #wp-admin-bar-query-monitor-errors a {
89
- color: #eee !important;
90
  }
91
 
92
  #wp-admin-bar-query-monitor small {
93
- font-size: 11px !important;
94
- text-transform: uppercase !important;
95
  }
96
 
97
  #wp-admin-bar-query-monitor.hover a small,
98
  #wp-admin-bar-query-monitor.hover a .ab-label {
99
- text-shadow: none !important;
100
  }
101
 
102
  #wp-admin-bar-query-monitor-placeholder,
103
  #wp-admin-bar-query-monitor-default {
104
- display: none;
105
  }
106
 
107
  #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
108
- font: 18px/44px 'Open Sans', sans-serif !important; /* @todo remove open sans */
109
- width: auto !important;
110
- padding: 0 10px !important;
111
- color: #aaa !important;
112
- display: none !important;
 
113
  }
114
 
115
  @media screen and (max-width: 782px) {
116
- /* force menu icon to show up */
117
- #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
118
- display: block !important;
119
- }
120
- /* hide menu text */
121
- #wpadminbar #wp-admin-bar-query-monitor .ab-label {
122
- display: none !important;
123
- }
124
- }
125
 
 
 
 
 
 
126
  /* === Main QM Panel === */
127
-
128
  #query-monitor,
 
 
 
129
  #query-monitor button,
130
  #query-monitor label,
131
  #query-monitor select,
@@ -137,7 +112,6 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
137
  #query-monitor li,
138
  #query-monitor code,
139
  #query-monitor a,
140
- #query-monitor caption,
141
  #query-monitor h1,
142
  #query-monitor h2,
143
  #query-monitor h3,
@@ -145,572 +119,552 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
145
  #query-monitor h5,
146
  #query-monitor h6,
147
  #query-monitor p {
148
- /* reset */
149
- background: transparent !important;
150
- color: #333 !important;
151
- box-sizing: border-box !important;
152
- text-align: left !important;
153
- font-style: normal !important;
154
- font-weight: normal !important;
155
- font-size: 12px !important;
156
- line-height: 18px !important;
157
- font-family: 'Helvetica Neue', 'Lucida Grande', 'Arial', sans-serif !important;
158
- border: none !important;
159
- padding: 0 !important;
160
- margin: 0 !important;
161
- vertical-align: top !important;
162
- text-shadow: none !important;
163
- text-transform: none !important;
164
- -webkit-font-smoothing: auto !important;
165
- letter-spacing: normal !important;
166
- border-radius: 0 !important;
167
- transition: none !important;
168
- word-wrap: normal !important;
169
- word-break: normal !important;
 
 
170
  }
171
 
172
  #query-monitor {
173
- background: #fff !important;
174
- margin: 0 !important;
175
- border-top: 1px solid #aaa !important;
176
- text-align: left !important;
177
- display: none;
178
- position: fixed;
179
- z-index: 99998 !important;
180
- bottom: 0 !important;
181
- left: 0 !important;
182
- right: 0 !important;
183
- width: 100% !important;
 
184
  }
185
 
186
  #query-monitor.qm-show,
187
  #query-monitor.qm-peek {
188
- height: 27px;
189
- display: flex;
190
- flex-direction: column;
191
  }
192
 
193
  #query-monitor.qm-show {
194
- height: 40%;
195
- }
196
-
197
- #qm-wrapper {
198
- display: flex;
199
- flex-grow: 1;
200
- /* Fix nested scrolling in Firefox. See https://bugzilla.mozilla.org/show_bug.cgi?id=1043520: */
201
- min-height: 0;
202
- }
203
-
204
- #qm-title {
205
- background: #f3f3f3 !important;
206
- border-bottom: 1px solid #aaa !important;
207
- cursor: ns-resize !important;
208
- align-items: center;
209
- display: flex !important;
210
- padding: 0 2px 0 5px !important;
211
- height: 27px !important;
212
- flex-shrink: 0;
213
- }
214
-
215
- #qm-title .qm-title-heading {
216
- flex-grow: 1;
217
- border-right: 1px solid #bbb !important;
218
- margin-right: 8px !important;
219
- }
220
-
221
- #qm-title div.qm-title-heading {
222
- display: none;
223
- }
224
-
225
- #qm-title .qm-title-button {
226
- flex-shrink: 0;
227
- }
228
-
229
- #qm-title .dashicons {
230
- transition: none !important;
231
- }
232
-
233
- #qm-title .qm-button-container-settings .dashicons,
234
- #qm-title .qm-button-container-pin .dashicons {
235
- font-size: 17px !important;
236
- margin-top: 3px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  }
238
-
239
- #qm-title button {
240
- color: #777 !important;
241
- cursor: pointer !important;
242
- margin: 0 0 0 0px !important;
243
- display: inline-block !important;
244
- padding: 0px 2px !important;
245
- }
246
-
247
- #qm-title button:focus,
248
- #qm-title button:hover {
249
- color: #000 !important;
250
- }
251
-
252
- #qm-title button.qm-button-active {
253
- color: #3879d9 !important;
254
- }
255
-
256
- #qm-title .qm-button-container-pin.qm-button-active .dashicons {
257
- transform: rotate( -45deg ) !important;
258
- }
259
-
260
- #qm-title .qm-button-container-pin.qm-button-active .dashicons:before {
261
- margin-left: 2px !important;
262
- }
263
-
264
  #query-monitor .qm {
265
- display: none !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  }
267
-
268
- #qm-panel-menu {
269
- overflow-y: scroll !important;
270
- flex-shrink: 0;
271
- background: #ececec !important;
272
- }
273
-
274
- #qm-panel-menu ul {
275
- padding: 0 !important;
276
- margin: 0 !important;
277
- }
278
-
279
- #qm-panel-menu ul:after {
280
- height: 30px !important;
281
- content: " ";
282
- display: block;
283
- border-right: 1px solid #aaaaaa !important;
284
- }
285
-
286
- #qm-panel-menu li {
287
- padding: 0 !important;
288
- margin: 0 !important;
289
- }
290
-
291
- #qm-panel-menu li a {
292
- display: block !important;
293
- padding: 8px 28px 8px 6px !important;
294
- color: #555 !important;
295
- text-decoration: none !important;
296
- border-bottom: 1px solid #ddd !important;
297
- position: relative !important;
298
- border-right: 1px solid #aaa !important;
299
- background: #f3f3f3 !important;
300
- }
301
-
302
- #qm-panel-menu li a:focus,
303
- #qm-panel-menu li a:hover {
304
- background: #def !important;
305
- color: #222 !important;
306
- }
307
-
308
- #qm-panel-menu li a.qm-selected-menu {
309
- background: #0372aa !important;
310
- color: #fff !important;
311
- }
312
-
313
- #qm-panel-menu li a.qm-selected-menu:after {
314
- right: -1px;
315
- border: solid 8px transparent;
316
- content: " ";
317
- height: 0;
318
- width: 0;
319
- position: absolute;
320
- pointer-events: none;
321
- border-right-color: #fff;
322
- top: 50%;
323
- margin-top: -8px;
324
- }
325
-
326
- #qm-panels {
327
- flex-grow: 1;
328
- overflow-y: scroll;
329
- }
330
-
331
  #query-monitor .qm.qm-panel-show {
332
- display: block !important;
333
  }
334
-
335
  #query-monitor .qm:focus {
336
- outline: 0 !important; /* @TODO might not need this any more */
 
337
  }
338
-
339
  #query-monitor .qm-non-tabular {
340
- padding: 10px 20px !important;
341
  }
342
-
343
  #query-monitor .qm-boxed {
344
- display: flex !important;
 
345
  }
346
-
347
  #query-monitor .qm-boxed:not(#qm-broken) + .qm-boxed {
348
- border-top: 1px solid #dddddd !important;
349
- padding-top: 10px !important;
350
  }
351
-
352
  #query-monitor .qm-boxed-wrap {
353
- flex-wrap: wrap !important;
354
  }
355
-
356
  #query-monitor .qm .qm-none {
357
- margin: 2em !important;
358
  }
359
-
360
  #query-monitor .qm .qm-none p {
361
- text-align: center !important;
362
- font-style: italic !important;
363
  }
364
-
365
  #query-monitor .qm table {
366
- color: #333 !important;
367
- border-collapse: collapse !important;
368
- box-shadow: none !important;
369
- width: 100% !important;
370
- table-layout: auto !important;
371
- margin: 0 !important;
372
- border: none !important;
373
- border-bottom: 1px solid #cccccc !important;
374
  }
375
-
376
  #query-monitor .qm table + table {
377
- margin-top: 5px !important;
378
- border-top: 1px solid #cccccc !important;
379
  }
380
-
381
  #query-monitor #qm-conditionals table,
382
  #query-monitor #qm-overview table {
383
- table-layout: fixed !important;
384
  }
385
-
386
  #query-monitor .qm tr {
387
- border: none !important;
388
  }
389
-
390
  #query-monitor .qm tbody th,
391
  #query-monitor .qm tbody td,
392
  #query-monitor .qm tfoot th,
393
  #query-monitor .qm tfoot td {
394
- border: 1px solid #e0e0e0 !important;
395
- padding: 5px !important;
396
  }
397
-
398
  #query-monitor .qm tbody th,
399
  #query-monitor .qm tbody td {
400
- border-top: none !important;
401
- border-bottom: none !important;
402
  }
403
-
404
  #query-monitor .qm thead th {
405
- box-shadow: 0px 1px 0px #e0e0e0;
406
- border: 1px solid #e0e0e0 !important;
407
- border-top: none !important;
408
- padding: 5px !important;
409
- position: -webkit-sticky !important;
410
- position: sticky !important;
411
- top: 0 !important;
412
- background: #fff !important;
413
- z-index: 1 !important;
414
  }
415
-
416
  #query-monitor .qm thead .qm-th {
417
- display: flex !important;
418
  }
419
-
420
  #query-monitor .qm tfoot tr td,
421
  #query-monitor .qm tfoot tr th {
422
- box-shadow: inset 0px 1px 0px #e0e0e0;
423
- border: 1px solid #e0e0e0 !important;
424
- border-bottom: none !important;
425
- background: #f3f3f3 !important;
426
- position: -webkit-sticky !important;
427
- position: sticky !important;
428
- bottom: 0 !important;
429
  }
430
-
431
- #query-monitor .qm tfoot tr.qm-items-shown td,
432
- #query-monitor .qm tfoot tr.qm-items-shown th {
433
- bottom: 28px !important;
434
- }
435
-
436
  #query-monitor .qm th:first-child,
437
  #query-monitor .qm td:first-child {
438
- border-left: none !important;
439
  }
440
-
441
  #query-monitor .qm th:last-child,
442
  #query-monitor .qm td:last-child {
443
- border-right: none !important;
444
- }
445
-
446
- #query-monitor .qm caption {
447
- caption-side: top !important;
448
- border: none !important;
449
- display: none !important; /* @TODO remove */
450
  }
451
-
452
  #query-monitor .qm tfoot td.qm-num,
453
- #query-monitor .qm th.qm-num {
454
- width: 5.5em !important;
 
 
455
  }
456
-
457
  #query-monitor .qm td.qm-num {
458
- text-align: right !important;
 
 
 
 
 
 
 
 
 
459
  }
460
-
461
  #query-monitor .qm td.qm-has-toggle p,
462
  #query-monitor .qm td .qm-toggler {
463
- padding: 0 22px 0 0 !important;
464
- position: relative !important;
465
  }
466
-
467
  #query-monitor .qm td.qm-has-toggle:not(.qm-toggled-on) .qm-supplemental {
468
- display: none;
469
  }
470
-
471
  #query-monitor .qm .qm-inner-toggle {
472
- padding: 4px 6px !important;
473
  }
474
 
475
  .qm-has-inner .qm-toggled > table {
476
- border-top: 1px solid #eee !important;
477
  }
478
 
479
  .qm-inner {
480
- border-collapse: collapse !important;
481
- margin: 0 !important;
482
- border-style: hidden !important;
483
- width: 100% !important;
484
  }
485
 
486
  #query-monitor .qm td.qm-has-inner .qm-toggler,
487
  #query-monitor .qm td.qm-has-inner {
488
- padding: 0 !important;
489
  }
490
-
491
- #query-monitor .qm-non-tabular h2 {
492
- margin: 0 0 15px 0 !important;
493
- font-size: 14px !important;
494
- color: #444 !important;
495
- }
496
-
497
  #query-monitor .qm-non-tabular h3 {
498
- margin: 15px 0 !important;
499
- font-size: 12px !important;
500
- color: #444 !important;
 
 
 
501
  }
502
-
503
  #query-monitor .qm-non-tabular p {
504
- margin-bottom: 10px !important;
505
  }
506
-
507
- #query-monitor .qm-non-tabular h2 a {
508
- float: right !important;
 
 
509
  }
510
-
511
  #query-monitor .qm-non-tabular .qm-item {
512
- display: inline-block !important;
513
- margin: 0 20px 5px 0 !important;
514
  }
515
-
516
  #query-monitor .qm-non-tabular .qm-section {
517
- margin: 0 0 30px 0 !important;
518
  }
519
-
520
  #query-monitor .qm-non-tabular .qm-boxed .qm-section {
521
- margin: 0 20px 10px 0 !important;
522
- border-right: 1px solid #ddd !important;
523
- padding: 10px 20px 10px 0 !important;
524
  }
525
-
526
  #query-monitor .qm-non-tabular .qm-boxed .qm-section:last-child {
527
- margin-right: 0 !important;
528
- border-right: none !important;
529
- padding-right: 20px !important;
530
  }
531
-
532
  #query-monitor .qm-non-tabular table {
533
- border-bottom-color: #e0e0e0 !important;
534
  }
535
-
536
  #query-monitor .qm ol,
537
  #query-monitor .qm ul {
538
- list-style: none !important;
539
  }
540
-
541
  #query-monitor .qm li {
542
- display: list-item !important;
543
- list-style: none !important;
544
  }
545
-
546
  #query-monitor .qm li::before {
547
- content: '' !important;
548
  }
549
-
550
  #query-monitor .qm .qm-has-toggle ol.qm-numbered li {
551
- list-style: none !important;
552
  }
553
-
554
  #query-monitor .qm .qm-toggled-on ol.qm-numbered li,
555
  #query-monitor .qm ol.qm-numbered li {
556
- list-style: decimal inside !important;
557
  }
558
-
559
  #query-monitor .qm pre {
560
- font-size: 12px !important;
561
- line-height: 18px !important;
562
- font-family: Menlo, Monaco, Consolas, monospace !important;
563
- background: transparent !important;
564
  }
565
-
566
- #query-monitor .qm code {
567
- font-size: 11px !important;
568
- line-height: 18px !important;
569
- font-family: Menlo, Monaco, Consolas, monospace !important;
570
- }
571
-
572
- #query-monitor .qm code.qm-inline-code {
573
- background: #f1f1f1 !important;
574
- padding: 3px 4px 2px !important;
575
  }
576
-
577
  #query-monitor .qm .qm-true code,
578
  #query-monitor .qm p.qm-true,
579
  #query-monitor .qm span.qm-true,
580
  #query-monitor .qm td.qm-true {
581
- color: #4a4 !important;
582
  }
583
-
584
  #query-monitor .qm .qm-false code,
585
  #query-monitor .qm span.qm-false,
586
  #query-monitor .qm td.qm-false {
587
- color: #999 !important;
588
  }
589
-
590
  #query-monitor .qm code,
591
  #query-monitor .qm .qm-nowrap {
592
- white-space: nowrap !important;
593
  }
594
-
595
  #query-monitor .qm .qm-wrap code,
596
  #query-monitor .qm .qm-wrap {
597
- word-wrap: break-word !important;
598
- word-break: break-all !important;
599
- white-space: normal !important;
 
 
 
 
600
  }
601
-
602
  #query-monitor .qm .qm-current,
603
  #query-monitor .qm td.qm-has-toggle p,
604
  #query-monitor .qm .qm-nonselectsql code,
605
  #query-monitor .qm .qm-nonselectsql {
606
- color: #a0a !important;
607
  }
608
-
609
  #query-monitor .qm .qm-info {
610
- color: #777 !important;
611
  }
612
-
613
  #query-monitor .qm .qm-supplemental {
614
- margin-right: 0.75em !important;
615
- margin-left: 0.75em !important;
616
  }
617
-
618
  #query-monitor .qm td .qm-toggled {
619
- display: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
  }
621
-
622
- #query-monitor .qm .qm-toggle,
623
- html[dir="rtl"] #query-monitor .qm .qm-ltr .qm-toggle {
624
- color: #ffffff !important;
625
- padding: 0px 5px !important;
626
- font-weight: normal !important;
627
- font-family: Menlo, Monaco, Consolas, monospace !important;
628
- position: absolute !important;
629
- top: 0 !important;
630
- right: 0 !important;
631
- left: auto !important;
632
- background: #589cbd !important;
633
- cursor: pointer !important;
634
- bottom: auto !important;
635
- }
636
-
637
  #query-monitor .qm .qm-has-inner .qm-toggle {
638
- top: 5px !important;
639
- right: 5px !important;
640
  }
641
-
 
642
  #query-monitor .qm .qm-toggle:focus,
643
  #query-monitor .qm .qm-toggle:hover {
644
- text-decoration: none !important;
645
- color: #ffffff !important;
646
- background: #3878d9 !important;
647
  }
648
-
649
- /* @TODO this striping breaks when rows are filtered out. can visible rows be targeted? */
650
- #query-monitor .qm tbody tr:nth-child(odd) td,
651
- #query-monitor .qm tbody tr:nth-child(odd) th {
652
- background: #f7f7f7 !important;
653
  }
654
 
655
  .qm-debug-bar tbody tr:hover th,
656
- .qm-debug-bar tbody tr:hover td,
657
- #qm-conditionals tbody tr:hover td,
658
- #qm-overview tbody tr:hover td,
659
- #qm-settings tbody tr:hover td {
660
- background: #fff !important;
661
  }
662
 
663
  #query-monitor .qm-non-tabular .qm-warn,
664
  #query-monitor .qm thead tr .qm-warn,
665
  #query-monitor .qm tbody tr .qm-warn {
666
- background-color: #fff0f0 !important;
667
- color: #800 !important;
668
  }
669
-
670
  #query-monitor .qm tbody tr th.qm-warn,
671
  #query-monitor .qm tbody tr td.qm-warn,
672
  #query-monitor .qm tbody tr.qm-warn td,
673
  #query-monitor .qm tbody tr.qm-warn th {
674
- background-color: #fff0f0 !important;
675
- box-shadow: inset 0 -1px #ffd6d6 !important;
676
- border-color: #ffd6d6 !important;
677
- color: #800 !important;
678
  }
679
-
680
  #query-monitor .qm-non-tabular .qm-warn code,
681
  #query-monitor .qm tbody .qm-warn li,
682
  #query-monitor .qm tbody .qm-warn .qm-info,
683
  #query-monitor .qm tbody .qm-warn code {
684
- color: #800 !important;
685
- background-color: transparent !important;
686
  }
687
-
688
- #query-monitor .qm .dashicons {
689
- font-size: 16px !important;
690
- width: 16px !important;
691
- height: 16px !important;
692
- margin-right: 0.3em !important;
693
- transition: none !important;
694
  }
695
-
 
 
 
 
 
 
 
 
 
 
 
 
 
696
  #query-monitor .qm tbody tr:hover th,
697
  #query-monitor .qm tbody tr:hover td {
698
- background: rgb( 238, 243, 250 ) !important;
 
 
 
 
699
  }
700
-
701
- #query-monitor .qm select.qm-filter.qm-highlight,
702
  #query-monitor .qm tbody tr td.qm-highlight,
703
  #query-monitor .qm tbody tr.qm-highlight td {
704
- background-color: #ffd !important;
 
 
 
705
  }
706
 
707
  #query-monitor .qm tbody .qm-warn a code,
708
  #qm-title a,
709
  #query-monitor .qm a code,
710
  #query-monitor .qm a {
711
- color: #0073aa !important;
712
- text-decoration: none !important;
713
- cursor: pointer !important;
714
  }
715
 
716
  #qm-title a:focus,
@@ -718,89 +672,111 @@ html[dir="rtl"] #query-monitor .qm .qm-ltr .qm-toggle {
718
  #query-monitor .qm a:after,
719
  #query-monitor .qm a:focus,
720
  #query-monitor .qm a:hover {
721
- text-decoration: underline !important;
722
- color: #0073aa !important;
723
  }
724
 
 
 
725
  #query-monitor .qm a.qm-edit-link:after,
726
  #query-monitor .qm a.qm-filter-trigger:after {
727
- font-family: dashicons !important;
728
- text-decoration: none !important;
729
- visibility: hidden !important;
730
- display: inline-block !important;
731
- }
732
-
 
 
 
 
 
 
 
 
 
 
733
  #query-monitor .qm a.qm-edit-link:hover:after,
734
  #query-monitor .qm a.qm-edit-link:focus:after,
 
735
  #query-monitor .qm a.qm-filter-trigger:hover:after,
736
  #query-monitor .qm a.qm-filter-trigger:focus:after {
737
- visibility: visible !important;
738
  }
739
 
740
  #query-monitor .qm a.qm-filter-trigger:after {
741
- content: '\f536' !important;
742
  }
743
 
744
  #query-monitor .qm a.qm-edit-link:after {
745
- content: '\f464' !important;
746
- font-size: 15px !important;
747
  }
748
 
749
- /* Filters */
 
 
 
750
 
 
 
 
 
 
751
  #query-monitor button,
752
- #query-monitor a,
753
  #query-monitor select {
754
- outline: none !important; /* a11y */
755
- margin: 0 !important;
756
- height: auto !important;
757
- width: auto !important;
758
- background: none !important;
759
- box-shadow: none !important;
760
  }
761
 
762
  #query-monitor .qm label {
763
- cursor: pointer !important;
764
- color: #333 !important;
765
- font-weight: normal !important;
766
- font-size: 12px !important;
767
- font-style: normal !important;
768
- margin: 0 !important;
769
  }
770
 
771
  #query-monitor .qm thead label {
772
- flex-grow: 1;
773
  }
774
 
775
  #query-monitor .qm .qm-filter-container {
776
- display: flex;
777
  }
778
 
779
  #query-monitor .qm .qm-filter-container label {
780
- cursor: default !important;
781
  }
782
 
783
  #query-monitor .qm .qm-filter-container div {
784
- /* Some themes use Select2 etc on all selects. This hides that. */
785
- display: none !important;
786
  }
787
 
788
  #query-monitor .qm select.qm-filter {
789
- display: block !important;
790
- margin: 0 0 0 5px !important;
791
- outline: 1px solid #aaa !important;
792
- border: none !important;
793
- padding: 0 !important;
794
- background: #fff !important;
795
- color: #333 !important;
796
- height: auto !important;
797
- width: auto !important;
798
- float: none !important;
799
- cursor: pointer !important;
800
- -webkit-appearance: menulist !important;
801
- -moz-appearance: menulist !important;
802
- letter-spacing: normal !important;
803
- max-width: 15em !important;
 
 
 
 
 
804
  }
805
 
806
  .qm-hide,
@@ -812,209 +788,194 @@ html[dir="rtl"] #query-monitor .qm .qm-ltr .qm-toggle {
812
  .qm-hide-type,
813
  .qm-hide-caller,
814
  .qm-hide-component {
815
- display: none !important;
816
  }
817
 
818
  /* Sorters */
819
-
820
  #query-monitor .qm thead th.qm-sortable-column {
821
- cursor: pointer !important;
822
  }
823
 
824
  #query-monitor .qm thead th.qm-sortable-column:hover {
825
- background: #f3f3f3 !important;
826
  }
827
 
828
  #query-monitor .qm .qm-sort-heading {
829
- flex-grow: 1;
830
  }
831
 
832
  #query-monitor .qm .qm-sort-controls {
833
- text-align: right !important;
834
- flex-shrink: 0;
835
  }
836
 
837
  #query-monitor .qm .qm-sortable-column .qm-sort-arrow {
838
- font-size: 24px !important;
839
- color: #ccc !important;
840
- margin: 0 !important;
841
- width: 16px !important;
842
- height: 10px !important;
 
 
843
  }
844
 
845
- #query-monitor .qm .qm-sorted-desc .qm-sort-arrow,
846
- #query-monitor .qm .qm-sorted-asc .qm-sort-arrow {
847
- color: #444444 !important;
848
  }
849
 
850
  #query-monitor .qm thead th.qm-sortable-column:hover .qm-sort-arrow {
851
- color: #3878d9 !important;
852
  }
853
 
854
  #query-monitor .qm .qm-sortable-column .qm-sort-arrow:before {
855
- content: "\f140";
856
- top: 1px;
857
- right: 0;
858
- position: absolute;
859
  }
860
 
861
  #query-monitor .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow:before {
862
- content: "\f142";
863
  }
864
 
865
  #query-monitor .qm button:focus,
866
  #query-monitor .qm a:focus,
867
  #query-monitor .qm select:focus {
868
- box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8) !important;
869
  }
870
 
 
871
  #query-monitor .screen-reader-text {
872
- position: absolute !important;
873
- margin: -1px !important;
874
- padding: 0 !important;
875
- height: 1px !important;
876
- width: 1px !important;
877
- overflow: hidden !important;
878
- clip: rect(0 0 0 0) !important;
879
- border: 0 !important;
880
  }
881
 
882
  @media screen and (max-width: 782px) {
 
 
 
 
883
 
884
- #qm-panel-menu,
885
- #qm-title h1.qm-title-heading {
886
- display: none;
887
- }
888
-
889
- #qm-title div.qm-title-heading {
890
- display: block;
891
- }
892
-
893
  }
894
-
895
- /* RTL */
896
-
897
- html[dir="rtl"] #query-monitor,
898
- html[dir="rtl"] #query-monitor .qm caption,
899
- html[dir="rtl"] #query-monitor .qm td,
900
- html[dir="rtl"] #query-monitor .qm th {
901
- text-align: right !important;
902
- }
903
-
904
- html[dir="rtl"] #wpadminbar .quicklinks .menupop ul li.qm-ltr,
905
- html[dir="rtl"] #query-monitor .qm .qm-filter,
906
- html[dir="rtl"] #query-monitor .qm .qm-ltr {
907
- direction: ltr !important;
908
- text-align: left !important;
909
- }
910
-
911
- html[dir="rtl"] #query-monitor .qm .qm-toggle {
912
- right: auto !important;
913
- left: 1px !important;
914
  }
915
 
916
  /* No-JS tweaks */
917
-
918
  .qm-no-js .qm-sort-controls,
919
  .qm-no-js .qm-toggle,
920
  .qm-no-js select.qm-filter {
921
- display: none !important;
922
  }
923
 
924
  /* Debug bar add-ons */
925
-
926
  #query-monitor .qm.qm-debug-bar textarea,
927
  #query-monitor .qm.qm-debug-bar pre {
928
- padding: 10px !important;
929
- border: 1px solid #e0e0e0 !important;
930
- margin: 4px 0 !important;
931
  }
932
 
933
  #query-monitor .qm.qm-debug-bar textarea {
934
- resize: vertical !important;
935
  }
936
 
937
  #query-monitor .qm.qm-debug-bar .left {
938
- float: left !important;
939
  }
940
 
941
  #query-monitor .qm.qm-debug-bar .right {
942
- float: right !important;
943
  }
944
 
945
- #query-monitor .qm.qm-debug-bar h1 {
946
- margin: 4px 6px 15px !important;
 
947
  }
948
 
949
- #query-monitor .qm.qm-debug-bar h2 {
950
- float: left !important; /* why */
951
- min-width: 150px !important;
952
- padding: 5px 10px 15px !important;
953
- clear: none !important;
954
- text-align: center !important;
955
- font-size: 14px !important;
956
- margin: 3px 8px 15px 0 !important;
 
957
  }
958
 
959
- #query-monitor .qm.qm-debug-bar h2 small {
960
- font-size: 14px !important;
961
  }
962
 
963
- #query-monitor .qm.qm-debug-bar h2 span {
964
- white-space: nowrap !important;
965
- display: block !important;
966
- margin-bottom: 8px !important;
967
  }
968
 
969
- #query-monitor .qm.qm-debug-bar h3 {
970
- margin: 15px 6px 5px !important;
971
- font-size: 13px !important;
972
  }
973
 
974
  #query-monitor .qm.qm-debug-bar .qm-debug-bar-output {
975
- position: relative !important;
976
  }
977
 
978
  #query-monitor .qm.qm-debug-bar .qm-debug-bar-output table {
979
- margin-top: 4px !important;
980
- margin-bottom: 4px !important;
981
  }
982
 
983
  #query-monitor #debug-menu-target-Debug_Bar_Console {
984
- min-height: 400px !important;
985
  }
986
 
987
  #query-monitor #debug-menu-target-Debug_Bar_Cache_Lookup,
988
  #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules,
989
  #query-monitor #debug-menu-target-Debug_Bar_Widgets {
990
- margin: 4px 6px !important;
991
  }
992
 
993
  #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules_Panel .filterui,
994
  #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules_Panel .dbrr {
995
- margin: 0;
996
  }
997
 
998
  /* Broken output handling */
999
-
1000
  #query-monitor.qm-broken #qm-title {
1001
- cursor: default !important;
1002
  }
1003
 
1004
  #query-monitor #qm-broken,
1005
  #query-monitor.qm-broken .qm-title-button {
1006
- display: none !important;
1007
  }
1008
 
1009
  #query-monitor.qm-broken #qm-broken,
1010
  #query-monitor.qm-broken .qm {
1011
- display: block !important;
1012
  }
1013
 
1014
  #query-monitor.qm-broken .qm {
1015
- margin-bottom: 50px !important;
1016
  }
1017
 
1018
  #query-monitor.qm-broken #qm-broken h2 {
1019
- padding: 20px !important;
1020
  }
 
 
1
+ /**
2
+ * All the styles for Query Monitor.
3
+ *
4
+ * @package query-monitor
5
+ */
 
 
 
 
 
 
 
 
 
 
6
  /* === Admin Toolbar === */
 
7
  #wpadminbar .quicklinks .menupop ul li.qm-true > a {
8
+ color: #8c8 !important;
9
  }
10
+ #wpadminbar .quicklinks .menupop ul li.qm-true > a:focus, #wpadminbar .quicklinks .menupop ul li.qm-true > a:hover {
11
+ color: #52b552 !important;
 
 
12
  }
 
13
  #wpadminbar .qm-alert {
14
+ background-color: #f60;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  }
16
+ #wpadminbar #wp-admin-bar-query-monitor-notices a,
17
  #wpadminbar .qm-notice {
18
+ background-color: #740;
19
  }
20
+ #wpadminbar #wp-admin-bar-query-monitor-deprecateds a,
21
+ #wpadminbar .qm-deprecated {
22
+ background-color: #3c3c3c;
23
  }
24
+ #wpadminbar #wp-admin-bar-query-monitor-stricts a,
25
+ #wpadminbar .qm-strict {
26
+ background-color: #3c3c3c;
27
  }
28
+ #wpadminbar #wp-admin-bar-query-monitor-expensive a,
29
+ #wpadminbar .qm-expensive {
30
+ background-color: #b60;
31
  }
32
+ #wpadminbar #wp-admin-bar-query-monitor-logger-warning a,
33
+ #wpadminbar #wp-admin-bar-query-monitor-warnings a,
34
  #wpadminbar .qm-warning {
35
+ background-color: #c00;
36
  }
37
+ #wpadminbar #wp-admin-bar-query-monitor-logger-warning a:hover,
38
+ #wpadminbar #wp-admin-bar-query-monitor-warnings a:hover,
39
+ #wpadminbar .qm-warning:hover {
40
+ background-color: #b00;
41
+ color: #ddd !important;
 
 
42
  }
43
+ #wpadminbar #wp-admin-bar-query-monitor-errors a,
44
  #wpadminbar .qm-error {
45
+ background-color: #c00;
46
  }
47
 
48
+ #wp-admin-bar-query-monitor *,
49
+ #wp-admin-bar-query-monitor {
50
+ direction: ltr !important;
51
+ text-align: left !important;
52
  }
53
 
54
  body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover):not(.hover) .ab-label,
56
  #wp-admin-bar-query-monitor-stricts a,
57
  #wp-admin-bar-query-monitor-notices a,
58
  #wp-admin-bar-query-monitor-expensive a,
59
+ #wp-admin-bar-query-monitor-logger-warning a,
60
  #wp-admin-bar-query-monitor-warnings a,
61
  #wp-admin-bar-query-monitor-errors a {
62
+ color: #eee !important;
63
  }
64
 
65
  #wp-admin-bar-query-monitor small {
66
+ font-size: 11px !important;
 
67
  }
68
 
69
  #wp-admin-bar-query-monitor.hover a small,
70
  #wp-admin-bar-query-monitor.hover a .ab-label {
71
+ text-shadow: none !important;
72
  }
73
 
74
  #wp-admin-bar-query-monitor-placeholder,
75
  #wp-admin-bar-query-monitor-default {
76
+ display: none;
77
  }
78
 
79
  #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
80
+ font: 18px/44px 'Open Sans', sans-serif !important;
81
+ /* @todo remove open sans */
82
+ width: auto !important;
83
+ padding: 0 10px !important;
84
+ color: #aaa !important;
85
+ display: none !important;
86
  }
87
 
88
  @media screen and (max-width: 782px) {
89
+ /* force menu icon to show up */
90
+ #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
91
+ display: block !important;
92
+ }
 
 
 
 
 
93
 
94
+ /* hide menu text */
95
+ #wpadminbar #wp-admin-bar-query-monitor .ab-label {
96
+ display: none !important;
97
+ }
98
+ }
99
  /* === Main QM Panel === */
 
100
  #query-monitor,
101
+ #query-monitor dl,
102
+ #query-monitor dt,
103
+ #query-monitor dd,
104
  #query-monitor button,
105
  #query-monitor label,
106
  #query-monitor select,
112
  #query-monitor li,
113
  #query-monitor code,
114
  #query-monitor a,
 
115
  #query-monitor h1,
116
  #query-monitor h2,
117
  #query-monitor h3,
119
  #query-monitor h5,
120
  #query-monitor h6,
121
  #query-monitor p {
122
+ /* reset */
123
+ background: transparent !important;
124
+ color: #222 !important;
125
+ box-sizing: border-box !important;
126
+ text-align: left !important;
127
+ font-style: normal !important;
128
+ font-weight: normal !important;
129
+ font-size: 12px !important;
130
+ line-height: 18px !important;
131
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
132
+ border: none !important;
133
+ padding: 0 !important;
134
+ margin: 0 !important;
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;
141
+ transition: none !important;
142
+ word-wrap: normal !important;
143
+ word-break: normal !important;
144
+ outline: none !important;
145
+ box-shadow: none !important;
146
  }
147
 
148
  #query-monitor {
149
+ background: #fff !important;
150
+ margin: 0 !important;
151
+ border-top: 1px solid #aaa !important;
152
+ text-align: left !important;
153
+ display: none;
154
+ position: fixed;
155
+ z-index: 99998 !important;
156
+ bottom: 0 !important;
157
+ left: 0 !important;
158
+ right: 0 !important;
159
+ width: 100% !important;
160
+ direction: ltr !important;
161
  }
162
 
163
  #query-monitor.qm-show,
164
  #query-monitor.qm-peek {
165
+ height: 27px;
166
+ display: flex;
167
+ flex-direction: column !important;
168
  }
169
 
170
  #query-monitor.qm-show {
171
+ height: 40%;
172
+ }
173
+
174
+ #query-monitor #qm-wrapper {
175
+ display: flex;
176
+ flex-grow: 1 !important;
177
+ /* Fix nested scrolling in Firefox. See https://bugzilla.mozilla.org/show_bug.cgi?id=1043520: */
178
+ min-height: 0;
179
+ }
180
+ #query-monitor #qm-title {
181
+ background: #f3f3f3 !important;
182
+ border-bottom: 1px solid #aaa !important;
183
+ cursor: ns-resize !important;
184
+ align-items: center !important;
185
+ display: flex !important;
186
+ padding: 0 0 0 5px !important;
187
+ height: 27px !important;
188
+ flex-shrink: 0 !important;
189
+ -moz-user-select: none !important;
190
+ -ms-user-select: none !important;
191
+ -webkit-user-select: none !important;
192
+ user-select: none !important;
193
+ }
194
+ #query-monitor #qm-title .qm-title-heading {
195
+ flex-grow: 1 !important;
196
+ border-right: 1px solid #bbb !important;
197
+ margin-right: 8px !important;
198
+ }
199
+ #query-monitor #qm-title div.qm-title-heading {
200
+ display: none;
201
+ }
202
+ #query-monitor #qm-title .qm-title-button {
203
+ flex-shrink: 0 !important;
204
+ }
205
+ #query-monitor #qm-title .dashicons {
206
+ transition: none !important;
207
+ }
208
+ #query-monitor #qm-title .qm-button-container-settings .dashicons,
209
+ #query-monitor #qm-title .qm-button-container-pin .dashicons {
210
+ font-size: 17px !important;
211
+ margin: 3px 0 2px !important;
212
+ }
213
+ #query-monitor #qm-title .qm-button-container-close .dashicons {
214
+ margin: 2px 0 3px !important;
215
+ }
216
+ #query-monitor #qm-title button {
217
+ color: #666 !important;
218
+ cursor: pointer !important;
219
+ margin: 0 0 0 0px !important;
220
+ display: inline-block !important;
221
+ padding: 0px 4px !important;
222
+ }
223
+ #query-monitor #qm-title button:focus,
224
+ #query-monitor #qm-title button:hover {
225
+ color: #000 !important;
226
+ background: #e6e6e6 !important;
227
+ }
228
+ #query-monitor #qm-title button:active {
229
+ background: #ccc !important;
230
+ }
231
+ #query-monitor #qm-title button.qm-button-active {
232
+ color: #3879d9 !important;
233
+ }
234
+ #query-monitor #qm-title .qm-button-container-pin.qm-button-active .dashicons {
235
+ transform: rotate(-45deg) !important;
236
+ }
237
+ #query-monitor #qm-title .qm-button-container-pin.qm-button-active .dashicons:before {
238
+ margin-left: 2px !important;
239
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  #query-monitor .qm {
241
+ display: none !important;
242
+ }
243
+ #query-monitor #qm-panel-menu {
244
+ overflow-y: scroll !important;
245
+ flex-shrink: 0 !important;
246
+ background: #ececec !important;
247
+ overscroll-behavior: contain !important;
248
+ }
249
+ #query-monitor #qm-panel-menu ul {
250
+ padding: 0 !important;
251
+ margin: 0 !important;
252
+ }
253
+ #query-monitor #qm-panel-menu li {
254
+ padding: 0 !important;
255
+ margin: 0 !important;
256
+ }
257
+ #query-monitor #qm-panel-menu li button {
258
+ display: block !important;
259
+ padding: 8px 28px 8px 6px !important;
260
+ color: #333 !important;
261
+ text-decoration: none !important;
262
+ border-bottom: 1px solid #ddd !important;
263
+ position: relative !important;
264
+ border-right: 1px solid #aaa !important;
265
+ background: #f3f3f3 !important;
266
+ width: 100% !important;
267
+ cursor: pointer !important;
268
+ }
269
+ #query-monitor #qm-panel-menu li button:focus,
270
+ #query-monitor #qm-panel-menu li button:hover {
271
+ background: #def !important;
272
+ color: #222 !important;
273
+ }
274
+ #query-monitor #qm-panel-menu li button:focus {
275
+ text-decoration: underline !important;
276
+ }
277
+ #query-monitor #qm-panel-menu li button.qm-selected-menu {
278
+ background: #0073aa !important;
279
+ color: #fff !important;
280
+ text-shadow: 0 -1px 1px #006291, 1px 0 1px #006291, 0 1px 1px #006291, -1px 0 1px #006291 !important;
281
+ }
282
+ #query-monitor #qm-panel-menu li button.qm-selected-menu:focus {
283
+ background: #0084c4 !important;
284
+ color: #fff !important;
285
+ }
286
+ #query-monitor #qm-panel-menu li button.qm-selected-menu:after {
287
+ right: -1px;
288
+ border: solid 8px transparent;
289
+ content: " ";
290
+ height: 0;
291
+ width: 0;
292
+ position: absolute;
293
+ pointer-events: none;
294
+ border-right-color: #fff;
295
+ top: 50%;
296
+ margin-top: -8px;
297
+ }
298
+ #query-monitor #qm-panels {
299
+ flex-grow: 1 !important;
300
+ overflow-y: scroll !important;
301
+ overscroll-behavior: contain !important;
302
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  #query-monitor .qm.qm-panel-show {
304
+ display: block !important;
305
  }
 
306
  #query-monitor .qm:focus {
307
+ outline: 0 !important;
308
+ /* @TODO might not need this any more */
309
  }
 
310
  #query-monitor .qm-non-tabular {
311
+ padding: 10px 20px !important;
312
  }
 
313
  #query-monitor .qm-boxed {
314
+ display: flex !important;
315
+ flex-wrap: wrap !important;
316
  }
 
317
  #query-monitor .qm-boxed:not(#qm-broken) + .qm-boxed {
318
+ border-top: 1px solid #ddd !important;
319
+ padding-top: 10px !important;
320
  }
 
321
  #query-monitor .qm-boxed-wrap {
322
+ flex-wrap: wrap !important;
323
  }
 
324
  #query-monitor .qm .qm-none {
325
+ margin: 2em !important;
326
  }
 
327
  #query-monitor .qm .qm-none p {
328
+ text-align: center !important;
329
+ font-style: italic !important;
330
  }
 
331
  #query-monitor .qm table {
332
+ color: #222 !important;
333
+ border-collapse: collapse !important;
334
+ box-shadow: none !important;
335
+ width: 100% !important;
336
+ table-layout: auto !important;
337
+ margin: 0 !important;
338
+ border: none !important;
339
+ border-bottom: 1px solid #e0e0e0 !important;
340
  }
 
341
  #query-monitor .qm table + table {
342
+ margin-top: 5px !important;
343
+ border-top: 1px solid #e0e0e0 !important;
344
  }
 
345
  #query-monitor #qm-conditionals table,
346
  #query-monitor #qm-overview table {
347
+ table-layout: fixed !important;
348
  }
 
349
  #query-monitor .qm tr {
350
+ border: none !important;
351
  }
 
352
  #query-monitor .qm tbody th,
353
  #query-monitor .qm tbody td,
354
  #query-monitor .qm tfoot th,
355
  #query-monitor .qm tfoot td {
356
+ border: 1px solid #e0e0e0 !important;
357
+ padding: 5px 5px 4px 5px !important;
358
  }
 
359
  #query-monitor .qm tbody th,
360
  #query-monitor .qm tbody td {
361
+ border-top: none !important;
362
+ border-bottom: none !important;
363
  }
 
364
  #query-monitor .qm thead th {
365
+ box-shadow: 0px 1px 0px #e0e0e0 !important;
366
+ border: 1px solid #e0e0e0 !important;
367
+ border-top: none !important;
368
+ padding: 5px !important;
369
+ position: -webkit-sticky !important;
370
+ position: sticky !important;
371
+ top: 0 !important;
372
+ background: #fff !important;
373
+ z-index: 1 !important;
374
  }
 
375
  #query-monitor .qm thead .qm-th {
376
+ display: flex !important;
377
  }
 
378
  #query-monitor .qm tfoot tr td,
379
  #query-monitor .qm tfoot tr th {
380
+ box-shadow: inset 0px 1px 0px #e0e0e0 !important;
381
+ border: 1px solid #e0e0e0 !important;
382
+ border-bottom: none !important;
383
+ background: #f3f3f3 !important;
384
+ position: -webkit-sticky !important;
385
+ position: sticky !important;
386
+ bottom: 0 !important;
387
  }
 
 
 
 
 
 
388
  #query-monitor .qm th:first-child,
389
  #query-monitor .qm td:first-child {
390
+ border-left: none !important;
391
  }
 
392
  #query-monitor .qm th:last-child,
393
  #query-monitor .qm td:last-child {
394
+ border-right: none !important;
 
 
 
 
 
 
395
  }
 
396
  #query-monitor .qm tfoot td.qm-num,
397
+ #query-monitor .qm tfoot th.qm-num,
398
+ #query-monitor .qm thead td.qm-num,
399
+ #query-monitor .qm thead th.qm-num {
400
+ width: 5.5em !important;
401
  }
402
+ #query-monitor .qm th.qm-num,
403
  #query-monitor .qm td.qm-num {
404
+ text-align: right !important;
405
+ }
406
+ #query-monitor .qm td.qm-row-sql {
407
+ min-width: 25em !important;
408
+ }
409
+ #query-monitor .qm tr.qm-warn td.qm-col-status,
410
+ #query-monitor .qm td.qm-url,
411
+ #query-monitor .qm th.qm-col-message,
412
+ #query-monitor .qm td.qm-row-component {
413
+ min-width: 15em !important;
414
  }
 
415
  #query-monitor .qm td.qm-has-toggle p,
416
  #query-monitor .qm td .qm-toggler {
417
+ padding: 0 22px 0 0 !important;
418
+ position: relative !important;
419
  }
 
420
  #query-monitor .qm td.qm-has-toggle:not(.qm-toggled-on) .qm-supplemental {
421
+ display: none;
422
  }
 
423
  #query-monitor .qm .qm-inner-toggle {
424
+ padding: 4px 6px !important;
425
  }
426
 
427
  .qm-has-inner .qm-toggled > table {
428
+ border-top: 1px solid #e0e0e0 !important;
429
  }
430
 
431
  .qm-inner {
432
+ border-collapse: collapse !important;
433
+ margin: 0 !important;
434
+ border-style: hidden !important;
435
+ width: 100% !important;
436
  }
437
 
438
  #query-monitor .qm td.qm-has-inner .qm-toggler,
439
  #query-monitor .qm td.qm-has-inner {
440
+ padding: 0 !important;
441
  }
 
 
 
 
 
 
 
442
  #query-monitor .qm-non-tabular h3 {
443
+ margin: 0 0 15px 0 !important;
444
+ font-size: 14px !important;
445
+ }
446
+ #query-monitor .qm-non-tabular h4 {
447
+ margin: 20px 0 10px !important;
448
+ font-size: 12px !important;
449
  }
 
450
  #query-monitor .qm-non-tabular p {
451
+ margin-bottom: 10px !important;
452
  }
453
+ #query-monitor .qm-non-tabular dd {
454
+ margin: 0 0 10px 10px !important;
455
+ }
456
+ #query-monitor .qm-non-tabular h3 a {
457
+ float: right !important;
458
  }
 
459
  #query-monitor .qm-non-tabular .qm-item {
460
+ display: inline-block !important;
461
+ margin: 0 20px 5px 0 !important;
462
  }
 
463
  #query-monitor .qm-non-tabular .qm-section {
464
+ margin: 0 0 30px 0 !important;
465
  }
 
466
  #query-monitor .qm-non-tabular .qm-boxed .qm-section {
467
+ margin: 0 20px 10px 0 !important;
468
+ border-right: 1px solid #ddd !important;
469
+ padding: 10px 20px 10px 0 !important;
470
  }
 
471
  #query-monitor .qm-non-tabular .qm-boxed .qm-section:last-child {
472
+ margin-right: 0 !important;
473
+ border-right: none !important;
474
+ padding-right: 20px !important;
475
  }
 
476
  #query-monitor .qm-non-tabular table {
477
+ border-bottom-color: #e0e0e0 !important;
478
  }
 
479
  #query-monitor .qm ol,
480
  #query-monitor .qm ul {
481
+ list-style: none !important;
482
  }
 
483
  #query-monitor .qm li {
484
+ display: list-item !important;
485
+ list-style: none !important;
486
  }
 
487
  #query-monitor .qm li::before {
488
+ content: '' !important;
489
  }
 
490
  #query-monitor .qm .qm-has-toggle ol.qm-numbered li {
491
+ list-style: none !important;
492
  }
 
493
  #query-monitor .qm .qm-toggled-on ol.qm-numbered li,
494
  #query-monitor .qm ol.qm-numbered li {
495
+ list-style: decimal inside !important;
496
  }
497
+ #query-monitor .qm code,
498
  #query-monitor .qm pre {
499
+ font-size: 11px !important;
500
+ line-height: 18px !important;
501
+ font-family: Menlo, Monaco, Consolas, monospace !important;
 
502
  }
503
+ #query-monitor .qm pre {
504
+ background: transparent !important;
505
+ margin: 0 !important;
506
+ width: auto !important;
507
+ height: auto !important;
508
+ padding: 0 !important;
 
 
 
 
509
  }
 
510
  #query-monitor .qm .qm-true code,
511
  #query-monitor .qm p.qm-true,
512
  #query-monitor .qm span.qm-true,
513
  #query-monitor .qm td.qm-true {
514
+ color: #4a4 !important;
515
  }
 
516
  #query-monitor .qm .qm-false code,
517
  #query-monitor .qm span.qm-false,
518
  #query-monitor .qm td.qm-false {
519
+ color: #999 !important;
520
  }
 
521
  #query-monitor .qm code,
522
  #query-monitor .qm .qm-nowrap {
523
+ white-space: nowrap !important;
524
  }
 
525
  #query-monitor .qm .qm-wrap code,
526
  #query-monitor .qm .qm-wrap {
527
+ word-wrap: break-word !important;
528
+ word-break: break-all !important;
529
+ white-space: normal !important;
530
+ }
531
+ #query-monitor .qm .qm-sticky {
532
+ position: sticky !important;
533
+ top: 36px !important;
534
  }
 
535
  #query-monitor .qm .qm-current,
536
  #query-monitor .qm td.qm-has-toggle p,
537
  #query-monitor .qm .qm-nonselectsql code,
538
  #query-monitor .qm .qm-nonselectsql {
539
+ color: #a0a !important;
540
  }
 
541
  #query-monitor .qm .qm-info {
542
+ color: #777 !important;
543
  }
 
544
  #query-monitor .qm .qm-supplemental {
545
+ margin-right: 0.75em !important;
546
+ margin-left: 0.75em !important;
547
  }
 
548
  #query-monitor .qm td .qm-toggled {
549
+ display: none;
550
+ }
551
+ #query-monitor .qm button.qm-button,
552
+ #query-monitor .qm .qm-toggle {
553
+ color: #fff !important;
554
+ font-weight: normal !important;
555
+ background: #0085ba !important;
556
+ cursor: pointer !important;
557
+ border: 1px solid #0073a1 !important;
558
+ border-radius: 2px !important;
559
+ text-shadow: 0 -1px 1px #0073a1, 1px 0 1px #0073a1, 0 1px 1px #0073a1, -1px 0 1px #0073a1 !important;
560
+ }
561
+ #query-monitor .qm .qm-toggle {
562
+ padding: 0 !important;
563
+ font-family: Menlo, Monaco, Consolas, monospace !important;
564
+ position: absolute !important;
565
+ top: 0 !important;
566
+ right: 0 !important;
567
+ left: auto !important;
568
+ bottom: auto !important;
569
+ text-align: center !important;
570
+ line-height: 16px !important;
571
+ height: 18px !important;
572
+ width: 18px !important;
573
+ }
574
+ #query-monitor .qm button {
575
+ cursor: pointer !important;
576
+ }
577
+ #query-monitor .qm button.qm-button {
578
+ padding: 4px 10px !important;
579
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  #query-monitor .qm .qm-has-inner .qm-toggle {
581
+ top: 5px !important;
582
+ right: 5px !important;
583
  }
584
+ #query-monitor .qm button.qm-button:hover,
585
+ #query-monitor .qm button.qm-button:focus,
586
  #query-monitor .qm .qm-toggle:focus,
587
  #query-monitor .qm .qm-toggle:hover {
588
+ text-decoration: none !important;
589
+ color: #fff !important;
590
+ background: #0094ce !important;
591
  }
592
+ #query-monitor .qm tbody tr.qm-odd td,
593
+ #query-monitor .qm tbody tr.qm-odd th {
594
+ background: #f7f7f7 !important;
 
 
595
  }
596
 
597
  .qm-debug-bar tbody tr:hover th,
598
+ .qm-debug-bar tbody tr:hover td {
599
+ background: #fff !important;
600
+ /* transparent? */
 
 
601
  }
602
 
603
  #query-monitor .qm-non-tabular .qm-warn,
604
  #query-monitor .qm thead tr .qm-warn,
605
  #query-monitor .qm tbody tr .qm-warn {
606
+ background-color: #fff0f0 !important;
607
+ color: #800 !important;
608
  }
 
609
  #query-monitor .qm tbody tr th.qm-warn,
610
  #query-monitor .qm tbody tr td.qm-warn,
611
  #query-monitor .qm tbody tr.qm-warn td,
612
  #query-monitor .qm tbody tr.qm-warn th {
613
+ background-color: #fff0f0 !important;
614
+ box-shadow: inset 0 -1px #ffd6d6 !important;
615
+ border-color: #ffd6d6 !important;
616
+ color: #800 !important;
617
  }
 
618
  #query-monitor .qm-non-tabular .qm-warn code,
619
  #query-monitor .qm tbody .qm-warn li,
620
  #query-monitor .qm tbody .qm-warn .qm-info,
621
  #query-monitor .qm tbody .qm-warn code {
622
+ color: #800 !important;
623
+ background-color: transparent !important;
624
  }
625
+ #query-monitor .qm .qm-notice {
626
+ background: #def !important;
627
+ border: 1px solid #aad5ff !important;
628
+ padding: 10px 20px 0 !important;
629
+ margin: 0 0 10px 0 !important;
 
 
630
  }
631
+ #query-monitor .qm .dashicons {
632
+ font-size: 16px !important;
633
+ width: 16px !important;
634
+ height: 16px !important;
635
+ margin-right: 0.3em !important;
636
+ transition: none !important;
637
+ }
638
+ #query-monitor .qm .qm-dashicons-yes {
639
+ color: #fff !important;
640
+ background-color: #0a0 !important;
641
+ border-radius: 50% !important;
642
+ }
643
+ #query-monitor .qm tbody tr.qm-hovered th,
644
+ #query-monitor .qm tbody tr.qm-hovered td,
645
  #query-monitor .qm tbody tr:hover th,
646
  #query-monitor .qm tbody tr:hover td {
647
+ background: #eef3fa !important;
648
+ }
649
+ #query-monitor .qm thead th.qm-filtered select.qm-filter {
650
+ background-color: #ffd !important;
651
+ color: #222 !important;
652
  }
 
 
653
  #query-monitor .qm tbody tr td.qm-highlight,
654
  #query-monitor .qm tbody tr.qm-highlight td {
655
+ background-color: #ffd !important;
656
+ box-shadow: inset 0 -1px #eec !important;
657
+ border-color: #eec !important;
658
+ color: #222 !important;
659
  }
660
 
661
  #query-monitor .qm tbody .qm-warn a code,
662
  #qm-title a,
663
  #query-monitor .qm a code,
664
  #query-monitor .qm a {
665
+ color: #0073aa !important;
666
+ text-decoration: none !important;
667
+ cursor: pointer !important;
668
  }
669
 
670
  #qm-title a:focus,
672
  #query-monitor .qm a:after,
673
  #query-monitor .qm a:focus,
674
  #query-monitor .qm a:hover {
675
+ text-decoration: underline !important;
676
+ color: #0096dd !important;
677
  }
678
 
679
+ #query-monitor .qm a.qm-external-link:after,
680
+ #query-monitor .qm a.qm-link:after,
681
  #query-monitor .qm a.qm-edit-link:after,
682
  #query-monitor .qm a.qm-filter-trigger:after {
683
+ font-family: dashicons !important;
684
+ text-decoration: none !important;
685
+ visibility: hidden !important;
686
+ display: inline-block !important;
687
+ font-size: 13px !important;
688
+ line-height: 15px !important;
689
+ position: relative !important;
690
+ top: 2px !important;
691
+ left: 2px !important;
692
+ }
693
+
694
+ #query-monitor .qm a.qm-external-link:after,
695
+ #query-monitor.qm-touch .qm a.qm-link:after,
696
+ #query-monitor .qm a.qm-link:hover:after,
697
+ #query-monitor .qm a.qm-link:focus:after,
698
+ #query-monitor.qm-touch .qm a.qm-edit-link:after,
699
  #query-monitor .qm a.qm-edit-link:hover:after,
700
  #query-monitor .qm a.qm-edit-link:focus:after,
701
+ #query-monitor.qm-touch .qm a.qm-filter-trigger:after,
702
  #query-monitor .qm a.qm-filter-trigger:hover:after,
703
  #query-monitor .qm a.qm-filter-trigger:focus:after {
704
+ visibility: visible !important;
705
  }
706
 
707
  #query-monitor .qm a.qm-filter-trigger:after {
708
+ content: '\f536' !important;
709
  }
710
 
711
  #query-monitor .qm a.qm-edit-link:after {
712
+ content: '\f464' !important;
 
713
  }
714
 
715
+ #query-monitor .qm a.qm-external-link:after,
716
+ #query-monitor .qm a.qm-link:after {
717
+ content: '\f504' !important;
718
+ }
719
 
720
+ #query-monitor #qm-ajax-errors {
721
+ display: none;
722
+ }
723
+
724
+ /* Filters */
725
  #query-monitor button,
 
726
  #query-monitor select {
727
+ margin: 0 !important;
728
+ height: auto !important;
729
+ width: auto !important;
730
+ background: none !important;
 
 
731
  }
732
 
733
  #query-monitor .qm label {
734
+ cursor: pointer !important;
735
+ color: #222 !important;
736
+ font-weight: normal !important;
737
+ font-size: 12px !important;
738
+ font-style: normal !important;
739
+ margin: 0 !important;
740
  }
741
 
742
  #query-monitor .qm thead label {
743
+ flex-grow: 1 !important;
744
  }
745
 
746
  #query-monitor .qm .qm-filter-container {
747
+ display: flex !important;
748
  }
749
 
750
  #query-monitor .qm .qm-filter-container label {
751
+ cursor: default !important;
752
  }
753
 
754
  #query-monitor .qm .qm-filter-container div {
755
+ /* Some themes use Select2 etc on all selects. This hides that. */
756
+ display: none !important;
757
  }
758
 
759
  #query-monitor .qm select.qm-filter {
760
+ display: block !important;
761
+ margin: 0 0 0 5px !important;
762
+ outline: 1px solid #aaa !important;
763
+ border: none !important;
764
+ padding: 0 !important;
765
+ background: #fff !important;
766
+ color: #222 !important;
767
+ height: auto !important;
768
+ width: auto !important;
769
+ float: none !important;
770
+ cursor: pointer !important;
771
+ -webkit-appearance: menulist !important;
772
+ -moz-appearance: menulist !important;
773
+ appearance: menulist !important;
774
+ letter-spacing: normal !important;
775
+ max-width: 10em !important;
776
+ }
777
+
778
+ #query-monitor .qm select.qm-filter:hover {
779
+ background: #f3f3f3 !important;
780
  }
781
 
782
  .qm-hide,
788
  .qm-hide-type,
789
  .qm-hide-caller,
790
  .qm-hide-component {
791
+ display: none !important;
792
  }
793
 
794
  /* Sorters */
 
795
  #query-monitor .qm thead th.qm-sortable-column {
796
+ cursor: pointer !important;
797
  }
798
 
799
  #query-monitor .qm thead th.qm-sortable-column:hover {
800
+ background: #f3f3f3 !important;
801
  }
802
 
803
  #query-monitor .qm .qm-sort-heading {
804
+ flex-grow: 1 !important;
805
  }
806
 
807
  #query-monitor .qm .qm-sort-controls {
808
+ text-align: right !important;
809
+ flex-shrink: 0 !important;
810
  }
811
 
812
  #query-monitor .qm .qm-sortable-column .qm-sort-arrow {
813
+ font-family: dashicons !important;
814
+ font-size: 23px !important;
815
+ color: #ccc !important;
816
+ margin: 0 !important;
817
+ width: 16px !important;
818
+ height: 10px !important;
819
+ display: block !important;
820
  }
821
 
822
+ #query-monitor .qm .qm-sorted-desc .qm-sort-arrow,
823
+ #query-monitor .qm .qm-sorted-asc .qm-sort-arrow {
824
+ color: #222 !important;
825
  }
826
 
827
  #query-monitor .qm thead th.qm-sortable-column:hover .qm-sort-arrow {
828
+ color: #0073aa !important;
829
  }
830
 
831
  #query-monitor .qm .qm-sortable-column .qm-sort-arrow:before {
832
+ content: "\f140" !important;
833
+ top: 4px !important;
834
+ right: 0 !important;
835
+ position: absolute !important;
836
  }
837
 
838
  #query-monitor .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow:before {
839
+ content: "\f142" !important;
840
  }
841
 
842
  #query-monitor .qm button:focus,
843
  #query-monitor .qm a:focus,
844
  #query-monitor .qm select:focus {
845
+ box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, 0.8) !important;
846
  }
847
 
848
+ #query-monitor .qm-screen-reader-text,
849
  #query-monitor .screen-reader-text {
850
+ position: absolute !important;
851
+ margin: -1px !important;
852
+ padding: 0 !important;
853
+ height: 1px !important;
854
+ width: 1px !important;
855
+ overflow: hidden !important;
856
+ clip: rect(0 0 0 0) !important;
857
+ border: 0 !important;
858
  }
859
 
860
  @media screen and (max-width: 782px) {
861
+ #query-monitor #qm-panel-menu,
862
+ #query-monitor #qm-title h1.qm-title-heading {
863
+ display: none;
864
+ }
865
 
866
+ #query-monitor #qm-title div.qm-title-heading {
867
+ display: block;
868
+ }
 
 
 
 
 
 
869
  }
870
+ /* State Toggle */
871
+ #query-monitor [data-qm-state="off"] [data-qm-state-visibility="on"],
872
+ #query-monitor [data-qm-state="on"] [data-qm-state-visibility="off"] {
873
+ display: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
874
  }
875
 
876
  /* No-JS tweaks */
 
877
  .qm-no-js .qm-sort-controls,
878
  .qm-no-js .qm-toggle,
879
  .qm-no-js select.qm-filter {
880
+ display: none !important;
881
  }
882
 
883
  /* Debug bar add-ons */
 
884
  #query-monitor .qm.qm-debug-bar textarea,
885
  #query-monitor .qm.qm-debug-bar pre {
886
+ padding: 10px !important;
887
+ border: 1px solid #ddd !important;
888
+ margin: 4px 0 !important;
889
  }
890
 
891
  #query-monitor .qm.qm-debug-bar textarea {
892
+ resize: vertical !important;
893
  }
894
 
895
  #query-monitor .qm.qm-debug-bar .left {
896
+ float: left !important;
897
  }
898
 
899
  #query-monitor .qm.qm-debug-bar .right {
900
+ float: right !important;
901
  }
902
 
903
+ #query-monitor .qm.qm-debug-bar h2 {
904
+ font-size: 14px !important;
905
+ margin: 4px 6px 15px !important;
906
  }
907
 
908
+ #query-monitor .qm.qm-debug-bar h3 {
909
+ float: left !important;
910
+ /* why */
911
+ min-width: 150px !important;
912
+ padding: 5px 10px 15px !important;
913
+ clear: none !important;
914
+ text-align: center !important;
915
+ font-size: 14px !important;
916
+ margin: 3px 8px 15px 0 !important;
917
  }
918
 
919
+ #query-monitor .qm.qm-debug-bar h3 small {
920
+ font-size: 14px !important;
921
  }
922
 
923
+ #query-monitor .qm.qm-debug-bar h3 span {
924
+ white-space: nowrap !important;
925
+ display: block !important;
926
+ margin-bottom: 8px !important;
927
  }
928
 
929
+ #query-monitor .qm.qm-debug-bar h4 {
930
+ margin: 15px 6px 5px !important;
931
+ font-size: 13px !important;
932
  }
933
 
934
  #query-monitor .qm.qm-debug-bar .qm-debug-bar-output {
935
+ position: relative !important;
936
  }
937
 
938
  #query-monitor .qm.qm-debug-bar .qm-debug-bar-output table {
939
+ margin-top: 4px !important;
940
+ margin-bottom: 4px !important;
941
  }
942
 
943
  #query-monitor #debug-menu-target-Debug_Bar_Console {
944
+ min-height: 400px !important;
945
  }
946
 
947
  #query-monitor #debug-menu-target-Debug_Bar_Cache_Lookup,
948
  #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules,
949
  #query-monitor #debug-menu-target-Debug_Bar_Widgets {
950
+ margin: 4px 6px !important;
951
  }
952
 
953
  #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules_Panel .filterui,
954
  #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules_Panel .dbrr {
955
+ margin: 0 !important;
956
  }
957
 
958
  /* Broken output handling */
 
959
  #query-monitor.qm-broken #qm-title {
960
+ cursor: default !important;
961
  }
962
 
963
  #query-monitor #qm-broken,
964
  #query-monitor.qm-broken .qm-title-button {
965
+ display: none !important;
966
  }
967
 
968
  #query-monitor.qm-broken #qm-broken,
969
  #query-monitor.qm-broken .qm {
970
+ display: block !important;
971
  }
972
 
973
  #query-monitor.qm-broken .qm {
974
+ margin-bottom: 50px !important;
975
  }
976
 
977
  #query-monitor.qm-broken #qm-broken h2 {
978
+ padding: 20px !important;
979
  }
980
+
981
+ /*# sourceMappingURL=query-monitor.css.map */
assets/query-monitor.js CHANGED
@@ -1,17 +1,8 @@
1
- /*
2
- Copyright 2009-2017 John Blackbourn
3
-
4
- This program is free software; you can redistribute it and/or modify
5
- it under the terms of the GNU General Public License as published by
6
- the Free Software Foundation; either version 2 of the License, or
7
- (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU General Public License for more details.
13
-
14
- */
15
 
16
  var QM_i18n = {
17
 
@@ -70,10 +61,19 @@ if ( window.jQuery ) {
70
  $('#query-monitor').removeClass('qm-no-js').addClass('qm-js');
71
 
72
  var link_click = function(e){
73
- show_panel( $( this ).attr('href') );
 
 
 
74
  e.preventDefault();
75
  };
76
 
 
 
 
 
 
 
77
  var show_panel = function( panel ) {
78
  $('#query-monitor').addClass('qm-show').removeClass('qm-hide');
79
  $( '.qm' ).removeClass('qm-panel-show');
@@ -84,8 +84,8 @@ if ( window.jQuery ) {
84
  container.height( minheight );
85
  }
86
 
87
- $('#qm-panel-menu').find('a').removeClass('qm-selected-menu');
88
- var selected_menu = $('#qm-panel-menu').find('a[href="' + panel + '"]').addClass('qm-selected-menu');
89
 
90
  if ( selected_menu.length ) {
91
  var selected_menu_pos = selected_menu.position();
@@ -103,7 +103,13 @@ if ( window.jQuery ) {
103
  localStorage.setItem( container_pinned_key, panel );
104
  }
105
 
106
- $( panel ).find('.qm-filter').change();
 
 
 
 
 
 
107
 
108
  };
109
 
@@ -114,6 +120,7 @@ if ( window.jQuery ) {
114
  if ( window.qm && window.qm.menu ) {
115
  $('#wp-admin-bar-query-monitor')
116
  .addClass(qm.menu.top.classname)
 
117
  .find('a').eq(0)
118
  .html(qm.menu.top.title)
119
  ;
@@ -150,7 +157,7 @@ if ( window.jQuery ) {
150
  $('#qm-overview').addClass('qm-panel-show');
151
  }
152
 
153
- $('#qm-panel-menu').find('a').on('click',link_click);
154
 
155
  $('#query-monitor').find('.qm-filter').on('change',function(e){
156
 
@@ -179,9 +186,9 @@ if ( window.jQuery ) {
179
  tr.filter('[data-qm-' + hilite + '*="' + val + '"]').addClass('qm-highlight');
180
  }
181
  tr.not('[data-qm-' + filter + '*="' + val + '"]').addClass('qm-hide-' + filter);
182
- $(this).addClass('qm-highlight');
183
  } else {
184
- $(this).removeClass('qm-highlight');
185
  }
186
 
187
  var matches = tr.filter(':visible');
@@ -195,15 +202,16 @@ if ( window.jQuery ) {
195
  time = QM_i18n.number_format( time, 4 );
196
  }
197
 
198
- var results = table.find('.qm-items-shown');
199
- results.find('.qm-items-number').text( QM_i18n.number_format( matches.length, 0 ) );
200
- results.find('.qm-items-time').text(time);
201
-
202
- if ( table.find('.qm-filter.qm-highlight').length ) {
203
- results.removeClass('qm-hide');
204
  } else {
205
- results.addClass('qm-hide');
206
  }
 
 
 
 
 
207
  });
208
 
209
  $('#query-monitor').find('.qm-filter').each(function () {
@@ -226,6 +234,7 @@ if ( window.jQuery ) {
226
  $('#qm-' + target).find('.qm-filter').not('[data-filter="' + filter + '"]').val('').removeClass('qm-highlight').change();
227
  $('#qm-' + target).find('[data-filter="' + filter + '"]').val(value).addClass('qm-highlight').change();
228
  show_panel( '#qm-' + target );
 
229
  e.preventDefault();
230
  });
231
 
@@ -278,6 +287,16 @@ if ( window.jQuery ) {
278
 
279
  });
280
 
 
 
 
 
 
 
 
 
 
 
281
  $( document ).ajaxSuccess( function( event, response, options ) {
282
 
283
  var errors = response.getResponseHeader( 'X-QM-php_errors-error-count' );
@@ -317,21 +336,26 @@ if ( window.jQuery ) {
317
  console.groupEnd();
318
  }
319
 
 
 
320
  return event;
321
 
322
  } );
323
 
324
  $('.qm-auth').on('click',function(e){
325
- var action = $(this).data('action');
 
326
 
327
  $.ajax(qm_l10n.ajaxurl,{
328
  type : 'POST',
 
329
  data : {
330
  action : 'qm_auth_' + action,
331
  nonce : qm_l10n.auth_nonce[action]
332
  },
333
  success : function(response){
334
- alert( response.data );
 
335
  },
336
  dataType : 'json',
337
  xhrFields: {
@@ -412,16 +436,19 @@ if ( window.jQuery ) {
412
 
413
  $('.qm-button-container-settings').click(function(){
414
  show_panel( '#qm-settings' );
 
415
  });
416
 
417
  var pinned = localStorage.getItem( container_pinned_key );
418
  if ( pinned && $( pinned ).length ) {
419
  show_panel( pinned );
 
420
  $('.qm-button-container-pin').addClass( 'qm-button-active' );
421
  }
422
 
423
  $('.qm-title-heading select').change(function(){
424
  show_panel( $(this).val() );
 
425
  });
426
 
427
  } );
@@ -483,21 +510,21 @@ if ( window.jQuery ) {
483
  var desc = ! $(this).hasClass('qm-sorted-desc');
484
  var index = $(this).index();
485
 
486
- table.find('thead th').removeClass('qm-sorted-asc qm-sorted-desc');
487
 
488
  if ( desc ) {
489
- $(this).addClass('qm-sorted-desc');
490
  } else {
491
- $(this).addClass('qm-sorted-asc');
492
  }
493
 
494
  table.find('tbody').each(function () {
495
  var tbody = $(this);
496
  var rows = this.rows;
497
- var columns = this.getElementsByTagName('td');
498
 
499
  if (this.data_matrix === undefined) {
500
- this.data_matrix = table_to_array(columns, $(rows[0]).find('td').length);
501
  }
502
 
503
  var data = this.data_matrix;
@@ -531,6 +558,9 @@ if ( window.jQuery ) {
531
 
532
  table.append(tbody);
533
  });
 
 
 
534
  e.preventDefault();
535
  });
536
  });
1
+ /**
2
+ * Front-end functionality for Query Monitor.
3
+ *
4
+ * @package query-monitor
5
+ */
 
 
 
 
 
 
 
 
 
6
 
7
  var QM_i18n = {
8
 
61
  $('#query-monitor').removeClass('qm-no-js').addClass('qm-js');
62
 
63
  var link_click = function(e){
64
+ var href = $( this ).attr('href') || $( this ).data('qm-href');
65
+ show_panel( href );
66
+ $(href).focus();
67
+ $('#wp-admin-bar-query-monitor').removeClass('hover');
68
  e.preventDefault();
69
  };
70
 
71
+ var stripes = function( table ) {
72
+ table.each(function() {
73
+ $(this).find('tbody tr').removeClass('qm-odd').not('[class*="qm-hide-"]').filter(':even').addClass('qm-odd');
74
+ } );
75
+ };
76
+
77
  var show_panel = function( panel ) {
78
  $('#query-monitor').addClass('qm-show').removeClass('qm-hide');
79
  $( '.qm' ).removeClass('qm-panel-show');
84
  container.height( minheight );
85
  }
86
 
87
+ $('#qm-panel-menu').find('button').removeClass('qm-selected-menu');
88
+ var selected_menu = $('#qm-panel-menu').find('[data-qm-href="' + panel + '"]').addClass('qm-selected-menu');
89
 
90
  if ( selected_menu.length ) {
91
  var selected_menu_pos = selected_menu.position();
103
  localStorage.setItem( container_pinned_key, panel );
104
  }
105
 
106
+ var filters = $( panel ).find('.qm-filter');
107
+
108
+ if ( filters.length ) {
109
+ filters.change();
110
+ } else {
111
+ stripes( $(panel).find('table') );
112
+ }
113
 
114
  };
115
 
120
  if ( window.qm && window.qm.menu ) {
121
  $('#wp-admin-bar-query-monitor')
122
  .addClass(qm.menu.top.classname)
123
+ .attr('dir','ltr')
124
  .find('a').eq(0)
125
  .html(qm.menu.top.title)
126
  ;
157
  $('#qm-overview').addClass('qm-panel-show');
158
  }
159
 
160
+ $('#qm-panel-menu').find('button').on('click',link_click);
161
 
162
  $('#query-monitor').find('.qm-filter').on('change',function(e){
163
 
186
  tr.filter('[data-qm-' + hilite + '*="' + val + '"]').addClass('qm-highlight');
187
  }
188
  tr.not('[data-qm-' + filter + '*="' + val + '"]').addClass('qm-hide-' + filter);
189
+ $(this).closest('th').addClass('qm-filtered');
190
  } else {
191
+ $(this).closest('th').removeClass('qm-filtered');
192
  }
193
 
194
  var matches = tr.filter(':visible');
202
  time = QM_i18n.number_format( time, 4 );
203
  }
204
 
205
+ if ( table.find('.qm-filtered').length ) {
206
+ var count = matches.length + ' / ' + tr.length;
 
 
 
 
207
  } else {
208
+ var count = matches.length;
209
  }
210
+
211
+ table.find('.qm-items-number').text(count);
212
+ table.find('.qm-items-time').text(time);
213
+
214
+ stripes(table);
215
  });
216
 
217
  $('#query-monitor').find('.qm-filter').each(function () {
234
  $('#qm-' + target).find('.qm-filter').not('[data-filter="' + filter + '"]').val('').removeClass('qm-highlight').change();
235
  $('#qm-' + target).find('[data-filter="' + filter + '"]').val(value).addClass('qm-highlight').change();
236
  show_panel( '#qm-' + target );
237
+ $('#qm-' + target).focus();
238
  e.preventDefault();
239
  });
240
 
287
 
288
  });
289
 
290
+ $('.qm').find('tbody a,tbody button').on('focus',function(e){
291
+ $(this).closest('tr').addClass('qm-hovered');
292
+ }).on('blur',function(e){
293
+ $(this).closest('tr').removeClass('qm-hovered');
294
+ });
295
+
296
+ $('#query-monitor').find('.qm table').on('sorted.qm',function(){
297
+ stripes( $(this) );
298
+ });
299
+
300
  $( document ).ajaxSuccess( function( event, response, options ) {
301
 
302
  var errors = response.getResponseHeader( 'X-QM-php_errors-error-count' );
336
  console.groupEnd();
337
  }
338
 
339
+ $( '#qm-ajax-errors' ).show();
340
+
341
  return event;
342
 
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,{
350
  type : 'POST',
351
+ context : this,
352
  data : {
353
  action : 'qm_auth_' + action,
354
  nonce : qm_l10n.auth_nonce[action]
355
  },
356
  success : function(response){
357
+ $(this).text( $(this).data('qm-text-' + action) );
358
+ $('#qm-settings').attr('data-qm-state',action).data('qm-state',action);
359
  },
360
  dataType : 'json',
361
  xhrFields: {
436
 
437
  $('.qm-button-container-settings').click(function(){
438
  show_panel( '#qm-settings' );
439
+ $('#qm-settings').focus();
440
  });
441
 
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(){
450
  show_panel( $(this).val() );
451
+ $($(this).val()).focus();
452
  });
453
 
454
  } );
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');
514
 
515
  if ( desc ) {
516
+ $(this).addClass('qm-sorted-desc').attr('aria-sort','descending');
517
  } else {
518
+ $(this).addClass('qm-sorted-asc').attr('aria-sort','ascending');
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) {
527
+ this.data_matrix = table_to_array(columns, $(rows[0]).find('th,td').length);
528
  }
529
 
530
  var data = this.data_matrix;
558
 
559
  table.append(tbody);
560
  });
561
+
562
+ table.trigger('sorted.qm');
563
+
564
  e.preventDefault();
565
  });
566
  });
classes/Backtrace.php CHANGED
@@ -82,7 +82,7 @@ class QM_Backtrace {
82
  continue;
83
  }
84
 
85
- if ( isset( self::$show_args[ $frame['function'] ] ) ) {
86
  $show = self::$show_args[ $frame['function'] ];
87
 
88
  if ( 'dir' === $show ) {
@@ -237,11 +237,11 @@ class QM_Backtrace {
237
  $return = null;
238
  } elseif ( isset( self::$ignore_method[ $trace['class'] ][ $trace['function'] ] ) ) {
239
  $return = null;
240
- } elseif ( 0 === strpos( $trace['class'], 'QM_' ) ) {
241
  $return = null;
242
  } else {
243
  $return['id'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
244
- $return['display'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
245
  }
246
  } else {
247
  if ( isset( self::$ignore_func[ $trace['function'] ] ) ) {
@@ -253,7 +253,7 @@ class QM_Backtrace {
253
  if ( isset( $trace['args'][0] ) ) {
254
  $arg = QM_Util::standard_dir( $trace['args'][0], '' );
255
  $return['id'] = $trace['function'] . '()';
256
- $return['display'] = $trace['function'] . "('{$arg}')";
257
  }
258
  } else {
259
  $args = array();
@@ -267,11 +267,11 @@ class QM_Backtrace {
267
  }
268
  }
269
  $return['id'] = $trace['function'] . '()';
270
- $return['display'] = $trace['function'] . '(' . implode( ',', $args ) . ')';
271
  }
272
  } else {
273
  $return['id'] = $trace['function'] . '()';
274
- $return['display'] = $trace['function'] . '()';
275
  }
276
  }
277
 
82
  continue;
83
  }
84
 
85
+ if ( isset( $frame['function'] ) && isset( self::$show_args[ $frame['function'] ] ) ) {
86
  $show = self::$show_args[ $frame['function'] ];
87
 
88
  if ( 'dir' === $show ) {
237
  $return = null;
238
  } elseif ( isset( self::$ignore_method[ $trace['class'] ][ $trace['function'] ] ) ) {
239
  $return = null;
240
+ } elseif ( 0 === strpos( $trace['class'], 'QM' ) ) {
241
  $return = null;
242
  } else {
243
  $return['id'] = $trace['class'] . $trace['type'] . $trace['function'] . '()';
244
+ $return['display'] = QM_Util::shorten_fqn( $trace['class'] . $trace['type'] . $trace['function'] ) . '()';
245
  }
246
  } else {
247
  if ( isset( self::$ignore_func[ $trace['function'] ] ) ) {
253
  if ( isset( $trace['args'][0] ) ) {
254
  $arg = QM_Util::standard_dir( $trace['args'][0], '' );
255
  $return['id'] = $trace['function'] . '()';
256
+ $return['display'] = QM_Util::shorten_fqn( $trace['function'] ) . "('{$arg}')";
257
  }
258
  } else {
259
  $args = array();
267
  }
268
  }
269
  $return['id'] = $trace['function'] . '()';
270
+ $return['display'] = QM_Util::shorten_fqn( $trace['function'] ) . '(' . implode( ',', $args ) . ')';
271
  }
272
  } else {
273
  $return['id'] = $trace['function'] . '()';
274
+ $return['display'] = QM_Util::shorten_fqn( $trace['function'] ) . '()';
275
  }
276
  }
277
 
classes/Collector.php CHANGED
@@ -70,6 +70,8 @@ abstract class QM_Collector {
70
  }
71
 
72
  public static function format_bool_constant( $constant ) {
 
 
73
  if ( ! defined( $constant ) ) {
74
  /* translators: Undefined PHP constant */
75
  return __( 'undefined', 'query-monitor' );
70
  }
71
 
72
  public static function format_bool_constant( $constant ) {
73
+ // @TODO this should be in QM_Util
74
+
75
  if ( ! defined( $constant ) ) {
76
  /* translators: Undefined PHP constant */
77
  return __( 'undefined', 'query-monitor' );
classes/QM.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A convenience class for wrapping certain user-facing functionality.
4
+ *
5
+ * @package query-monitor
6
+ */
7
+
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
+
42
+ public static function log( $level, $message, array $context = array() ) {
43
+ $logger = QM_Collectors::get( 'logger' );
44
+ $logger->log( $level, $message, $context );
45
+ }
46
+ }
classes/Util.php CHANGED
@@ -200,22 +200,25 @@ class QM_Util {
200
  $access = '::';
201
  }
202
 
203
- $callback['name'] = $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
  /* translators: 1: Line number, 2: File name */
210
  $callback['name'] = sprintf( __( 'Closure on line %1$d of %2$s', 'query-monitor' ), $ref->getStartLine(), $file );
211
  } else {
212
  // the object should have a __invoke() method
213
  $class = get_class( $callback['function'] );
214
- $callback['name'] = $class . '->__invoke()';
215
  $ref = new ReflectionMethod( $class, '__invoke' );
216
  }
217
  } else {
218
- $callback['name'] = $callback['function'] . '()';
219
  $ref = new ReflectionFunction( $callback['function'] );
220
  }
221
 
@@ -342,31 +345,75 @@ class QM_Util {
342
  return $value;
343
  } elseif ( is_object( $value ) ) {
344
  $class = get_class( $value );
345
- $id = false;
346
 
347
- switch ( $class ) {
348
 
349
- case 'WP_Post':
350
- case 'WP_User':
351
- $id = $value->ID;
352
  break;
353
 
354
- case 'WP_Term':
355
- $id = $value->term_id;
356
  break;
357
 
358
- }
 
 
359
 
360
- if ( $id ) {
361
- return sprintf( '%s (ID:%d)', $class, $id );
362
- }
363
 
364
- return $class;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
  } else {
366
  return gettype( $value );
367
  }
368
  }
369
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  public static function sort( array &$array, $field ) {
371
  self::$sort_field = $field;
372
  usort( $array, array( __CLASS__, '_sort' ) );
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
+ }
212
  /* translators: 1: Line number, 2: File name */
213
  $callback['name'] = sprintf( __( 'Closure on line %1$d of %2$s', 'query-monitor' ), $ref->getStartLine(), $file );
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
 
345
  return $value;
346
  } elseif ( is_object( $value ) ) {
347
  $class = get_class( $value );
 
348
 
349
+ switch ( true ) {
350
 
351
+ case ( $value instanceof WP_Post ):
352
+ case ( $value instanceof WP_User ):
353
+ return sprintf( '%s (ID: %s)', $class, $value->ID );
354
  break;
355
 
356
+ case ( $value instanceof WP_Term ):
357
+ return sprintf( '%s (term_id: %s)', $class, $value->term_id );
358
  break;
359
 
360
+ case ( $value instanceof WP_Comment ):
361
+ return sprintf( '%s (comment_ID: %s)', $class, $value->comment_ID );
362
+ break;
363
 
364
+ case ( $value instanceof WP_Error ):
365
+ return sprintf( '%s (%s)', $class, $value->get_error_code() );
366
+ break;
367
 
368
+ case ( $value instanceof WP_Role ):
369
+ case ( $value instanceof WP_Post_Type ):
370
+ case ( $value instanceof WP_Taxonomy ):
371
+ return sprintf( '%s (%s)', $class, $value->name );
372
+ break;
373
+
374
+ case ( $value instanceof WP_Network ):
375
+ return sprintf( '%s (id: %s)', $class, $value->id );
376
+ break;
377
+
378
+ case ( $value instanceof WP_Site ):
379
+ return sprintf( '%s (blog_id: %s)', $class, $value->blog_id );
380
+ break;
381
+
382
+ case ( $value instanceof WP_Theme ):
383
+ return sprintf( '%s (%s)', $class, $value->get_stylesheet() );
384
+ break;
385
+
386
+ default:
387
+ return $class;
388
+ break;
389
+
390
+ }
391
  } else {
392
  return gettype( $value );
393
  }
394
  }
395
 
396
+ /**
397
+ * Shortens a fully qualified name to reduce the length of the names of long namespaced symbols.
398
+ *
399
+ * This initialises portions that do not form the first or last portion of the name. For example:
400
+ *
401
+ * Inpsyde\Wonolog\HookListener\HookListenersRegistry->hook_callback()
402
+ *
403
+ * becomes:
404
+ *
405
+ * Inpsyde\W\H\HookListenersRegistry->hook_callback()
406
+ *
407
+ * @param string $fqn A fully qualified name.
408
+ * @return string A shortened version of the name.
409
+ */
410
+ public static function shorten_fqn( $fqn ) {
411
+ return preg_replace_callback( '#\\\\[a-zA-Z0-9_\\\\]{4,}\\\\#', function( array $matches ) {
412
+ preg_match_all( '#\\\\([a-zA-Z0-9_])#', $matches[0], $m );
413
+ return '\\' . implode( '\\', $m[1] ) . '\\';
414
+ }, $fqn );
415
+ }
416
+
417
  public static function sort( array &$array, $field ) {
418
  self::$sort_field = $field;
419
  usort( $array, array( __CLASS__, '_sort' ) );
collectors/admin.php CHANGED
@@ -7,7 +7,7 @@
7
 
8
  class QM_Collector_Admin extends QM_Collector {
9
 
10
- public $id = 'admin';
11
 
12
  public function name() {
13
  return __( 'Admin Screen', 'query-monitor' );
@@ -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['admin'] = new QM_Collector_Admin;
92
  return $collectors;
93
  }
94
 
7
 
8
  class QM_Collector_Admin extends QM_Collector {
9
 
10
+ public $id = 'response';
11
 
12
  public function name() {
13
  return __( 'Admin Screen', 'query-monitor' );
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/cache.php CHANGED
@@ -28,14 +28,41 @@ class QM_Collector_Cache extends QM_Collector {
28
  $this->data['stats']['cache_misses'] = (int) $wp_object_cache->cache_misses;
29
  }
30
 
31
- if ( property_exists( $wp_object_cache, 'stats' ) && is_array( $wp_object_cache->stats ) ) {
32
- foreach ( $wp_object_cache->stats as $key => $value ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  if ( ! is_scalar( $value ) ) {
34
  continue;
35
  }
36
  $this->data['stats'][ $key ] = $value;
37
  }
38
  }
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
40
 
41
  if ( isset( $this->data['stats']['cache_hits'] ) && isset( $this->data['stats']['cache_misses'] ) ) {
@@ -45,6 +72,18 @@ class QM_Collector_Cache extends QM_Collector {
45
 
46
  $this->data['display_hit_rate_warning'] = ( 100 === $this->data['cache_hit_percentage'] );
47
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
 
50
  }
28
  $this->data['stats']['cache_misses'] = (int) $wp_object_cache->cache_misses;
29
  }
30
 
31
+ if ( method_exists( $wp_object_cache, 'getStats' ) ) {
32
+ $stats = $wp_object_cache->getStats();
33
+ } elseif ( property_exists( $wp_object_cache, 'stats' ) && is_array( $wp_object_cache->stats ) ) {
34
+ $stats = $wp_object_cache->stats;
35
+ } elseif ( function_exists( 'wp_cache_get_stats' ) ) {
36
+ $stats = wp_cache_get_stats();
37
+ }
38
+
39
+ if ( ! empty( $stats ) ) {
40
+ if ( is_array( $stats ) && ! isset( $stats['get_hits'] ) && 1 === count( $stats ) ) {
41
+ $first_server = reset( $stats );
42
+ if ( isset( $first_server['get_hits'] ) ) {
43
+ $stats = $first_server;
44
+ }
45
+ }
46
+
47
+ foreach ( $stats as $key => $value ) {
48
  if ( ! is_scalar( $value ) ) {
49
  continue;
50
  }
51
  $this->data['stats'][ $key ] = $value;
52
  }
53
  }
54
+
55
+ if ( ! isset( $this->data['stats']['cache_hits'] ) ) {
56
+ if ( isset( $this->data['stats']['get_hits'] ) ) {
57
+ $this->data['stats']['cache_hits'] = (int) $this->data['stats']['get_hits'];
58
+ }
59
+ }
60
+
61
+ if ( ! isset( $this->data['stats']['cache_misses'] ) ) {
62
+ if ( isset( $this->data['stats']['get_misses'] ) ) {
63
+ $this->data['stats']['cache_misses'] = (int) $this->data['stats']['get_misses'];
64
+ }
65
+ }
66
  }
67
 
68
  if ( isset( $this->data['stats']['cache_hits'] ) && isset( $this->data['stats']['cache_misses'] ) ) {
72
 
73
  $this->data['display_hit_rate_warning'] = ( 100 === $this->data['cache_hit_percentage'] );
74
 
75
+ if ( function_exists( 'extension_loaded' ) ) {
76
+ $this->data['extensions'] = array_map( 'extension_loaded', array(
77
+ 'APC' => 'APC',
78
+ 'APCu' => 'APCu',
79
+ 'Memcache' => 'Memcache',
80
+ 'Memcached' => 'Memcached',
81
+ 'Redis' => 'Redis',
82
+ 'Zend OPcache' => 'Zend OPcache',
83
+ ) );
84
+ } else {
85
+ $this->data['extensions'] = array();
86
+ }
87
  }
88
 
89
  }
collectors/caps.php CHANGED
@@ -15,13 +15,18 @@ class QM_Collector_Caps extends QM_Collector {
15
 
16
  public function __construct() {
17
  parent::__construct();
18
- if ( ! defined( 'QM_ENABLE_CAPS_PANEL' ) ) {
19
  return;
20
  }
21
  add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 9999, 3 );
22
  add_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 9999, 4 );
23
  }
24
 
 
 
 
 
 
25
  /**
26
  * Logs user capability checks.
27
  *
15
 
16
  public function __construct() {
17
  parent::__construct();
18
+ if ( ! defined( 'QM_ENABLE_CAPS_PANEL' ) || ! QM_ENABLE_CAPS_PANEL ) {
19
  return;
20
  }
21
  add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 9999, 3 );
22
  add_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 9999, 4 );
23
  }
24
 
25
+ public function tear_down() {
26
+ remove_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 9999 );
27
+ remove_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 9999 );
28
+ }
29
+
30
  /**
31
  * Logs user capability checks.
32
  *
collectors/db_queries.php CHANGED
@@ -129,7 +129,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
129
  $trace = $query['trace'];
130
  $component = $query['trace']->get_component();
131
  $caller = $query['trace']->get_caller();
132
- $caller_name = $caller['id'];
133
  $caller = $caller['display'];
134
 
135
  } else {
129
  $trace = $query['trace'];
130
  $component = $query['trace']->get_component();
131
  $caller = $query['trace']->get_caller();
132
+ $caller_name = $caller['display'];
133
  $caller = $caller['display'];
134
 
135
  } else {
collectors/debug_bar.php CHANGED
@@ -16,7 +16,11 @@ final class QM_Collector_Debug_Bar extends QM_Collector {
16
 
17
  public function name() {
18
  $title = $this->get_panel()->title();
19
- return sprintf( 'Debug Bar: %s', $title );
 
 
 
 
20
  }
21
 
22
  public function set_panel( Debug_Bar_Panel $panel ) {
16
 
17
  public function name() {
18
  $title = $this->get_panel()->title();
19
+ return sprintf(
20
+ /* translators: Debug Bar add-on name */
21
+ __( 'Debug Bar: %s', 'query-monitor' ),
22
+ $title
23
+ );
24
  }
25
 
26
  public function set_panel( Debug_Bar_Panel $panel ) {
collectors/environment.php CHANGED
@@ -143,9 +143,9 @@ class QM_Collector_Environment extends QM_Collector {
143
 
144
  $info = array(
145
  'rdbms' => $rdbms,
146
- 'server version' => $server,
147
  'extension' => $extension,
148
- 'client version' => $client_version,
149
  'user' => $db->dbuser,
150
  'host' => $db->dbhost,
151
  'database' => $db->dbname,
@@ -187,8 +187,8 @@ class QM_Collector_Environment extends QM_Collector {
187
  $this->data['php']['error_reporting'] = error_reporting();
188
  $this->data['php']['error_levels'] = self::get_error_levels( $this->data['php']['error_reporting'] );
189
 
190
- $this->data['wp'] = array(
191
- 'version' => $wp_version,
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' ),
@@ -201,7 +201,7 @@ class QM_Collector_Environment extends QM_Collector {
201
  );
202
 
203
  if ( is_multisite() ) {
204
- $this->data['wp']['SUNRISE'] = self::format_bool_constant( 'SUNRISE' );
205
  }
206
 
207
  if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) { // WPCS: input var ok
143
 
144
  $info = array(
145
  'rdbms' => $rdbms,
146
+ 'server-version' => $server,
147
  'extension' => $extension,
148
+ 'client-version' => $client_version,
149
  'user' => $db->dbuser,
150
  'host' => $db->dbhost,
151
  'database' => $db->dbname,
187
  $this->data['php']['error_reporting'] = error_reporting();
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' ),
201
  );
202
 
203
  if ( is_multisite() ) {
204
+ $this->data['wp']['constants']['SUNRISE'] = self::format_bool_constant( 'SUNRISE' );
205
  }
206
 
207
  if ( isset( $_SERVER['SERVER_SOFTWARE'] ) ) { // WPCS: input var ok
collectors/hooks.php CHANGED
@@ -19,7 +19,7 @@ class QM_Collector_Hooks extends QM_Collector {
19
  global $wp_actions, $wp_filter;
20
 
21
  self::$hide_qm = self::hide_qm();
22
- self::$hide_core = ( defined( 'QM_HIDE_CORE_HOOKS' ) && QM_HIDE_CORE_HOOKS );
23
 
24
  $hooks = $all_parts = $components = array();
25
 
@@ -51,7 +51,7 @@ class QM_Collector_Hooks extends QM_Collector {
51
  }
52
 
53
  public function post_process() {
54
- $admin = QM_Collectors::get( 'admin' );
55
 
56
  if ( is_admin() && $admin ) {
57
  $this->data['screen'] = $admin->data['base'];
19
  global $wp_actions, $wp_filter;
20
 
21
  self::$hide_qm = self::hide_qm();
22
+ self::$hide_core = ( defined( 'QM_HIDE_CORE_ACTIONS' ) && QM_HIDE_CORE_ACTIONS );
23
 
24
  $hooks = $all_parts = $components = array();
25
 
51
  }
52
 
53
  public function post_process() {
54
+ $admin = QM_Collectors::get( 'response' );
55
 
56
  if ( is_admin() && $admin ) {
57
  $this->data['screen'] = $admin->data['base'];
collectors/languages.php CHANGED
@@ -36,6 +36,10 @@ class QM_Collector_Languages extends QM_Collector {
36
  */
37
  public function log_file_load( $override, $domain, $mofile ) {
38
 
 
 
 
 
39
  $trace = new QM_Backtrace;
40
  $filtered = $trace->get_filtered_trace();
41
  $caller = array();
36
  */
37
  public function log_file_load( $override, $domain, $mofile ) {
38
 
39
+ if ( 'query-monitor' === $domain && self::hide_qm() ) {
40
+ return $override;
41
+ }
42
+
43
  $trace = new QM_Backtrace;
44
  $filtered = $trace->get_filtered_trace();
45
  $caller = array();
collectors/logger.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PSR-3 compatible logging collector.
4
+ *
5
+ * @package query-monitor
6
+ */
7
+
8
+ class QM_Collector_Logger extends QM_Collector {
9
+
10
+ public $id = 'logger';
11
+
12
+ const EMERGENCY = 'emergency';
13
+ const ALERT = 'alert';
14
+ const CRITICAL = 'critical';
15
+ const ERROR = 'error';
16
+ const WARNING = 'warning';
17
+ const NOTICE = 'notice';
18
+ const INFO = 'info';
19
+ const DEBUG = 'debug';
20
+
21
+ public function name() {
22
+ return __( 'Logger', 'query-monitor' );
23
+ }
24
+
25
+ public function __construct() {
26
+ parent::__construct();
27
+ foreach ( $this->get_levels() as $level ) {
28
+ add_action( "qm/{$level}", array( $this, $level ), 10, 2 );
29
+ }
30
+
31
+ add_action( 'qm/log', array( $this, 'log' ), 10, 3 );
32
+ }
33
+
34
+ public function emergency( $message, array $context = array() ) {
35
+ $this->store( 'emergency', $message, $context );
36
+ }
37
+
38
+ public function alert( $message, array $context = array() ) {
39
+ $this->store( 'alert', $message, $context );
40
+ }
41
+
42
+ public function critical( $message, array $context = array() ) {
43
+ $this->store( 'critical', $message, $context );
44
+ }
45
+
46
+ public function error( $message, array $context = array() ) {
47
+ $this->store( 'error', $message, $context );
48
+ }
49
+
50
+ public function warning( $message, array $context = array() ) {
51
+ $this->store( 'warning', $message, $context );
52
+ }
53
+
54
+ public function notice( $message, array $context = array() ) {
55
+ $this->store( 'notice', $message, $context );
56
+ }
57
+
58
+ public function info( $message, array $context = array() ) {
59
+ $this->store( 'info', $message, $context );
60
+ }
61
+
62
+ public function debug( $message, array $context = array() ) {
63
+ $this->store( 'debug', $message, $context );
64
+ }
65
+
66
+ public function log( $level, $message, array $context = array() ) {
67
+ if ( ! in_array( $level, $this->get_levels(), true ) ) {
68
+ throw new InvalidArgumentException( __( 'Unsupported log level', 'query-monitor' ) );
69
+ }
70
+
71
+ $this->store( $level, $message, $context );
72
+ }
73
+
74
+ protected function store( $level, $message, array $context = array() ) {
75
+ $trace = new QM_Backtrace( array(
76
+ 'ignore_frames' => 2,
77
+ ) );
78
+
79
+ if ( is_wp_error( $message ) ) {
80
+ $message = sprintf(
81
+ '%s (%s)',
82
+ $message->get_error_message(),
83
+ $message->get_error_code()
84
+ );
85
+ }
86
+
87
+ if ( $message instanceof Exception ) {
88
+ $message = $message->getMessage();
89
+ }
90
+
91
+ $this->data['logs'][] = array(
92
+ 'message' => $this->interpolate( $message, $context ),
93
+ 'context' => $context,
94
+ 'trace' => $trace,
95
+ 'level' => $level,
96
+ );
97
+ }
98
+
99
+ protected function interpolate( $message, array $context = array() ) {
100
+ // build a replacement array with braces around the context keys
101
+ $replace = array();
102
+
103
+ foreach ( $context as $key => $val ) {
104
+ // check that the value can be casted to string
105
+ if ( is_scalar( $val ) || ( is_object( $val ) && method_exists( $val, '__toString' ) ) ) {
106
+ $replace[ "{{$key}}" ] = $val;
107
+ }
108
+ }
109
+
110
+ // interpolate replacement values into the message and return
111
+ return strtr( $message, $replace );
112
+ }
113
+
114
+ public function process() {
115
+ if ( empty( $this->data['logs'] ) ) {
116
+ return;
117
+ }
118
+
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
+
126
+ $this->data['components'] = $components;
127
+ }
128
+
129
+ public function get_levels() {
130
+ return array(
131
+ self::EMERGENCY,
132
+ self::ALERT,
133
+ self::CRITICAL,
134
+ self::ERROR,
135
+ self::WARNING,
136
+ self::NOTICE,
137
+ self::INFO,
138
+ self::DEBUG,
139
+ );
140
+ }
141
+
142
+ public function get_warning_levels() {
143
+ return array(
144
+ self::EMERGENCY,
145
+ self::ALERT,
146
+ self::CRITICAL,
147
+ self::ERROR,
148
+ self::WARNING,
149
+ );
150
+ }
151
+
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
@@ -46,7 +46,15 @@ class QM_Collector_Overview extends QM_Collector {
46
  }
47
 
48
  $this->data['memory_limit'] = QM_Util::convert_hr_to_bytes( ini_get( 'memory_limit' ) );
49
- $this->data['memory_usage'] = ( 100 / $this->data['memory_limit'] ) * $this->data['memory'];
 
 
 
 
 
 
 
 
50
 
51
  $this->data['is_admin'] = is_admin();
52
  }
46
  }
47
 
48
  $this->data['memory_limit'] = QM_Util::convert_hr_to_bytes( ini_get( 'memory_limit' ) );
49
+
50
+ if ( $this->data['memory_limit'] > 0 ) {
51
+ $this->data['memory_usage'] = ( 100 / $this->data['memory_limit'] ) * $this->data['memory'];
52
+ } else {
53
+ $this->data['memory_usage'] = 0;
54
+ }
55
+
56
+ $this->data['display_time_usage_warning'] = ( $this->data['time_usage'] >= 75 );
57
+ $this->data['display_memory_usage_warning'] = ( $this->data['memory_usage'] >= 75 );
58
 
59
  $this->data['is_admin'] = is_admin();
60
  }
collectors/php_errors.php CHANGED
@@ -99,17 +99,15 @@ class QM_Collector_PHP_Errors extends QM_Collector {
99
  $caller = $trace->get_caller();
100
  $key = md5( $message . $file . $line . $caller['id'] );
101
 
102
- $filename = QM_Util::standard_dir( $file, '' );
103
-
104
  if ( isset( $this->data[ $error_group ][ $type ][ $key ] ) ) {
105
- $this->data[ $error_group ][ $type ][ $key ]->calls++;
106
  } else {
107
- $this->data[ $error_group ][ $type ][ $key ] = (object) array(
108
  'errno' => $errno,
109
  'type' => $type,
110
- 'message' => $message,
111
  'file' => $file,
112
- 'filename' => $filename,
113
  'line' => $line,
114
  'trace' => $trace,
115
  'calls' => 1,
@@ -255,7 +253,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
255
  foreach ( $error_types as $type => $title ) {
256
  if ( isset( $this->data[ $error_group ][ $type ] ) ) {
257
  foreach ( $this->data[ $error_group ][ $type ] as $error ) {
258
- $component = $error->trace->get_component();
259
  $components[ $component->name ] = $component->name;
260
  }
261
  }
@@ -279,10 +277,10 @@ class QM_Collector_PHP_Errors extends QM_Collector {
279
  foreach ( $components as $component_context => $allowed_level ) {
280
  foreach ( $all_errors as $error_level => $errors ) {
281
  foreach ( $errors as $error_id => $error ) {
282
- if ( $this->is_reportable_error( $error->errno, $allowed_level ) ) {
283
  continue;
284
  }
285
- if ( ! $this->is_affected_component( $error->trace->get_component(), $component_type, $component_context ) ) {
286
  continue;
287
  }
288
 
99
  $caller = $trace->get_caller();
100
  $key = md5( $message . $file . $line . $caller['id'] );
101
 
 
 
102
  if ( isset( $this->data[ $error_group ][ $type ][ $key ] ) ) {
103
+ $this->data[ $error_group ][ $type ][ $key ]['calls']++;
104
  } else {
105
+ $this->data[ $error_group ][ $type ][ $key ] = array(
106
  'errno' => $errno,
107
  'type' => $type,
108
+ 'message' => wp_strip_all_tags( $message ),
109
  'file' => $file,
110
+ 'filename' => QM_Util::standard_dir( $file, '' ),
111
  'line' => $line,
112
  'trace' => $trace,
113
  'calls' => 1,
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
  }
277
  foreach ( $components as $component_context => $allowed_level ) {
278
  foreach ( $all_errors as $error_level => $errors ) {
279
  foreach ( $errors as $error_id => $error ) {
280
+ if ( $this->is_reportable_error( $error['errno'], $allowed_level ) ) {
281
  continue;
282
  }
283
+ if ( ! $this->is_affected_component( $error['trace']->get_component(), $component_type, $component_context ) ) {
284
  continue;
285
  }
286
 
collectors/theme.php CHANGED
@@ -7,7 +7,7 @@
7
 
8
  class QM_Collector_Theme extends QM_Collector {
9
 
10
- public $id = 'theme';
11
  protected $got_theme_compat = false;
12
 
13
  public function name() {
@@ -118,8 +118,10 @@ 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
 
122
  foreach ( get_included_files() as $file ) {
 
123
  $filename = str_replace( array(
124
  $stylesheet_directory,
125
  $template_directory,
@@ -142,9 +144,9 @@ class QM_Collector_Theme extends QM_Collector {
142
  }
143
  }
144
 
145
- $this->data['stylesheet'] = get_stylesheet();
146
- $this->data['template'] = get_template();
147
- $this->data['is_child_theme'] = ( $this->data['stylesheet'] !== $this->data['template'] );
148
 
149
  if ( isset( $this->data['body_class'] ) ) {
150
  asort( $this->data['body_class'] );
@@ -155,7 +157,7 @@ class QM_Collector_Theme extends QM_Collector {
155
  }
156
 
157
  function register_qm_collector_theme( array $collectors, QueryMonitor $qm ) {
158
- $collectors['theme'] = new QM_Collector_Theme;
159
  return $collectors;
160
  }
161
 
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() {
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,
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
  }
158
 
159
  function register_qm_collector_theme( array $collectors, QueryMonitor $qm ) {
160
+ $collectors['response'] = new QM_Collector_Theme;
161
  return $collectors;
162
  }
163
 
composer.json CHANGED
@@ -16,12 +16,13 @@
16
  "source": "https://github.com/johnbillion/query-monitor"
17
  },
18
  "require": {
 
19
  "composer/installers": "~1.0"
20
  },
21
  "require-dev" : {
22
  "squizlabs/php_codesniffer": "^3.2",
23
- "wimg/php-compatibility": "^8",
24
- "wp-coding-standards/wpcs": "^0.13",
25
  "phpunit/phpunit": "^5"
26
  }
27
  }
16
  "source": "https://github.com/johnbillion/query-monitor"
17
  },
18
  "require": {
19
+ "php": ">=5.3",
20
  "composer/installers": "~1.0"
21
  },
22
  "require-dev" : {
23
  "squizlabs/php_codesniffer": "^3.2",
24
+ "phpcompatibility/php-compatibility": "~8.2",
25
+ "wp-coding-standards/wpcs": "0.13",
26
  "phpunit/phpunit": "^5"
27
  }
28
  }
dispatchers/Html.php CHANGED
@@ -49,7 +49,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
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( __( 'Could not set authentication cookie.', 'query-monitor' ) );
53
  }
54
 
55
  $expiration = time() + ( 2 * DAY_IN_SECONDS );
@@ -58,25 +58,21 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
58
 
59
  setcookie( QM_COOKIE, $cookie, $expiration, COOKIEPATH, COOKIE_DOMAIN, $secure, false );
60
 
61
- $text = __( 'Authentication cookie set. You can now view Query Monitor output while logged out or while logged in as a different user.', 'query-monitor' );
62
-
63
- wp_send_json_success( $text );
64
 
65
  }
66
 
67
  public function ajax_off() {
68
 
69
  if ( ! self::user_verified() or ! check_ajax_referer( 'qm-auth-off', 'nonce', false ) ) {
70
- wp_send_json_error( __( 'Could not clear authentication cookie.', 'query-monitor' ) );
71
  }
72
 
73
  $expiration = time() - 31536000;
74
 
75
  setcookie( QM_COOKIE, ' ', $expiration, COOKIEPATH, COOKIE_DOMAIN );
76
 
77
- $text = __( 'Authentication cookie cleared.', 'query-monitor' );
78
-
79
- wp_send_json_success( $text );
80
 
81
  }
82
 
@@ -165,6 +161,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
165
  'query-monitor',
166
  'qm_l10n',
167
  array(
 
168
  'ajaxurl' => admin_url( 'admin-ajax.php' ),
169
  'auth_nonce' => array(
170
  'on' => wp_create_nonce( 'qm-auth-on' ),
@@ -172,16 +169,6 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
172
  ),
173
  )
174
  );
175
-
176
- if ( floatval( $wp_version ) <= 3.7 ) {
177
- wp_enqueue_style(
178
- 'query-monitor-compat',
179
- $this->qm->plugin_url( 'assets/compat.css' ),
180
- null,
181
- $this->qm->plugin_ver( 'assets/compat.css' )
182
- );
183
- }
184
-
185
  }
186
 
187
  public function dispatch() {
@@ -197,7 +184,15 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
197
  $timer = new QM_Timer;
198
  $timer->start();
199
 
 
 
 
 
200
  $output->output();
 
 
 
 
201
 
202
  $output->set_timer( $timer->stop() );
203
  }
@@ -231,6 +226,10 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
231
  $class[] = 'qm-peek';
232
  }
233
 
 
 
 
 
234
  $json = array(
235
  'menu' => $this->js_admin_bar_menu(),
236
  'ajax_errors' => array(), # @TODO move this into the php_errors collector
@@ -240,7 +239,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
240
  echo 'var qm = ' . json_encode( $json ) . ';' . "\n\n";
241
  echo '</script>' . "\n\n";
242
 
243
- echo '<div id="query-monitor" class="' . implode( ' ', array_map( 'esc_attr', $class ) ) . '">';
244
  echo '<div id="qm-title">';
245
  echo '<h1 class="qm-title-heading">' . esc_html__( 'Query Monitor', 'query-monitor' ) . '</h1>';
246
  echo '<div class="qm-title-heading">';
@@ -268,18 +267,19 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
268
  echo '</div>'; // #qm-title
269
 
270
  echo '<div id="qm-wrapper">';
271
- echo '<div id="qm-panel-menu">';
 
272
  echo '<ul>';
273
 
274
  printf(
275
- '<li><a href="%1$s">%2$s</a></li>',
276
  '#qm-overview',
277
  esc_html__( 'Overview', 'query-monitor' )
278
  );
279
 
280
  foreach ( $this->panel_menu as $menu ) {
281
  printf(
282
- '<li><a href="%1$s">%2$s</a></li>',
283
  esc_attr( $menu['href'] ),
284
  esc_html( $menu['title'] )
285
  );
@@ -294,28 +294,110 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
294
 
295
  protected function after_output() {
296
 
297
- echo '<div class="qm qm-non-tabular" id="qm-settings">';
 
 
 
 
298
 
299
- echo '<div class="qm-boxed qm-boxed-wrap">';
 
 
 
300
  echo '<div class="qm-section">';
301
- echo '<h2>' . esc_html__( 'Authentication', 'query-monitor' ) . '</h2>';
302
 
303
- if ( ! self::user_verified() ) {
304
 
305
- 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.', 'query-monitor' ) . '</p>';
306
- echo '<p><a href="#" class="qm-auth" data-action="on">' . esc_html__( 'Set authentication cookie', 'query-monitor' ) . '</a></p>';
307
 
308
- } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
 
310
- echo '<p>' . esc_html__( 'You currently have an authentication cookie which allows you to view Query Monitor output.', 'query-monitor' ) . '</p>';
311
- echo '<p><a href="#" class="qm-auth" data-action="off">' . esc_html__( 'Clear authentication cookie', 'query-monitor' ) . '</a></p>';
312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  }
314
 
 
315
  echo '</div>';
 
316
  echo '</div>';
317
 
318
  echo '</div>'; // #qm-settings
 
 
 
319
  echo '</div>'; // #qm-panels
320
  echo '</div>'; // #qm-wrapper
321
  echo '</div>'; // #qm
@@ -356,7 +438,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
356
 
357
  }
358
 
359
- protected static function size( $var ) {
360
  $start_memory = memory_get_usage();
361
 
362
  try {
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
 
55
  $expiration = time() + ( 2 * DAY_IN_SECONDS );
58
 
59
  setcookie( QM_COOKIE, $cookie, $expiration, COOKIEPATH, COOKIE_DOMAIN, $secure, false );
60
 
61
+ wp_send_json_success();
 
 
62
 
63
  }
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
 
71
  $expiration = time() - 31536000;
72
 
73
  setcookie( QM_COOKIE, ' ', $expiration, COOKIEPATH, COOKIE_DOMAIN );
74
 
75
+ wp_send_json_success();
 
 
76
 
77
  }
78
 
161
  'query-monitor',
162
  'qm_l10n',
163
  array(
164
+ 'ajax_error' => __( 'PHP Errors in Ajax Response', 'query-monitor' ),
165
  'ajaxurl' => admin_url( 'admin-ajax.php' ),
166
  'auth_nonce' => array(
167
  'on' => wp_create_nonce( 'qm-auth-on' ),
169
  ),
170
  )
171
  );
 
 
 
 
 
 
 
 
 
 
172
  }
173
 
174
  public function dispatch() {
184
  $timer = new QM_Timer;
185
  $timer->start();
186
 
187
+ printf(
188
+ "\n" . '<!-- Begin %s output -->' . "\n",
189
+ esc_html( $id )
190
+ );
191
  $output->output();
192
+ printf(
193
+ "\n" . '<!-- End %s output -->' . "\n",
194
+ esc_html( $id )
195
+ );
196
 
197
  $output->set_timer( $timer->stop() );
198
  }
226
  $class[] = 'qm-peek';
227
  }
228
 
229
+ if ( wp_is_mobile() ) {
230
+ $class[] = 'qm-touch';
231
+ }
232
+
233
  $json = array(
234
  'menu' => $this->js_admin_bar_menu(),
235
  'ajax_errors' => array(), # @TODO move this into the php_errors collector
239
  echo 'var qm = ' . json_encode( $json ) . ';' . "\n\n";
240
  echo '</script>' . "\n\n";
241
 
242
+ echo '<div id="query-monitor" class="' . implode( ' ', array_map( 'esc_attr', $class ) ) . '" dir="ltr">';
243
  echo '<div id="qm-title">';
244
  echo '<h1 class="qm-title-heading">' . esc_html__( 'Query Monitor', 'query-monitor' ) . '</h1>';
245
  echo '<div class="qm-title-heading">';
267
  echo '</div>'; // #qm-title
268
 
269
  echo '<div id="qm-wrapper">';
270
+ echo '<div id="qm-panel-menu" role="navigation" aria-labelledby="qm-panel-menu-caption">';
271
+ echo '<h2 class="qm-screen-reader-text" id="qm-panel-menu-caption">' . esc_html__( 'Query Monitor Menu', 'query-monitor' ) . '</h2>';
272
  echo '<ul>';
273
 
274
  printf(
275
+ '<li><button data-qm-href="%1$s">%2$s</button></li>',
276
  '#qm-overview',
277
  esc_html__( 'Overview', 'query-monitor' )
278
  );
279
 
280
  foreach ( $this->panel_menu as $menu ) {
281
  printf(
282
+ '<li><button data-qm-href="%1$s">%2$s</button></li>',
283
  esc_attr( $menu['href'] ),
284
  esc_html( $menu['title'] )
285
  );
294
 
295
  protected function after_output() {
296
 
297
+ $state = self::user_verified() ? 'on' : 'off';
298
+ $text = array(
299
+ 'on' => __( 'Clear authentication cookie', 'query-monitor' ),
300
+ 'off' => __( 'Set authentication cookie', 'query-monitor' ),
301
+ );
302
 
303
+ echo '<div class="qm qm-non-tabular" id="qm-settings" data-qm-state="' . esc_attr( $state ) . '">';
304
+ echo '<h2 class="qm-screen-reader-text">' . esc_html__( 'Settings', 'query-monitor' ) . '</h2>';
305
+
306
+ echo '<div class="qm-boxed">';
307
  echo '<div class="qm-section">';
308
+ echo '<h3>' . esc_html__( 'Authentication', 'query-monitor' ) . '</h3>';
309
 
310
+ 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>';
311
 
312
+ 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>';
 
313
 
314
+ 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>';
315
+ echo '</div>';
316
+
317
+ $constants = array(
318
+ 'QM_DB_EXPENSIVE' => array(
319
+ /* translators: %s: The default value for a PHP constant */
320
+ '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' ),
321
+ 'default' => 0.05,
322
+ ),
323
+ 'QM_DISABLED' => array(
324
+ 'label' => __( 'Disable Query Monitor entirely.', 'query-monitor' ),
325
+ 'default' => false,
326
+ ),
327
+ 'QM_DISABLE_ERROR_HANDLER' => array(
328
+ 'label' => __( 'Disable the handling of PHP errors.', 'query-monitor' ),
329
+ 'default' => false,
330
+ ),
331
+ 'QM_ENABLE_CAPS_PANEL' => array(
332
+ 'label' => __( 'Enable the Capability Checks panel.', 'query-monitor' ),
333
+ 'default' => false,
334
+ ),
335
+ 'QM_HIDE_CORE_ACTIONS' => array(
336
+ 'label' => __( 'Hide WordPress core on the Hooks & Actions panel.', 'query-monitor' ),
337
+ 'default' => false,
338
+ ),
339
+ 'QM_HIDE_SELF' => array(
340
+ 'label' => __( 'Hide Query Monitor itself from various panels.', 'query-monitor' ),
341
+ 'default' => false,
342
+ ),
343
+ 'QM_NO_JQUERY' => array(
344
+ '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' ),
345
+ 'default' => false,
346
+ ),
347
+ 'QM_SHOW_ALL_HOOKS' => array(
348
+ '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' ),
349
+ 'default' => false,
350
+ ),
351
+ );
352
+
353
+ echo '<div class="qm-section">';
354
+ echo '<h3>' . esc_html__( 'Configuration', 'query-monitor' ) . '</h3>';
355
+ echo '<p>';
356
+ printf(
357
+ /* translators: %s: Name of the config file */
358
+ esc_html__( 'The following PHP constants can be defined in your %s file in order to control the behaviour of Query Monitor:', 'query-monitor' ),
359
+ '<code>wp-config.php</code>'
360
+ );
361
+ echo '</p>';
362
 
363
+ echo '<dl>';
 
364
 
365
+ foreach ( $constants as $name => $constant ) {
366
+ echo '<dt><code>' . esc_html( $name ) . '</code></dt>';
367
+ echo '<dd>';
368
+ printf(
369
+ esc_html( $constant['label'] ),
370
+ '<code>' . esc_html( $constant['default'] ) . '</code>'
371
+ );
372
+
373
+ if ( defined( $name ) ) {
374
+ $current_value = constant( $name );
375
+ if ( is_bool( $current_value ) ) {
376
+ $current_value = QM_Collector::format_bool_constant( $name );
377
+ }
378
+ }
379
+
380
+ if ( defined( $name ) && ( constant( $name ) !== $constant['default'] ) ) {
381
+ echo '<br><span class="qm-info">';
382
+ printf(
383
+ /* translators: %s: Current value for a PHP constant */
384
+ esc_html__( 'Current value: %s', 'query-monitor' ),
385
+ '<code>' . esc_html( $current_value ) . '</code>'
386
+ );
387
+ echo '</span>';
388
+ }
389
+ echo '</dd>';
390
  }
391
 
392
+ echo '</dl>';
393
  echo '</div>';
394
+
395
  echo '</div>';
396
 
397
  echo '</div>'; // #qm-settings
398
+
399
+ do_action( 'qm/output/after', $this, $this->outputters );
400
+
401
  echo '</div>'; // #qm-panels
402
  echo '</div>'; // #qm-wrapper
403
  echo '</div>'; // #qm
438
 
439
  }
440
 
441
+ public static function size( $var ) {
442
  $start_memory = memory_get_usage();
443
 
444
  try {
output/Html.php CHANGED
@@ -26,6 +26,96 @@ abstract class QM_Output_Html extends QM_Output {
26
  return $out;
27
  }
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  public static function output_inner( $vars ) {
30
 
31
  echo '<table class="qm-inner">';
@@ -62,14 +152,14 @@ abstract class QM_Output_Html extends QM_Output {
62
  /**
63
  * Returns the table filter controls. Safe for output.
64
  *
65
- * @param string $name The name for the `data-` attributes that get filtered by this control.
66
- * @param array $values Possible values for this control.
67
- * @param string $label Label text for the filter control.
68
- * @param array $args {
69
  * @type string $highlihgt The name for the `data-` attributes that get highlighted by this control.
70
  * @type array $prepend Associative array of options to prepend to the list of values.
71
  * }
72
- * @return string Markup for the table filter controls.
73
  */
74
  protected function build_filter( $name, array $values, $label, $args = array() ) {
75
 
@@ -94,8 +184,6 @@ abstract class QM_Output_Html extends QM_Output {
94
  $args['prepend']['non-core'] = __( 'Non-Core', 'query-monitor' );
95
  }
96
 
97
- usort( $values, 'strcasecmp' );
98
-
99
  $filter_id = 'qm-filter-' . $this->collector->id . '-' . $name;
100
 
101
  $out = '<div class="qm-filter-container">';
@@ -123,23 +211,25 @@ abstract class QM_Output_Html extends QM_Output {
123
  /**
124
  * Returns the column sorter controls. Safe for output.
125
  *
126
- * @TODO needs to be converted to use a button for semantics and a11y.
127
- *
128
  * @param string $heading Heading text for the column. Optional.
129
  * @return string Markup for the column sorter controls.
130
  */
131
  protected function build_sorter( $heading = '' ) {
132
  $out = '';
133
- $out .= '<div class="qm-th">';
134
  $out .= '<span class="qm-sort-heading">';
135
- if ( $heading ) {
 
 
 
136
  $out .= esc_html( $heading );
137
  }
 
138
  $out .= '</span>';
139
- $out .= '<span class="qm-sort-controls">';
140
- $out .= '<span class="dashicons qm-sort-arrow" aria-hidden="true"></span>';
141
- $out .= '</span>';
142
- $out .= '</div>';
143
  return $out;
144
  }
145
 
@@ -149,7 +239,7 @@ abstract class QM_Output_Html extends QM_Output {
149
  * @return string Markup for the column sorter controls.
150
  */
151
  protected static function build_toggler() {
152
- $out = '<button class="qm-toggle" data-on="+" data-off="-" aria-expanded="false">+<span class="screen-reader-text">' . esc_html__( ' Toggle button', 'query-monitor' ) . '</span></button>';
153
  return $out;
154
  }
155
 
26
  return $out;
27
  }
28
 
29
+ protected function before_tabular_output( $id = null, $name = null ) {
30
+ if ( null === $id ) {
31
+ $id = $this->collector->id();
32
+ }
33
+ if ( null === $name ) {
34
+ $name = $this->collector->name();
35
+ }
36
+
37
+ printf(
38
+ '<div class="qm" id="%1$s" role="group" aria-labelledby="%1$s-caption" tabindex="-1">',
39
+ esc_attr( $id )
40
+ );
41
+
42
+ echo '<table class="qm-sortable">';
43
+
44
+ printf(
45
+ '<caption class="qm-screen-reader-text"><h2 id="%1$s-caption">%2$s</h2></caption>',
46
+ esc_attr( $id ),
47
+ esc_html( $name )
48
+ );
49
+ }
50
+
51
+ protected function after_tabular_output() {
52
+ echo '</table>';
53
+ echo '</div>';
54
+ }
55
+
56
+ protected function before_non_tabular_output( $id = null, $name = null ) {
57
+ if ( null === $id ) {
58
+ $id = $this->collector->id();
59
+ }
60
+ if ( null === $name ) {
61
+ $name = $this->collector->name();
62
+ }
63
+
64
+ printf(
65
+ '<div class="qm qm-non-tabular" id="%1$s" role="group" aria-labelledby="%1$s-caption" tabindex="-1">',
66
+ esc_attr( $id )
67
+ );
68
+
69
+ echo '<div class="qm-boxed">';
70
+
71
+ printf(
72
+ '<h2 class="qm-screen-reader-text" id="%1$s-caption">%2$s</h2>',
73
+ esc_attr( $id ),
74
+ esc_html( $name )
75
+ );
76
+ }
77
+
78
+ protected function after_non_tabular_output() {
79
+ echo '</div>';
80
+ echo '</div>';
81
+ }
82
+
83
+ protected function before_debug_bar_output( $id = null, $name = null ) {
84
+ if ( null === $id ) {
85
+ $id = $this->collector->id();
86
+ }
87
+ if ( null === $name ) {
88
+ $name = $this->collector->name();
89
+ }
90
+
91
+ printf(
92
+ '<div class="qm qm-debug-bar" id="%1$s" role="group" aria-labelledby="%1$s-caption" tabindex="-1">',
93
+ esc_attr( $id )
94
+ );
95
+
96
+ printf(
97
+ '<h2 class="qm-screen-reader-text" id="%1$s-caption">%2$s</h2>',
98
+ esc_attr( $id ),
99
+ esc_html( $name )
100
+ );
101
+ }
102
+
103
+ protected function after_debug_bar_output() {
104
+ echo '</div>';
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
+ }
118
+
119
  public static function output_inner( $vars ) {
120
 
121
  echo '<table class="qm-inner">';
152
  /**
153
  * Returns the table filter controls. Safe for output.
154
  *
155
+ * @param string $name The name for the `data-` attributes that get filtered by this control.
156
+ * @param string[] $values Option values for this control.
157
+ * @param string $label Label text for the filter control.
158
+ * @param array $args {
159
  * @type string $highlihgt The name for the `data-` attributes that get highlighted by this control.
160
  * @type array $prepend Associative array of options to prepend to the list of values.
161
  * }
162
+ * @return string Markup for the table filter controls.
163
  */
164
  protected function build_filter( $name, array $values, $label, $args = array() ) {
165
 
184
  $args['prepend']['non-core'] = __( 'Non-Core', 'query-monitor' );
185
  }
186
 
 
 
187
  $filter_id = 'qm-filter-' . $this->collector->id . '-' . $name;
188
 
189
  $out = '<div class="qm-filter-container">';
211
  /**
212
  * Returns the column sorter controls. Safe for output.
213
  *
 
 
214
  * @param string $heading Heading text for the column. Optional.
215
  * @return string Markup for the column sorter controls.
216
  */
217
  protected function build_sorter( $heading = '' ) {
218
  $out = '';
219
+ $out .= '<label class="qm-th">';
220
  $out .= '<span class="qm-sort-heading">';
221
+
222
+ if ( '#' === $heading ) {
223
+ $out .= '<span class="qm-screen-reader-text">' . esc_html__( 'Sequence', 'query-monitor' ) . '</span>';
224
+ } elseif ( $heading ) {
225
  $out .= esc_html( $heading );
226
  }
227
+
228
  $out .= '</span>';
229
+ $out .= '<button class="qm-sort-controls">';
230
+ $out .= '<span class="qm-sort-arrow" aria-hidden="true"></span>';
231
+ $out .= '</button>';
232
+ $out .= '</label>';
233
  return $out;
234
  }
235
 
239
  * @return string Markup for the column sorter controls.
240
  */
241
  protected static function build_toggler() {
242
+ $out = '<button class="qm-toggle" data-on="+" data-off="-" aria-expanded="false"><span aria-hidden="true">+</span><span class="screen-reader-text">' . esc_html__( ' Toggle button', 'query-monitor' ) . '</span></button>';
243
  return $out;
244
  }
245
 
output/headers/php_errors.php CHANGED
@@ -25,13 +25,13 @@ 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' => wp_strip_all_tags( $error->message ),
32
- 'file' => QM_Util::standard_dir( $error->file, '' ),
33
- 'line' => $error->line,
34
- 'stack' => $error->trace->get_stack(),
35
  'component' => $component->name,
36
  );
37
 
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'],
32
+ 'file' => QM_Util::standard_dir( $error['file'], '' ),
33
+ 'line' => $error['line'],
34
+ 'stack' => $error['trace']->get_stack(),
35
  'component' => $component->name,
36
  );
37
 
output/html/admin.php CHANGED
@@ -20,24 +20,23 @@ class QM_Output_Html_Admin extends QM_Output_Html {
20
  return;
21
  }
22
 
23
- echo '<div class="qm qm-non-tabular" id="' . esc_attr( $this->collector->id() ) . '">';
24
- echo '<div class="qm-boxed qm-boxed-wrap">';
25
 
26
  echo '<div class="qm-section">';
27
- echo '<h2>get_current_screen()</h2>';
28
 
29
  echo '<table>';
30
- echo '<thead class="screen-reader-text">';
31
  echo '<tr>';
32
- echo '<th>' . esc_html__( 'Property', 'query-monitor' ) . '</th>';
33
- echo '<th>' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
34
  echo '</tr>';
35
  echo '</thead>';
36
  echo '<tbody>';
37
 
38
  foreach ( $data['current_screen'] as $key => $value ) {
39
  echo '<tr>';
40
- echo '<td>' . esc_html( $key ) . '</td>';
41
  echo '<td>' . esc_html( $value ) . '</td>';
42
  echo '</tr>';
43
  }
@@ -47,38 +46,37 @@ class QM_Output_Html_Admin extends QM_Output_Html {
47
  echo '</div>';
48
 
49
  echo '<div class="qm-section">';
50
- echo '<h2>$pagenow</h2>';
51
  echo '<p>' . esc_html( $data['pagenow'] ) . '</p>';
52
  echo '</div>';
53
 
54
  if ( ! empty( $data['list_table'] ) ) {
55
 
56
  echo '<div class="qm-section">';
57
- echo '<h2>' . esc_html__( 'List Table', 'query-monitor' ) . '</h2>';
58
 
59
  if ( ! empty( $data['list_table']['class_name'] ) ) {
60
- echo '<h3>' . esc_html__( 'Class:', 'query-monitor' ) . '</h3>';
61
  echo '<p><code>' . esc_html( $data['list_table']['class_name'] ) . '</code></p>';
62
  }
63
 
64
- echo '<h3>' . esc_html__( 'Column Filters:', 'query-monitor' ) . '</h3>';
65
  echo '<p><code>' . esc_html( $data['list_table']['columns_filter'] ) . '</code></p>';
66
  echo '<p><code>' . esc_html( $data['list_table']['sortables_filter'] ) . '</code></p>';
67
- echo '<h3>' . esc_html__( 'Column Action:', 'query-monitor' ) . '</h3>';
68
  echo '<p><code>' . esc_html( $data['list_table']['column_action'] ) . '</code></p>';
69
  echo '</div>';
70
 
71
  }
72
 
73
- echo '</div>';
74
- echo '</div>';
75
  }
76
 
77
  }
78
 
79
  function register_qm_output_html_admin( array $output, QM_Collectors $collectors ) {
80
- if ( $collector = QM_Collectors::get( 'admin' ) ) {
81
- $output['admin'] = new QM_Output_Html_Admin( $collector );
82
  }
83
  return $output;
84
  }
20
  return;
21
  }
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>';
29
+ echo '<thead class="qm-screen-reader-text">';
30
  echo '<tr>';
31
+ echo '<th scope="col">' . esc_html__( 'Property', 'query-monitor' ) . '</th>';
32
+ echo '<th scope="col">' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
33
  echo '</tr>';
34
  echo '</thead>';
35
  echo '<tbody>';
36
 
37
  foreach ( $data['current_screen'] as $key => $value ) {
38
  echo '<tr>';
39
+ echo '<th scope="row">' . esc_html( $key ) . '</th>';
40
  echo '<td>' . esc_html( $value ) . '</td>';
41
  echo '</tr>';
42
  }
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'] ) ) {
59
+ echo '<h4>' . esc_html__( 'Class:', 'query-monitor' ) . '</h4>';
60
  echo '<p><code>' . esc_html( $data['list_table']['class_name'] ) . '</code></p>';
61
  }
62
 
63
+ echo '<h4>' . esc_html__( 'Column Filters:', 'query-monitor' ) . '</h4>';
64
  echo '<p><code>' . esc_html( $data['list_table']['columns_filter'] ) . '</code></p>';
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
 
72
+ $this->after_non_tabular_output();
 
73
  }
74
 
75
  }
76
 
77
  function register_qm_output_html_admin( array $output, QM_Collectors $collectors ) {
78
+ if ( is_admin() && $collector = QM_Collectors::get( 'response' ) ) {
79
+ $output['response'] = new QM_Output_Html_Admin( $collector );
80
  }
81
  return $output;
82
  }
output/html/assets.php CHANGED
@@ -30,13 +30,13 @@ class QM_Output_Html_Assets extends QM_Output_Html {
30
 
31
  $type_labels = array(
32
  'scripts' => array(
33
- /* translators: %s: Total number of scripts */
34
- 'total' => __( 'Total Scripts: %s', 'query-monitor' ),
35
  'plural' => __( 'Scripts', 'query-monitor' ),
36
  ),
37
  'styles' => array(
38
- /* translators: %s: Total number of styles */
39
- 'total' => __( 'Total Styles: %s', 'query-monitor' ),
40
  'plural' => __( 'Styles', 'query-monitor' ),
41
  ),
42
  );
@@ -55,12 +55,18 @@ class QM_Output_Html_Assets extends QM_Output_Html {
55
  __( 'Other', 'query-monitor' ),
56
  );
57
 
58
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '-' . esc_attr( $type ) . '">';
59
- echo '<table>';
60
- echo '<caption>' . esc_html( $type_label['plural'] ) . '</caption>';
 
 
 
 
 
61
  echo '<thead>';
62
  echo '<tr>';
63
  echo '<th scope="col">' . esc_html__( 'Position', 'query-monitor' ) . '</th>';
 
64
  echo '<th scope="col" class="qm-filterable-column">';
65
  $args = array(
66
  'prepend' => array(
@@ -70,7 +76,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
70
  );
71
  echo $this->build_filter( $type . '-host', $hosts, __( 'Host', 'query-monitor' ), $args ); // WPCS: XSS ok.
72
  echo '</th>';
73
- echo '<th scope="col">' . esc_html__( 'Handle', 'query-monitor' ) . '</th>';
74
  echo '<th scope="col">' . esc_html__( 'Dependencies', 'query-monitor' ) . '</th>';
75
  echo '<th scope="col">' . esc_html__( 'Dependents', 'query-monitor' ) . '</th>';
76
  echo '<th scope="col">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
@@ -94,18 +100,16 @@ class QM_Output_Html_Assets extends QM_Output_Html {
94
 
95
  echo '<tr>';
96
  printf(
97
- '<td colspan="6">%1$s</td>',
98
- esc_html( sprintf(
99
- $type_label['total'],
100
- number_format_i18n( $total )
101
- ) )
102
  );
103
  echo '</tr>';
104
  echo '</tfoot>';
105
 
106
- echo '</table>';
107
- echo '</div>';
108
-
109
  }
110
 
111
  }
@@ -198,19 +202,24 @@ class QM_Output_Html_Assets extends QM_Output_Html {
198
  $highlight_deps = array_map( array( $this, '_prefix_type' ), $deps );
199
  $highlight_dependents = array_map( array( $this, '_prefix_type' ), $dependents );
200
 
201
- echo '<td>' . esc_html( $host ) . '</td>';
202
- echo '<td class="qm-wrap qm-ltr">' . esc_html( $dependency->handle ) . '<br><span class="qm-info qm-supplemental">';
 
203
  if ( is_wp_error( $source ) ) {
204
  printf(
205
  '<span class="qm-warn">%s</span>',
206
  esc_html( $src )
207
  );
208
- } else {
209
- echo esc_html( $src );
 
 
 
 
210
  }
211
- echo '</span></td>';
212
- echo '<td class="qm-ltr qm-nowrap qm-highlighter" data-qm-highlight="' . esc_attr( implode( ' ', $highlight_deps ) ) . '"><ul><li>' . implode( '</li><li>', array_map( 'esc_html', $deps ) ) . '</li></ul></td>';
213
- echo '<td class="qm-ltr qm-nowrap qm-highlighter" data-qm-highlight="' . esc_attr( implode( ' ', $highlight_dependents ) ) . '"><ul><li>' . implode( '</li><li>', array_map( 'esc_html', $dependents ) ) . '</li></ul></td>';
214
  echo '<td class="qm-ltr">' . esc_html( $ver ) . '</td>';
215
 
216
  }
30
 
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
  );
55
  __( 'Other', 'query-monitor' ),
56
  );
57
 
58
+ $panel_id = sprintf(
59
+ '%s-%s',
60
+ $this->collector->id(),
61
+ $type
62
+ );
63
+
64
+ $this->before_tabular_output( $panel_id, $type_label['plural'] );
65
+
66
  echo '<thead>';
67
  echo '<tr>';
68
  echo '<th scope="col">' . esc_html__( 'Position', 'query-monitor' ) . '</th>';
69
+ echo '<th scope="col">' . esc_html__( 'Handle', 'query-monitor' ) . '</th>';
70
  echo '<th scope="col" class="qm-filterable-column">';
71
  $args = array(
72
  'prepend' => array(
76
  );
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>';
100
 
101
  echo '<tr>';
102
  printf(
103
+ '<td colspan="7">%1$s</td>',
104
+ sprintf(
105
+ esc_html( $type_label['total'] ),
106
+ '<span class="qm-items-number">' . esc_html( number_format_i18n( $total ) ) . '</span>'
107
+ )
108
  );
109
  echo '</tr>';
110
  echo '</tfoot>';
111
 
112
+ $this->after_tabular_output();
 
 
113
  }
114
 
115
  }
202
  $highlight_deps = array_map( array( $this, '_prefix_type' ), $deps );
203
  $highlight_dependents = array_map( array( $this, '_prefix_type' ), $dependents );
204
 
205
+ echo '<td class="qm-nowrap qm-ltr">' . esc_html( $dependency->handle ) . '</td>';
206
+ echo '<td class="qm-nowrap qm-ltr">' . esc_html( $host ) . '</td>';
207
+ echo '<td class="qm-ltr">';
208
  if ( is_wp_error( $source ) ) {
209
  printf(
210
  '<span class="qm-warn">%s</span>',
211
  esc_html( $src )
212
  );
213
+ } elseif ( ! empty( $src ) ) {
214
+ printf(
215
+ '<a href="%s" class="qm-link">%s</a>',
216
+ esc_attr( $src ),
217
+ esc_html( $src )
218
+ );
219
  }
220
+ echo '</td>';
221
+ echo '<td class="qm-ltr qm-highlighter" data-qm-highlight="' . esc_attr( implode( ' ', $highlight_deps ) ) . '">' . implode( ', ', array_map( 'esc_html', $deps ) ) . '</td>';
222
+ echo '<td class="qm-ltr qm-highlighter" data-qm-highlight="' . esc_attr( implode( ' ', $highlight_dependents ) ) . '">' . implode( ', ', array_map( 'esc_html', $dependents ) ) . '</td>';
223
  echo '<td class="qm-ltr">' . esc_html( $ver ) . '</td>';
224
 
225
  }
output/html/caps.php CHANGED
@@ -13,12 +13,12 @@ class QM_Output_Html_Caps extends QM_Output_Html {
13
  }
14
 
15
  public function output() {
16
- if ( ! defined( 'QM_ENABLE_CAPS_PANEL' ) ) {
17
- echo '<div class="qm qm-non-tabular" id="' . esc_attr( $this->collector->id() ) . '">';
18
- echo '<div class="qm-boxed qm-boxed-wrap">';
19
  echo '<div class="qm-section">';
20
- echo '<h2>' . esc_html( $this->collector->name() ) . '</h2>';
21
- echo '<p class="qm-warn">';
22
  printf(
23
  /* translators: %s: Configuration file name. */
24
  esc_html__( 'For performance reasons, this panel is not enabled by default. To enable it, add the following code to your %s file:', 'query-monitor' ),
@@ -28,35 +28,41 @@ class QM_Output_Html_Caps extends QM_Output_Html {
28
  echo "<p><code>define( 'QM_ENABLE_CAPS_PANEL', true );</code></p>";
29
  echo '</div>';
30
  echo '</div>';
31
- echo '</div>';
 
32
 
33
  return;
34
  }
35
 
36
  $data = $this->collector->get_data();
37
 
38
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
39
- echo '<table>';
40
-
41
  if ( ! empty( $data['caps'] ) ) {
 
42
 
43
  $results = array(
44
  'true',
45
  'false',
46
  );
47
- $show_user = ( count( $data['users'] ) > 1 );
 
 
48
 
49
- echo '<caption class="screen-reader-text">' . esc_html( $this->collector->name() ) . '</caption>';
 
50
 
51
  echo '<thead>';
52
  echo '<tr>';
53
  echo '<th scope="col" class="qm-filterable-column">';
54
- echo $this->build_filter( 'name', $data['parts'], __( 'Capability Check', 'query-monitor' ) ); // WPCS: XSS ok;
55
  echo '</th>';
56
 
57
  if ( $show_user ) {
 
 
 
 
58
  echo '<th scope="col" class="qm-filterable-column qm-num">';
59
- echo $this->build_filter( 'user', $data['users'], __( 'User', 'query-monitor' ) ); // WPCS: XSS ok;
60
  echo '</th>';
61
  }
62
 
@@ -65,7 +71,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
65
  echo '</th>';
66
  echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
67
  echo '<th scope="col" class="qm-filterable-column">';
68
- echo $this->build_filter( 'component', $data['components'], __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
69
  echo '</th>';
70
  echo '</tr>';
71
  echo '</thead>';
@@ -104,7 +110,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
104
 
105
  if ( ! empty( $row['args'] ) ) {
106
  foreach ( $row['args'] as $arg ) {
107
- $name .= '<br>' . esc_html( QM_Util::display_variable( $arg ) );
108
  }
109
  }
110
 
@@ -180,35 +186,25 @@ class QM_Output_Html_Caps extends QM_Output_Html {
180
  $colspan = ( $show_user ) ? 5 : 4;
181
 
182
  echo '<tr>';
 
183
  printf(
184
- '<td colspan="%1$d">%2$s</td>',
185
- esc_attr( $colspan ),
186
- esc_html( sprintf(
187
- /* translators: %s: Number of user capability checks */
188
- __( 'Total Checks: %s', 'query-monitor' ),
189
- number_format_i18n( count( $data['caps'] ) )
190
- ) )
191
  );
 
192
  echo '</tr>';
193
  echo '</tfoot>';
194
 
 
195
  } else {
 
196
 
197
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
198
-
199
- echo '<tbody>';
200
- echo '<tr>';
201
- echo '<td>';
202
- esc_html_e( 'No capability checks were recorded.', 'query-monitor' );
203
- echo '</td>';
204
- echo '</tr>';
205
- echo '</tbody>';
206
 
 
207
  }
208
-
209
- echo '</table>';
210
- echo '</div>';
211
-
212
  }
213
 
214
  public function admin_menu( array $menu ) {
13
  }
14
 
15
  public function output() {
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(
23
  /* translators: %s: Configuration file name. */
24
  esc_html__( 'For performance reasons, this panel is not enabled by default. To enable it, add the following code to your %s file:', 'query-monitor' ),
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
 
34
  return;
35
  }
36
 
37
  $data = $this->collector->get_data();
38
 
 
 
 
39
  if ( ! empty( $data['caps'] ) ) {
40
+ $this->before_tabular_output();
41
 
42
  $results = array(
43
  'true',
44
  'false',
45
  );
46
+ $show_user = ( count( $data['users'] ) > 1 );
47
+ $parts = $data['parts'];
48
+ $components = $data['components'];
49
 
50
+ usort( $parts, 'strcasecmp' );
51
+ usort( $components, 'strcasecmp' );
52
 
53
  echo '<thead>';
54
  echo '<tr>';
55
  echo '<th scope="col" class="qm-filterable-column">';
56
+ echo $this->build_filter( 'name', $parts, __( 'Capability Check', 'query-monitor' ) ); // WPCS: XSS ok;
57
  echo '</th>';
58
 
59
  if ( $show_user ) {
60
+ $users = $data['users'];
61
+
62
+ usort( $users, 'strcasecmp' );
63
+
64
  echo '<th scope="col" class="qm-filterable-column qm-num">';
65
+ echo $this->build_filter( 'user', $users, __( 'User', 'query-monitor' ) ); // WPCS: XSS ok;
66
  echo '</th>';
67
  }
68
 
71
  echo '</th>';
72
  echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
73
  echo '<th scope="col" class="qm-filterable-column">';
74
+ echo $this->build_filter( 'component', $components, __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
75
  echo '</th>';
76
  echo '</tr>';
77
  echo '</thead>';
110
 
111
  if ( ! empty( $row['args'] ) ) {
112
  foreach ( $row['args'] as $arg ) {
113
+ $name .= ',&nbsp;' . esc_html( QM_Util::display_variable( $arg ) );
114
  }
115
  }
116
 
186
  $colspan = ( $show_user ) ? 5 : 4;
187
 
188
  echo '<tr>';
189
+ echo '<td colspan="' . absint( $colspan ) . '">';
190
  printf(
191
+ /* translators: %s: Number of user capability checks */
192
+ esc_html_x( 'Total: %s', 'User capability checks', 'query-monitor' ),
193
+ '<span class="qm-items-number">' . esc_html( number_format_i18n( count( $data['caps'] ) ) ) . '</span>'
 
 
 
 
194
  );
195
+ echo '</td>';
196
  echo '</tr>';
197
  echo '</tfoot>';
198
 
199
+ $this->after_tabular_output();
200
  } else {
201
+ $this->before_non_tabular_output();
202
 
203
+ $notice = __( 'No capability checks were recorded.', 'query-monitor' );
204
+ echo $this->build_notice( $notice ); // WPCS: XSS ok.
 
 
 
 
 
 
 
205
 
206
+ $this->after_non_tabular_output();
207
  }
 
 
 
 
208
  }
209
 
210
  public function admin_menu( array $menu ) {
output/html/conditionals.php CHANGED
@@ -16,11 +16,10 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
16
  public function output() {
17
  $data = $this->collector->get_data();
18
 
19
- echo '<div class="qm qm-non-tabular" id="' . esc_attr( $this->collector->id() ) . '">';
20
- echo '<div class="qm-boxed">';
21
 
22
  echo '<div class="qm-section">';
23
- echo '<h2>' . esc_html__( 'True Conditionals', 'query-monitor' ) . '</h2>';
24
 
25
  foreach ( $data['conds']['true'] as $cond ) {
26
  echo '<p class="qm-item qm-ltr qm-true"><code>' . esc_html( $cond ) . '()</code></p>';
@@ -28,15 +27,15 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
28
 
29
  echo '</div>';
30
  echo '<div class="qm-section">';
31
- echo '<h2>' . esc_html__( 'False Conditionals', 'query-monitor' ) . '</h2>';
32
 
33
  foreach ( $data['conds']['false'] as $cond ) {
34
  echo '<p class="qm-item qm-ltr qm-false"><code>' . esc_html( $cond ) . '()</code></p>';
35
  }
36
 
37
  echo '</div>';
38
- echo '</div>';
39
- echo '</div>';
40
  }
41
 
42
  public function admin_menu( array $menu ) {
16
  public function output() {
17
  $data = $this->collector->get_data();
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>';
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
  }
40
 
41
  public function admin_menu( array $menu ) {
output/html/db_callers.php CHANGED
@@ -22,22 +22,20 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
22
 
23
  $total_time = 0;
24
 
25
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
26
-
27
  if ( ! empty( $data['times'] ) ) {
28
- echo '<table class="qm-sortable">';
29
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
30
  echo '<thead>';
31
  echo '<tr>';
32
  echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
33
 
34
  foreach ( $data['types'] as $type_name => $type_count ) {
35
- echo '<th scope="col" class="qm-num qm-ltr qm-sortable-column">';
36
  echo $this->build_sorter( $type_name ); // WPCS: XSS ok;
37
  echo '</th>';
38
  }
39
 
40
- echo '<th scope="col" class="qm-num qm-sorted-desc qm-sortable-column">';
41
  echo $this->build_sorter( __( 'Time', 'query-monitor' ) ); // WPCS: XSS ok;
42
  echo '</th>';
43
  echo '</tr>';
@@ -81,18 +79,17 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
81
  echo '</tr>';
82
 
83
  echo '</tfoot>';
84
- echo '</table>';
85
 
 
86
  } else {
 
87
 
88
  echo '<div class="qm-none">';
89
  echo '<p>' . esc_html__( 'None', 'query-monitor' ) . '</p>';
90
  echo '</div>';
91
 
 
92
  }
93
-
94
- echo '</div>';
95
-
96
  }
97
 
98
  public function admin_menu( array $menu ) {
22
 
23
  $total_time = 0;
24
 
 
 
25
  if ( ! empty( $data['times'] ) ) {
26
+ $this->before_tabular_output();
27
+
28
  echo '<thead>';
29
  echo '<tr>';
30
  echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
31
 
32
  foreach ( $data['types'] as $type_name => $type_count ) {
33
+ echo '<th scope="col" class="qm-num qm-ltr qm-sortable-column" role="columnheader" aria-sort="none">';
34
  echo $this->build_sorter( $type_name ); // WPCS: XSS ok;
35
  echo '</th>';
36
  }
37
 
38
+ echo '<th scope="col" class="qm-num qm-sorted-desc qm-sortable-column" role="columnheader" aria-sort="descending">';
39
  echo $this->build_sorter( __( 'Time', 'query-monitor' ) ); // WPCS: XSS ok;
40
  echo '</th>';
41
  echo '</tr>';
79
  echo '</tr>';
80
 
81
  echo '</tfoot>';
 
82
 
83
+ $this->after_tabular_output();
84
  } else {
85
+ $this->before_non_tabular_output();
86
 
87
  echo '<div class="qm-none">';
88
  echo '<p>' . esc_html__( 'None', 'query-monitor' ) . '</p>';
89
  echo '</div>';
90
 
91
+ $this->after_non_tabular_output();
92
  }
 
 
 
93
  }
94
 
95
  public function admin_menu( array $menu ) {
output/html/db_components.php CHANGED
@@ -23,21 +23,20 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
23
  $total_time = 0;
24
  $span = count( $data['types'] ) + 2;
25
 
26
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
27
- echo '<table class="qm-sortable">';
28
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
29
  echo '<thead>';
30
 
31
  echo '<tr>';
32
  echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
33
 
34
  foreach ( $data['types'] as $type_name => $type_count ) {
35
- echo '<th scope="col" class="qm-num qm-sortable-column">';
36
  echo $this->build_sorter( $type_name ); // WPCS: XSS ok;
37
  echo '</th>';
38
  }
39
 
40
- echo '<th scope="col" class="qm-num qm-sorted-desc qm-sortable-column">';
41
  echo $this->build_sorter( __( 'Time', 'query-monitor' ) ); // WPCS: XSS ok;
42
  echo '</th>';
43
  echo '</tr>';
@@ -50,7 +49,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
50
  $total_time += $row['ltime'];
51
 
52
  echo '<tr>';
53
- echo '<td><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>';
54
 
55
  foreach ( $data['types'] as $type_name => $type_count ) {
56
  if ( isset( $row['types'][ $type_name ] ) ) {
@@ -81,9 +80,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
81
  echo '</tr>';
82
  echo '</tfoot>';
83
 
84
- echo '</table>';
85
- echo '</div>';
86
-
87
  }
88
 
89
  public function admin_menu( array $menu ) {
23
  $total_time = 0;
24
  $span = count( $data['types'] ) + 2;
25
 
26
+ $this->before_tabular_output();
27
+
 
28
  echo '<thead>';
29
 
30
  echo '<tr>';
31
  echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
32
 
33
  foreach ( $data['types'] as $type_name => $type_count ) {
34
+ echo '<th scope="col" class="qm-num qm-sortable-column" role="columnheader" aria-sort="none">';
35
  echo $this->build_sorter( $type_name ); // WPCS: XSS ok;
36
  echo '</th>';
37
  }
38
 
39
+ echo '<th scope="col" class="qm-num qm-sorted-desc qm-sortable-column" role="columnheader" aria-sort="descending">';
40
  echo $this->build_sorter( __( 'Time', 'query-monitor' ) ); // WPCS: XSS ok;
41
  echo '</th>';
42
  echo '</tr>';
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>';
53
 
54
  foreach ( $data['types'] as $type_name => $type_count ) {
55
  if ( isset( $row['types'][ $type_name ] ) ) {
80
  echo '</tr>';
81
  echo '</tfoot>';
82
 
83
+ $this->after_tabular_output();
 
 
84
  }
85
 
86
  public function admin_menu( array $menu ) {
output/html/db_dupes.php CHANGED
@@ -20,9 +20,8 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
20
  return;
21
  }
22
 
23
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
24
- echo '<table>';
25
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
26
  echo '<thead>';
27
 
28
  echo '<tr>';
@@ -30,7 +29,7 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
30
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Count', 'query-monitor' ) . '</th>';
31
  echo '<th scope="col">' . esc_html__( 'Callers', 'query-monitor' ) . '</th>';
32
  if ( ! empty( $data['dupe_components'] ) ) {
33
- echo '<th>' . esc_html__( 'Components', 'query-monitor' ) . '</th>';
34
  }
35
  echo '<th scope="col">' . esc_html__( 'Potential Troublemakers', 'query-monitor' ) . '</th>';
36
  echo '</tr>';
@@ -102,9 +101,7 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
102
  }
103
  echo '</tbody>';
104
 
105
- echo '</table>';
106
- echo '</div>';
107
-
108
  }
109
 
110
  public function admin_menu( array $menu ) {
20
  return;
21
  }
22
 
23
+ $this->before_tabular_output();
24
+
 
25
  echo '<thead>';
26
 
27
  echo '<tr>';
29
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Count', 'query-monitor' ) . '</th>';
30
  echo '<th scope="col">' . esc_html__( 'Callers', 'query-monitor' ) . '</th>';
31
  if ( ! empty( $data['dupe_components'] ) ) {
32
+ echo '<th scope="col">' . esc_html__( 'Components', 'query-monitor' ) . '</th>';
33
  }
34
  echo '<th scope="col">' . esc_html__( 'Potential Troublemakers', 'query-monitor' ) . '</th>';
35
  echo '</tr>';
101
  }
102
  echo '</tbody>';
103
 
104
+ $this->after_tabular_output();
 
 
105
  }
106
 
107
  public function admin_menu( array $menu ) {
output/html/db_queries.php CHANGED
@@ -40,38 +40,30 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
40
  }
41
 
42
  protected function output_empty_queries() {
43
-
44
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '-wpdb">';
45
- echo '<table>';
46
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
47
- echo '<tbody>';
48
- echo '<tr>';
49
- echo '<td class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
50
 
51
  if ( ! SAVEQUERIES ) {
52
- printf(
53
  /* translators: 1: Name of PHP constant, 2: Value of PHP constant */
54
  esc_html__( 'No database queries were logged because the %1$s constant is set to %2$s.', 'query-monitor' ),
55
  '<code>SAVEQUERIES</code>',
56
  '<code>false</code>'
57
  );
58
  } else {
59
- esc_html_e( 'No database queries were logged.', 'query-monitor' );
60
  }
61
 
62
- echo '</td>';
63
- echo '</tr>';
64
- echo '</tbody>';
65
- echo '</table>';
66
- echo '</div>';
67
-
68
  }
69
 
70
  protected function output_error_queries( array $errors ) {
 
71
 
72
- echo '<div class="qm" id="qm-query-errors">';
73
- echo '<table>';
74
- echo '<caption>' . esc_html__( 'Database Errors', 'query-monitor' ) . '</caption>';
75
  echo '<thead>';
76
  echo '<tr>';
77
  echo '<th scope="col">' . esc_html__( 'Query', 'query-monitor' ) . '</th>';
@@ -88,24 +80,20 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
88
  }
89
 
90
  echo '</tbody>';
91
- echo '</table>';
92
- echo '</div>';
93
 
 
94
  }
95
 
96
  protected function output_expensive_queries( array $expensive ) {
97
-
98
  $dp = strlen( substr( strrchr( QM_DB_EXPENSIVE, '.' ), 1 ) );
99
 
100
- echo '<div class="qm" id="qm-query-expensive">';
101
- echo '<table>';
102
- echo '<caption>';
103
- printf(
104
  /* translators: %s: Database query time in seconds */
105
  esc_html__( 'Slow Database Queries (above %ss)', 'query-monitor' ),
106
  '<span class="qm-warn">' . esc_html( number_format_i18n( QM_DB_EXPENSIVE, $dp ) ) . '</span>'
107
  );
108
- echo '</caption>';
 
109
  echo '<thead>';
110
  echo '<tr>';
111
  echo '<th scope="col">' . esc_html__( 'Query', 'query-monitor' ) . '</th>';
@@ -129,9 +117,8 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
129
  }
130
 
131
  echo '</tbody>';
132
- echo '</table>';
133
- echo '</div>';
134
 
 
135
  }
136
 
137
  protected function output_queries( $name, stdClass $db, array $data ) {
@@ -145,12 +132,20 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
145
  $span++;
146
  }
147
 
148
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() . '-' . sanitize_title_with_dashes( $name ) ) . '">';
 
 
 
 
 
 
 
 
 
149
 
150
  if ( ! empty( $db->rows ) ) {
151
- echo '<table class="qm-sortable">';
152
- /* translators: %s: Name of database controller */
153
- echo '<caption>' . esc_html( sprintf( __( '%s Queries', 'query-monitor' ), $name ) ) . '</caption>';
154
  echo '<thead>';
155
 
156
  /**
@@ -166,10 +161,10 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
166
  echo '<th colspan="' . absint( $span ) . '" class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
167
  if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) {
168
  /* translators: 1: Symlink file name, 2: URL to wiki page */
169
- $message = __( 'Extended query information such as the component and affected rows is not available. A conflicting %1$s file is present. <a href="%2$s" target="_blank">See this wiki page for more information.</a>', 'query-monitor' );
170
  } else {
171
  /* translators: 1: Symlink file name, 2: URL to wiki page */
172
- $message = __( 'Extended query information such as the component and affected rows is not available. Query Monitor was unable to symlink its %1$s file into place. <a href="%2$s" target="_blank">See this wiki page for more information.</a>', 'query-monitor' );
173
  }
174
  echo wp_kses( sprintf(
175
  $message,
@@ -179,14 +174,19 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
179
  'a' => array(
180
  'href' => array(),
181
  'target' => array(),
 
182
  ),
183
  ) );
184
  echo '</th>';
185
  echo '</tr>';
186
  }
187
 
188
- $types = array_keys( $db->types );
189
- $prepend = array();
 
 
 
 
190
 
191
  if ( count( $types ) > 1 ) {
192
  $prepend['non-select'] = __( 'Non-SELECT', 'query-monitor' );
@@ -197,8 +197,8 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
197
  );
198
 
199
  echo '<tr>';
200
- echo '<th scope="col" class="qm-sorted-asc qm-sortable-column">';
201
- echo $this->build_sorter(); // WPCS: XSS ok;
202
  echo '</th>';
203
  echo '<th scope="col" class="qm-filterable-column">';
204
  echo $this->build_filter( 'type', $types, __( 'Query', 'query-monitor' ), $args ); // WPCS: XSS ok;
@@ -214,12 +214,16 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
214
  $args = array(
215
  'prepend' => $prepend,
216
  );
217
- echo $this->build_filter( 'caller', wp_list_pluck( $data['times'], 'caller' ), __( 'Caller', 'query-monitor' ), $args ); // WPCS: XSS ok.
218
  echo '</th>';
219
 
220
  if ( $db->has_trace ) {
 
 
 
 
221
  echo '<th scope="col" class="qm-filterable-column">';
222
- echo $this->build_filter( 'component', wp_list_pluck( $data['component_times'], 'component' ), __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
223
  echo '</th>';
224
  }
225
 
@@ -229,12 +233,12 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
229
  } else {
230
  $class = '';
231
  }
232
- echo '<th scope="col" class="' . esc_attr( $class ) . ' qm-sortable-column">';
233
  echo $this->build_sorter( __( 'Rows', 'query-monitor' ) ); // WPCS: XSS ok.
234
  echo '</th>';
235
  }
236
 
237
- echo '<th scope="col" class="qm-num qm-sortable-column">';
238
  echo $this->build_sorter( __( 'Time', 'query-monitor' ) ); // WPCS: XSS ok.
239
  echo '</th>';
240
  echo '</tr>';
@@ -251,40 +255,27 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
251
 
252
  $total_stime = number_format_i18n( $db->total_time, 4 );
253
 
254
- echo '<tr class="qm-items-shown qm-hide">';
255
  echo '<td colspan="' . absint( $span - 1 ) . '">';
256
  printf(
257
- /* translators: %s: Number of database queries in the current filtered view */
258
- esc_html__( 'Queries in filter: %s', 'query-monitor' ),
259
  '<span class="qm-items-number">' . esc_html( number_format_i18n( $db->total_qs ) ) . '</span>'
260
  );
261
  echo '</td>';
262
- echo '<td class="qm-items-time qm-num">' . esc_html( $total_stime ) . '</td>';
263
- echo '</tr>';
264
-
265
- echo '<tr>';
266
- echo '<td colspan="' . absint( $span - 1 ) . '">';
267
- echo esc_html( sprintf(
268
- /* translators: %s: Number of database queries */
269
- __( 'Total Queries: %s', 'query-monitor' ),
270
- number_format_i18n( $db->total_qs )
271
- ) );
272
- echo '</td>';
273
- echo '<td class="qm-num">' . esc_html( $total_stime ) . '</td>';
274
  echo '</tr>';
275
  echo '</tfoot>';
276
- echo '</table>';
277
 
 
278
  } else {
 
279
 
280
- echo '<div class="qm-none">';
281
- echo '<p>' . esc_html__( 'None', 'query-monitor' ) . '</p>';
282
- echo '</div>';
283
 
 
284
  }
285
-
286
- echo '</div>';
287
-
288
  }
289
 
290
  protected function output_query_row( array $row, array $cols ) {
@@ -368,7 +359,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
368
  echo "<tr{$attr}>"; // WPCS: XSS ok.
369
 
370
  if ( isset( $cols['row'] ) ) {
371
- echo '<td class="qm-row-num qm-num">' . absint( ++$this->query_row ) . '</td>';
372
  }
373
 
374
  if ( isset( $cols['sql'] ) ) {
40
  }
41
 
42
  protected function output_empty_queries() {
43
+ $id = sprintf(
44
+ '%s-wpdb',
45
+ $this->collector->id()
46
+ );
47
+ $this->before_non_tabular_output( $id );
 
 
48
 
49
  if ( ! SAVEQUERIES ) {
50
+ $notice = sprintf(
51
  /* translators: 1: Name of PHP constant, 2: Value of PHP constant */
52
  esc_html__( 'No database queries were logged because the %1$s constant is set to %2$s.', 'query-monitor' ),
53
  '<code>SAVEQUERIES</code>',
54
  '<code>false</code>'
55
  );
56
  } else {
57
+ $notice = __( 'No database queries were logged.', 'query-monitor' );
58
  }
59
 
60
+ echo $this->build_notice( $notice ); // WPCS: XSS ok.
61
+ $this->after_non_tabular_output();
 
 
 
 
62
  }
63
 
64
  protected function output_error_queries( array $errors ) {
65
+ $this->before_tabular_output( 'qm-query-errors', __( 'Database Errors', 'query-monitor' ) );
66
 
 
 
 
67
  echo '<thead>';
68
  echo '<tr>';
69
  echo '<th scope="col">' . esc_html__( 'Query', 'query-monitor' ) . '</th>';
80
  }
81
 
82
  echo '</tbody>';
 
 
83
 
84
+ $this->after_tabular_output();
85
  }
86
 
87
  protected function output_expensive_queries( array $expensive ) {
 
88
  $dp = strlen( substr( strrchr( QM_DB_EXPENSIVE, '.' ), 1 ) );
89
 
90
+ $panel_name = sprintf(
 
 
 
91
  /* translators: %s: Database query time in seconds */
92
  esc_html__( 'Slow Database Queries (above %ss)', 'query-monitor' ),
93
  '<span class="qm-warn">' . esc_html( number_format_i18n( QM_DB_EXPENSIVE, $dp ) ) . '</span>'
94
  );
95
+ $this->before_tabular_output( 'qm-query-expensive', $panel_name );
96
+
97
  echo '<thead>';
98
  echo '<tr>';
99
  echo '<th scope="col">' . esc_html__( 'Query', 'query-monitor' ) . '</th>';
117
  }
118
 
119
  echo '</tbody>';
 
 
120
 
121
+ $this->after_tabular_output();
122
  }
123
 
124
  protected function output_queries( $name, stdClass $db, array $data ) {
132
  $span++;
133
  }
134
 
135
+ $panel_id = sprintf(
136
+ '%s-%s',
137
+ $this->collector->id(),
138
+ sanitize_title_with_dashes( $name )
139
+ );
140
+ $panel_name = sprintf(
141
+ /* translators: %s: Name of database controller */
142
+ __( '%s Queries', 'query-monitor' ),
143
+ $name
144
+ );
145
 
146
  if ( ! empty( $db->rows ) ) {
147
+ $this->before_tabular_output( $panel_id, $panel_name );
148
+
 
149
  echo '<thead>';
150
 
151
  /**
161
  echo '<th colspan="' . absint( $span ) . '" class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
162
  if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) {
163
  /* translators: 1: Symlink file name, 2: URL to wiki page */
164
+ $message = __( 'Extended query information such as the component and affected rows is not available. A conflicting %1$s file is present. <a href="%2$s" target="_blank" class="qm-external-link">See this wiki page for more information.</a>', 'query-monitor' );
165
  } else {
166
  /* translators: 1: Symlink file name, 2: URL to wiki page */
167
+ $message = __( 'Extended query information such as the component and affected rows is not available. Query Monitor was unable to symlink its %1$s file into place. <a href="%2$s" target="_blank" class="qm-external-link">See this wiki page for more information.</a>', 'query-monitor' );
168
  }
169
  echo wp_kses( sprintf(
170
  $message,
174
  'a' => array(
175
  'href' => array(),
176
  'target' => array(),
177
+ 'class' => array(),
178
  ),
179
  ) );
180
  echo '</th>';
181
  echo '</tr>';
182
  }
183
 
184
+ $types = array_keys( $db->types );
185
+ $prepend = array();
186
+ $callers = wp_list_pluck( $data['times'], 'caller' );
187
+
188
+ sort( $types );
189
+ usort( $callers, 'strcasecmp' );
190
 
191
  if ( count( $types ) > 1 ) {
192
  $prepend['non-select'] = __( 'Non-SELECT', 'query-monitor' );
197
  );
198
 
199
  echo '<tr>';
200
+ echo '<th scope="col" class="qm-sorted-asc qm-sortable-column" role="columnheader" aria-sort="ascending">';
201
+ echo $this->build_sorter( '#' ); // WPCS: XSS ok;
202
  echo '</th>';
203
  echo '<th scope="col" class="qm-filterable-column">';
204
  echo $this->build_filter( 'type', $types, __( 'Query', 'query-monitor' ), $args ); // WPCS: XSS ok;
214
  $args = array(
215
  'prepend' => $prepend,
216
  );
217
+ echo $this->build_filter( 'caller', $callers, __( 'Caller', 'query-monitor' ), $args ); // WPCS: XSS ok.
218
  echo '</th>';
219
 
220
  if ( $db->has_trace ) {
221
+ $components = wp_list_pluck( $data['component_times'], 'component' );
222
+
223
+ usort( $components, 'strcasecmp' );
224
+
225
  echo '<th scope="col" class="qm-filterable-column">';
226
+ echo $this->build_filter( 'component', $components, __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
227
  echo '</th>';
228
  }
229
 
233
  } else {
234
  $class = '';
235
  }
236
+ echo '<th scope="col" class="' . esc_attr( $class ) . ' qm-sortable-column" role="columnheader" aria-sort="none">';
237
  echo $this->build_sorter( __( 'Rows', 'query-monitor' ) ); // WPCS: XSS ok.
238
  echo '</th>';
239
  }
240
 
241
+ echo '<th scope="col" class="qm-num qm-sortable-column" role="columnheader" aria-sort="none">';
242
  echo $this->build_sorter( __( 'Time', 'query-monitor' ) ); // WPCS: XSS ok.
243
  echo '</th>';
244
  echo '</tr>';
255
 
256
  $total_stime = number_format_i18n( $db->total_time, 4 );
257
 
258
+ echo '<tr>';
259
  echo '<td colspan="' . absint( $span - 1 ) . '">';
260
  printf(
261
+ /* translators: %s: Number of database queries */
262
+ esc_html_x( 'Total: %s', 'Database queries', 'query-monitor' ),
263
  '<span class="qm-items-number">' . esc_html( number_format_i18n( $db->total_qs ) ) . '</span>'
264
  );
265
  echo '</td>';
266
+ echo '<td class="qm-num qm-items-time">' . esc_html( $total_stime ) . '</td>';
 
 
 
 
 
 
 
 
 
 
 
267
  echo '</tr>';
268
  echo '</tfoot>';
 
269
 
270
+ $this->after_tabular_output();
271
  } else {
272
+ $this->before_non_tabular_output( $panel_id, $panel_name );
273
 
274
+ $notice = __( 'No queries! Nice work.', 'query-monitor' );
275
+ echo $this->build_notice( $notice ); // WPCS: XSS ok.
 
276
 
277
+ $this->after_non_tabular_output();
278
  }
 
 
 
279
  }
280
 
281
  protected function output_query_row( array $row, array $cols ) {
359
  echo "<tr{$attr}>"; // WPCS: XSS ok.
360
 
361
  if ( isset( $cols['row'] ) ) {
362
+ echo '<th scope="row" class="qm-row-num qm-num">' . absint( ++$this->query_row ) . '</th>';
363
  }
364
 
365
  if ( isset( $cols['sql'] ) ) {
output/html/debug_bar.php CHANGED
@@ -13,17 +13,41 @@ class QM_Output_Html_Debug_Bar extends QM_Output_Html {
13
  }
14
 
15
  public function output() {
16
-
17
  $target = sanitize_html_class( get_class( $this->collector->get_panel() ) );
18
 
19
- echo '<div class="qm qm-debug-bar" id="' . esc_attr( $this->collector->id() ) . '">';
 
20
  echo '<div id="debug-menu-target-' . esc_attr( $target ) . '" class="debug-menu-target qm-debug-bar-output">';
21
 
 
22
  $this->collector->render();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- echo '</div>';
25
  echo '</div>';
26
 
 
27
  }
28
 
29
  }
13
  }
14
 
15
  public function output() {
 
16
  $target = sanitize_html_class( get_class( $this->collector->get_panel() ) );
17
 
18
+ $this->before_debug_bar_output();
19
+
20
  echo '<div id="debug-menu-target-' . esc_attr( $target ) . '" class="debug-menu-target qm-debug-bar-output">';
21
 
22
+ ob_start();
23
  $this->collector->render();
24
+ $panel = ob_get_clean();
25
+
26
+ $panel = str_replace( array(
27
+ '<h4',
28
+ '<h3',
29
+ '<h2',
30
+ '<h1',
31
+ '</h4>',
32
+ '</h3>',
33
+ '</h2>',
34
+ '</h1>',
35
+ ), array(
36
+ '<h5',
37
+ '<h4',
38
+ '<h3',
39
+ '<h2',
40
+ '</h5>',
41
+ '</h4>',
42
+ '</h3>',
43
+ '</h2>',
44
+ ), $panel );
45
+
46
+ echo $panel; // @codingStandardsIgnoreLine
47
 
 
48
  echo '</div>';
49
 
50
+ $this->after_debug_bar_output();
51
  }
52
 
53
  }
output/html/environment.php CHANGED
@@ -16,11 +16,10 @@ class QM_Output_Html_Environment extends QM_Output_Html {
16
 
17
  $data = $this->collector->get_data();
18
 
19
- echo '<div class="qm qm-non-tabular" id="' . esc_attr( $this->collector->id() ) . '">';
20
- echo '<div class="qm-boxed qm-boxed-wrap">';
21
 
22
  echo '<div class="qm-section">';
23
- echo '<h2>PHP</h2>';
24
 
25
  echo '<table>';
26
  echo '<tbody>';
@@ -31,7 +30,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
31
 
32
  if ( $php_warning ) {
33
  $append .= sprintf(
34
- '&nbsp;<span class="qm-info">(<a href="%s" target="_blank">%s</a>)</span>',
35
  'https://wordpress.org/support/upgrade-php/',
36
  esc_html__( 'Help', 'query-monitor' )
37
  );
@@ -39,7 +38,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
39
  }
40
 
41
  echo '<tr class="' . esc_attr( $class ) . '">';
42
- echo '<th scope="row">version</th>';
43
  echo '<td>';
44
  echo esc_html( $data['php']['version'] );
45
  echo $append; // WPCS: XSS ok.
@@ -47,12 +46,12 @@ class QM_Output_Html_Environment extends QM_Output_Html {
47
  echo '</tr>';
48
 
49
  echo '<tr>';
50
- echo '<th scope="row">sapi</th>';
51
  echo '<td>' . esc_html( $data['php']['sapi'] ) . '</td>';
52
  echo '</tr>';
53
 
54
  echo '<tr>';
55
- echo '<th scope="row">user</th>';
56
  if ( ! empty( $data['php']['user'] ) ) {
57
  echo '<td>' . esc_html( $data['php']['user'] ) . '</td>';
58
  } else {
@@ -144,20 +143,30 @@ class QM_Output_Html_Environment extends QM_Output_Html {
144
  }
145
 
146
  echo '<div class="qm-section">';
147
- echo '<h2>' . esc_html( $name ) . '</h2>';
148
 
149
  echo '<table>';
150
  echo '<tbody>';
151
 
152
- foreach ( $db['info'] as $key => $value ) {
 
 
 
 
 
 
 
 
 
 
153
 
154
  echo '<tr>';
155
- echo '<th scope="row">' . esc_html( $key ) . '</th>';
156
 
157
- if ( ! isset( $value ) ) {
158
  echo '<td><span class="qm-warn">' . esc_html__( 'Unknown', 'query-monitor' ) . '</span></td>';
159
  } else {
160
- echo '<td>' . esc_html( $value ) . '</td>';
161
  }
162
 
163
  echo '</tr>';
@@ -187,7 +196,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
187
 
188
  if ( $show_warning ) {
189
  $append .= sprintf(
190
- '&nbsp;<span class="qm-info">(<a href="%s" target="_blank">%s</a>)</span>',
191
  esc_url( sprintf( $search, rawurlencode( $key ) ) ),
192
  esc_html__( 'Help', 'query-monitor' )
193
  );
@@ -195,7 +204,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
195
 
196
  if ( is_numeric( $val ) and ( $val >= ( 1024 * 1024 ) ) ) {
197
  $append .= sprintf(
198
- '<br><span class="qm-info qm-supplemental">~%s</span>',
199
  esc_html( size_format( $val ) )
200
  );
201
  }
@@ -227,12 +236,17 @@ class QM_Output_Html_Environment extends QM_Output_Html {
227
  }
228
 
229
  echo '<div class="qm-section">';
230
- echo '<h2>WordPress</h2>';
231
 
232
  echo '<table>';
233
  echo '<tbody>';
234
 
235
- foreach ( $data['wp'] as $key => $val ) {
 
 
 
 
 
236
 
237
  echo '<tr>';
238
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
@@ -247,13 +261,13 @@ class QM_Output_Html_Environment extends QM_Output_Html {
247
  echo '</div>';
248
 
249
  echo '<div class="qm-section">';
250
- echo '<h2>' . esc_html( 'Server', 'query-monitor' ) . '</h2>';
251
 
252
  $server = array(
253
- 'name' => __( 'software', 'query-monitor' ),
254
- 'version' => __( 'version', 'query-monitor' ),
255
- 'address' => __( 'address', 'query-monitor' ),
256
- 'host' => __( 'host', 'query-monitor' ),
257
  'OS' => __( 'OS', 'query-monitor' ),
258
  );
259
 
@@ -275,8 +289,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
275
  echo '</table>';
276
  echo '</div>';
277
 
278
- echo '</div>';
279
- echo '</div>';
280
  }
281
 
282
  }
16
 
17
  $data = $this->collector->get_data();
18
 
19
+ $this->before_non_tabular_output();
 
20
 
21
  echo '<div class="qm-section">';
22
+ echo '<h3>PHP</h3>';
23
 
24
  echo '<table>';
25
  echo '<tbody>';
30
 
31
  if ( $php_warning ) {
32
  $append .= sprintf(
33
+ '&nbsp;<span class="qm-info">(<a href="%s" target="_blank" class="qm-external-link">%s</a>)</span>',
34
  'https://wordpress.org/support/upgrade-php/',
35
  esc_html__( 'Help', 'query-monitor' )
36
  );
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.
46
  echo '</tr>';
47
 
48
  echo '<tr>';
49
+ echo '<th scope="row">SAPI</th>';
50
  echo '<td>' . esc_html( $data['php']['sapi'] ) . '</td>';
51
  echo '</tr>';
52
 
53
  echo '<tr>';
54
+ echo '<th scope="row">' . esc_html__( 'User', 'query-monitor' ) . '</th>';
55
  if ( ! empty( $data['php']['user'] ) ) {
56
  echo '<td>' . esc_html( $data['php']['user'] ) . '</td>';
57
  } else {
143
  }
144
 
145
  echo '<div class="qm-section">';
146
+ echo '<h3>' . esc_html( $name ) . '</h3>';
147
 
148
  echo '<table>';
149
  echo '<tbody>';
150
 
151
+ $info = array(
152
+ 'rdbms' => __( 'RDBMS', 'query-monitor' ),
153
+ 'server-version' => __( 'Server Version', 'query-monitor' ),
154
+ 'extension' => __( 'Extension', 'query-monitor' ),
155
+ 'client-version' => __( 'Client Version', 'query-monitor' ),
156
+ 'user' => __( 'User', 'query-monitor' ),
157
+ 'host' => __( 'Host', 'query-monitor' ),
158
+ 'database' => __( 'Database', 'query-monitor' ),
159
+ );
160
+
161
+ foreach ( $info as $field => $label ) {
162
 
163
  echo '<tr>';
164
+ echo '<th scope="row">' . esc_html( $label ) . '</th>';
165
 
166
+ if ( ! isset( $db['info'][ $field ] ) ) {
167
  echo '<td><span class="qm-warn">' . esc_html__( 'Unknown', 'query-monitor' ) . '</span></td>';
168
  } else {
169
+ echo '<td>' . esc_html( $db['info'][ $field ] ) . '</td>';
170
  }
171
 
172
  echo '</tr>';
196
 
197
  if ( $show_warning ) {
198
  $append .= sprintf(
199
+ '&nbsp;<span class="qm-info">(<a href="%s" target="_blank" class="qm-external-link">%s</a>)</span>',
200
  esc_url( sprintf( $search, rawurlencode( $key ) ) ),
201
  esc_html__( 'Help', 'query-monitor' )
202
  );
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 ) )
209
  );
210
  }
236
  }
237
 
238
  echo '<div class="qm-section">';
239
+ echo '<h3>WordPress</h3>';
240
 
241
  echo '<table>';
242
  echo '<tbody>';
243
 
244
+ echo '<tr>';
245
+ echo '<th scope="row">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
246
+ echo '<td>' . esc_html( $data['wp']['version'] ) . '</td>';
247
+ echo '</tr>';
248
+
249
+ foreach ( $data['wp']['constants'] as $key => $val ) {
250
 
251
  echo '<tr>';
252
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
261
  echo '</div>';
262
 
263
  echo '<div class="qm-section">';
264
+ echo '<h3>' . esc_html__( 'Server', 'query-monitor' ) . '</h3>';
265
 
266
  $server = array(
267
+ 'name' => __( 'Software', 'query-monitor' ),
268
+ 'version' => __( 'Version', 'query-monitor' ),
269
+ 'address' => __( 'Address', 'query-monitor' ),
270
+ 'host' => __( 'Host', 'query-monitor' ),
271
  'OS' => __( 'OS', 'query-monitor' ),
272
  );
273
 
289
  echo '</table>';
290
  echo '</div>';
291
 
292
+ $this->after_non_tabular_output();
 
293
  }
294
 
295
  }
output/html/hooks.php CHANGED
@@ -28,18 +28,23 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
28
  $screen = $data['screen'];
29
  }
30
 
31
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
32
- echo '<table>';
33
- echo '<caption class="screen-reader-text">' . esc_html__( 'Hooks', 'query-monitor' ) . '</caption>';
 
 
 
 
 
34
  echo '<thead>';
35
  echo '<tr>';
36
  echo '<th scope="col" class="qm-filterable-column">';
37
- echo $this->build_filter( 'name', $data['parts'], __( 'Hook', 'query-monitor' ) ); // WPCS: XSS ok.
38
  echo '</th>';
39
  echo '<th scope="col">' . esc_html__( 'Priority', 'query-monitor' ) . '</th>';
40
  echo '<th scope="col">' . esc_html__( 'Action', 'query-monitor' ) . '</th>';
41
  echo '<th scope="col" class="qm-filterable-column">';
42
- echo $this->build_filter( 'component', $data['components'], __( 'Component', 'query-monitor' ), 'subject' ); // WPCS: XSS ok.
43
  echo '</th>';
44
  echo '</tr>';
45
  echo '</thead>';
@@ -48,9 +53,7 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
48
  self::output_hook_table( $data['hooks'], $screen );
49
  echo '</tbody>';
50
 
51
- echo '</table>';
52
- echo '</div>';
53
-
54
  }
55
 
56
  public static function output_hook_table( array $hooks, $screen = '' ) {
@@ -132,7 +135,7 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
132
 
133
  if ( isset( $action['callback']['file'] ) ) {
134
  if ( self::has_clickable_links() ) {
135
- echo '<td class="qm-wrap qm-ltr' . esc_attr( $class ) . '">';
136
  echo self::output_filename( $action['callback']['name'], $action['callback']['file'], $action['callback']['line'] ); // WPCS: XSS ok.
137
  echo '</td>';
138
  } else {
@@ -144,7 +147,7 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
144
  echo '</ol></td>';
145
  }
146
  } else {
147
- echo '<td class="qm-ltr qm-wrap' . esc_attr( $class ) . '">';
148
  echo '<code>' . esc_html( $action['callback']['name'] ) . '</code>';
149
  }
150
 
@@ -166,9 +169,9 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
166
  }
167
  } else {
168
  echo "<tr{$attr}>"; // WPCS: XSS ok.
169
- echo '<th scope="row" class="qm-ltr">';
170
  echo '<code>' . $hook_name . '</code>'; // WPCS: XSS ok.
171
- echo '</th>';
172
  echo '<td>&nbsp;</td>';
173
  echo '<td>&nbsp;</td>';
174
  echo '<td>&nbsp;</td>';
28
  $screen = $data['screen'];
29
  }
30
 
31
+ $parts = $data['parts'];
32
+ $components = $data['components'];
33
+
34
+ usort( $parts, 'strcasecmp' );
35
+ usort( $components, 'strcasecmp' );
36
+
37
+ $this->before_tabular_output();
38
+
39
  echo '<thead>';
40
  echo '<tr>';
41
  echo '<th scope="col" class="qm-filterable-column">';
42
+ echo $this->build_filter( 'name', $parts, __( 'Hook', 'query-monitor' ) ); // WPCS: XSS ok.
43
  echo '</th>';
44
  echo '<th scope="col">' . esc_html__( 'Priority', 'query-monitor' ) . '</th>';
45
  echo '<th scope="col">' . esc_html__( 'Action', 'query-monitor' ) . '</th>';
46
  echo '<th scope="col" class="qm-filterable-column">';
47
+ echo $this->build_filter( 'component', $components, __( 'Component', 'query-monitor' ), 'subject' ); // WPCS: XSS ok.
48
  echo '</th>';
49
  echo '</tr>';
50
  echo '</thead>';
53
  self::output_hook_table( $data['hooks'], $screen );
54
  echo '</tbody>';
55
 
56
+ $this->after_tabular_output();
 
 
57
  }
58
 
59
  public static function output_hook_table( array $hooks, $screen = '' ) {
135
 
136
  if ( isset( $action['callback']['file'] ) ) {
137
  if ( self::has_clickable_links() ) {
138
+ echo '<td class="qm-nowrap qm-ltr' . esc_attr( $class ) . '">';
139
  echo self::output_filename( $action['callback']['name'], $action['callback']['file'], $action['callback']['line'] ); // WPCS: XSS ok.
140
  echo '</td>';
141
  } else {
147
  echo '</ol></td>';
148
  }
149
  } else {
150
+ echo '<td class="qm-ltr qm-nowrap' . esc_attr( $class ) . '">';
151
  echo '<code>' . esc_html( $action['callback']['name'] ) . '</code>';
152
  }
153
 
169
  }
170
  } else {
171
  echo "<tr{$attr}>"; // WPCS: XSS ok.
172
+ echo '<th scope="row" class="qm-ltr"><span class="qm-sticky">';
173
  echo '<code>' . $hook_name . '</code>'; // WPCS: XSS ok.
174
+ echo '</span></th>';
175
  echo '<td>&nbsp;</td>';
176
  echo '<td>&nbsp;</td>';
177
  echo '<td>&nbsp;</td>';
output/html/http.php CHANGED
@@ -19,8 +19,6 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
19
 
20
  $total_time = 0;
21
 
22
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
23
-
24
  $vars = array();
25
 
26
  if ( ! empty( $data['vars'] ) ) {
@@ -30,30 +28,27 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
30
  }
31
 
32
  if ( ! empty( $data['http'] ) ) {
33
- echo '<table class="qm-sortable">';
 
 
 
 
34
 
35
- echo '<caption class="screen-reader-text">' . esc_html__( 'HTTP API Calls', 'query-monitor' ) . '</caption>';
36
 
37
  echo '<thead>';
38
  echo '<tr>';
39
- echo '<th scope="col" class="qm-sorted-asc qm-sortable-column">';
40
- echo $this->build_sorter(); // WPCS: XSS ok.
41
- echo '</th>';
42
  echo '<th scope="col">' . esc_html__( 'Method', 'query-monitor' ) . '</th>';
43
  echo '<th scope="col">' . esc_html__( 'URL', 'query-monitor' ) . '</th>';
44
  echo '<th scope="col" class="qm-filterable-column">';
45
- echo $this->build_filter( 'type', array_keys( $data['types'] ), __( 'Status', 'query-monitor' ) ); // WPCS: XSS ok.
46
  echo '</th>';
47
  echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
48
  echo '<th scope="col" class="qm-filterable-column">';
49
- echo $this->build_filter( 'component', wp_list_pluck( $data['component_times'], 'component' ), __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
50
- echo '</th>';
51
- echo '<th scope="col" class="qm-num qm-sortable-column">';
52
- echo $this->build_sorter( __( 'Timeout', 'query-monitor' ) ); // WPCS: XSS ok.
53
- echo '</th>';
54
- echo '<th scope="col" class="qm-num qm-sortable-column">';
55
- echo $this->build_sorter( __( 'Time', 'query-monitor' ) ); // WPCS: XSS ok.
56
  echo '</th>';
 
 
57
  echo '</tr>';
58
  echo '</thead>';
59
 
@@ -144,6 +139,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
144
 
145
  $row_attr['data-qm-component'] = $component->name;
146
  $row_attr['data-qm-type'] = $row['type'];
 
147
 
148
  if ( 'core' !== $component->context ) {
149
  $row_attr['data-qm-component'] .= ' non-core';
@@ -159,10 +155,6 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
159
  $attr,
160
  esc_attr( $css )
161
  );
162
- printf(
163
- '<td class="qm-num">%s</td>',
164
- intval( $i )
165
- );
166
  printf(
167
  '<td>%s</td>',
168
  esc_html( $row['args']['method'] )
@@ -183,23 +175,30 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
183
  $url
184
  );
185
 
186
- echo '<td class="qm-has-toggle"><div class="qm-toggler">';
 
 
187
  if ( $is_error ) {
188
  echo '<span class="dashicons dashicons-warning" aria-hidden="true"></span>';
189
  }
190
  echo esc_html( $response );
191
- echo self::build_toggler(); // WPCS: XSS ok;
192
 
193
- echo '<ul class="qm-toggled">';
194
- $transport = sprintf(
195
- /* translators: %s HTTP API transport name */
196
- __( 'HTTP API Transport: %s', 'query-monitor' ),
197
- $row['transport']
198
- );
199
- printf(
200
- '<li><span class="qm-info qm-supplemental">%s</span></li>',
201
- esc_html( $transport )
202
- );
 
 
 
 
 
 
203
 
204
  if ( ! empty( $row['info'] ) ) {
205
  $time_fields = array(
@@ -247,7 +246,11 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
247
  );
248
  }
249
  }
250
- echo '</ul>';
 
 
 
 
251
  echo '</td>';
252
 
253
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
@@ -278,8 +281,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
278
  }
279
 
280
  printf(
281
- '<td class="qm-num" data-qm-sort-weight="%s">%s</td>',
282
- esc_attr( $ltime ),
283
  esc_html( $stime )
284
  );
285
  echo '</tr>';
@@ -292,29 +294,27 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
292
 
293
  echo '<tr>';
294
  printf(
295
- '<td colspan="7">%1$s<br>%2$s</td>',
296
- esc_html( sprintf(
297
  /* translators: %s: Number of HTTP API requests */
298
- __( 'Total Requests: %s', 'query-monitor' ),
299
- number_format_i18n( count( $data['http'] ) )
300
- ) ),
301
  implode( '<br>', array_map( 'esc_html', $vars ) )
302
  );
303
- echo '<td class="qm-num">' . esc_html( $total_stime ) . '</td>';
304
  echo '</tr>';
305
  echo '</tfoot>';
306
- echo '</table>';
307
 
 
308
  } else {
 
309
 
310
- echo '<div class="qm-none">';
311
- echo '<p>' . esc_html__( 'None', 'query-monitor' ) . '</p>';
312
- echo '</div>';
313
 
 
314
  }
315
-
316
- echo '</div>';
317
-
318
  }
319
 
320
  public function admin_class( array $class ) {
19
 
20
  $total_time = 0;
21
 
 
 
22
  $vars = array();
23
 
24
  if ( ! empty( $data['vars'] ) ) {
28
  }
29
 
30
  if ( ! empty( $data['http'] ) ) {
31
+ $statuses = array_keys( $data['types'] );
32
+ $components = wp_list_pluck( $data['component_times'], 'component' );
33
+
34
+ usort( $statuses, 'strcasecmp' );
35
+ usort( $components, 'strcasecmp' );
36
 
37
+ $this->before_tabular_output();
38
 
39
  echo '<thead>';
40
  echo '<tr>';
 
 
 
41
  echo '<th scope="col">' . esc_html__( 'Method', 'query-monitor' ) . '</th>';
42
  echo '<th scope="col">' . esc_html__( 'URL', 'query-monitor' ) . '</th>';
43
  echo '<th scope="col" class="qm-filterable-column">';
44
+ echo $this->build_filter( 'type', $statuses, __( 'Status', 'query-monitor' ) ); // WPCS: XSS ok.
45
  echo '</th>';
46
  echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
47
  echo '<th scope="col" class="qm-filterable-column">';
48
+ echo $this->build_filter( 'component', $components, __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
 
 
 
 
 
 
49
  echo '</th>';
50
+ echo '<th scope="col" class="qm-num">' . esc_html__( 'Timeout', 'query-monitor' ) . '</th>';
51
+ echo '<th scope="col" class="qm-num">' . esc_html__( 'Time', 'query-monitor' ) . '</th>';
52
  echo '</tr>';
53
  echo '</thead>';
54
 
139
 
140
  $row_attr['data-qm-component'] = $component->name;
141
  $row_attr['data-qm-type'] = $row['type'];
142
+ $row_attr['data-qm-time'] = $row['ltime'];
143
 
144
  if ( 'core' !== $component->context ) {
145
  $row_attr['data-qm-component'] .= ' non-core';
155
  $attr,
156
  esc_attr( $css )
157
  );
 
 
 
 
158
  printf(
159
  '<td>%s</td>',
160
  esc_html( $row['args']['method'] )
175
  $url
176
  );
177
 
178
+ $show_toggle = ( ! empty( $row['transport'] ) && ! empty( $row['info'] ) );
179
+
180
+ echo '<td class="qm-has-toggle qm-col-status"><div class="qm-toggler">';
181
  if ( $is_error ) {
182
  echo '<span class="dashicons dashicons-warning" aria-hidden="true"></span>';
183
  }
184
  echo esc_html( $response );
 
185
 
186
+ if ( $show_toggle ) {
187
+ echo self::build_toggler(); // WPCS: XSS ok;
188
+ echo '<ul class="qm-toggled">';
189
+ }
190
+
191
+ if ( ! empty( $row['transport'] ) ) {
192
+ $transport = sprintf(
193
+ /* translators: %s HTTP API transport name */
194
+ __( 'HTTP API Transport: %s', 'query-monitor' ),
195
+ $row['transport']
196
+ );
197
+ printf(
198
+ '<li><span class="qm-info qm-supplemental">%s</span></li>',
199
+ esc_html( $transport )
200
+ );
201
+ }
202
 
203
  if ( ! empty( $row['info'] ) ) {
204
  $time_fields = array(
246
  );
247
  }
248
  }
249
+
250
+ if ( $show_toggle ) {
251
+ echo '</ul>';
252
+ }
253
+
254
  echo '</td>';
255
 
256
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
281
  }
282
 
283
  printf(
284
+ '<td class="qm-num">%s</td>',
 
285
  esc_html( $stime )
286
  );
287
  echo '</tr>';
294
 
295
  echo '<tr>';
296
  printf(
297
+ '<td colspan="6">%1$s<br>%2$s</td>',
298
+ sprintf(
299
  /* translators: %s: Number of HTTP API requests */
300
+ esc_html_x( 'Total: %s', 'HTTP API calls', 'query-monitor' ),
301
+ '<span class="qm-items-number">' . esc_html( number_format_i18n( count( $data['http'] ) ) ) . '</span>'
302
+ ),
303
  implode( '<br>', array_map( 'esc_html', $vars ) )
304
  );
305
+ echo '<td class="qm-num qm-items-time">' . esc_html( $total_stime ) . '</td>';
306
  echo '</tr>';
307
  echo '</tfoot>';
 
308
 
309
+ $this->after_tabular_output();
310
  } else {
311
+ $this->before_non_tabular_output();
312
 
313
+ $notice = __( 'No HTTP API calls.', 'query-monitor' );
314
+ echo $this->build_notice( $notice ); // WPCS: XSS ok.
 
315
 
316
+ $this->after_non_tabular_output();
317
  }
 
 
 
318
  }
319
 
320
  public function admin_class( array $class ) {
output/html/languages.php CHANGED
@@ -22,19 +22,14 @@ class QM_Output_Html_Languages extends QM_Output_Html {
22
  return;
23
  }
24
 
25
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
26
- echo '<table>';
27
- echo '<caption>' . esc_html( sprintf(
28
- /* translators: %s: Name of current language */
29
- __( 'Language Setting: %s', 'query-monitor' ),
30
- $data['locale']
31
- ) ) . '</caption>';
32
  echo '<thead>';
33
  echo '<tr>';
34
- echo '<th>' . esc_html__( 'Text Domain', 'query-monitor' ) . '</th>';
35
- echo '<th>' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
36
- echo '<th>' . esc_html__( 'MO File', 'query-monitor' ) . '</th>';
37
- echo '<th>' . esc_html__( 'Size', 'query-monitor' ) . '</th>';
38
  echo '</tr>';
39
  echo '</thead>';
40
 
@@ -46,7 +41,7 @@ class QM_Output_Html_Languages extends QM_Output_Html {
46
  foreach ( $mofiles as $mofile ) {
47
  echo '<tr>';
48
 
49
- echo '<th class="qm-ltr">' . esc_html( $mofile['domain'] ) . '</th>';
50
 
51
  if ( self::has_clickable_links() ) {
52
  echo '<td class="qm-nowrap qm-ltr">';
@@ -82,9 +77,7 @@ class QM_Output_Html_Languages extends QM_Output_Html {
82
 
83
  echo '</tbody>';
84
 
85
- echo '</table>';
86
- echo '</div>';
87
-
88
  }
89
 
90
  public function admin_menu( array $menu ) {
22
  return;
23
  }
24
 
25
+ $this->before_tabular_output();
26
+
 
 
 
 
 
27
  echo '<thead>';
28
  echo '<tr>';
29
+ echo '<th scope="col">' . esc_html__( 'Text Domain', 'query-monitor' ) . '</th>';
30
+ echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
31
+ echo '<th scope="col">' . esc_html__( 'MO File', 'query-monitor' ) . '</th>';
32
+ echo '<th scope="col">' . esc_html__( 'Size', 'query-monitor' ) . '</th>';
33
  echo '</tr>';
34
  echo '</thead>';
35
 
41
  foreach ( $mofiles as $mofile ) {
42
  echo '<tr>';
43
 
44
+ echo '<td class="qm-ltr">' . esc_html( $mofile['domain'] ) . '</td>';
45
 
46
  if ( self::has_clickable_links() ) {
47
  echo '<td class="qm-nowrap qm-ltr">';
77
 
78
  echo '</tbody>';
79
 
80
+ $this->after_tabular_output();
 
 
81
  }
82
 
83
  public function admin_menu( array $menu ) {
output/html/logger.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PSR-3 compatible logging output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
7
+
8
+ class QM_Output_Html_Logger extends QM_Output_Html {
9
+
10
+ public function __construct( QM_Collector $collector ) {
11
+ parent::__construct( $collector );
12
+ add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 12 );
13
+ add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
14
+ }
15
+
16
+ public function output() {
17
+
18
+ $data = $this->collector->get_data();
19
+
20
+ if ( empty( $data['logs'] ) ) {
21
+ return;
22
+ }
23
+
24
+ $levels = array_map( 'ucfirst', $this->collector->get_levels() );
25
+
26
+ $this->before_tabular_output();
27
+
28
+ echo '<thead>';
29
+ echo '<tr>';
30
+ echo '<th scope="col" class="qm-filterable-column">';
31
+ echo $this->build_filter( 'type', $levels, __( 'Level', 'query-monitor' ) ); // WPCS: XSS ok.
32
+ echo '</th>';
33
+ echo '<th scope="col" class="qm-col-message">' . esc_html__( 'Message', 'query-monitor' ) . '</th>';
34
+ echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
35
+ echo '<th scope="col" class="qm-filterable-column">';
36
+ echo $this->build_filter( 'component', $data['components'], __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
37
+ echo '</th>';
38
+ echo '</tr>';
39
+ echo '</thead>';
40
+
41
+ echo '<tbody>';
42
+
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
+
50
+ $attr = '';
51
+
52
+ foreach ( $row_attr as $a => $v ) {
53
+ $attr .= ' ' . $a . '="' . esc_attr( $v ) . '"';
54
+ }
55
+
56
+ $is_warning = in_array( $row['level'], $this->collector->get_warning_levels(), true );
57
+
58
+ if ( $is_warning ) {
59
+ $class = 'qm-warn';
60
+ } else {
61
+ $class = '';
62
+ }
63
+
64
+ echo '<tr ' . $attr . 'class="' . esc_attr( $class ) . '">'; // WPCS: XSS ok.
65
+
66
+ echo '<td scope="row" class="qm-nowrap">';
67
+
68
+ if ( $is_warning ) {
69
+ echo '<span class="dashicons dashicons-warning" aria-hidden="true"></span>';
70
+ } else {
71
+ echo '<span class="dashicons" aria-hidden="true"></span>';
72
+ }
73
+
74
+ echo esc_html( ucfirst( $row['level'] ) );
75
+ echo '</td>';
76
+
77
+ printf(
78
+ '<td>%s</td>',
79
+ esc_html( $row['message'] )
80
+ );
81
+
82
+ $stack = array();
83
+ $filtered_trace = $row['trace']->get_display_trace();
84
+
85
+ foreach ( $filtered_trace as $item ) {
86
+ $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
87
+ }
88
+
89
+ echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
90
+
91
+ $caller = array_pop( $stack );
92
+
93
+ if ( ! empty( $stack ) ) {
94
+ echo self::build_toggler(); // WPCS: XSS ok;
95
+ echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
96
+ }
97
+
98
+ echo "<li>{$caller}</li>"; // WPCS: XSS ok.
99
+ echo '</ol></td>';
100
+
101
+ printf(
102
+ '<td class="qm-nowrap">%s</td>',
103
+ esc_html( $component->name )
104
+ );
105
+
106
+ echo '</tr>';
107
+
108
+ }
109
+
110
+ echo '</tbody>';
111
+
112
+ $this->after_tabular_output();
113
+ }
114
+
115
+ public function admin_class( array $class ) {
116
+ $data = $this->collector->get_data();
117
+
118
+ if ( empty( $data['logs'] ) ) {
119
+ return $class;
120
+ }
121
+
122
+ foreach ( $data['logs'] as $log ) {
123
+ if ( in_array( $log['level'], $this->collector->get_warning_levels(), true ) ) {
124
+ $class[] = 'qm-warning';
125
+ break;
126
+ }
127
+ }
128
+
129
+ return $class;
130
+ }
131
+
132
+ public function admin_menu( array $menu ) {
133
+ $data = $this->collector->get_data();
134
+
135
+ if ( empty( $data['logs'] ) ) {
136
+ return $menu;
137
+ }
138
+
139
+ $key = 'log';
140
+
141
+ foreach ( $data['logs'] as $log ) {
142
+ if ( in_array( $log['level'], $this->collector->get_warning_levels(), true ) ) {
143
+ $key = 'warning';
144
+ break;
145
+ }
146
+ }
147
+
148
+ $menu[] = $this->menu( array(
149
+ 'id' => "query-monitor-logger-{$key}",
150
+ 'title' => esc_html__( 'Logs', 'query-monitor' ),
151
+ ) );
152
+
153
+ return $menu;
154
+ }
155
+
156
+ }
157
+
158
+ function register_qm_output_html_logger( array $output, QM_Collectors $collectors ) {
159
+ if ( $collector = QM_Collectors::get( 'logger' ) ) {
160
+ $output['logger'] = new QM_Output_Html_Logger( $collector );
161
+ }
162
+ return $output;
163
+ }
164
+
165
+ add_filter( 'qm/outputter/html', 'register_qm_output_html_logger', 12, 2 );
output/html/overview.php CHANGED
@@ -37,34 +37,49 @@ class QM_Output_Html_Overview extends QM_Output_Html {
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
 
41
- echo '<div class="qm qm-non-tabular" id="' . esc_attr( $this->collector->id() ) . '">';
42
- echo '<div class="qm-boxed" id="qm-broken">';
43
 
44
- echo '<div class="qm-section">';
45
- echo '<h2 class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $qm_broken ) . '</h2>';
 
 
 
 
46
  echo '</div>';
47
 
48
  echo '</div>';
49
- echo '<div class="qm-boxed qm-boxed-wrap">';
50
 
51
  echo '<div class="qm-section">';
52
- echo '<h2>' . esc_html__( 'Page Generation Time', 'query-monitor' ) . '</h2>';
53
  echo '<p class="qm-item">';
54
  echo esc_html( number_format_i18n( $data['time_taken'], 4 ) );
55
- echo '<br><span class="qm-info">';
56
- echo esc_html( sprintf(
57
- /* translators: 1: Percentage of time limit used, 2: Time limit in seconds */
58
- __( '%1$s%% of %2$ss limit', 'query-monitor' ),
59
- number_format_i18n( $data['time_usage'], 1 ),
60
- number_format_i18n( $data['time_limit'] )
61
- ) );
62
- echo '</span>';
 
 
 
 
 
 
 
 
 
 
 
63
  echo '</p>';
64
  echo '</div>';
65
 
66
  echo '<div class="qm-section">';
67
- echo '<h2>' . esc_html__( 'Peak Memory Usage', 'query-monitor' ) . '</h2>';
68
  echo '<p class="qm-item">';
69
 
70
  if ( empty( $data['memory'] ) ) {
@@ -75,14 +90,25 @@ class QM_Output_Html_Overview extends QM_Output_Html {
75
  __( '%s kB', 'query-monitor' ),
76
  number_format_i18n( $data['memory'] / 1024 )
77
  ) );
78
- echo '<br><span class="qm-info">';
79
- echo esc_html( sprintf(
80
- /* translators: 1: Percentage of memory limit used, 2: Memory limit in kilobytes */
81
- __( '%1$s%% of %2$s kB limit', 'query-monitor' ),
82
- number_format_i18n( $data['memory_usage'], 1 ),
83
- number_format_i18n( $data['memory_limit'] / 1024 )
84
- ) );
85
- echo '</span>';
 
 
 
 
 
 
 
 
 
 
 
86
  }
87
 
88
  echo '</p>';
@@ -90,14 +116,14 @@ class QM_Output_Html_Overview extends QM_Output_Html {
90
 
91
  if ( isset( $db_query_num ) ) {
92
  echo '<div class="qm-section">';
93
- echo '<h2>' . esc_html__( 'Database Query Time', 'query-monitor' ) . '</h2>';
94
  echo '<p class="qm-item">';
95
  echo esc_html( number_format_i18n( $db_queries_data['total_time'], 4 ) );
96
  echo '</p>';
97
  echo '</div>';
98
 
99
  echo '<div class="qm-section">';
100
- echo '<h2>' . esc_html__( 'Database Queries', 'query-monitor' ) . '</h2>';
101
  echo '<p class="qm-item">';
102
 
103
  if ( ! isset( $db_query_num['SELECT'] ) || count( $db_query_num ) > 1 ) {
@@ -118,7 +144,7 @@ class QM_Output_Html_Overview extends QM_Output_Html {
118
  }
119
 
120
  echo '<div class="qm-section">';
121
- echo '<h2>' . esc_html__( 'Object Cache', 'query-monitor' ) . '</h2>';
122
  echo '<p class="qm-item">';
123
 
124
  if ( isset( $cache_hit_percentage ) ) {
@@ -131,7 +157,7 @@ class QM_Output_Html_Overview extends QM_Output_Html {
131
  ) );
132
  if ( $cache_data['display_hit_rate_warning'] ) {
133
  printf(
134
- '<br><a href="%s">%s</a>',
135
  'https://github.com/johnbillion/query-monitor/wiki/Cache-Hit-Rate',
136
  esc_html__( 'Why is this value 100%?', 'query-monitor' )
137
  );
@@ -139,15 +165,31 @@ class QM_Output_Html_Overview extends QM_Output_Html {
139
  if ( $cache_data['ext_object_cache'] ) {
140
  echo '<br><span class="qm-info">';
141
  printf(
142
- '<a href="%s">%s</a>',
143
  esc_url( network_admin_url( 'plugins.php?plugin_status=dropins' ) ),
144
  esc_html__( 'External object cache in use', 'query-monitor' )
145
  );
146
  echo '</span>';
147
  } else {
148
- echo '<br><span class="qm-warn">';
149
  echo esc_html__( 'External object cache not in use', 'query-monitor' );
150
  echo '</span>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
152
  } else {
153
  echo '<span class="qm-info">';
@@ -158,8 +200,7 @@ class QM_Output_Html_Overview extends QM_Output_Html {
158
  echo '</p>';
159
  echo '</div>';
160
 
161
- echo '</div>';
162
- echo '</div>';
163
  }
164
 
165
  public function admin_title( array $title ) {
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 ) );
59
+
60
+ if ( $data['time_limit'] > 0 ) {
61
+ if ( $data['display_time_usage_warning'] ) {
62
+ echo '<br><span class="qm-warn">';
63
+ } else {
64
+ echo '<br><span class="qm-info">';
65
+ }
66
+ echo esc_html( sprintf(
67
+ /* translators: 1: Percentage of time limit used, 2: Time limit in seconds */
68
+ __( '%1$s%% of %2$ss limit', 'query-monitor' ),
69
+ number_format_i18n( $data['time_usage'], 1 ),
70
+ number_format_i18n( $data['time_limit'] )
71
+ ) );
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
 
85
  if ( empty( $data['memory'] ) ) {
90
  __( '%s kB', 'query-monitor' ),
91
  number_format_i18n( $data['memory'] / 1024 )
92
  ) );
93
+
94
+ if ( $data['memory_limit'] > 0 ) {
95
+ if ( $data['display_memory_usage_warning'] ) {
96
+ echo '<br><span class="qm-warn">';
97
+ } else {
98
+ echo '<br><span class="qm-info">';
99
+ }
100
+ echo esc_html( sprintf(
101
+ /* translators: 1: Percentage of memory limit used, 2: Memory limit in kilobytes */
102
+ __( '%1$s%% of %2$s kB limit', 'query-monitor' ),
103
+ number_format_i18n( $data['memory_usage'], 1 ),
104
+ number_format_i18n( $data['memory_limit'] / 1024 )
105
+ ) );
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>';
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
 
129
  if ( ! isset( $db_query_num['SELECT'] ) || count( $db_query_num ) > 1 ) {
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
 
150
  if ( isset( $cache_hit_percentage ) ) {
157
  ) );
158
  if ( $cache_data['display_hit_rate_warning'] ) {
159
  printf(
160
+ '<br><a href="%s" class="qm-external-link">%s</a>',
161
  'https://github.com/johnbillion/query-monitor/wiki/Cache-Hit-Rate',
162
  esc_html__( 'Why is this value 100%?', 'query-monitor' )
163
  );
165
  if ( $cache_data['ext_object_cache'] ) {
166
  echo '<br><span class="qm-info">';
167
  printf(
168
+ '<a href="%s" class="qm-link">%s</a>',
169
  esc_url( network_admin_url( 'plugins.php?plugin_status=dropins' ) ),
170
  esc_html__( 'External object cache in use', 'query-monitor' )
171
  );
172
  echo '</span>';
173
  } else {
174
+ echo '<br><span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
175
  echo esc_html__( 'External object cache not in use', 'query-monitor' );
176
  echo '</span>';
177
+
178
+ $potentials = array_filter( $cache_data['extensions'] );
179
+
180
+ if ( ! empty( $potentials ) ) {
181
+ echo '<ul>';
182
+ foreach ( $potentials as $name => $value ) {
183
+ echo '<li class="qm-warn">';
184
+ echo esc_html( sprintf(
185
+ /* translators: %s: PHP extension name */
186
+ __( 'The %s extension for PHP is installed but is not in use by WordPress', 'query-monitor' ),
187
+ $name
188
+ ) );
189
+ echo '</li>';
190
+ }
191
+ echo '</ul>';
192
+ }
193
  }
194
  } else {
195
  echo '<span class="qm-info">';
200
  echo '</p>';
201
  echo '</div>';
202
 
203
+ $this->after_non_tabular_output();
 
204
  }
205
 
206
  public function admin_title( array $title ) {
output/html/php_errors.php CHANGED
@@ -22,18 +22,28 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
22
  return;
23
  }
24
 
25
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
26
- echo '<table>';
27
- echo '<caption class="screen-reader-text">' . esc_html( 'PHP Errors', 'query-monitor' ) . '</caption>';
 
 
 
 
 
 
 
 
 
28
  echo '<thead>';
29
  echo '<tr>';
30
- echo '<th scope="col"><span class="dashicons"></span>' . esc_html__( 'Level', 'query-monitor' ) . '</th>';
31
- echo '<th scope="col">' . esc_html__( 'Message', 'query-monitor' ) . '</th>';
 
 
32
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Count', 'query-monitor' ) . '</th>';
33
  echo '<th scope="col">' . esc_html__( 'Location', 'query-monitor' ) . '</th>';
34
- echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
35
  echo '<th scope="col" class="qm-filterable-column">';
36
- echo $this->build_filter( 'component', $data['components'], __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
37
  echo '</th>';
38
  echo '</tr>';
39
  echo '</thead>';
@@ -43,14 +53,16 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
43
  foreach ( $this->collector->types as $error_group => $error_types ) {
44
  foreach ( $error_types as $type => $title ) {
45
 
46
- if ( isset( $data[ $error_group ][ $type ] ) ) {
 
 
47
 
48
  foreach ( $data[ $error_group ][ $type ] as $error ) {
49
 
50
- $component = $error->trace->get_component();
51
- $message = wp_strip_all_tags( $error->message );
52
  $row_attr = array();
53
  $row_attr['data-qm-component'] = $component->name;
 
54
 
55
  if ( 'core' !== $component->context ) {
56
  $row_attr['data-qm-component'] .= ' non-core';
@@ -71,7 +83,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
71
  }
72
 
73
  echo '<tr ' . $attr . 'class="' . esc_attr( $class ) . '">'; // WPCS: XSS ok.
74
- echo '<th scope="row">';
75
 
76
  if ( $is_warning ) {
77
  echo '<span class="dashicons dashicons-warning" aria-hidden="true"></span>';
@@ -80,16 +92,13 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
80
  }
81
 
82
  echo esc_html( $title );
83
- echo '</th>';
84
-
85
- echo '<td class="qm-ltr">' . esc_html( $message ) . '</td>';
86
- echo '<td class="qm-num">' . esc_html( number_format_i18n( $error->calls ) ) . '</td>';
87
- echo '<td class="qm-ltr">';
88
- echo self::output_filename( $error->filename . ':' . $error->line, $error->file, $error->line, true ); // WPCS: XSS ok.
89
  echo '</td>';
90
 
 
 
 
91
  $stack = array();
92
- $filtered_trace = $error->trace->get_display_trace();
93
 
94
  // debug_backtrace() (used within QM_Backtrace) doesn't like being used within an error handler so
95
  // we need to handle its somewhat unreliable stack trace items.
@@ -99,14 +108,12 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
99
  if ( isset( $item['file'] ) && isset( $item['line'] ) ) {
100
  $stack[] = self::output_filename( $item['display'], $item['file'], $item['line'] );
101
  } elseif ( 0 === $i ) {
102
- $stack[] = self::output_filename( $item['display'], $error->file, $error->line );
103
  } else {
104
  $stack[] = $item['display'] . '<br><span class="qm-info qm-supplemental"><em>' . __( 'Unknown location', 'query-monitor' ) . '</em></span>';
105
  }
106
  }
107
 
108
- $caller_name = array_pop( $stack );
109
-
110
  echo '<td class="qm-row-caller qm-row-stack qm-nowrap qm-ltr qm-has-toggle"><ol class="qm-toggler qm-numbered">';
111
 
112
  echo self::build_toggler(); // WPCS: XSS ok;
@@ -114,7 +121,9 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
114
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
115
  }
116
 
117
- echo "<li>{$caller_name}</li>"; // WPCS: XSS ok.
 
 
118
 
119
  echo '</ol></td>';
120
 
@@ -127,13 +136,11 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
127
  echo '</tr>';
128
  }
129
  }
130
- }
131
  }
132
 
133
  echo '</tbody>';
134
- echo '</table>';
135
- echo '</div>';
136
 
 
137
  }
138
 
139
  public function admin_class( array $class ) {
22
  return;
23
  }
24
 
25
+ $levels = array(
26
+ 'Warning',
27
+ 'Notice',
28
+ 'Strict',
29
+ 'Deprecated',
30
+ );
31
+ $components = $data['components'];
32
+
33
+ usort( $components, 'strcasecmp' );
34
+
35
+ $this->before_tabular_output();
36
+
37
  echo '<thead>';
38
  echo '<tr>';
39
+ echo '<th scope="col" class="qm-filterable-column">';
40
+ echo $this->build_filter( 'type', $levels, __( 'Level', 'query-monitor' ) ); // WPCS: XSS ok.
41
+ echo '</th>';
42
+ echo '<th scope="col" class="qm-col-message">' . esc_html__( 'Message', 'query-monitor' ) . '</th>';
43
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Count', 'query-monitor' ) . '</th>';
44
  echo '<th scope="col">' . esc_html__( 'Location', 'query-monitor' ) . '</th>';
 
45
  echo '<th scope="col" class="qm-filterable-column">';
46
+ echo $this->build_filter( 'component', $components, __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
47
  echo '</th>';
48
  echo '</tr>';
49
  echo '</thead>';
53
  foreach ( $this->collector->types as $error_group => $error_types ) {
54
  foreach ( $error_types as $type => $title ) {
55
 
56
+ if ( ! isset( $data[ $error_group ][ $type ] ) ) {
57
+ continue;
58
+ }
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
 
67
  if ( 'core' !== $component->context ) {
68
  $row_attr['data-qm-component'] .= ' non-core';
83
  }
84
 
85
  echo '<tr ' . $attr . 'class="' . esc_attr( $class ) . '">'; // WPCS: XSS ok.
86
+ echo '<td scope="row" class="qm-nowrap">';
87
 
88
  if ( $is_warning ) {
89
  echo '<span class="dashicons dashicons-warning" aria-hidden="true"></span>';
92
  }
93
 
94
  echo esc_html( $title );
 
 
 
 
 
 
95
  echo '</td>';
96
 
97
+ echo '<td class="qm-ltr">' . esc_html( $error['message'] ) . '</td>';
98
+ echo '<td class="qm-num">' . esc_html( number_format_i18n( $error['calls'] ) ) . '</td>';
99
+
100
  $stack = array();
101
+ $filtered_trace = $error['trace']->get_display_trace();
102
 
103
  // debug_backtrace() (used within QM_Backtrace) doesn't like being used within an error handler so
104
  // we need to handle its somewhat unreliable stack trace items.
108
  if ( isset( $item['file'] ) && isset( $item['line'] ) ) {
109
  $stack[] = self::output_filename( $item['display'], $item['file'], $item['line'] );
110
  } elseif ( 0 === $i ) {
111
+ $stack[] = self::output_filename( $item['display'], $error['file'], $error['line'] );
112
  } else {
113
  $stack[] = $item['display'] . '<br><span class="qm-info qm-supplemental"><em>' . __( 'Unknown location', 'query-monitor' ) . '</em></span>';
114
  }
115
  }
116
 
 
 
117
  echo '<td class="qm-row-caller qm-row-stack qm-nowrap qm-ltr qm-has-toggle"><ol class="qm-toggler qm-numbered">';
118
 
119
  echo self::build_toggler(); // WPCS: XSS ok;
121
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
122
  }
123
 
124
+ echo '<li>';
125
+ echo self::output_filename( $error['filename'] . ':' . $error['line'], $error['file'], $error['line'], true ); // WPCS: XSS ok.
126
+ echo '</li>';
127
 
128
  echo '</ol></td>';
129
 
136
  echo '</tr>';
137
  }
138
  }
 
139
  }
140
 
141
  echo '</tbody>';
 
 
142
 
143
+ $this->after_tabular_output();
144
  }
145
 
146
  public function admin_class( array $class ) {
output/html/request.php CHANGED
@@ -18,8 +18,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
18
 
19
  $db_queries = QM_Collectors::get( 'db_queries' );
20
 
21
- echo '<div class="qm qm-non-tabular" id="' . esc_attr( $this->collector->id() ) . '">';
22
- echo '<div class="qm-boxed qm-boxed-wrap">';
23
 
24
  foreach ( array(
25
  'request' => __( 'Request', 'query-monitor' ),
@@ -42,7 +41,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
42
  }
43
 
44
  echo '<div class="qm-section">';
45
- echo '<h2>' . esc_html( $name ) . '</h2>';
46
  echo '<p class="qm-ltr"><code>' . $value . '</code></p>'; // WPCS: XSS ok.
47
  echo '</div>';
48
  }
@@ -53,7 +52,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
53
 
54
  if ( ! empty( $data['matching_rewrites'] ) ) {
55
  echo '<div class="qm-section">';
56
- echo '<h2>' . esc_html__( 'All Matching Rewrite Rules', 'query-monitor' ) . '</h2>';
57
  echo '<table>';
58
 
59
  foreach ( $data['matching_rewrites'] as $rule => $query ) {
@@ -72,21 +71,20 @@ class QM_Output_Html_Request extends QM_Output_Html {
72
  }
73
 
74
  echo '<div class="qm-section">';
75
- echo '<h2>';
76
  esc_html_e( 'Query Vars', 'query-monitor' );
 
77
 
78
  if ( $db_queries ) {
79
  $db_queries_data = $db_queries->get_data();
80
  if ( ! empty( $db_queries_data['dbs']['$wpdb']->has_main_query ) ) {
81
  printf(
82
- ' <a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="qm-main-query">%s</a>',
83
  esc_html__( 'View Main Query', 'query-monitor' )
84
  );
85
  }
86
  }
87
 
88
- echo '</h2>';
89
-
90
  if ( ! empty( $data['qvars'] ) ) {
91
 
92
  echo '<table>';
@@ -96,9 +94,9 @@ class QM_Output_Html_Request extends QM_Output_Html {
96
  echo '<tr>';
97
 
98
  if ( isset( $data['plugin_qvars'][ $var ] ) ) {
99
- echo '<td class="qm-ltr"><span class="qm-current">' . esc_html( $var ) . '</span></td>';
100
  } else {
101
- echo '<td class="qm-ltr">' . esc_html( $var ) . '</td>';
102
  }
103
 
104
  if ( is_array( $value ) or is_object( $value ) ) {
@@ -123,7 +121,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
123
  echo '</div>';
124
 
125
  echo '<div class="qm-section">';
126
- echo '<h2>' . esc_html__( 'Queried Object', 'query-monitor' ) . '</h2>';
127
 
128
  if ( ! empty( $data['queried_object'] ) ) {
129
  printf( // WPCS: XSS ok.
@@ -138,7 +136,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
138
  echo '</div>';
139
 
140
  echo '<div class="qm-section">';
141
- echo '<h2>' . esc_html__( 'Current User', 'query-monitor' ) . '</h2>';
142
 
143
  if ( ! empty( $data['user']['data'] ) ) {
144
  printf( // WPCS: XSS ok.
@@ -153,7 +151,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
153
 
154
  if ( ! empty( $data['multisite'] ) ) {
155
  echo '<div class="qm-section">';
156
- echo '<h2>' . esc_html__( 'Multisite', 'query-monitor' ) . '</h2>';
157
 
158
  foreach ( $data['multisite'] as $var => $value ) {
159
  printf( // WPCS: XSS ok.
@@ -165,8 +163,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
165
  echo '</div>';
166
  }
167
 
168
- echo '</div>';
169
- echo '</div>';
170
  }
171
 
172
  public function admin_menu( array $menu ) {
18
 
19
  $db_queries = QM_Collectors::get( 'db_queries' );
20
 
21
+ $this->before_non_tabular_output();
 
22
 
23
  foreach ( array(
24
  'request' => __( 'Request', 'query-monitor' ),
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
  }
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
 
58
  foreach ( $data['matching_rewrites'] as $rule => $query ) {
71
  }
72
 
73
  echo '<div class="qm-section">';
74
+ echo '<h3>';
75
  esc_html_e( 'Query Vars', 'query-monitor' );
76
+ echo '</h3>';
77
 
78
  if ( $db_queries ) {
79
  $db_queries_data = $db_queries->get_data();
80
  if ( ! empty( $db_queries_data['dbs']['$wpdb']->has_main_query ) ) {
81
  printf(
82
+ '<p><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="qm-main-query">%s</a></p>',
83
  esc_html__( 'View Main Query', 'query-monitor' )
84
  );
85
  }
86
  }
87
 
 
 
88
  if ( ! empty( $data['qvars'] ) ) {
89
 
90
  echo '<table>';
94
  echo '<tr>';
95
 
96
  if ( isset( $data['plugin_qvars'][ $var ] ) ) {
97
+ echo '<th scope="row" class="qm-ltr"><span class="qm-current">' . esc_html( $var ) . '</span></td>';
98
  } else {
99
+ echo '<th scope="row" class="qm-ltr">' . esc_html( $var ) . '</td>';
100
  }
101
 
102
  if ( is_array( $value ) or is_object( $value ) ) {
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'] ) ) {
127
  printf( // WPCS: XSS ok.
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'] ) ) {
142
  printf( // WPCS: XSS ok.
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 ) {
157
  printf( // WPCS: XSS ok.
163
  echo '</div>';
164
  }
165
 
166
+ $this->after_non_tabular_output();
 
167
  }
168
 
169
  public function admin_menu( array $menu ) {
output/html/theme.php CHANGED
@@ -20,11 +20,10 @@ class QM_Output_Html_Theme extends QM_Output_Html {
20
  return;
21
  }
22
 
23
- echo '<div class="qm qm-non-tabular" id="' . esc_attr( $this->collector->id() ) . '">';
24
- echo '<div class="qm-boxed qm-boxed-wrap">';
25
 
26
  echo '<div class="qm-section">';
27
- echo '<h2>' . esc_html__( 'Template File', 'query-monitor' ) . '</h2>';
28
 
29
  if ( ! empty( $data['template_path'] ) ) {
30
  if ( $data['is_child_theme'] ) {
@@ -40,13 +39,13 @@ class QM_Output_Html_Theme extends QM_Output_Html {
40
 
41
  if ( ! empty( $data['template_hierarchy'] ) ) {
42
  echo '<div class="qm-section">';
43
- echo '<h2>' . esc_html__( 'Template Hierarchy', 'query-monitor' ) . '</h2>';
44
  echo '<ol class="qm-ltr qm-numbered"><li>' . implode( '</li><li>', array_map( 'esc_html', $data['template_hierarchy'] ) ) . '</li></ol>';
45
  echo '</div>';
46
  }
47
 
48
  echo '<div class="qm-section">';
49
- echo '<h2>' . esc_html__( 'Template Parts', 'query-monitor' ) . '</h2>';
50
 
51
  if ( ! empty( $data['template_parts'] ) ) {
52
 
@@ -72,7 +71,7 @@ class QM_Output_Html_Theme extends QM_Output_Html {
72
 
73
  if ( ! empty( $data['timber_files'] ) ) {
74
  echo '<div class="qm-section">';
75
- echo '<h2>' . esc_html__( 'Timber Files', 'query-monitor' ) . '</h2>';
76
  echo '<ul class="qm-ltr">';
77
 
78
  foreach ( $data['timber_files'] as $filename ) {
@@ -84,7 +83,7 @@ class QM_Output_Html_Theme extends QM_Output_Html {
84
  }
85
 
86
  echo '<div class="qm-section">';
87
- echo '<h2>' . esc_html__( 'Theme', 'query-monitor' ) . '</h2>';
88
  echo '<p>' . esc_html( $data['stylesheet'] ) . '</p>';
89
 
90
  if ( $data['is_child_theme'] ) {
@@ -97,7 +96,7 @@ class QM_Output_Html_Theme extends QM_Output_Html {
97
  if ( ! empty( $data['body_class'] ) ) {
98
  echo '<div class="qm-section">';
99
 
100
- echo '<h2>' . esc_html__( 'Body Classes', 'query-monitor' ) . '</h2>';
101
  echo '<ul class="qm-ltr">';
102
 
103
  foreach ( $data['body_class'] as $class ) {
@@ -108,8 +107,7 @@ class QM_Output_Html_Theme extends QM_Output_Html {
108
  echo '</div>';
109
  }
110
 
111
- echo '</div>';
112
- echo '</div>';
113
  }
114
 
115
  public function admin_menu( array $menu ) {
@@ -140,8 +138,8 @@ class QM_Output_Html_Theme extends QM_Output_Html {
140
  }
141
 
142
  function register_qm_output_html_theme( array $output, QM_Collectors $collectors ) {
143
- if ( ! is_admin() && $collector = QM_Collectors::get( 'theme' ) ) {
144
- $output['theme'] = new QM_Output_Html_Theme( $collector );
145
  }
146
  return $output;
147
  }
20
  return;
21
  }
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'] ) {
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'] ) ) {
51
 
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
 
77
  foreach ( $data['timber_files'] as $filename ) {
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'] ) {
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">';
101
 
102
  foreach ( $data['body_class'] as $class ) {
107
  echo '</div>';
108
  }
109
 
110
+ $this->after_non_tabular_output();
 
111
  }
112
 
113
  public function admin_menu( array $menu ) {
138
  }
139
 
140
  function register_qm_output_html_theme( array $output, QM_Collectors $collectors ) {
141
+ if ( ! is_admin() && $collector = QM_Collectors::get( 'response' ) ) {
142
+ $output['response'] = new QM_Output_Html_Theme( $collector );
143
  }
144
  return $output;
145
  }
output/html/timing.php CHANGED
@@ -20,10 +20,7 @@ class QM_Output_Html_Timing extends QM_Output_Html {
20
  return;
21
  }
22
 
23
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
24
- echo '<table>';
25
-
26
- echo '<caption class="screen-reader-text">' . esc_html__( 'Function Timing', 'query-monitor' ) . '</caption>';
27
 
28
  echo '<thead>';
29
  echo '<tr>';
@@ -140,9 +137,8 @@ class QM_Output_Html_Timing extends QM_Output_Html {
140
  }
141
 
142
  echo '</tbody>';
143
- echo '</table>';
144
- echo '</div>';
145
 
 
146
  }
147
 
148
  public function admin_menu( array $menu ) {
20
  return;
21
  }
22
 
23
+ $this->before_tabular_output();
 
 
 
24
 
25
  echo '<thead>';
26
  echo '<tr>';
137
  }
138
 
139
  echo '</tbody>';
 
 
140
 
141
+ $this->after_tabular_output();
142
  }
143
 
144
  public function admin_menu( array $menu ) {
output/html/transients.php CHANGED
@@ -16,18 +16,15 @@ class QM_Output_Html_Transients extends QM_Output_Html {
16
 
17
  $data = $this->collector->get_data();
18
 
19
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
20
-
21
  if ( ! empty( $data['trans'] ) ) {
22
 
23
- echo '<table>';
24
- echo '<caption class="screen-reader-text">' . esc_html__( 'Transient Updates', 'query-monitor' ) . '</caption>';
25
 
26
  echo '<thead>';
27
  echo '<tr>';
28
  echo '<th scope="col">' . esc_html__( 'Updated Transient', 'query-monitor' ) . '</th>';
29
  if ( is_multisite() ) {
30
- echo '<th>' . esc_html_x( 'Type', 'transient type', 'query-monitor' ) . '</th>';
31
  }
32
  echo '<th scope="col">' . esc_html__( 'Expiration', 'query-monitor' ) . '</th>';
33
  echo '<th scope="col">' . esc_html_x( 'Size', 'size of transient value', 'query-monitor' ) . '</th>';
@@ -53,25 +50,26 @@ class QM_Output_Html_Transients extends QM_Output_Html {
53
  );
54
  if ( is_multisite() ) {
55
  printf(
56
- '<td class="qm-ltr">%s</td>',
57
  esc_html( $row['type'] )
58
  );
59
  }
60
 
61
  if ( 0 === $row['expiration'] ) {
62
  printf(
63
- '<td><em>%s</em></td>',
64
  esc_html__( 'none', 'query-monitor' )
65
  );
66
  } else {
67
  printf(
68
- '<td>%s</td>',
69
- esc_html( $row['expiration'] )
 
70
  );
71
  }
72
 
73
  printf(
74
- '<td>~%s</td>',
75
  esc_html( size_format( $row['size'] ) )
76
  );
77
 
@@ -105,19 +103,15 @@ class QM_Output_Html_Transients extends QM_Output_Html {
105
 
106
  }
107
 
108
- echo '</tbody>';
109
- echo '</table>';
110
-
111
  } else {
 
112
 
113
- echo '<div class="qm-none">';
114
- echo '<p>' . esc_html__( 'None', 'query-monitor' ) . '</p>';
115
- echo '</div>';
116
 
 
117
  }
118
-
119
- echo '</div>';
120
-
121
  }
122
 
123
  public function admin_menu( array $menu ) {
16
 
17
  $data = $this->collector->get_data();
18
 
 
 
19
  if ( ! empty( $data['trans'] ) ) {
20
 
21
+ $this->before_tabular_output();
 
22
 
23
  echo '<thead>';
24
  echo '<tr>';
25
  echo '<th scope="col">' . esc_html__( 'Updated Transient', 'query-monitor' ) . '</th>';
26
  if ( is_multisite() ) {
27
+ echo '<th scope="col">' . esc_html_x( 'Type', 'transient type', 'query-monitor' ) . '</th>';
28
  }
29
  echo '<th scope="col">' . esc_html__( 'Expiration', 'query-monitor' ) . '</th>';
30
  echo '<th scope="col">' . esc_html_x( 'Size', 'size of transient value', 'query-monitor' ) . '</th>';
50
  );
51
  if ( is_multisite() ) {
52
  printf(
53
+ '<td class="qm-ltr qm-nowrap">%s</td>',
54
  esc_html( $row['type'] )
55
  );
56
  }
57
 
58
  if ( 0 === $row['expiration'] ) {
59
  printf(
60
+ '<td class="qm-nowrap"><em>%s</em></td>',
61
  esc_html__( 'none', 'query-monitor' )
62
  );
63
  } else {
64
  printf(
65
+ '<td class="qm-nowrap">%s <span class="qm-info">(~%s)</span></td>',
66
+ esc_html( $row['expiration'] ),
67
+ esc_html( human_time_diff( 0, $row['expiration'] ) )
68
  );
69
  }
70
 
71
  printf(
72
+ '<td class="qm-nowrap">~%s</td>',
73
  esc_html( size_format( $row['size'] ) )
74
  );
75
 
103
 
104
  }
105
 
106
+ $this->after_tabular_output();
 
 
107
  } else {
108
+ $this->before_non_tabular_output();
109
 
110
+ $notice = __( 'No transients set.', 'query-monitor' );
111
+ echo $this->build_notice( $notice ); // WPCS: XSS ok.
 
112
 
113
+ $this->after_non_tabular_output();
114
  }
 
 
 
115
  }
116
 
117
  public function admin_menu( array $menu ) {
query-monitor.php CHANGED
@@ -9,11 +9,11 @@
9
  * @license GPL v2 or later
10
  *
11
  * Plugin Name: Query Monitor
12
- * Description: The Developer Tools panel for WordPress.
13
- * Version: 3.0.1
14
- * Plugin URI: https://github.com/johnbillion/query-monitor
15
  * Author: John Blackbourn & contributors
16
- * Author URI: https://github.com/johnbillion/query-monitor/graphs/contributors
17
  * Text Domain: query-monitor
18
  * Domain Path: /languages/
19
  * Requires PHP: 5.3.6
@@ -36,7 +36,7 @@ $qm_dir = dirname( __FILE__ );
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' ) as $qm_class ) {
40
  require_once "{$qm_dir}/classes/{$qm_class}.php";
41
  }
42
 
9
  * @license GPL v2 or later
10
  *
11
  * Plugin Name: Query Monitor
12
+ * Description: The Developer Tools Panel for WordPress.
13
+ * Version: 3.1.0
14
+ * Plugin URI: https://querymonitor.com/
15
  * Author: John Blackbourn & contributors
16
+ * Author URI: https://querymonitor.com/
17
  * Text Domain: query-monitor
18
  * Domain Path: /languages/
19
  * Requires PHP: 5.3.6
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";
41
  }
42
 
readme.txt CHANGED
@@ -1,21 +1,21 @@
1
  === Query Monitor ===
2
  Contributors: johnbillion
3
- Tags: ajax, debug, debug-bar, debugging, development, developer, performance, profiler, profiling, queries, query monitor, rest-api
4
  Requires at least: 3.7
5
  Tested up to: 4.9
6
- Stable tag: 3.0.1
7
  License: GPLv2 or later
8
  Requires PHP: 5.3
9
 
10
- 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 not available in other debugging plugins, including 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. It adds an admin toolbar menu showing an overview of the current page, with complete data shown in a panel once you select an item.
17
 
18
- For complete information, please see [Query Monitor's GitHub repo](https://github.com/johnbillion/query-monitor).
19
 
20
  Here's an overview of some of what's shown:
21
 
@@ -76,9 +76,9 @@ Filtering queries by component or calling function makes it easy to see which pl
76
 
77
  * Whenever a redirect occurs, Query Monitor adds an `X-QM-Redirect` HTTP header containing the call stack, so you can use your favourite HTTP inspector or browser developer tools to easily trace where a redirect has come from
78
 
79
- = AJAX =
80
 
81
- The response from any jQuery AJAX request on the page will contain various debugging information in its headers. Any errors also get output to the developer console. No hooking required.
82
 
83
  Currently this includes PHP errors and some overview information such as memory usage, but this will be built upon in future versions.
84
 
@@ -98,11 +98,7 @@ In addition to this, you can set an authentication cookie which allows you to vi
98
 
99
  Query Monitor does not persistently store any of the data that it collects. It does not send data to any third party, nor does it include any third party resources.
100
 
101
- Query Monitor implements an optional browser cookie that allows users to view Query Monitor output when not logged in, or when logged in as another user who cannot usually view Query Monitor's output. This cookie can be set and cleared from the Settings panel in Query Monitor. This cookie operates using the same mechanism as the authentication cookies in WordPress core, and therefore it contains the user's `user_login` field in plain text which should be treated as potentially personally identifiable information. The name of the cookie is `query_monitor_{hash}` where `{hash}` is an identifier unique to the installation of WordPress.
102
-
103
- Query Monitor stores some user preferences in the browser's Local Storage. It stores the ID of the most recently accessed panel and the height of the panel if the user has resized it. This data is stored using the browser's `localStorage` API, does not get sent with HTTP requests, and does not contain any personally identifiable information.
104
-
105
- Please note that in a future version of Query Monitor, opt-in features may be introduced which allow a user to choose to persistently store data and/or send data to a third party service. Such features will only ever be opt-in.
106
 
107
  == Screenshots ==
108
 
1
  === Query Monitor ===
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.0
7
  License: GPLv2 or later
8
  Requires PHP: 5.3
9
 
10
+ 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
 
18
+ For complete information, please see [the Query Monitor website](https://querymonitor.com/).
19
 
20
  Here's an overview of some of what's shown:
21
 
76
 
77
  * Whenever a redirect occurs, Query Monitor adds an `X-QM-Redirect` HTTP header containing the call stack, so you can use your favourite HTTP inspector or browser developer tools to easily trace where a redirect has come from
78
 
79
+ = Ajax =
80
 
81
+ The response from any jQuery Ajax request on the page will contain various debugging information in its headers. Any errors also get output to the developer console. No hooking required.
82
 
83
  Currently this includes PHP errors and some overview information such as memory usage, but this will be built upon in future versions.
84
 
98
 
99
  Query Monitor does not persistently store any of the data that it collects. It does not send data to any third party, nor does it include any third party resources.
100
 
101
+ [Query Monitor's full privacy statement can be found here](https://github.com/johnbillion/query-monitor/wiki/Privacy-Statement).
 
 
 
 
102
 
103
  == Screenshots ==
104