Query Monitor - Version 3.0.0

Version Description

Download this release

Release Info

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

Code changes from version 2.17.0 to 3.0.0

Files changed (70) hide show
  1. assets/query-monitor.css +585 -392
  2. assets/query-monitor.js +371 -299
  3. classes/Activation.php +29 -14
  4. classes/Backtrace.php +44 -29
  5. classes/Collector.php +16 -16
  6. classes/Collectors.php +17 -14
  7. classes/Dispatcher.php +6 -24
  8. classes/Dispatchers.php +5 -14
  9. classes/Output.php +14 -14
  10. classes/Plugin.php +16 -14
  11. classes/QueryMonitor.php +12 -15
  12. classes/Timer.php +92 -0
  13. classes/Util.php +8 -14
  14. classes/debug_bar.php +5 -14
  15. classes/debug_bar_panel.php +5 -14
  16. collectors/admin.php +9 -20
  17. collectors/assets.php +24 -18
  18. collectors/cache.php +5 -14
  19. collectors/caps.php +8 -14
  20. collectors/conditionals.php +5 -14
  21. collectors/db_callers.php +5 -14
  22. collectors/db_components.php +5 -14
  23. collectors/db_dupes.php +5 -14
  24. collectors/db_queries.php +21 -20
  25. collectors/debug_bar.php +9 -18
  26. collectors/environment.php +57 -33
  27. collectors/hooks.php +20 -26
  28. collectors/http.php +49 -14
  29. collectors/languages.php +5 -14
  30. collectors/overview.php +5 -14
  31. collectors/php_errors.php +199 -33
  32. collectors/redirects.php +5 -14
  33. collectors/request.php +32 -25
  34. collectors/rewrites.php +0 -63
  35. collectors/theme.php +5 -14
  36. collectors/timing.php +90 -0
  37. collectors/transients.php +6 -15
  38. composer.json +5 -4
  39. dispatchers/AJAX.php +5 -14
  40. dispatchers/Html.php +134 -71
  41. dispatchers/REST.php +5 -14
  42. dispatchers/Redirect.php +5 -14
  43. output/Headers.php +5 -14
  44. output/Html.php +92 -46
  45. output/headers/overview.php +5 -14
  46. output/headers/php_errors.php +6 -16
  47. output/headers/redirects.php +5 -15
  48. output/html/admin.php +33 -47
  49. output/html/assets.php +93 -86
  50. output/html/caps.php +49 -22
  51. output/html/conditionals.php +37 -47
  52. output/html/db_callers.php +29 -43
  53. output/html/db_components.php +47 -76
  54. output/html/db_dupes.php +8 -19
  55. output/html/db_queries.php +61 -74
  56. output/html/debug_bar.php +5 -25
  57. output/html/environment.php +68 -79
  58. output/html/hooks.php +43 -36
  59. output/html/http.php +146 -69
  60. output/html/languages.php +25 -28
  61. output/html/overview.php +55 -54
  62. output/html/php_errors.php +128 -67
  63. output/html/request.php +66 -117
  64. output/html/rewrites.php +0 -77
  65. output/html/theme.php +54 -72
  66. output/html/timing.php +154 -0
  67. output/html/transients.php +12 -29
  68. query-monitor.php +18 -11
  69. readme.txt +148 -176
  70. wp-content/db.php +28 -24
assets/query-monitor.css CHANGED
@@ -13,6 +13,8 @@ GNU General Public License for more details.
13
 
14
  */
15
 
 
 
16
  #wpadminbar .quicklinks .menupop ul li.qm-true > a {
17
  color: #8c8 !important;
18
  }
@@ -60,13 +62,6 @@ GNU General Public License for more details.
60
  background-color: #c00;
61
  }
62
 
63
- .qm .qm-php-error-warning td,
64
- .qm .qm-php-error-warning th,
65
- .qm .qm-php-error-warning-suppressed td,
66
- .qm .qm-php-error-warning-suppressed th {
67
- color: #c00 !important;
68
- }
69
-
70
  #wpadminbar .qm-warning > a {
71
  color: #fff !important;
72
  }
@@ -110,7 +105,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
110
  }
111
 
112
  #wpadminbar #wp-admin-bar-query-monitor .ab-icon {
113
- font: 18px/44px 'Open Sans', sans-serif !important;
114
  width: auto !important;
115
  padding: 0 10px !important;
116
  color: #aaa !important;
@@ -128,248 +123,355 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
128
  }
129
  }
130
 
131
- #qm {
132
- clear: both !important;
133
- background: #eee !important;
134
- margin: 25px 0 0 !important;
135
- border-top: 1px solid #ccc !important;
136
- padding: 0 0 35px !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  text-align: left !important;
138
- min-width: 800px !important;
139
  display: none;
140
- position: relative !important;
141
  z-index: 99998 !important;
 
 
 
 
142
  }
143
 
144
- #qm.qm-show,
145
- #qm.qm-peek,
146
- .no-js #qm,
147
- .nojs #qm {
148
- display: block;
 
 
149
  }
150
 
151
- #qm.qm-peek .qm {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  display: none;
153
  }
154
 
155
- #qm:after {
156
- display: block !important;
157
- content: '' !important;
158
- clear: both !important;
159
- height: 0 !important;
160
  }
161
 
162
- body.wp-admin #qm {
163
- margin: 0 0 0 160px !important;
164
  }
165
 
166
- @media only screen and (max-width: 960px) {
167
- body.wp-admin.auto-fold #qm {
168
- margin-left: 36px !important;
169
- margin-right: 0 !important;
170
- }
171
  }
172
 
173
- body.wp-admin.folded #qm {
174
- margin-left: 36px !important;
 
 
 
 
175
  }
176
 
177
- @media screen and (max-width: 782px) {
178
- body.wp-admin.auto-fold #qm,
179
- body.wp-admin #qm {
180
- margin-left: 0 !important;
181
- }
182
  }
183
 
184
- #qm-wrapper {
185
- margin: 0 auto 60px !important;
186
  }
187
 
188
- #qm.qm-peek #qm-wrapper {
189
- margin: 0 auto !important;
190
  }
191
 
192
- #qm-title {
193
- color: #555d66 !important;
194
- font: 13px/15px 'Open Sans', Arial !important;
195
- margin: 35px 0 -15px !important;
196
  }
197
 
198
- #qm-title p {
199
- font-style: italic !important;
200
- margin: 0 20px !important;
201
  }
202
 
203
- #qm-title ul {
204
- margin: 10px 10px 0 !important;
205
- font-style: normal !important;
206
- font-weight: normal !important;
207
- font-size: 11px !important;
208
- line-height: 18px !important;
209
- font-family: Menlo, Monaco, Consolas, monospace !important;
210
- list-style: none !important;
211
  padding: 0 !important;
 
212
  }
213
 
214
- #qm-title li {
215
- display: inline-block !important;
216
- width: 24em !important;
217
- background: #fff !important;
218
- border: 1px solid #e0e0e0 !important;
219
- margin: 0 5px 5px 0 !important;
 
 
 
 
220
  }
221
 
222
- #qm-title li a {
223
  display: block !important;
224
- padding: 4px 7px !important;
225
- font: 13px/15px 'Open Sans', Arial !important;
 
 
 
 
 
226
  }
227
 
228
- .qm {
229
- margin: 0 0 -20px !important;
230
- padding: 40px 10px 0 !important;
231
- box-sizing: border-box !important;
232
- clear: both !important;
233
  }
234
 
235
- .qm-half {
236
- float: left !important;
237
- width: 50% !important;
238
- clear: none !important;
239
  }
240
 
241
- .qm-third {
242
- float: left !important;
243
- width: 33.33% !important;
244
- clear: none !important;
 
 
 
 
 
 
 
245
  }
246
 
247
- .qm-two-thirds {
248
- float: left !important;
249
- width: 66.66% !important;
250
- clear: none !important;
251
  }
252
 
253
- .qm:focus {
254
- outline: 0 !important;
255
  }
256
 
257
- #qm.qm-theme-twentysixteen .qm {
258
- padding-top: 65px !important;
259
- margin-bottom: -45px !important;
260
  }
261
 
262
- #qm.qm-theme-twentysixteen #qm-title {
263
- margin-bottom: -45px !important;
264
  }
265
 
266
- @media all and (max-width: 900px) {
267
- .qm-third,
268
- .qm-two-thirds,
269
- .qm-half {
270
- float: none !important;
271
- width: 100% !important;
272
- clear: both !important;
273
- }
 
 
 
 
 
 
 
274
  }
275
 
276
- .qm-clear {
277
- clear: left !important;
 
278
  }
279
 
280
- .qm table {
281
  color: #333 !important;
282
  border-collapse: collapse !important;
283
  box-shadow: none !important;
284
  width: 100% !important;
285
  table-layout: auto !important;
286
  margin: 0 !important;
 
 
 
 
 
 
 
287
  }
288
 
289
- #qm-conditionals table,
290
- #qm-overview table {
291
  table-layout: fixed !important;
292
  }
293
 
294
- .qm td,
295
- .qm th,
296
- .qm caption {
297
- background: #fff !important;
298
- color: #333 !important;
299
- box-sizing: border-box !important;
300
- text-align: left !important;
301
- font-style: normal !important;
302
- font-weight: normal !important;
303
- font-size: 11px !important;
304
- line-height: 18px !important;
305
- font-family: Menlo, Monaco, Consolas, monospace !important;
306
  border: 1px solid #e0e0e0 !important;
307
- padding: 5px 8px 4px !important;
308
- vertical-align: top !important;
309
- text-shadow: none !important;
310
- text-transform: none !important;
311
- -webkit-font-smoothing: auto !important;
312
- letter-spacing: normal !important;
313
  }
314
 
315
- .qm caption,
316
- .qm th[scope=col] {
317
- border-bottom-width: 0 !important;
318
- margin-bottom: 0 !important;
319
  }
320
 
321
- .qm caption {
322
- caption-side: top !important;
 
 
 
 
 
 
 
 
323
  }
324
 
325
- .qm tbody.qm-group:hover th,
326
- .qm tbody tr:hover th,
327
- .qm tbody tr:hover td {
328
- background: #f7f7f7 !important;
329
  }
330
 
331
- .qm-debug-bar tbody tr:hover th,
332
- .qm-debug-bar tbody tr:hover td,
333
- #qm-conditionals tbody tr:hover td,
334
- #qm-overview tbody tr:hover td,
335
- #qm-authentication tbody tr:hover td {
336
- background: #fff !important;
 
 
 
337
  }
338
 
339
- .qm th {
340
- color: #333 !important;
 
341
  }
342
 
343
- .qm th.qm-num {
344
- width: 5.5em !important;
345
- text-align: center !important;
346
  }
347
 
348
- .qm td.qm-num {
349
- text-align: right !important;
 
350
  }
351
 
352
- .qm td.qm-has-toggle {
353
- padding: 0 !important;
 
 
354
  }
355
 
356
- .qm td.qm-has-toggle p,
357
- .qm td .qm-toggler {
358
- padding: 5px 22px 4px 8px !important;
 
 
 
 
 
 
 
 
 
359
  position: relative !important;
360
  }
361
 
362
- .qm td.qm-has-toggle p {
363
- font-style: normal !important;
364
- font-weight: normal !important;
365
- font-size: 11px !important;
366
- line-height: 18px !important;
367
- font-family: Menlo, Monaco, Consolas, monospace !important;
368
- margin: 0 !important;
369
  }
370
 
371
- .qm .qm-inner-toggle {
372
- padding: 5px 8px 4px !important;
373
  }
374
 
375
  .qm-has-inner .qm-toggled > table {
@@ -379,244 +481,333 @@ body.wp-admin.folded #qm {
379
  .qm-inner {
380
  border-collapse: collapse !important;
381
  margin: 0 !important;
382
- background: #fff !important;
383
- color: #333 !important;
384
  border-style: hidden !important;
385
  width: 100% !important;
386
  }
387
 
388
- .qm td.qm-has-inner .qm-toggler,
389
- .qm td.qm-has-inner {
390
  padding: 0 !important;
391
  }
392
 
393
- .qm ol,
394
- .qm ul {
395
- margin: 0 !important;
396
- padding: 0 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
397
  list-style: none !important;
398
  }
399
 
400
- .qm li {
401
- margin: 0 !important;
402
- padding: 0 !important;
403
  display: list-item !important;
404
  list-style: none !important;
405
- font-style: normal !important;
406
- font-weight: normal !important;
407
- font-size: 11px !important;
408
- line-height: 18px !important;
409
- font-family: Menlo, Monaco, Consolas, monospace !important;
410
- margin-left: 0 !important;
411
  }
412
 
413
- .qm li::before {
414
  content: '' !important;
415
  }
416
 
417
- .qm .qm-has-toggle ol.qm-numbered li {
418
  list-style: none !important;
419
  }
420
 
421
- .qm .qm-toggled-on ol.qm-numbered li,
422
- .qm ol.qm-numbered li {
423
  list-style: decimal inside !important;
424
  }
425
 
426
- .qm pre {
427
- font-style: normal !important;
428
- font-weight: normal !important;
429
- font-size: 11px !important;
430
  line-height: 18px !important;
431
  font-family: Menlo, Monaco, Consolas, monospace !important;
432
- color: inherit !important;
433
  background: transparent !important;
434
- border: none !important;
435
- margin: 0 !important;
436
- padding: 0 !important;
437
  }
438
 
439
- .qm code {
440
- font-style: normal !important;
441
- font-weight: normal !important;
442
  font-size: 11px !important;
443
  line-height: 18px !important;
444
  font-family: Menlo, Monaco, Consolas, monospace !important;
445
- color: inherit !important;
 
 
446
  background: #f1f1f1 !important;
447
  padding: 3px 4px 2px !important;
448
- margin: 0 !important;
449
  }
450
 
451
- .qm span.qm-true,
452
- .qm td.qm-true {
 
 
453
  color: #4a4 !important;
454
  }
455
 
456
- .qm span.qm-false,
457
- .qm td.qm-false {
458
- color: #bbb !important;
 
459
  }
460
 
461
- .qm .qm-wrap {
462
- word-wrap: break-word !important;
463
- word-break: break-all !important;
464
- }
465
-
466
- .qm .qm-nowrap {
467
  white-space: nowrap !important;
468
  }
469
 
470
- .qm td.qm-has-toggle p,
471
- .qm .qm-nonselectsql {
472
- color: #a0a !important;
 
 
473
  }
474
 
475
- .qm .qm-current {
 
 
 
476
  color: #a0a !important;
477
  }
478
 
479
- .qm .qm-info {
480
  color: #777 !important;
481
- font-style: normal !important;
482
- font-weight: normal !important;
483
- font-size: 11px !important;
484
- line-height: 18px !important;
485
- font-family: Menlo, Monaco, Consolas, monospace !important;
486
  }
487
 
488
- .qm .qm-supplemental {
489
  margin-right: 0.75em !important;
490
  margin-left: 0.75em !important;
491
  }
492
 
493
- .qm td .qm-toggled {
494
  display: none;
495
  }
496
 
497
- #qm-title a,
498
- .qm a {
499
- color: #0073aa !important;
500
- text-decoration: none !important;
501
- text-shadow: none !important;
502
  font-weight: normal !important;
503
- border: none !important;
 
 
 
 
 
504
  cursor: pointer !important;
 
505
  }
506
 
507
- #qm-title a:focus,
508
- #qm-title a:hover,
509
- .qm a:focus,
510
- .qm a:hover {
511
- text-decoration: underline !important;
512
- color: #0073aa !important;
513
  }
514
 
515
- .qm a.qm-warn {
516
- text-decoration: underline !important;
 
 
 
517
  }
518
 
519
- .qm .qm-toggle,
520
- html[dir="rtl"] .qm .qm-ltr .qm-toggle {
521
- color: #555 !important;
522
- padding: 1px 6px 0 !important;
523
- border: none !important;
524
- font-style: normal !important;
525
- font-weight: bold !important;
526
- font-size: 11px !important;
527
- line-height: 18px !important;
528
- font-family: Menlo, Monaco, Consolas, monospace !important;
529
- position: absolute !important;
530
- top: 4px !important;
531
- right: 4px !important;
532
- left: auto !important;
533
- background: #f1f1f1 !important;
534
- cursor: pointer !important;
535
  }
536
 
537
- .qm .qm-toggle:focus,
538
- .qm .qm-toggle:hover {
539
- text-decoration: none !important;
540
- border-color: #e0e0e0 !important;
541
- color: #0073aa !important;
542
- background: #e0e0e0 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
543
  }
544
 
545
- .qm tr.error,
546
- .qm .qm-warn,
547
- .qm .qm-warn td,
548
- .qm .qm-warn th,
549
- .qm .qm-warn td .qm-nonselectsql,
550
- .qm .qm-warn td .qm-info {
551
- color: #f00 !important;
552
  }
553
 
554
- .qm .dashicons {
555
  font-size: 16px !important;
556
  width: 16px !important;
557
  height: 16px !important;
558
  margin-right: 0.3em !important;
 
559
  }
560
 
561
- select.qm-filter.qm-highlight,
562
- .qm tbody tr td.qm-highlight,
563
- .qm .qm-highlight td {
 
 
 
 
 
564
  background-color: #ffd !important;
565
  }
566
 
567
- .qm span.qm-expensive,
568
- .qm td.qm-expensive {
569
- color: #f44 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
570
  }
571
 
572
  /* Filters */
573
 
574
- .qm button,
575
- .qm a,
576
- .qm select {
577
- outline: none !important;
578
  margin: 0 !important;
579
- border-radius: 0 !important;
580
- transition: none !important;
581
  height: auto !important;
582
  width: auto !important;
583
  background: none !important;
584
  box-shadow: none !important;
585
  }
586
 
587
- .qm label {
588
  cursor: pointer !important;
589
  color: #333 !important;
590
  font-weight: normal !important;
591
- font-size: 11px !important;
592
  font-style: normal !important;
593
  margin: 0 !important;
594
  }
595
 
596
- select.qm-filter {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
597
  display: block !important;
598
- font-style: normal !important;
599
- font-weight: normal !important;
600
- font-size: 11px !important;
601
- line-height: 18px !important;
602
- font-family: Menlo, Monaco, Consolas, monospace !important;
603
- margin: 4px 0 2px !important;
604
- border: 1px solid #ccc !important;
605
- padding: 1px !important;
606
  background: #fff !important;
607
  color: #333 !important;
608
- height: 2em !important;
609
  width: auto !important;
610
- border-radius: 0 !important;
611
  float: none !important;
612
  cursor: pointer !important;
613
- text-transform: none !important;
614
  -webkit-appearance: menulist !important;
615
  -moz-appearance: menulist !important;
616
  letter-spacing: normal !important;
 
617
  }
618
 
619
  .qm-hide,
 
 
620
  .qm-hide-user,
621
  .qm-hide-result,
622
  .qm-hide-name,
@@ -628,69 +819,58 @@ select.qm-filter {
628
 
629
  /* Sorters */
630
 
631
- .qm .qm-sort-controls {
632
- display: block !important;
633
- margin-top: 4px !important;
634
- text-align: center !important;
635
  }
636
 
637
- .qm button:focus,
638
- .qm a:focus,
639
- .qm select:focus {
640
- box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8) !important;
641
  }
642
 
643
- .qm .qm-sort {
644
- color: #767676 !important;
645
- display: block !important;
646
- border: 0 !important;
647
- padding: 0 !important;
648
- width: 30px !important;
649
- background-color: transparent !important;
650
- cursor: pointer !important;
651
- margin: 0 auto !important;
652
- height: 10px !important;
653
  }
654
 
655
- .qm .qm-sort:before {
656
- border-width: 7px 5px !important;
657
- border-style: solid !important;
658
- border-color: transparent !important;
659
- display: block !important;
660
- content: '' !important;
661
- width: 0 !important;
662
- height: 0 !important;
663
- position: relative !important;
664
- left: 10px !important;
665
  }
666
 
667
- .qm .qm-sort-asc {
668
- margin-bottom: 2px !important;
 
 
 
 
669
  }
670
- .qm .qm-sort-asc:before {
671
- border-bottom-color: #aaa !important;
672
- top: -4px !important;
 
673
  }
674
- .qm .qm-sort-asc:hover:before,
675
- .qm .qm-sort-asc:focus:before,
676
- .qm .qm-sorted-asc .qm-sort-asc:before {
677
- border-bottom-color: #333 !important;
678
  }
679
 
680
- .qm .qm-sort-desc {
681
- margin-top: 2px !important;
 
 
 
682
  }
683
- .qm .qm-sort-desc:before {
684
- border-top-color: #aaa !important;
685
- top: 0px !important;
686
  }
687
- .qm .qm-sort-desc:hover:before,
688
- .qm .qm-sort-desc:focus:before,
689
- .qm .qm-sorted-desc .qm-sort-desc:before {
690
- border-top-color: #333 !important;
 
691
  }
692
 
693
- .qm .screen-reader-text {
694
  position: absolute !important;
695
  margin: -1px !important;
696
  padding: 0 !important;
@@ -701,56 +881,42 @@ select.qm-filter {
701
  border: 0 !important;
702
  }
703
 
704
- /* RTL */
705
-
706
- html[dir="rtl"] body.wp-admin #qm {
707
- margin-right: 160px !important;
708
- margin-left: 0 !important;
709
- }
710
 
711
- @media all and (max-width: 782px) {
712
- html[dir="rtl"] body.wp-admin #qm {
713
- margin-right: 36px !important;
714
- margin-left: 0 !important;
715
  }
716
- }
717
 
718
- @media only screen and (max-width: 960px) {
719
- html[dir="rtl"] body.wp-admin.auto-fold #qm {
720
- margin-right: 36px !important;
721
- margin-left: 0 !important;
722
  }
723
- }
724
 
725
- html[dir="rtl"] body.wp-admin.folded #qm {
726
- margin-right: 36px !important;
727
- margin-left: 0 !important;
728
  }
729
 
730
- html[dir="rtl"] #qm,
731
- html[dir="rtl"] .qm caption,
732
- html[dir="rtl"] .qm td,
733
- html[dir="rtl"] .qm th {
 
 
734
  text-align: right !important;
735
  }
736
 
737
  html[dir="rtl"] #wpadminbar .quicklinks .menupop ul li.qm-ltr,
738
- html[dir="rtl"] .qm .qm-filter,
739
- html[dir="rtl"] .qm .qm-ltr {
740
  direction: ltr !important;
741
  text-align: left !important;
742
  }
743
 
744
- html[dir="rtl"] .qm .qm-toggle {
745
- border-right: 1px solid #e0e0e0 !important;
746
- border-left: none !important;
747
  right: auto !important;
748
  left: 1px !important;
749
  }
750
 
751
  /* No-JS tweaks */
752
 
753
- .qm-no-js #qm-authentication,
754
  .qm-no-js .qm-sort-controls,
755
  .qm-no-js .qm-toggle,
756
  .qm-no-js select.qm-filter {
@@ -759,71 +925,98 @@ html[dir="rtl"] .qm .qm-toggle {
759
 
760
  /* Debug bar add-ons */
761
 
762
- .qm-debug-bar textarea,
763
- .qm-debug-bar pre {
764
  padding: 10px !important;
765
  border: 1px solid #e0e0e0 !important;
766
  margin: 4px 0 !important;
767
- color: inherit !important;
768
- background: transparent !important;
769
- font-style: normal !important;
770
- font-weight: normal !important;
771
- font-size: 11px !important;
772
- line-height: 18px !important;
773
- font-family: Menlo, Monaco, Consolas, monospace !important;
774
  }
775
 
776
- .qm-debug-bar textarea {
777
  resize: vertical !important;
778
  }
779
 
780
- .qm-debug-bar .left {
781
  float: left !important;
782
  }
783
 
784
- .qm-debug-bar .right {
785
  float: right !important;
786
  }
787
 
788
- .qm-debug-bar h1, .qm-debug-bar h2, .qm-debug-bar h3 {
789
- font-style: normal !important;
790
- font-weight: normal !important;
791
- font-size: 11px !important;
792
- line-height: 18px !important;
793
- font-family: Menlo, Monaco, Consolas, monospace !important;
794
  }
795
 
796
- .qm-debug-bar h2 {
797
- float: left !important;
798
  min-width: 150px !important;
799
  padding: 5px 10px 15px !important;
800
  clear: none !important;
801
  text-align: center !important;
802
- font-size: 18px !important;
803
  margin: 3px 8px 15px 0 !important;
804
  }
805
 
806
- .qm-debug-bar h2 span {
807
- font-size: 11px !important;
 
 
 
808
  white-space: nowrap !important;
809
  display: block !important;
810
  margin-bottom: 8px !important;
811
  }
812
 
813
- .qm-debug-bar h3 {
814
- margin: 15px 0 5px !important;
815
  font-size: 13px !important;
816
  }
817
 
818
- .qm-debug-bar .qm-debug-bar-output {
819
  position: relative !important;
820
  }
821
 
822
- .qm-debug-bar .qm-debug-bar-output table {
823
  margin-top: 4px !important;
824
  margin-bottom: 4px !important;
825
  }
826
 
827
- #qm #debug-menu-target-Debug_Bar_Console {
828
  min-height: 400px !important;
829
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  */
15
 
16
+ /* === Admin Toolbar === */
17
+
18
  #wpadminbar .quicklinks .menupop ul li.qm-true > a {
19
  color: #8c8 !important;
20
  }
62
  background-color: #c00;
63
  }
64
 
 
 
 
 
 
 
 
65
  #wpadminbar .qm-warning > a {
66
  color: #fff !important;
67
  }
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;
123
  }
124
  }
125
 
126
+ /* === Main QM Panel === */
127
+
128
+ #query-monitor,
129
+ #query-monitor button,
130
+ #query-monitor label,
131
+ #query-monitor select,
132
+ #query-monitor table,
133
+ #query-monitor td,
134
+ #query-monitor th,
135
+ #query-monitor ul,
136
+ #query-monitor ol,
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,
144
+ #query-monitor h4,
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
+ .no-js #query-monitor,
189
+ .nojs #query-monitor {
190
+ height: 27px;
191
+ display: flex;
192
+ flex-direction: column;
193
  }
194
 
195
+ #query-monitor.qm-show {
196
+ height: 40%;
197
+ }
198
+
199
+ #qm-wrapper {
200
+ display: flex;
201
+ flex-grow: 1;
202
+ /* Fix nested scrolling in Firefox. See https://bugzilla.mozilla.org/show_bug.cgi?id=1043520: */
203
+ min-height: 0;
204
+ }
205
+
206
+ #qm-title {
207
+ background: #f3f3f3 !important;
208
+ border-bottom: 1px solid #aaa !important;
209
+ cursor: ns-resize !important;
210
+ align-items: center;
211
+ display: flex !important;
212
+ padding: 0 2px 0 5px !important;
213
+ height: 27px !important;
214
+ flex-shrink: 0;
215
+ }
216
+
217
+ #qm-title .qm-title-heading {
218
+ flex-grow: 1;
219
+ border-right: 1px solid #bbb !important;
220
+ margin-right: 8px !important;
221
+ }
222
+
223
+ #qm-title div.qm-title-heading {
224
  display: none;
225
  }
226
 
227
+ #qm-title .qm-title-button {
228
+ flex-shrink: 0;
 
 
 
229
  }
230
 
231
+ #qm-title .dashicons {
232
+ transition: none !important;
233
  }
234
 
235
+ #qm-title .qm-button-container-settings .dashicons,
236
+ #qm-title .qm-button-container-pin .dashicons {
237
+ font-size: 17px !important;
238
+ margin-top: 3px !important;
 
239
  }
240
 
241
+ #qm-title button {
242
+ color: #777 !important;
243
+ cursor: pointer !important;
244
+ margin: 0 0 0 0px !important;
245
+ display: inline-block !important;
246
+ padding: 0px 2px !important;
247
  }
248
 
249
+ #qm-title button:focus,
250
+ #qm-title button:hover {
251
+ color: #000 !important;
 
 
252
  }
253
 
254
+ #qm-title button.qm-button-active {
255
+ color: #3879d9 !important;
256
  }
257
 
258
+ #qm-title .qm-button-container-pin.qm-button-active .dashicons {
259
+ transform: rotate( -45deg ) !important;
260
  }
261
 
262
+ #qm-title .qm-button-container-pin.qm-button-active .dashicons:before {
263
+ margin-left: 2px !important;
 
 
264
  }
265
 
266
+ #query-monitor .qm {
267
+ display: none !important;
 
268
  }
269
 
270
+ #qm-panel-menu {
271
+ overflow-y: scroll !important;
272
+ flex-shrink: 0;
273
+ background: #ececec !important;
274
+ }
275
+
276
+ #qm-panel-menu ul {
 
277
  padding: 0 !important;
278
+ margin: 0 !important;
279
  }
280
 
281
+ #qm-panel-menu ul:after {
282
+ height: 30px !important;
283
+ content: " ";
284
+ display: block;
285
+ border-right: 1px solid #aaaaaa !important;
286
+ }
287
+
288
+ #qm-panel-menu li {
289
+ padding: 0 !important;
290
+ margin: 0 !important;
291
  }
292
 
293
+ #qm-panel-menu li a {
294
  display: block !important;
295
+ padding: 8px 28px 8px 6px !important;
296
+ color: #555 !important;
297
+ text-decoration: none !important;
298
+ border-bottom: 1px solid #ddd !important;
299
+ position: relative !important;
300
+ border-right: 1px solid #aaa !important;
301
+ background: #f3f3f3 !important;
302
  }
303
 
304
+ #qm-panel-menu li a:focus,
305
+ #qm-panel-menu li a:hover {
306
+ background: #def !important;
307
+ color: #222 !important;
 
308
  }
309
 
310
+ #qm-panel-menu li a.qm-selected-menu {
311
+ background: #0372aa !important;
312
+ color: #fff !important;
 
313
  }
314
 
315
+ #qm-panel-menu li a.qm-selected-menu:after {
316
+ right: -1px;
317
+ border: solid 8px transparent;
318
+ content: " ";
319
+ height: 0;
320
+ width: 0;
321
+ position: absolute;
322
+ pointer-events: none;
323
+ border-right-color: #fff;
324
+ top: 50%;
325
+ margin-top: -8px;
326
  }
327
 
328
+ #qm-panels {
329
+ flex-grow: 1;
330
+ overflow-y: scroll;
 
331
  }
332
 
333
+ #query-monitor .qm.qm-panel-show {
334
+ display: block !important;
335
  }
336
 
337
+ #query-monitor .qm:focus {
338
+ outline: 0 !important; /* @TODO might not need this any more */
 
339
  }
340
 
341
+ #query-monitor .qm-non-tabular {
342
+ padding: 10px 20px !important;
343
  }
344
 
345
+ #query-monitor .qm-boxed {
346
+ display: flex !important;
347
+ }
348
+
349
+ #query-monitor .qm-boxed:not(#qm-broken) + .qm-boxed {
350
+ border-top: 1px solid #dddddd !important;
351
+ padding-top: 10px !important;
352
+ }
353
+
354
+ #query-monitor .qm-boxed-wrap {
355
+ flex-wrap: wrap !important;
356
+ }
357
+
358
+ #query-monitor .qm .qm-none {
359
+ margin: 2em !important;
360
  }
361
 
362
+ #query-monitor .qm .qm-none p {
363
+ text-align: center !important;
364
+ font-style: italic !important;
365
  }
366
 
367
+ #query-monitor .qm table {
368
  color: #333 !important;
369
  border-collapse: collapse !important;
370
  box-shadow: none !important;
371
  width: 100% !important;
372
  table-layout: auto !important;
373
  margin: 0 !important;
374
+ border: none !important;
375
+ border-bottom: 1px solid #cccccc !important;
376
+ }
377
+
378
+ #query-monitor .qm table + table {
379
+ margin-top: 5px !important;
380
+ border-top: 1px solid #cccccc !important;
381
  }
382
 
383
+ #query-monitor #qm-conditionals table,
384
+ #query-monitor #qm-overview table {
385
  table-layout: fixed !important;
386
  }
387
 
388
+ #query-monitor .qm tr {
389
+ border: none !important;
390
+ }
391
+
392
+ #query-monitor .qm tbody th,
393
+ #query-monitor .qm tbody td,
394
+ #query-monitor .qm tfoot th,
395
+ #query-monitor .qm tfoot td {
 
 
 
 
396
  border: 1px solid #e0e0e0 !important;
397
+ padding: 5px !important;
 
 
 
 
 
398
  }
399
 
400
+ #query-monitor .qm tbody th,
401
+ #query-monitor .qm tbody td {
402
+ border-top: none !important;
403
+ border-bottom: none !important;
404
  }
405
 
406
+ #query-monitor .qm thead th {
407
+ box-shadow: 0px 1px 0px #e0e0e0;
408
+ border: 1px solid #e0e0e0 !important;
409
+ border-top: none !important;
410
+ padding: 5px !important;
411
+ position: -webkit-sticky !important;
412
+ position: sticky !important;
413
+ top: 0 !important;
414
+ background: #fff !important;
415
+ z-index: 1 !important;
416
  }
417
 
418
+ #query-monitor .qm thead .qm-th {
419
+ display: flex !important;
 
 
420
  }
421
 
422
+ #query-monitor .qm tfoot tr td,
423
+ #query-monitor .qm tfoot tr th {
424
+ box-shadow: inset 0px 1px 0px #e0e0e0;
425
+ border: 1px solid #e0e0e0 !important;
426
+ border-bottom: none !important;
427
+ background: #f3f3f3 !important;
428
+ position: -webkit-sticky !important;
429
+ position: sticky !important;
430
+ bottom: 0 !important;
431
  }
432
 
433
+ #query-monitor .qm tfoot tr.qm-items-shown td,
434
+ #query-monitor .qm tfoot tr.qm-items-shown th {
435
+ bottom: 28px !important;
436
  }
437
 
438
+ #query-monitor .qm th:first-child,
439
+ #query-monitor .qm td:first-child {
440
+ border-left: none !important;
441
  }
442
 
443
+ #query-monitor .qm th:last-child,
444
+ #query-monitor .qm td:last-child {
445
+ border-right: none !important;
446
  }
447
 
448
+ #query-monitor .qm caption {
449
+ caption-side: top !important;
450
+ border: none !important;
451
+ display: none !important; /* @TODO remove */
452
  }
453
 
454
+ #query-monitor .qm tfoot td.qm-num,
455
+ #query-monitor .qm th.qm-num {
456
+ width: 5.5em !important;
457
+ }
458
+
459
+ #query-monitor .qm td.qm-num {
460
+ text-align: right !important;
461
+ }
462
+
463
+ #query-monitor .qm td.qm-has-toggle p,
464
+ #query-monitor .qm td .qm-toggler {
465
+ padding: 0 22px 0 0 !important;
466
  position: relative !important;
467
  }
468
 
469
+ #query-monitor .qm td.qm-has-toggle:not(.qm-toggled-on) .qm-supplemental {
470
+ display: none;
 
 
 
 
 
471
  }
472
 
473
+ #query-monitor .qm .qm-inner-toggle {
474
+ padding: 4px 6px !important;
475
  }
476
 
477
  .qm-has-inner .qm-toggled > table {
481
  .qm-inner {
482
  border-collapse: collapse !important;
483
  margin: 0 !important;
 
 
484
  border-style: hidden !important;
485
  width: 100% !important;
486
  }
487
 
488
+ #query-monitor .qm td.qm-has-inner .qm-toggler,
489
+ #query-monitor .qm td.qm-has-inner {
490
  padding: 0 !important;
491
  }
492
 
493
+ #query-monitor .qm-non-tabular h2 {
494
+ margin: 0 0 15px 0 !important;
495
+ font-size: 14px !important;
496
+ color: #444 !important;
497
+ }
498
+
499
+ #query-monitor .qm-non-tabular h3 {
500
+ margin: 15px 0 !important;
501
+ font-size: 12px !important;
502
+ color: #444 !important;
503
+ }
504
+
505
+ #query-monitor .qm-non-tabular p {
506
+ margin-bottom: 10px !important;
507
+ }
508
+
509
+ #query-monitor .qm-non-tabular h2 a {
510
+ float: right !important;
511
+ }
512
+
513
+ #query-monitor .qm-non-tabular .qm-item {
514
+ display: inline-block !important;
515
+ margin: 0 20px 5px 0 !important;
516
+ }
517
+
518
+ #query-monitor .qm-non-tabular .qm-section {
519
+ margin: 0 0 30px 0 !important;
520
+ }
521
+
522
+ #query-monitor .qm-non-tabular .qm-boxed .qm-section {
523
+ margin: 0 20px 10px 0 !important;
524
+ border-right: 1px solid #ddd !important;
525
+ padding: 10px 20px 10px 0 !important;
526
+ }
527
+
528
+ #query-monitor .qm-non-tabular .qm-boxed .qm-section:last-child {
529
+ margin-right: 0 !important;
530
+ border-right: none !important;
531
+ padding-right: 20px !important;
532
+ }
533
+
534
+ #query-monitor .qm-non-tabular table {
535
+ border-bottom-color: #e0e0e0 !important;
536
+ }
537
+
538
+ #query-monitor .qm ol,
539
+ #query-monitor .qm ul {
540
  list-style: none !important;
541
  }
542
 
543
+ #query-monitor .qm li {
 
 
544
  display: list-item !important;
545
  list-style: none !important;
 
 
 
 
 
 
546
  }
547
 
548
+ #query-monitor .qm li::before {
549
  content: '' !important;
550
  }
551
 
552
+ #query-monitor .qm .qm-has-toggle ol.qm-numbered li {
553
  list-style: none !important;
554
  }
555
 
556
+ #query-monitor .qm .qm-toggled-on ol.qm-numbered li,
557
+ #query-monitor .qm ol.qm-numbered li {
558
  list-style: decimal inside !important;
559
  }
560
 
561
+ #query-monitor .qm pre {
562
+ font-size: 12px !important;
 
 
563
  line-height: 18px !important;
564
  font-family: Menlo, Monaco, Consolas, monospace !important;
 
565
  background: transparent !important;
 
 
 
566
  }
567
 
568
+ #query-monitor .qm code {
 
 
569
  font-size: 11px !important;
570
  line-height: 18px !important;
571
  font-family: Menlo, Monaco, Consolas, monospace !important;
572
+ }
573
+
574
+ #query-monitor .qm code.qm-inline-code {
575
  background: #f1f1f1 !important;
576
  padding: 3px 4px 2px !important;
 
577
  }
578
 
579
+ #query-monitor .qm .qm-true code,
580
+ #query-monitor .qm p.qm-true,
581
+ #query-monitor .qm span.qm-true,
582
+ #query-monitor .qm td.qm-true {
583
  color: #4a4 !important;
584
  }
585
 
586
+ #query-monitor .qm .qm-false code,
587
+ #query-monitor .qm span.qm-false,
588
+ #query-monitor .qm td.qm-false {
589
+ color: #999 !important;
590
  }
591
 
592
+ #query-monitor .qm code,
593
+ #query-monitor .qm .qm-nowrap {
 
 
 
 
594
  white-space: nowrap !important;
595
  }
596
 
597
+ #query-monitor .qm .qm-wrap code,
598
+ #query-monitor .qm .qm-wrap {
599
+ word-wrap: break-word !important;
600
+ word-break: break-all !important;
601
+ white-space: normal !important;
602
  }
603
 
604
+ #query-monitor .qm .qm-current,
605
+ #query-monitor .qm td.qm-has-toggle p,
606
+ #query-monitor .qm .qm-nonselectsql code,
607
+ #query-monitor .qm .qm-nonselectsql {
608
  color: #a0a !important;
609
  }
610
 
611
+ #query-monitor .qm .qm-info {
612
  color: #777 !important;
 
 
 
 
 
613
  }
614
 
615
+ #query-monitor .qm .qm-supplemental {
616
  margin-right: 0.75em !important;
617
  margin-left: 0.75em !important;
618
  }
619
 
620
+ #query-monitor .qm td .qm-toggled {
621
  display: none;
622
  }
623
 
624
+ #query-monitor .qm .qm-toggle,
625
+ html[dir="rtl"] #query-monitor .qm .qm-ltr .qm-toggle {
626
+ color: #ffffff !important;
627
+ padding: 0px 5px !important;
 
628
  font-weight: normal !important;
629
+ font-family: Menlo, Monaco, Consolas, monospace !important;
630
+ position: absolute !important;
631
+ top: 0 !important;
632
+ right: 0 !important;
633
+ left: auto !important;
634
+ background: #589cbd !important;
635
  cursor: pointer !important;
636
+ bottom: auto !important;
637
  }
638
 
639
+ #query-monitor .qm .qm-has-inner .qm-toggle {
640
+ top: 5px !important;
641
+ right: 5px !important;
 
 
 
642
  }
643
 
644
+ #query-monitor .qm .qm-toggle:focus,
645
+ #query-monitor .qm .qm-toggle:hover {
646
+ text-decoration: none !important;
647
+ color: #ffffff !important;
648
+ background: #3878d9 !important;
649
  }
650
 
651
+ /* @TODO this striping breaks when rows are filtered out. can visible rows be targeted? */
652
+ #query-monitor .qm tbody tr:nth-child(odd) td,
653
+ #query-monitor .qm tbody tr:nth-child(odd) th {
654
+ background: #f7f7f7 !important;
 
 
 
 
 
 
 
 
 
 
 
 
655
  }
656
 
657
+ .qm-debug-bar tbody tr:hover th,
658
+ .qm-debug-bar tbody tr:hover td,
659
+ #qm-conditionals tbody tr:hover td,
660
+ #qm-overview tbody tr:hover td,
661
+ #qm-settings tbody tr:hover td {
662
+ background: #fff !important;
663
+ }
664
+
665
+ #query-monitor .qm-non-tabular .qm-warn,
666
+ #query-monitor .qm thead tr .qm-warn,
667
+ #query-monitor .qm tbody tr .qm-warn {
668
+ background-color: #fff0f0 !important;
669
+ color: #800 !important;
670
+ }
671
+
672
+ #query-monitor .qm tbody tr th.qm-warn,
673
+ #query-monitor .qm tbody tr td.qm-warn,
674
+ #query-monitor .qm tbody tr.qm-warn td,
675
+ #query-monitor .qm tbody tr.qm-warn th {
676
+ background-color: #fff0f0 !important;
677
+ box-shadow: inset 0 -1px #ffd6d6 !important;
678
+ border-color: #ffd6d6 !important;
679
+ color: #800 !important;
680
  }
681
 
682
+ #query-monitor .qm-non-tabular .qm-warn code,
683
+ #query-monitor .qm tbody .qm-warn li,
684
+ #query-monitor .qm tbody .qm-warn .qm-info,
685
+ #query-monitor .qm tbody .qm-warn code {
686
+ color: #800 !important;
687
+ background-color: transparent !important;
 
688
  }
689
 
690
+ #query-monitor .qm .dashicons {
691
  font-size: 16px !important;
692
  width: 16px !important;
693
  height: 16px !important;
694
  margin-right: 0.3em !important;
695
+ transition: none !important;
696
  }
697
 
698
+ #query-monitor .qm tbody tr:hover th,
699
+ #query-monitor .qm tbody tr:hover td {
700
+ background: rgb( 238, 243, 250 ) !important;
701
+ }
702
+
703
+ #query-monitor .qm select.qm-filter.qm-highlight,
704
+ #query-monitor .qm tbody tr td.qm-highlight,
705
+ #query-monitor .qm tbody tr.qm-highlight td {
706
  background-color: #ffd !important;
707
  }
708
 
709
+ #query-monitor .qm tbody .qm-warn a code,
710
+ #qm-title a,
711
+ #query-monitor .qm a code,
712
+ #query-monitor .qm a {
713
+ color: #0073aa !important;
714
+ text-decoration: none !important;
715
+ cursor: pointer !important;
716
+ }
717
+
718
+ #qm-title a:focus,
719
+ #qm-title a:hover,
720
+ #query-monitor .qm a:after,
721
+ #query-monitor .qm a:focus,
722
+ #query-monitor .qm a:hover {
723
+ text-decoration: underline !important;
724
+ color: #0073aa !important;
725
+ }
726
+
727
+ #query-monitor .qm a.qm-edit-link:after,
728
+ #query-monitor .qm a.qm-filter-trigger:after {
729
+ font-family: dashicons !important;
730
+ text-decoration: none !important;
731
+ visibility: hidden !important;
732
+ display: inline-block !important;
733
+ }
734
+
735
+ #query-monitor .qm a.qm-edit-link:hover:after,
736
+ #query-monitor .qm a.qm-edit-link:focus:after,
737
+ #query-monitor .qm a.qm-filter-trigger:hover:after,
738
+ #query-monitor .qm a.qm-filter-trigger:focus:after {
739
+ visibility: visible !important;
740
+ }
741
+
742
+ #query-monitor .qm a.qm-filter-trigger:after {
743
+ content: '\f536' !important;
744
+ }
745
+
746
+ #query-monitor .qm a.qm-edit-link:after {
747
+ content: '\f464' !important;
748
+ font-size: 15px !important;
749
  }
750
 
751
  /* Filters */
752
 
753
+ #query-monitor button,
754
+ #query-monitor a,
755
+ #query-monitor select {
756
+ outline: none !important; /* a11y */
757
  margin: 0 !important;
 
 
758
  height: auto !important;
759
  width: auto !important;
760
  background: none !important;
761
  box-shadow: none !important;
762
  }
763
 
764
+ #query-monitor .qm label {
765
  cursor: pointer !important;
766
  color: #333 !important;
767
  font-weight: normal !important;
768
+ font-size: 12px !important;
769
  font-style: normal !important;
770
  margin: 0 !important;
771
  }
772
 
773
+ #query-monitor .qm thead label {
774
+ flex-grow: 1;
775
+ }
776
+
777
+ #query-monitor .qm .qm-filter-container {
778
+ display: flex;
779
+ }
780
+
781
+ #query-monitor .qm .qm-filter-container label {
782
+ cursor: default !important;
783
+ }
784
+
785
+ #query-monitor .qm .qm-filter-container div {
786
+ /* Some themes use Select2 etc on all selects. This hides that. */
787
+ display: none !important;
788
+ }
789
+
790
+ #query-monitor .qm select.qm-filter {
791
  display: block !important;
792
+ margin: 0 0 0 5px !important;
793
+ outline: 1px solid #aaa !important;
794
+ border: none !important;
795
+ padding: 0 !important;
 
 
 
 
796
  background: #fff !important;
797
  color: #333 !important;
798
+ height: auto !important;
799
  width: auto !important;
 
800
  float: none !important;
801
  cursor: pointer !important;
 
802
  -webkit-appearance: menulist !important;
803
  -moz-appearance: menulist !important;
804
  letter-spacing: normal !important;
805
+ max-width: 15em !important;
806
  }
807
 
808
  .qm-hide,
809
+ .qm-hide-scripts-host,
810
+ .qm-hide-styles-host,
811
  .qm-hide-user,
812
  .qm-hide-result,
813
  .qm-hide-name,
819
 
820
  /* Sorters */
821
 
822
+ #query-monitor .qm thead th.qm-sortable-column {
823
+ cursor: pointer !important;
 
 
824
  }
825
 
826
+ #query-monitor .qm thead th.qm-sortable-column:hover {
827
+ background: #f3f3f3 !important;
 
 
828
  }
829
 
830
+ #query-monitor .qm .qm-sort-heading {
831
+ flex-grow: 1;
 
 
 
 
 
 
 
 
832
  }
833
 
834
+ #query-monitor .qm .qm-sort-controls {
835
+ text-align: right !important;
836
+ flex-shrink: 0;
 
 
 
 
 
 
 
837
  }
838
 
839
+ #query-monitor .qm .qm-sortable-column .qm-sort-arrow {
840
+ font-size: 24px !important;
841
+ color: #ccc !important;
842
+ margin: 0 !important;
843
+ width: 16px !important;
844
+ height: 10px !important;
845
  }
846
+
847
+ #query-monitor .qm .qm-sorted-desc .qm-sort-arrow,
848
+ #query-monitor .qm .qm-sorted-asc .qm-sort-arrow {
849
+ color: #444444 !important;
850
  }
851
+
852
+ #query-monitor .qm thead th.qm-sortable-column:hover .qm-sort-arrow {
853
+ color: #3878d9 !important;
 
854
  }
855
 
856
+ #query-monitor .qm .qm-sortable-column .qm-sort-arrow:before {
857
+ content: "\f140";
858
+ top: 1px;
859
+ right: 0;
860
+ position: absolute;
861
  }
862
+
863
+ #query-monitor .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow:before {
864
+ content: "\f142";
865
  }
866
+
867
+ #query-monitor .qm button:focus,
868
+ #query-monitor .qm a:focus,
869
+ #query-monitor .qm select:focus {
870
+ box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8) !important;
871
  }
872
 
873
+ #query-monitor .screen-reader-text {
874
  position: absolute !important;
875
  margin: -1px !important;
876
  padding: 0 !important;
881
  border: 0 !important;
882
  }
883
 
884
+ @media screen and (max-width: 782px) {
 
 
 
 
 
885
 
886
+ #qm-panel-menu,
887
+ #qm-title h1.qm-title-heading {
888
+ display: none;
 
889
  }
 
890
 
891
+ #qm-title div.qm-title-heading {
892
+ display: block;
 
 
893
  }
 
894
 
 
 
 
895
  }
896
 
897
+ /* RTL */
898
+
899
+ html[dir="rtl"] #query-monitor,
900
+ html[dir="rtl"] #query-monitor .qm caption,
901
+ html[dir="rtl"] #query-monitor .qm td,
902
+ html[dir="rtl"] #query-monitor .qm th {
903
  text-align: right !important;
904
  }
905
 
906
  html[dir="rtl"] #wpadminbar .quicklinks .menupop ul li.qm-ltr,
907
+ html[dir="rtl"] #query-monitor .qm .qm-filter,
908
+ html[dir="rtl"] #query-monitor .qm .qm-ltr {
909
  direction: ltr !important;
910
  text-align: left !important;
911
  }
912
 
913
+ html[dir="rtl"] #query-monitor .qm .qm-toggle {
 
 
914
  right: auto !important;
915
  left: 1px !important;
916
  }
917
 
918
  /* No-JS tweaks */
919
 
 
920
  .qm-no-js .qm-sort-controls,
921
  .qm-no-js .qm-toggle,
922
  .qm-no-js select.qm-filter {
925
 
926
  /* Debug bar add-ons */
927
 
928
+ #query-monitor .qm.qm-debug-bar textarea,
929
+ #query-monitor .qm.qm-debug-bar pre {
930
  padding: 10px !important;
931
  border: 1px solid #e0e0e0 !important;
932
  margin: 4px 0 !important;
 
 
 
 
 
 
 
933
  }
934
 
935
+ #query-monitor .qm.qm-debug-bar textarea {
936
  resize: vertical !important;
937
  }
938
 
939
+ #query-monitor .qm.qm-debug-bar .left {
940
  float: left !important;
941
  }
942
 
943
+ #query-monitor .qm.qm-debug-bar .right {
944
  float: right !important;
945
  }
946
 
947
+ #query-monitor .qm.qm-debug-bar h1 {
948
+ margin: 4px 6px 15px !important;
 
 
 
 
949
  }
950
 
951
+ #query-monitor .qm.qm-debug-bar h2 {
952
+ float: left !important; /* why */
953
  min-width: 150px !important;
954
  padding: 5px 10px 15px !important;
955
  clear: none !important;
956
  text-align: center !important;
957
+ font-size: 14px !important;
958
  margin: 3px 8px 15px 0 !important;
959
  }
960
 
961
+ #query-monitor .qm.qm-debug-bar h2 small {
962
+ font-size: 14px !important;
963
+ }
964
+
965
+ #query-monitor .qm.qm-debug-bar h2 span {
966
  white-space: nowrap !important;
967
  display: block !important;
968
  margin-bottom: 8px !important;
969
  }
970
 
971
+ #query-monitor .qm.qm-debug-bar h3 {
972
+ margin: 15px 6px 5px !important;
973
  font-size: 13px !important;
974
  }
975
 
976
+ #query-monitor .qm.qm-debug-bar .qm-debug-bar-output {
977
  position: relative !important;
978
  }
979
 
980
+ #query-monitor .qm.qm-debug-bar .qm-debug-bar-output table {
981
  margin-top: 4px !important;
982
  margin-bottom: 4px !important;
983
  }
984
 
985
+ #query-monitor #debug-menu-target-Debug_Bar_Console {
986
  min-height: 400px !important;
987
  }
988
+
989
+ #query-monitor #debug-menu-target-Debug_Bar_Cache_Lookup,
990
+ #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules,
991
+ #query-monitor #debug-menu-target-Debug_Bar_Widgets {
992
+ margin: 4px 6px !important;
993
+ }
994
+
995
+ #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules_Panel .filterui,
996
+ #query-monitor #debug-menu-target-Debug_Bar_Rewrite_Rules_Panel .dbrr {
997
+ margin: 0;
998
+ }
999
+
1000
+ /* Broken output handling */
1001
+
1002
+ #query-monitor.qm-broken #qm-title {
1003
+ cursor: default !important;
1004
+ }
1005
+
1006
+ #query-monitor #qm-broken,
1007
+ #query-monitor.qm-broken .qm-title-button {
1008
+ display: none !important;
1009
+ }
1010
+
1011
+ #query-monitor.qm-broken #qm-broken,
1012
+ #query-monitor.qm-broken .qm {
1013
+ display: block !important;
1014
+ }
1015
+
1016
+ #query-monitor.qm-broken .qm {
1017
+ margin-bottom: 50px !important;
1018
+ }
1019
+
1020
+ #query-monitor.qm-broken #qm-broken h2 {
1021
+ padding: 20px !important;
1022
+ }
assets/query-monitor.js CHANGED
@@ -37,7 +37,7 @@ var QM_i18n = {
37
 
38
  if ( num_str.length > 3 ) {
39
  for ( i = num_str.length; i > 3; i -= 3 ) {
40
- o = qm_locale.number_format.thousands_sep + num_str.slice( i - 3, i ) + o;
41
  }
42
  o = num_str.slice( 0, i ) + o;
43
  } else {
@@ -45,7 +45,7 @@ var QM_i18n = {
45
  }
46
 
47
  if ( decimals ) {
48
- o = o + qm_locale.number_format.decimal_point + fraction;
49
  }
50
 
51
  return o;
@@ -54,159 +54,159 @@ var QM_i18n = {
54
 
55
  };
56
 
57
- jQuery( function($) {
58
 
59
- if ( ! window.qm ) {
60
- return;
61
- }
62
-
63
- var is_admin = $('body').hasClass('wp-admin');
64
-
65
- $('#qm').removeClass('qm-no-js').addClass('qm-js');
66
-
67
- if ( $('#wp-admin-bar-query-monitor').length ) {
68
 
69
- var container = document.createDocumentFragment();
 
 
70
 
71
- $('#wp-admin-bar-query-monitor')
72
- .addClass(qm.menu.top.classname)
73
- .find('a').eq(0)
74
- .html(qm.menu.top.title)
75
- ;
76
 
77
- $.each( qm.menu.sub, function( i, el ) {
 
 
 
78
 
79
- var new_menu = $('#wp-admin-bar-query-monitor-placeholder')
80
- .clone()
81
- .attr('id','wp-admin-bar-' + el.id)
82
- ;
83
- new_menu
84
- .find('a').eq(0)
85
- .html(el.title)
86
- .attr('href',el.href)
87
- ;
88
 
89
- if ( ( typeof el.meta != 'undefined' ) && ( typeof el.meta.classname != 'undefined' ) ) {
90
- new_menu.addClass(el.meta.classname);
91
  }
92
 
93
- container.appendChild( new_menu.get(0) );
 
94
 
95
- } );
 
 
 
96
 
97
- $('#wp-admin-bar-query-monitor ul').append(container);
 
 
 
98
 
99
- $('#wp-admin-bar-query-monitor').find('a').on('click',function(e){
100
- var paused = true;
101
 
102
- if ( is_admin ) {
103
- $('#wpfooter').css('position','relative');
104
  }
105
- if ( window.infinite_scroll && infinite_scroll.contentSelector ) {
106
- // Infinite Scroll plugin
107
-
108
- $( infinite_scroll.contentSelector ).infinitescroll('pause');
109
 
110
- } else if ( window.infiniteScroll && infiniteScroll.scroller ) {
111
- // Jetpack Infinite Scroll module
112
 
113
- infiniteScroll.scroller.check = function(){
114
- return false;
115
- };
116
 
117
- } else if ( window.wp && wp.themes && wp.themes.RunInstaller && wp.themes.RunInstaller.view ) {
118
- // Infinite scrolling on Appearance -> Add New screens
119
 
120
- var view = wp.themes.RunInstaller.view.view;
121
- view.stopListening( view.parent, 'theme:scroll' );
122
 
123
- } else {
124
- paused = false;
125
- }
 
 
 
126
 
127
- if ( paused && window.console ) {
128
- console.debug( qm_l10n.infinitescroll_paused );
129
- }
130
 
131
- $('#qm').addClass('qm-show').removeClass('qm-hide');
132
- });
 
 
 
 
 
 
 
133
 
134
- $('#wp-admin-bar-query-monitor,#wp-admin-bar-query-monitor-default').show();
 
 
135
 
136
- } else {
137
 
138
- var container = document.createDocumentFragment();
139
 
140
- $.each( qm.menu.sub, function( i, el ) {
 
141
 
142
- var new_menu = $('<li><a/></li>');
143
- new_menu
144
- .find('a').eq(0)
145
- .html(el.title)
146
- .attr('href',el.href)
147
- ;
148
 
149
- container.appendChild( new_menu.get(0) );
150
 
151
- } );
 
 
 
152
 
153
- $('<ul/>').appendTo('#qm-title').append(container).find('a').on('click',function(e){
154
- $('#qm').addClass('qm-show').removeClass('qm-hide qm-peek');
155
- } );
156
- }
157
 
158
- $('#qm').find('.qm-filter').on('change',function(e){
159
 
160
- var filter = $(this).attr('data-filter'),
161
- table = $(this).closest('table'),
162
- tr = table.find('tbody tr[data-qm-' + filter + ']'),
163
- // Escape the following chars with a backslash before passing into jQ selectors: [ ] ( ) ' " \
164
- val = $(this).val().replace(/[[\]()'"\\]/g, "\\$&"),
165
- total = tr.removeClass('qm-hide-' + filter).length,
166
- hilite = $(this).attr('data-highlight'),
167
- time = 0;
168
 
169
- if ( window.localStorage ) {
170
  key = $(this).attr('id');
171
  if ( val ) {
172
  localStorage.setItem( key, $(this).val() );
173
  } else {
174
  localStorage.removeItem( key );
175
  }
176
- }
177
-
178
- if ( hilite ) {
179
- table.find('tr').removeClass('qm-highlight');
180
- }
181
 
182
- if ( $(this).val() !== '' ) {
183
  if ( hilite ) {
184
- tr.filter('[data-qm-' + hilite + '*="' + val + '"]').addClass('qm-highlight');
185
  }
186
- tr.not('[data-qm-' + filter + '*="' + val + '"]').addClass('qm-hide-' + filter);
187
- $(this).addClass('qm-highlight');
188
- } else {
189
- $(this).removeClass('qm-highlight');
190
- }
191
 
192
- var matches = tr.filter(':visible');
193
- matches.each(function(i){
194
- var row_time = $(this).attr('data-qm-time');
195
- if ( row_time ) {
196
- time += parseFloat( row_time );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  }
198
- });
199
- if ( time ) {
200
- time = QM_i18n.number_format( time, 4 );
201
- }
202
 
203
- var results = table.find('.qm-items-shown').removeClass('qm-hide');
204
- results.find('.qm-items-number').text( QM_i18n.number_format( matches.length, 0 ) );
205
- results.find('.qm-items-time').text(time);
206
- });
207
 
208
- if ( window.localStorage ) {
209
- $('#qm').find('.qm-filter').each(function () {
 
 
 
 
 
 
210
  var key = $(this).attr('id');
211
  var value = localStorage.getItem( key );
212
  if ( value !== null ) {
@@ -218,265 +218,337 @@ jQuery( function($) {
218
  $(this).val(value).change();
219
  }
220
  });
221
- }
222
 
223
- $('#qm').find('.qm-filter-trigger').on('click',function(e){
224
- var filter = $(this).data('qm-filter'),
225
- value = $(this).data('qm-value'),
226
- target = $(this).data('qm-target');
227
- $('#qm-' + target).find('.qm-filter').not('[data-filter="' + filter + '"]').val('').removeClass('qm-highlight').change();
228
- $('#qm-' + target).find('[data-filter="' + filter + '"]').val(value).addClass('qm-highlight').change();
229
- $('html, body').scrollTop( $(this).closest('.qm').offset().top );
230
- $('html, body').animate({
231
- scrollTop: $('#qm-' + target).offset().top
232
- }, 500);
233
- e.preventDefault();
234
- });
235
-
236
- $('#qm').find('.qm-toggle').on('click',function(e){
237
- var el = $(this);
238
- $(this).closest('td').find('.qm-toggled').slideToggle(100,function(){
239
- if ( el.attr('data-off') == el.text() ) {
240
- el.closest('td').removeClass('qm-toggled-on');
241
- el.text(el.attr('data-on'));
 
 
 
 
 
 
 
 
 
 
242
  } else {
243
  el.closest('td').addClass('qm-toggled-on');
244
  el.text(el.attr('data-off'));
 
245
  }
 
246
  });
247
- e.preventDefault();
248
- });
249
-
250
- $('#qm').find('.qm-highlighter').on('mouseenter',function(e){
251
 
252
- var subject = $(this).data('qm-highlight');
253
- var table = $(this).closest('table');
254
 
255
- if ( ! subject ) {
256
- return;
257
- }
258
 
259
- $(this).addClass('qm-highlight');
260
-
261
- $.each( subject.split(' '), function( i, el ){
262
- table.find('tr[data-qm-subject="' + el + '"]').addClass('qm-highlight');
263
- });
264
 
265
- }).on('mouseleave',function(e){
266
 
267
- $(this).removeClass('qm-highlight');
268
- $(this).closest('table').find('tr').removeClass('qm-highlight');
 
269
 
270
- });
271
 
272
- $( document ).ajaxSuccess( function( event, response, options ) {
 
273
 
274
- var errors = response.getResponseHeader( 'X-QM-error-count' );
275
 
276
- if ( ! errors ) {
277
- return event;
278
- }
279
 
280
- errors = parseInt( errors, 10 );
281
 
282
- for ( var key = 1; key <= errors; key++ ) {
 
 
283
 
284
- error = $.parseJSON( response.getResponseHeader( 'X-QM-error-' + key ) );
285
 
286
  if ( window.console ) {
287
- console.debug( '=== ' + qm_l10n.ajax_error + ' ===' );
288
- console.debug( error );
289
  }
290
 
291
- if ( $('#wp-admin-bar-query-monitor').length ) {
292
- if ( ! qm.ajax_errors[error.type] ) {
293
- $('#wp-admin-bar-query-monitor')
294
- .addClass('qm-' + error.type)
295
- .find('a').first().append('<span class="ab-label qm-ajax-' + error.type + '"> &nbsp; AJAX: ' + error.type + '</span>')
296
- ;
297
- }
298
- }
299
-
300
- qm.ajax_errors[error.type] = true;
301
 
302
- }
303
 
304
- return event;
 
 
305
 
306
- } );
 
 
 
 
 
 
 
307
 
308
- if ( is_admin ) {
309
- $('#qm').detach().appendTo('#wpwrap');
310
- }
311
 
312
- $('.qm-auth').on('click',function(e){
313
- var action = $(this).data('action');
314
-
315
- $.ajax(qm_l10n.ajaxurl,{
316
- type : 'POST',
317
- data : {
318
- action : 'qm_auth_' + action,
319
- nonce : qm_l10n.auth_nonce[action]
320
- },
321
- success : function(response){
322
- alert( response.data );
323
- },
324
- dataType : 'json',
325
- xhrFields: {
326
- withCredentials: true
327
  }
328
- });
329
 
330
- e.preventDefault();
331
- });
332
-
333
- $.qm.tableSort({target: $('.qm-sortable'), debug: false});
334
-
335
- } );
336
-
337
- /**
338
- * Table sorting library.
339
- *
340
- * This is a modified version of jQuery table-sort v0.1.1
341
- * https://github.com/gajus/table-sort
342
- *
343
- * Licensed under the BSD.
344
- * https://github.com/gajus/table-sort/blob/master/LICENSE
345
- *
346
- * Author: Gajus Kuizinas <g.kuizinas@anuary.com>
347
- */
348
- (function ($) {
349
- $.qm = $.qm || {};
350
- $.qm.tableSort = function (options) {
351
- var settings = $.extend({
352
- 'debug': false
353
- }, options);
354
-
355
- // @param object columns NodeList table colums.
356
- // @param integer row_width defines the number of columns per row.
357
- var table_to_array = function (columns, row_width) {
358
- if (settings.debug) {
359
- console.time('table to array');
360
  }
361
 
362
- columns = Array.prototype.slice.call(columns, 0);
363
 
364
- var rows = [];
365
- var row_index = 0;
366
 
367
- for (var i = 0, j = columns.length; i < j; i += row_width) {
368
- var row = [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
 
370
- for (var k = 0, l = row_width; k < l; k++) {
371
- var e = columns[i + k];
372
 
373
- var data = e.dataset.qmSortWeight;
374
 
375
- if (data === undefined) {
376
- data = e.textContent || e.innerText;
377
- }
378
 
379
- var number = parseFloat(data);
380
 
381
- data = isNaN(number) ? data : number;
 
 
382
 
383
- row.push(data);
384
- }
 
385
 
386
- rows.push({index: row_index++, data: row});
 
 
 
387
  }
 
388
 
389
- if (settings.debug) {
390
- console.timeEnd('table to array');
391
- }
392
 
393
- return rows;
394
- };
395
 
396
- if ( ! settings.target || ! settings.target instanceof $) {
397
- throw 'Target is not defined or it is not instance of jQuery.';
 
 
 
 
 
 
 
398
  }
399
 
400
- settings.target.each(function () {
401
- var table = $(this);
 
402
 
403
- table.find('.qm-sort').on('click', function (e) {
404
- var desc = $(this).hasClass('qm-sort-desc');
 
 
 
 
 
 
405
 
406
- var index = $(this).closest('th').index();
 
 
 
 
407
 
408
- table.find('th').removeClass('qm-sorted-asc qm-sorted-desc');
 
 
 
 
 
409
 
410
- if ( desc ) {
411
- $(this).closest('th').addClass('qm-sorted-desc');
412
- } else {
413
- $(this).closest('th').addClass('qm-sorted-asc');
414
- }
415
 
416
- table.find('tbody:not(.qm-sort-no)').each(function () {
417
- var tbody = $(this);
 
418
 
419
- var rows = this.rows;
 
 
 
 
420
 
421
- var anomalies = $(rows).has('[colspan]').detach();
 
 
422
 
423
- var columns = this.getElementsByTagName('td');
424
 
425
- if (this.data_matrix === undefined) {
426
- this.data_matrix = table_to_array(columns, $(rows[0]).find('td').length);
427
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
 
429
- var data = this.data_matrix;
430
 
431
- if (settings.debug) {
432
- console.time('sort data');
433
  }
434
 
435
- data.sort(function (a, b) {
436
- if (a.data[index] == b.data[index]) {
437
- return 0;
438
- }
439
 
440
- return (desc ? a.data[index] > b.data[index] : a.data[index] < b.data[index]) ? -1 : 1;
441
- });
 
 
 
 
 
 
 
442
 
443
- if (settings.debug) {
444
- console.timeEnd('sort data');
445
- console.time('build table');
 
 
 
 
 
 
 
446
  }
447
 
448
- // Will use this to re-attach the tbody object.
449
- var table = tbody.parent();
 
 
450
 
451
- // Detach the tbody to prevent unnecassy overhead related
452
- // to the browser environment.
453
- tbody = tbody.detach();
454
 
455
- // Convert NodeList into an array.
456
- rows = Array.prototype.slice.call(rows, 0);
457
 
458
- var last_row = rows[data[data.length - 1].index];
 
 
 
459
 
460
- for (var i = 0, j = data.length - 1; i < j; i++) {
461
- tbody[0].insertBefore(rows[data[i].index], last_row);
462
 
463
- // Restore the index.
464
- data[i].index = i;
465
- }
466
 
467
- // // Restore the index.
468
- data[data.length - 1].index = data.length - 1;
469
 
470
- tbody.prepend(anomalies);
471
 
472
- table.append(tbody);
 
473
 
474
- if (settings.debug) {
475
- console.timeEnd('build table');
476
- }
 
 
 
 
 
 
 
477
  });
478
- e.preventDefault();
479
  });
480
- });
481
- };
482
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  if ( num_str.length > 3 ) {
39
  for ( i = num_str.length; i > 3; i -= 3 ) {
40
+ o = qm_number_format.thousands_sep + num_str.slice( i - 3, i ) + o;
41
  }
42
  o = num_str.slice( 0, i ) + o;
43
  } else {
45
  }
46
 
47
  if ( decimals ) {
48
+ o = o + qm_number_format.decimal_point + fraction;
49
  }
50
 
51
  return o;
54
 
55
  };
56
 
57
+ if ( window.jQuery ) {
58
 
59
+ jQuery( function($) {
60
+ var minheight = 100;
61
+ var maxheight = ( $(window).height() - 50 );
62
+ var container = $('#query-monitor');
63
+ var container_storage_key = 'qm-container-height';
64
+ var container_pinned_key = 'qm-container-pinned';
 
 
 
65
 
66
+ if ( $('#query-monitor').hasClass('qm-peek') ) {
67
+ minheight = 27;
68
+ }
69
 
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');
80
+ $('#qm-panels').scrollTop(0);
81
+ $( panel ).addClass('qm-panel-show');
 
 
 
 
82
 
83
+ if ( container.height() < minheight ) {
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();
92
+ var menu_height = $('#qm-panel-menu').height();
93
+ var menu_scroll = $('#qm-panel-menu').scrollTop();
94
 
95
+ if ( ( selected_menu_pos.top > ( menu_height + menu_scroll ) ) || ( selected_menu_pos.top < menu_scroll ) ) {
96
+ $('#qm-panel-menu').scrollTop( selected_menu_pos.top - ( menu_height / 2 ) );
97
+ }
98
+ }
99
 
100
+ $('.qm-title-heading select').val(panel);
 
101
 
102
+ if ( localStorage.getItem( container_pinned_key ) ) {
103
+ localStorage.setItem( container_pinned_key, panel );
104
  }
 
 
 
 
105
 
106
+ $( panel ).find('.qm-filter').change();
 
107
 
108
+ };
 
 
109
 
110
+ if ( $('#wp-admin-bar-query-monitor').length ) {
 
111
 
112
+ var admin_bar_menu_container = document.createDocumentFragment();
 
113
 
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
+ ;
120
 
121
+ $.each( qm.menu.sub, function( i, el ) {
 
 
122
 
123
+ var new_menu = $('#wp-admin-bar-query-monitor-placeholder')
124
+ .clone()
125
+ .attr('id','wp-admin-bar-' + el.id)
126
+ ;
127
+ new_menu
128
+ .find('a').eq(0)
129
+ .html(el.title)
130
+ .attr('href',el.href)
131
+ ;
132
 
133
+ if ( ( typeof el.meta != 'undefined' ) && ( typeof el.meta.classname != 'undefined' ) ) {
134
+ new_menu.addClass(el.meta.classname);
135
+ }
136
 
137
+ admin_bar_menu_container.appendChild( new_menu.get(0) );
138
 
139
+ } );
140
 
141
+ $('#wp-admin-bar-query-monitor ul').append(admin_bar_menu_container);
142
+ }
143
 
144
+ $('#wp-admin-bar-query-monitor').find('a').on('click',link_click);
 
 
 
 
 
145
 
146
+ $('#wp-admin-bar-query-monitor,#wp-admin-bar-query-monitor-default').show();
147
 
148
+ } else {
149
+ $('#query-monitor').addClass('qm-peek').removeClass('qm-hide');
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
 
157
+ var filter = $(this).attr('data-filter'),
158
+ table = $(this).closest('table'),
159
+ tr = table.find('tbody tr[data-qm-' + filter + ']'),
160
+ // Escape the following chars with a backslash before passing into jQ selectors: [ ] ( ) ' " \
161
+ val = $(this).val().replace(/[[\]()'"\\]/g, "\\$&"),
162
+ total = tr.removeClass('qm-hide-' + filter).length,
163
+ hilite = $(this).attr('data-highlight'),
164
+ time = 0;
165
 
 
166
  key = $(this).attr('id');
167
  if ( val ) {
168
  localStorage.setItem( key, $(this).val() );
169
  } else {
170
  localStorage.removeItem( key );
171
  }
 
 
 
 
 
172
 
 
173
  if ( hilite ) {
174
+ table.find('tr').removeClass('qm-highlight');
175
  }
 
 
 
 
 
176
 
177
+ if ( $(this).val() !== '' ) {
178
+ if ( hilite ) {
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');
188
+ matches.each(function(i){
189
+ var row_time = $(this).attr('data-qm-time');
190
+ if ( row_time ) {
191
+ time += parseFloat( row_time );
192
+ }
193
+ });
194
+ if ( time ) {
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 () {
210
  var key = $(this).attr('id');
211
  var value = localStorage.getItem( key );
212
  if ( value !== null ) {
218
  $(this).val(value).change();
219
  }
220
  });
 
221
 
222
+ $('#query-monitor').find('.qm-filter-trigger').on('click',function(e){
223
+ var filter = $(this).data('qm-filter'),
224
+ value = $(this).data('qm-value'),
225
+ target = $(this).data('qm-target');
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
+
232
+ $('#query-monitor').find('.qm-toggle').on('click',function(e){
233
+ var el = $(this);
234
+ var currentState = el.attr('aria-expanded');
235
+ var newState = 'true';
236
+ if (currentState === 'true') {
237
+ newState = 'false';
238
+ }
239
+ el.attr('aria-expanded', newState);
240
+ var toggle = $(this).closest('td').find('.qm-toggled');
241
+ if ( currentState === 'true' ) {
242
+ if ( toggle.length ) {
243
+ toggle.slideToggle(200,function(){
244
+ el.closest('td').removeClass('qm-toggled-on');
245
+ el.text(el.attr('data-on'));
246
+ });
247
+ } else {
248
+ el.closest('td').removeClass('qm-toggled-on');
249
+ el.text(el.attr('data-on'));
250
+ }
251
  } else {
252
  el.closest('td').addClass('qm-toggled-on');
253
  el.text(el.attr('data-off'));
254
+ toggle.slideToggle(200);
255
  }
256
+ e.preventDefault();
257
  });
 
 
 
 
258
 
259
+ $('#query-monitor').find('.qm-highlighter').on('mouseenter',function(e){
 
260
 
261
+ var subject = $(this).data('qm-highlight');
262
+ var table = $(this).closest('table');
 
263
 
264
+ if ( ! subject ) {
265
+ return;
266
+ }
 
 
267
 
268
+ $(this).addClass('qm-highlight');
269
 
270
+ $.each( subject.split(' '), function( i, el ){
271
+ table.find('tr[data-qm-subject="' + el + '"]').addClass('qm-highlight');
272
+ });
273
 
274
+ }).on('mouseleave',function(e){
275
 
276
+ $(this).removeClass('qm-highlight');
277
+ $(this).closest('table').find('tr').removeClass('qm-highlight');
278
 
279
+ });
280
 
281
+ $( document ).ajaxSuccess( function( event, response, options ) {
 
 
282
 
283
+ var errors = response.getResponseHeader( 'X-QM-php_errors-error-count' );
284
 
285
+ if ( ! errors ) {
286
+ return event;
287
+ }
288
 
289
+ errors = parseInt( errors, 10 );
290
 
291
  if ( window.console ) {
292
+ console.group( qm_l10n.ajax_error );
 
293
  }
294
 
295
+ for ( var key = 1; key <= errors; key++ ) {
 
 
 
 
 
 
 
 
 
296
 
297
+ error = $.parseJSON( response.getResponseHeader( 'X-QM-php_errors-error-' + key ) );
298
 
299
+ if ( window.console ) {
300
+ console.error( error );
301
+ }
302
 
303
+ if ( $('#wp-admin-bar-query-monitor').length ) {
304
+ if ( ! qm.ajax_errors[error.type] ) {
305
+ $('#wp-admin-bar-query-monitor')
306
+ .addClass('qm-' + error.type)
307
+ .find('a').first().append('<span class="ab-label qm-ajax-' + error.type + '"> &nbsp; Ajax: ' + error.type + '</span>')
308
+ ;
309
+ }
310
+ }
311
 
312
+ qm.ajax_errors[error.type] = true;
 
 
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  }
 
315
 
316
+ if ( window.console ) {
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: {
338
+ withCredentials: true
339
+ }
340
+ });
341
 
342
+ e.preventDefault();
343
+ });
344
 
345
+ $.qm.tableSort({target: $('.qm-sortable')});
346
 
347
+ var startY, resizerHeight, toolbarHeight;
 
 
348
 
349
+ toolbarHeight = $('#wpadminbar').outerHeight();
350
 
351
+ $(document).on('mousedown', '#qm-title', function(event) {
352
+ resizerHeight = $(this).outerHeight() - 1;
353
+ startY = container.outerHeight() + event.clientY;
354
 
355
+ $(document).on('mousemove', qm_do_resizer_drag);
356
+ $(document).on('mouseup', qm_stop_resizer_drag);
357
+ });
358
 
359
+ function qm_do_resizer_drag(event) {
360
+ var h = ( startY - event.clientY );
361
+ if ( h >= resizerHeight && h < ( $(window).height() - toolbarHeight ) ) {
362
+ container.height( h );
363
  }
364
+ }
365
 
366
+ function qm_stop_resizer_drag(event) {
367
+ $(document).off('mousemove', qm_do_resizer_drag);
368
+ $(document).off('mouseup', qm_stop_resizer_drag);
369
 
370
+ localStorage.setItem( container_storage_key, container.height() );
371
+ }
372
 
373
+ var h = localStorage.getItem( container_storage_key );
374
+ if ( h !== null && ! $('#query-monitor').hasClass('qm-peek') ) {
375
+ if ( h < minheight ) {
376
+ h = minheight;
377
+ }
378
+ if ( h > maxheight ) {
379
+ h = maxheight;
380
+ }
381
+ container.height( h );
382
  }
383
 
384
+ $(window).on('resize', function(){
385
+ var maxheight = ( $(window).height() - toolbarHeight );
386
+ var h = container.height();
387
 
388
+ if ( h < minheight ) {
389
+ container.height( minheight );
390
+ }
391
+ if ( h > maxheight ) {
392
+ container.height( maxheight );
393
+ }
394
+ localStorage.setItem( container_storage_key, container.height() );
395
+ });
396
 
397
+ $('.qm-button-container-close').click(function(){
398
+ $('#query-monitor').removeClass('qm-show');
399
+ localStorage.removeItem( container_pinned_key );
400
+ $('.qm-button-container-pin').removeClass( 'qm-button-active' );
401
+ });
402
 
403
+ $('.qm-button-container-pin').click(function(){
404
+ if ( $(this).hasClass( 'qm-button-active' ) ) {
405
+ localStorage.removeItem( container_pinned_key );
406
+ } else {
407
+ localStorage.setItem( container_pinned_key, '#' + $('.qm-panel-show').first().attr('id') );
408
+ }
409
 
410
+ $(this).toggleClass( 'qm-button-active' );
411
+ });
 
 
 
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
+ } );
428
 
429
+ /**
430
+ * Table sorting library.
431
+ *
432
+ * This is a modified version of jQuery table-sort v0.1.1
433
+ * https://github.com/gajus/table-sort
434
+ *
435
+ * Licensed under the BSD.
436
+ * https://github.com/gajus/table-sort/blob/master/LICENSE
437
+ *
438
+ * Author: Gajus Kuizinas <g.kuizinas@anuary.com>
439
+ */
440
+ (function ($) {
441
+ $.qm = $.qm || {};
442
+ $.qm.tableSort = function (settings) {
443
+ // @param object columns NodeList table colums.
444
+ // @param integer row_width defines the number of columns per row.
445
+ var table_to_array = function (columns, row_width) {
446
+ columns = Array.prototype.slice.call(columns, 0);
447
+
448
+ var rows = [];
449
+ var row_index = 0;
450
+
451
+ for (var i = 0, j = columns.length; i < j; i += row_width) {
452
+ var row = [];
453
+
454
+ for (var k = 0; k < row_width; k++) {
455
+ var e = columns[i + k];
456
+ var data = e.dataset.qmSortWeight;
457
+
458
+ if (data === undefined) {
459
+ data = e.textContent || e.innerText;
460
+ }
461
+
462
+ var number = parseFloat(data);
463
 
464
+ data = isNaN(number) ? data : number;
465
 
466
+ row.push(data);
 
467
  }
468
 
469
+ rows.push({index: row_index++, data: row});
470
+ }
 
 
471
 
472
+ return rows;
473
+ };
474
+
475
+ if ( ! settings.target || ! ( settings.target instanceof $) ) {
476
+ throw 'Target is not defined or it is not instance of jQuery.';
477
+ }
478
+
479
+ settings.target.each(function () {
480
+ var table = $(this);
481
 
482
+ table.find('.qm-sortable-column').on('click', function (e) {
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;
 
504
 
505
+ data.sort(function (a, b) {
506
+ if (a.data[index] == b.data[index]) {
507
+ return 0;
508
+ }
509
 
510
+ return (desc ? a.data[index] > b.data[index] : a.data[index] < b.data[index]) ? -1 : 1;
511
+ });
512
 
513
+ // Detach the tbody to prevent unnecessary overhead related
514
+ // to the browser environment.
515
+ tbody = tbody.detach();
516
 
517
+ // Convert NodeList into an array.
518
+ rows = Array.prototype.slice.call(rows, 0);
519
 
520
+ var last_row = rows[data[data.length - 1].index];
521
 
522
+ for (var i = 0, j = data.length - 1; i < j; i++) {
523
+ tbody[0].insertBefore(rows[data[i].index], last_row);
524
 
525
+ // Restore the index.
526
+ data[i].index = i;
527
+ }
528
+
529
+ // Restore the index.
530
+ data[data.length - 1].index = data.length - 1;
531
+
532
+ table.append(tbody);
533
+ });
534
+ e.preventDefault();
535
  });
 
536
  });
537
+ };
538
+ })(jQuery);
539
+
540
+ }
541
+
542
+ if ( ( 'undefined' === typeof jQuery ) || ! jQuery ) {
543
+ window.addEventListener('load', function() {
544
+ /* Fallback for running without jQuery (`QM_NO_JQUERY`) */
545
+ document.getElementById( 'query-monitor' ).className += ' qm-broken';
546
+ console.error( document.getElementById( 'qm-broken' ).textContent );
547
+ var menu_item = document.getElementById( 'wp-admin-bar-query-monitor' );
548
+ if ( menu_item ) {
549
+ menu_item.addEventListener( 'click', function() {
550
+ document.getElementById( 'query-monitor' ).className += ' qm-show';
551
+ } );
552
+ }
553
+ } );
554
+ }
classes/Activation.php CHANGED
@@ -1,23 +1,20 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Activation extends QM_Plugin {
18
 
19
  protected function __construct( $file ) {
20
 
 
 
 
 
 
 
21
  # Filters
22
  add_filter( 'pre_update_option_active_plugins', array( $this, 'filter_active_plugins' ) );
23
  add_filter( 'pre_update_site_option_active_sitewide_plugins', array( $this, 'filter_active_sitewide_plugins' ) );
@@ -98,6 +95,24 @@ class QM_Activation extends QM_Plugin {
98
 
99
  }
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  public static function init( $file = null ) {
102
 
103
  static $instance = null;
1
  <?php
2
+ /**
3
+ * Plugin activation handler.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Activation extends QM_Plugin {
9
 
10
  protected function __construct( $file ) {
11
 
12
+ # PHP version handling
13
+ if ( ! self::php_version_met() ) {
14
+ add_action( 'all_admin_notices', array( $this, 'php_notice' ) );
15
+ return;
16
+ }
17
+
18
  # Filters
19
  add_filter( 'pre_update_option_active_plugins', array( $this, 'filter_active_plugins' ) );
20
  add_filter( 'pre_update_site_option_active_sitewide_plugins', array( $this, 'filter_active_sitewide_plugins' ) );
95
 
96
  }
97
 
98
+ public function php_notice() {
99
+ ?>
100
+ <div id="qm_php_notice" class="error">
101
+ <p>
102
+ <span class="dashicons dashicons-warning" style="color:#dd3232" aria-hidden="true"></span>
103
+ <?php
104
+ echo esc_html( sprintf(
105
+ /* Translators: 1: Minimum required PHP version, 2: Current PHP version. */
106
+ __( 'The Query Monitor plugin requires PHP version %1$s or higher. This site is running version %2$s.', 'query-monitor' ),
107
+ self::$minimum_php_version,
108
+ PHP_VERSION
109
+ ) );
110
+ ?>
111
+ </p>
112
+ </div>
113
+ <?php
114
+ }
115
+
116
  public static function init( $file = null ) {
117
 
118
  static $instance = null;
classes/Backtrace.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  if ( ! class_exists( 'QM_Backtrace' ) ) {
18
  class QM_Backtrace {
@@ -20,7 +11,6 @@ class QM_Backtrace {
20
  protected static $ignore_class = array(
21
  'wpdb' => true,
22
  'QueryMonitor' => true,
23
- 'ExtQuery' => true,
24
  'W3_Db' => true,
25
  'Debug_Bar_PHP' => true,
26
  'WP_Hook' => true,
@@ -65,10 +55,9 @@ class QM_Backtrace {
65
  protected $calling_file = '';
66
 
67
  public function __construct( array $args = array() ) {
68
- # @TODO save the args as a property and process the trace JIT
69
  $args = array_merge( array(
70
  'ignore_current_filter' => true,
71
- 'ignore_items' => 0,
72
  ), $args );
73
  $this->trace = debug_backtrace( false );
74
  $this->ignore( 1 ); # Self-awareness
@@ -81,13 +70,33 @@ class QM_Backtrace {
81
  $this->ignore( 1 );
82
  }
83
 
84
- if ( $args['ignore_items'] ) {
85
- $this->ignore( $args['ignore_items'] );
86
  }
87
  if ( $args['ignore_current_filter'] ) {
88
  $this->ignore_current_filter();
89
  }
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  }
92
 
93
  public function get_stack() {
@@ -111,29 +120,35 @@ class QM_Backtrace {
111
 
112
  $components = array();
113
 
114
- foreach ( $this->trace as $item ) {
115
  try {
116
 
117
- if ( isset( $item['class'] ) ) {
118
- if ( ! is_object( $item['class'] ) and ! class_exists( $item['class'], false ) ) {
119
  continue;
120
  }
121
- if ( ! method_exists( $item['class'], $item['function'] ) ) {
122
  continue;
123
  }
124
- $ref = new ReflectionMethod( $item['class'], $item['function'] );
125
  $file = $ref->getFileName();
126
- } elseif ( function_exists( $item['function'] ) ) {
127
- $ref = new ReflectionFunction( $item['function'] );
128
  $file = $ref->getFileName();
129
- } elseif ( isset( $item['file'] ) ) {
130
- $file = $item['file'];
131
  } else {
132
  continue;
133
  }
134
 
135
  $comp = QM_Util::get_file_component( $file );
136
  $components[ $comp->type ] = $comp;
 
 
 
 
 
 
137
  } catch ( ReflectionException $e ) {
138
  # nothing
139
  }
@@ -236,7 +251,7 @@ class QM_Backtrace {
236
 
237
  if ( 'dir' === $show ) {
238
  if ( isset( $trace['args'][0] ) ) {
239
- $arg = QM_Util::standard_dir( $trace['args'][0], '~/' );
240
  $return['id'] = $trace['function'] . '()';
241
  $return['display'] = $trace['function'] . "('{$arg}')";
242
  }
1
  <?php
2
+ /**
3
+ * Function call backtrace container.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  if ( ! class_exists( 'QM_Backtrace' ) ) {
9
  class QM_Backtrace {
11
  protected static $ignore_class = array(
12
  'wpdb' => true,
13
  'QueryMonitor' => true,
 
14
  'W3_Db' => true,
15
  'Debug_Bar_PHP' => true,
16
  'WP_Hook' => true,
55
  protected $calling_file = '';
56
 
57
  public function __construct( array $args = array() ) {
 
58
  $args = array_merge( array(
59
  'ignore_current_filter' => true,
60
+ 'ignore_frames' => 0,
61
  ), $args );
62
  $this->trace = debug_backtrace( false );
63
  $this->ignore( 1 ); # Self-awareness
70
  $this->ignore( 1 );
71
  }
72
 
73
+ if ( $args['ignore_frames'] ) {
74
+ $this->ignore( $args['ignore_frames'] );
75
  }
76
  if ( $args['ignore_current_filter'] ) {
77
  $this->ignore_current_filter();
78
  }
79
 
80
+ foreach ( $this->trace as $k => $frame ) {
81
+ if ( ! isset( $frame['args'] ) ) {
82
+ continue;
83
+ }
84
+
85
+ if ( isset( self::$show_args[ $frame['function'] ] ) ) {
86
+ $show = self::$show_args[ $frame['function'] ];
87
+
88
+ if ( 'dir' === $show ) {
89
+ $show = 1;
90
+ }
91
+
92
+ $frame['args'] = array_slice( $frame['args'], 0, $show );
93
+
94
+ } else {
95
+ unset( $frame['args'] );
96
+ }
97
+
98
+ $this->trace[ $k ] = $frame;
99
+ }
100
  }
101
 
102
  public function get_stack() {
120
 
121
  $components = array();
122
 
123
+ foreach ( $this->trace as $frame ) {
124
  try {
125
 
126
+ if ( isset( $frame['class'] ) ) {
127
+ if ( ! class_exists( $frame['class'], false ) ) {
128
  continue;
129
  }
130
+ if ( ! method_exists( $frame['class'], $frame['function'] ) ) {
131
  continue;
132
  }
133
+ $ref = new ReflectionMethod( $frame['class'], $frame['function'] );
134
  $file = $ref->getFileName();
135
+ } elseif ( isset( $frame['function'] ) && function_exists( $frame['function'] ) ) {
136
+ $ref = new ReflectionFunction( $frame['function'] );
137
  $file = $ref->getFileName();
138
+ } elseif ( isset( $frame['file'] ) ) {
139
+ $file = $frame['file'];
140
  } else {
141
  continue;
142
  }
143
 
144
  $comp = QM_Util::get_file_component( $file );
145
  $components[ $comp->type ] = $comp;
146
+
147
+ if ( 'plugin' === $comp->type ) {
148
+ // If the component is a plugin then it can't be anything else,
149
+ // so short-circuit and return early.
150
+ return $comp;
151
+ }
152
  } catch ( ReflectionException $e ) {
153
  # nothing
154
  }
251
 
252
  if ( 'dir' === $show ) {
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
  }
classes/Collector.php CHANGED
@@ -1,22 +1,14 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  if ( ! class_exists( 'QM_Collector' ) ) {
18
  abstract class QM_Collector {
19
 
 
20
  protected $data = array(
21
  'types' => array(),
22
  'component_times' => array(),
@@ -57,13 +49,11 @@ abstract class QM_Collector {
57
  if ( ! isset( $this->data['component_times'][ $component->name ] ) ) {
58
  $this->data['component_times'][ $component->name ] = array(
59
  'component' => $component->name,
60
- 'calls' => 0,
61
  'ltime' => 0,
62
  'types' => array(),
63
  );
64
  }
65
 
66
- $this->data['component_times'][ $component->name ]['calls']++;
67
  $this->data['component_times'][ $component->name ]['ltime'] += $ltime;
68
 
69
  if ( isset( $this->data['component_times'][ $component->name ]['types'][ $type ] ) ) {
@@ -124,7 +114,17 @@ abstract class QM_Collector {
124
 
125
  public function process() {}
126
 
 
 
127
  public function tear_down() {}
128
 
 
 
 
 
 
 
 
 
129
  }
130
  }
1
  <?php
2
+ /**
3
+ * Abstract data collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  if ( ! class_exists( 'QM_Collector' ) ) {
9
  abstract class QM_Collector {
10
 
11
+ protected $timer;
12
  protected $data = array(
13
  'types' => array(),
14
  'component_times' => array(),
49
  if ( ! isset( $this->data['component_times'][ $component->name ] ) ) {
50
  $this->data['component_times'][ $component->name ] = array(
51
  'component' => $component->name,
 
52
  'ltime' => 0,
53
  'types' => array(),
54
  );
55
  }
56
 
 
57
  $this->data['component_times'][ $component->name ]['ltime'] += $ltime;
58
 
59
  if ( isset( $this->data['component_times'][ $component->name ]['types'][ $type ] ) ) {
114
 
115
  public function process() {}
116
 
117
+ public function post_process() {}
118
+
119
  public function tear_down() {}
120
 
121
+ public function get_timer() {
122
+ return $this->timer;
123
+ }
124
+
125
+ public function set_timer( QM_Timer $timer ) {
126
+ $this->timer = $timer;
127
+ }
128
+
129
  }
130
  }
classes/Collectors.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  if ( ! class_exists( 'QM_Collectors' ) ) {
18
  class QM_Collectors implements IteratorAggregate {
@@ -52,10 +43,22 @@ class QM_Collectors implements IteratorAggregate {
52
  if ( $this->processed ) {
53
  return;
54
  }
 
55
  foreach ( $this as $collector ) {
56
  $collector->tear_down();
 
 
 
 
57
  $collector->process();
 
 
58
  }
 
 
 
 
 
59
  $this->processed = true;
60
  }
61
 
1
  <?php
2
+ /**
3
+ * Container for data collectors.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  if ( ! class_exists( 'QM_Collectors' ) ) {
9
  class QM_Collectors implements IteratorAggregate {
43
  if ( $this->processed ) {
44
  return;
45
  }
46
+
47
  foreach ( $this as $collector ) {
48
  $collector->tear_down();
49
+
50
+ $timer = new QM_Timer;
51
+ $timer->start();
52
+
53
  $collector->process();
54
+
55
+ $collector->set_timer( $timer->stop() );
56
  }
57
+
58
+ foreach ( $this as $collector ) {
59
+ $collector->post_process();
60
+ }
61
+
62
  $this->processed = true;
63
  }
64
 
classes/Dispatcher.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  if ( ! class_exists( 'QM_Dispatcher' ) ) {
18
  abstract class QM_Dispatcher {
@@ -49,21 +40,12 @@ abstract class QM_Dispatcher {
49
  }
50
 
51
  public function get_outputters( $outputter_id ) {
52
-
53
- $out = array();
54
-
55
  $collectors = QM_Collectors::init();
56
  $collectors->process();
57
 
58
  $this->outputters = apply_filters( "qm/outputter/{$outputter_id}", array(), $collectors );
59
 
60
- /* @var QM_Output[] */
61
- foreach ( $this->outputters as $id => $outputter ) {
62
- $out[ $id ] = $outputter;
63
- }
64
-
65
- return $out;
66
-
67
  }
68
 
69
  public function init() {
1
  <?php
2
+ /**
3
+ * Abstract dispatcher.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  if ( ! class_exists( 'QM_Dispatcher' ) ) {
9
  abstract class QM_Dispatcher {
40
  }
41
 
42
  public function get_outputters( $outputter_id ) {
 
 
 
43
  $collectors = QM_Collectors::init();
44
  $collectors->process();
45
 
46
  $this->outputters = apply_filters( "qm/outputter/{$outputter_id}", array(), $collectors );
47
 
48
+ return $this->outputters;
 
 
 
 
 
 
49
  }
50
 
51
  public function init() {
classes/Dispatchers.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Dispatchers implements IteratorAggregate {
18
 
1
  <?php
2
+ /**
3
+ * Container for dispatchers.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Dispatchers implements IteratorAggregate {
9
 
classes/Output.php CHANGED
@@ -1,23 +1,15 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  if ( ! class_exists( 'QM_Output' ) ) {
18
  abstract class QM_Output {
19
 
20
  protected $collector;
 
21
 
22
  public function __construct( QM_Collector $collector ) {
23
  $this->collector = $collector;
@@ -33,5 +25,13 @@ abstract class QM_Output {
33
  return $this->collector;
34
  }
35
 
 
 
 
 
 
 
 
 
36
  }
37
  }
1
  <?php
2
+ /**
3
+ * Abstract output handler.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  if ( ! class_exists( 'QM_Output' ) ) {
9
  abstract class QM_Output {
10
 
11
  protected $collector;
12
+ protected $timer;
13
 
14
  public function __construct( QM_Collector $collector ) {
15
  $this->collector = $collector;
25
  return $this->collector;
26
  }
27
 
28
+ final public function get_timer() {
29
+ return $this->timer;
30
+ }
31
+
32
+ final public function set_timer( QM_Timer $timer ) {
33
+ $this->timer = $timer;
34
+ }
35
+
36
  }
37
  }
classes/Plugin.php CHANGED
@@ -1,23 +1,15 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  if ( ! class_exists( 'QM_Plugin' ) ) {
18
  abstract class QM_Plugin {
19
 
20
  private $plugin = array();
 
21
 
22
  /**
23
  * Class constructor
@@ -93,5 +85,15 @@ abstract class QM_Plugin {
93
  return $this->plugin[ $item ] . ltrim( $file, '/' );
94
  }
95
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
  }
1
  <?php
2
+ /**
3
+ * Abstract plugin wrapper.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  if ( ! class_exists( 'QM_Plugin' ) ) {
9
  abstract class QM_Plugin {
10
 
11
  private $plugin = array();
12
+ public static $minimum_php_version = '5.3.6';
13
 
14
  /**
15
  * Class constructor
85
  return $this->plugin[ $item ] . ltrim( $file, '/' );
86
  }
87
 
88
+ public static function php_version_met() {
89
+ static $met = null;
90
+
91
+ if ( null === $met ) {
92
+ $met = version_compare( PHP_VERSION, self::$minimum_php_version, '>=' );
93
+ }
94
+
95
+ return $met;
96
+ }
97
+
98
  }
99
  }
classes/QueryMonitor.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QueryMonitor extends QM_Plugin {
18
 
@@ -29,7 +20,13 @@ class QueryMonitor extends QM_Plugin {
29
  parent::__construct( $file );
30
 
31
  # Load and register built-in collectors:
32
- foreach ( apply_filters( 'qm/built-in-collectors', glob( $this->plugin_path( 'collectors/*.php' ) ) ) as $file ) {
 
 
 
 
 
 
33
  include $file;
34
  }
35
 
1
  <?php
2
+ /**
3
+ * The main Query Monitor plugin class.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QueryMonitor extends QM_Plugin {
9
 
20
  parent::__construct( $file );
21
 
22
  # Load and register built-in collectors:
23
+ $collectors = array();
24
+ foreach ( glob( $this->plugin_path( 'collectors/*.php' ) ) as $file ) {
25
+ $key = basename( $file, '.php' );
26
+ $collectors[ $key ] = $file;
27
+ }
28
+
29
+ foreach ( apply_filters( 'qm/built-in-collectors', $collectors ) as $file ) {
30
  include $file;
31
  }
32
 
classes/Timer.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Timer that collects timing and memory usage.
4
+ *
5
+ * @package query-monitor
6
+ */
7
+
8
+ class QM_Timer {
9
+
10
+ protected $start = null;
11
+ protected $end = null;
12
+ protected $trace = null;
13
+ protected $laps = array();
14
+
15
+ public function start( array $data = null ) {
16
+ $this->trace = new QM_Backtrace;
17
+ $this->start = array(
18
+ 'time' => microtime( true ),
19
+ 'memory' => memory_get_usage(),
20
+ 'data' => $data,
21
+ );
22
+ return $this;
23
+ }
24
+
25
+ public function stop( array $data = null ) {
26
+
27
+ $this->end = array(
28
+ 'time' => microtime( true ),
29
+ 'memory' => memory_get_usage(),
30
+ 'data' => $data,
31
+ );
32
+
33
+ return $this;
34
+
35
+ }
36
+
37
+ public function lap( array $data = null, $name = null ) {
38
+
39
+ $lap = array(
40
+ 'time' => microtime( true ),
41
+ 'memory' => memory_get_usage(),
42
+ 'data' => $data,
43
+ );
44
+
45
+ if ( ! isset( $name ) ) {
46
+ /* translators: %d: Timing lap number */
47
+ $i = sprintf( __( 'Lap %d', 'query-monitor' ), count( $this->laps ) + 1 );
48
+ } else {
49
+ $i = $name;
50
+ }
51
+
52
+ $this->laps[ $i ] = $lap;
53
+
54
+ return $this;
55
+
56
+ }
57
+
58
+ public function get_laps() {
59
+
60
+ $laps = array();
61
+ $prev = $this->start;
62
+
63
+ foreach ( $this->laps as $lap_id => $lap ) {
64
+
65
+ $lap['time_used'] = $lap['time'] - $prev['time'];
66
+ $lap['memory_used'] = $lap['memory'] - $prev['memory'];
67
+
68
+ $laps[ $lap_id ] = $prev = $lap;
69
+
70
+ }
71
+
72
+ return $laps;
73
+
74
+ }
75
+
76
+ public function get_time() {
77
+ return $this->end['time'] - $this->start['time'];
78
+ }
79
+
80
+ public function get_memory() {
81
+ return $this->end['memory'] - $this->start['memory'];
82
+ }
83
+
84
+ public function get_trace() {
85
+ return $this->trace;
86
+ }
87
+
88
+ public function end( array $data = null ) {
89
+ return $this->stop( $data );
90
+ }
91
+
92
+ }
classes/Util.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  if ( ! class_exists( 'QM_Util' ) ) {
18
  class QM_Util {
@@ -83,6 +74,7 @@ class QM_Util {
83
  self::$file_dirs['go-plugin'] = self::standard_dir( WPMU_PLUGIN_DIR . '/shared-plugins' );
84
  self::$file_dirs['mu-plugin'] = self::standard_dir( WPMU_PLUGIN_DIR );
85
  self::$file_dirs['vip-plugin'] = self::standard_dir( get_theme_root() . '/vip/plugins' );
 
86
  self::$file_dirs['stylesheet'] = self::standard_dir( get_stylesheet_directory() );
87
  self::$file_dirs['template'] = self::standard_dir( get_template_directory() );
88
  self::$file_dirs['other'] = self::standard_dir( WP_CONTENT_DIR );
@@ -152,9 +144,11 @@ class QM_Util {
152
  } else {
153
  $name = __( 'Theme', 'query-monitor' );
154
  }
 
155
  break;
156
  case 'template':
157
  $name = __( 'Parent Theme', 'query-monitor' );
 
158
  break;
159
  case 'other':
160
  // Anything else that's within the content directory should appear as
1
  <?php
2
+ /**
3
+ * General utilities class.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  if ( ! class_exists( 'QM_Util' ) ) {
9
  class QM_Util {
74
  self::$file_dirs['go-plugin'] = self::standard_dir( WPMU_PLUGIN_DIR . '/shared-plugins' );
75
  self::$file_dirs['mu-plugin'] = self::standard_dir( WPMU_PLUGIN_DIR );
76
  self::$file_dirs['vip-plugin'] = self::standard_dir( get_theme_root() . '/vip/plugins' );
77
+ self::$file_dirs['theme'] = null;
78
  self::$file_dirs['stylesheet'] = self::standard_dir( get_stylesheet_directory() );
79
  self::$file_dirs['template'] = self::standard_dir( get_template_directory() );
80
  self::$file_dirs['other'] = self::standard_dir( WP_CONTENT_DIR );
144
  } else {
145
  $name = __( 'Theme', 'query-monitor' );
146
  }
147
+ $type = 'theme';
148
  break;
149
  case 'template':
150
  $name = __( 'Parent Theme', 'query-monitor' );
151
+ $type = 'theme';
152
  break;
153
  case 'other':
154
  // Anything else that's within the content directory should appear as
classes/debug_bar.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class Debug_Bar {
18
  public $panels = array();
1
  <?php
2
+ /**
3
+ * Mock 'Debug Bar' plugin class.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class Debug_Bar {
9
  public $panels = array();
classes/debug_bar_panel.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  abstract class Debug_Bar_Panel {
18
 
1
  <?php
2
+ /**
3
+ * Mock 'Debug Bar' panel class.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  abstract class Debug_Bar_Panel {
9
 
collectors/admin.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Admin extends QM_Collector {
18
 
@@ -24,7 +15,7 @@ class QM_Collector_Admin extends QM_Collector {
24
 
25
  public function process() {
26
 
27
- global $pagenow;
28
 
29
  $current_screen = get_current_screen();
30
 
@@ -86,12 +77,10 @@ class QM_Collector_Admin extends QM_Collector {
86
  'sortables_filter' => "manage_{$list_table['sortables']}_sortable_columns",
87
  'column_action' => "manage_{$list_table['column']}_custom_column",
88
  );
89
- $this->data['list_table_markup'] = array(
90
- 'columns_filter' => 'manage_<span class="qm-current">' . esc_html( $list_table['columns'] ) . '</span>_columns',
91
- 'sortables_filter' => 'manage_<span class="qm-current">' . esc_html( $list_table['sortables'] ) . '</span>_sortable_columns',
92
- 'column_action' => 'manage_<span class="qm-current">' . esc_html( $list_table['column'] ) . '</span>_custom_column',
93
- );
94
 
 
 
 
95
  }
96
 
97
  }
1
  <?php
2
+ /**
3
+ * Admin screen collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Admin extends QM_Collector {
9
 
15
 
16
  public function process() {
17
 
18
+ global $pagenow, $wp_list_table;
19
 
20
  $current_screen = get_current_screen();
21
 
77
  'sortables_filter' => "manage_{$list_table['sortables']}_sortable_columns",
78
  'column_action' => "manage_{$list_table['column']}_custom_column",
79
  );
 
 
 
 
 
80
 
81
+ if ( ! empty( $wp_list_table ) ) {
82
+ $this->data['list_table']['class_name'] = get_class( $wp_list_table );
83
+ }
84
  }
85
 
86
  }
collectors/assets.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Assets extends QM_Collector {
18
 
@@ -70,7 +61,7 @@ class QM_Collector_Assets extends QM_Collector {
70
  if ( ! empty( $broken ) ) {
71
  foreach ( $broken as $key => $handle ) {
72
  if ( $item = $raw->query( $handle ) ) {
73
- $broken = array_merge( $broken, $this->get_broken_dependencies( $item, $raw ) );
74
  } else {
75
  unset( $broken[ $key ] );
76
  $missing[] = $handle;
@@ -94,20 +85,35 @@ class QM_Collector_Assets extends QM_Collector {
94
  }
95
  }
96
 
97
- protected function get_broken_dependencies( _WP_Dependency $item, WP_Dependencies $dependencies ) {
98
-
99
  $broken = array();
100
 
101
  foreach ( $item->deps as $handle ) {
102
  if ( $dep = $dependencies->query( $handle ) ) {
103
- $broken = array_merge( $broken, $this->get_broken_dependencies( $dep, $dependencies ) );
104
  } else {
105
  $broken[] = $item->handle;
106
  }
107
  }
108
 
109
  return $broken;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
 
111
  }
112
 
113
  public function name() {
1
  <?php
2
+ /**
3
+ * Enqueued scripts and styles collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Assets extends QM_Collector {
9
 
61
  if ( ! empty( $broken ) ) {
62
  foreach ( $broken as $key => $handle ) {
63
  if ( $item = $raw->query( $handle ) ) {
64
+ $broken = array_merge( $broken, self::get_broken_dependencies( $item, $raw ) );
65
  } else {
66
  unset( $broken[ $key ] );
67
  $missing[] = $handle;
85
  }
86
  }
87
 
88
+ protected static function get_broken_dependencies( _WP_Dependency $item, WP_Dependencies $dependencies ) {
 
89
  $broken = array();
90
 
91
  foreach ( $item->deps as $handle ) {
92
  if ( $dep = $dependencies->query( $handle ) ) {
93
+ $broken = array_merge( $broken, self::get_broken_dependencies( $dep, $dependencies ) );
94
  } else {
95
  $broken[] = $item->handle;
96
  }
97
  }
98
 
99
  return $broken;
100
+ }
101
+
102
+ public function get_dependents( _WP_Dependency $dependency, WP_Dependencies $dependencies ) {
103
+ $dependents = array();
104
+ $handles = array_unique( array_merge( $dependencies->queue, $dependencies->done ) );
105
+
106
+ foreach ( $handles as $handle ) {
107
+ if ( $item = $dependencies->query( $handle ) ) {
108
+ if ( in_array( $dependency->handle, $item->deps, true ) ) {
109
+ $dependents[] = $handle;
110
+ }
111
+ }
112
+ }
113
+
114
+ sort( $dependents );
115
 
116
+ return $dependents;
117
  }
118
 
119
  public function name() {
collectors/cache.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Cache extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * Object cache collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Cache extends QM_Collector {
9
 
collectors/caps.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Caps extends QM_Collector {
18
 
@@ -24,6 +15,9 @@ class QM_Collector_Caps extends QM_Collector {
24
 
25
  public function __construct() {
26
  parent::__construct();
 
 
 
27
  add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 9999, 3 );
28
  add_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 9999, 4 );
29
  }
1
  <?php
2
+ /**
3
+ * User capability check collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Caps extends QM_Collector {
9
 
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
  }
collectors/conditionals.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Conditionals extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * Template conditionals collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Conditionals extends QM_Collector {
9
 
collectors/db_callers.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_DB_Callers extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * Database query calling function collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_DB_Callers extends QM_Collector {
9
 
collectors/db_components.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_DB_Components extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * Database query calling component collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_DB_Components extends QM_Collector {
9
 
collectors/db_dupes.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_DB_Dupes extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * Duplicate database query collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_DB_Dupes extends QM_Collector {
9
 
collectors/db_queries.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  if ( ! defined( 'SAVEQUERIES' ) ) {
18
  define( 'SAVEQUERIES', true );
@@ -81,13 +72,11 @@ class QM_Collector_DB_Queries extends QM_Collector {
81
  if ( ! isset( $this->data['times'][ $caller ] ) ) {
82
  $this->data['times'][ $caller ] = array(
83
  'caller' => $caller,
84
- 'calls' => 0,
85
  'ltime' => 0,
86
  'types' => array(),
87
  );
88
  }
89
 
90
- $this->data['times'][ $caller ]['calls']++;
91
  $this->data['times'][ $caller ]['ltime'] += $ltime;
92
 
93
  if ( isset( $this->data['times'][ $caller ]['types'][ $type ] ) ) {
@@ -107,6 +96,11 @@ class QM_Collector_DB_Queries extends QM_Collector {
107
  $has_result = false;
108
  $has_trace = false;
109
  $i = 0;
 
 
 
 
 
110
 
111
  foreach ( (array) $db->queries as $query ) {
112
 
@@ -118,10 +112,11 @@ class QM_Collector_DB_Queries extends QM_Collector {
118
  $sql = $query[0];
119
  $ltime = $query[1];
120
  $stack = $query[2];
 
121
  $has_trace = isset( $query['trace'] );
122
  $has_result = isset( $query['result'] );
123
 
124
- if ( isset( $query['result'] ) ) {
125
  $result = $query['result'];
126
  } else {
127
  $result = null;
@@ -129,7 +124,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
129
 
130
  $total_time += $ltime;
131
 
132
- if ( isset( $query['trace'] ) ) {
133
 
134
  $trace = $query['trace'];
135
  $component = $query['trace']->get_component();
@@ -175,9 +170,13 @@ class QM_Collector_DB_Queries extends QM_Collector {
175
  $types[ $type ]['callers'][ $caller ]++;
176
  }
177
 
178
- $is_main_query = ( trim( $wp_the_query->request ) === $sql && ( false !== strpos( $stack, ' WP->main,' ) ) );
 
 
179
 
180
- $row = compact( 'caller', 'caller_name', 'stack', 'sql', 'ltime', 'result', 'type', 'component', 'trace', 'is_main_query' );
 
 
181
 
182
  if ( is_wp_error( $result ) ) {
183
  $this->data['errors'][] = $row;
@@ -200,10 +199,12 @@ class QM_Collector_DB_Queries extends QM_Collector {
200
  'caller_name' => __( 'Unknown', 'query-monitor' ),
201
  'stack' => '',
202
  'sql' => $error['query'],
 
203
  'result' => new WP_Error( 'qmdb', $error['error_str'] ),
204
  'type' => '',
205
  'component' => false,
206
  'trace' => null,
 
207
  );
208
  $this->data['errors'][] = $row;
209
  }
1
  <?php
2
+ /**
3
+ * Database query collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  if ( ! defined( 'SAVEQUERIES' ) ) {
9
  define( 'SAVEQUERIES', true );
72
  if ( ! isset( $this->data['times'][ $caller ] ) ) {
73
  $this->data['times'][ $caller ] = array(
74
  'caller' => $caller,
 
75
  'ltime' => 0,
76
  'types' => array(),
77
  );
78
  }
79
 
 
80
  $this->data['times'][ $caller ]['ltime'] += $ltime;
81
 
82
  if ( isset( $this->data['times'][ $caller ]['types'][ $type ] ) ) {
96
  $has_result = false;
97
  $has_trace = false;
98
  $i = 0;
99
+ $request = trim( $wp_the_query->request );
100
+
101
+ if ( method_exists( $db, 'remove_placeholder_escape' ) ) {
102
+ $request = $db->remove_placeholder_escape( $request );
103
+ }
104
 
105
  foreach ( (array) $db->queries as $query ) {
106
 
112
  $sql = $query[0];
113
  $ltime = $query[1];
114
  $stack = $query[2];
115
+ $has_start = isset( $query[3] );
116
  $has_trace = isset( $query['trace'] );
117
  $has_result = isset( $query['result'] );
118
 
119
+ if ( $has_result ) {
120
  $result = $query['result'];
121
  } else {
122
  $result = null;
124
 
125
  $total_time += $ltime;
126
 
127
+ if ( $has_trace ) {
128
 
129
  $trace = $query['trace'];
130
  $component = $query['trace']->get_component();
170
  $types[ $type ]['callers'][ $caller ]++;
171
  }
172
 
173
+ $is_main_query = ( $request === $sql && ( false !== strpos( $stack, ' WP->main,' ) ) );
174
+
175
+ $row = compact( 'caller', 'caller_name', 'sql', 'ltime', 'result', 'type', 'component', 'trace', 'is_main_query' );
176
 
177
+ if ( ! isset( $trace ) ) {
178
+ $row['stack'] = $stack;
179
+ }
180
 
181
  if ( is_wp_error( $result ) ) {
182
  $this->data['errors'][] = $row;
199
  'caller_name' => __( 'Unknown', 'query-monitor' ),
200
  'stack' => '',
201
  'sql' => $error['query'],
202
+ 'ltime' => 0,
203
  'result' => new WP_Error( 'qmdb', $error['error_str'] ),
204
  'type' => '',
205
  'component' => false,
206
  'trace' => null,
207
+ 'is_main_query' => false,
208
  );
209
  $this->data['errors'][] = $row;
210
  }
collectors/debug_bar.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  final class QM_Collector_Debug_Bar extends QM_Collector {
18
 
@@ -65,10 +56,10 @@ function register_qm_collectors_debug_bar() {
65
 
66
  $debug_bar = new Debug_Bar;
67
  $redundant = array(
68
- 'debug_bar_actions_addon_panel',
69
- 'debug_bar_remote_requests_panel',
70
- 'debug_bar_screen_info_panel',
71
- 'ps_listdeps_debug_bar_panel',
72
  );
73
 
74
  foreach ( $debug_bar->panels as $panel ) {
1
  <?php
2
+ /**
3
+ * Mock 'Debug Bar' data collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  final class QM_Collector_Debug_Bar extends QM_Collector {
9
 
56
 
57
  $debug_bar = new Debug_Bar;
58
  $redundant = array(
59
+ 'debug_bar_actions_addon_panel', // Debug Bar Actions and Filters Addon
60
+ 'debug_bar_remote_requests_panel', // Debug Bar Remote Requests
61
+ 'debug_bar_screen_info_panel', // Debug Bar Screen Info
62
+ 'ps_listdeps_debug_bar_panel', // Debug Bar List Script & Style Dependencies
63
  );
64
 
65
  foreach ( $debug_bar->panels as $panel ) {
collectors/environment.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Environment extends QM_Collector {
18
 
@@ -50,7 +41,7 @@ class QM_Collector_Environment extends QM_Collector {
50
 
51
  }
52
 
53
- public static function get_error_levels( $error_reporting ) {
54
  $levels = array(
55
  'E_ERROR' => false,
56
  'E_WARNING' => false,
@@ -99,6 +90,16 @@ class QM_Collector_Environment extends QM_Collector {
99
 
100
  foreach ( $dbq->db_objects as $id => $db ) {
101
 
 
 
 
 
 
 
 
 
 
 
102
  $variables = $db->get_results( "
103
  SHOW VARIABLES
104
  WHERE Variable_name IN ( '" . implode( "', '", array_keys( $mysql_vars ) ) . "' )
@@ -115,20 +116,22 @@ class QM_Collector_Environment extends QM_Collector {
115
  $extension = null;
116
  }
117
 
118
- if ( method_exists( $db, 'db_version' ) ) {
119
- $server = $db->db_version();
120
- } else {
121
- $server = null;
122
- }
123
-
124
  if ( isset( $db->use_mysqli ) && $db->use_mysqli ) {
125
  $client = mysqli_get_client_version();
 
126
  } else {
127
  if ( preg_match( '|[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}|', mysql_get_client_info(), $matches ) ) {
128
  $client = $matches[0];
129
  } else {
130
  $client = null;
131
  }
 
 
 
 
 
 
 
132
  }
133
 
134
  if ( $client ) {
@@ -139,8 +142,9 @@ class QM_Collector_Environment extends QM_Collector {
139
  }
140
 
141
  $info = array(
142
- 'extension' => $extension,
143
  'server version' => $server,
 
144
  'client version' => $client_version,
145
  'user' => $db->dbuser,
146
  'host' => $db->dbhost,
@@ -159,30 +163,29 @@ class QM_Collector_Environment extends QM_Collector {
159
  $this->data['php']['version'] = phpversion();
160
  $this->data['php']['sapi'] = php_sapi_name();
161
  $this->data['php']['user'] = self::get_current_user();
162
-
163
- if ( defined( 'HHVM_VERSION' ) ) {
164
- $this->data['php']['hhvm'] = HHVM_VERSION;
165
- }
166
 
167
  foreach ( $this->php_vars as $setting ) {
168
  $this->data['php']['variables'][ $setting ]['after'] = ini_get( $setting );
169
  }
170
 
171
- if ( is_callable( 'get_loaded_extensions' ) ) {
172
- $this->data['php']['extensions'] = get_loaded_extensions();
173
- } else {
174
- $this->data['php']['extensions'] = array();
175
- }
176
-
177
  if ( defined( 'SORT_FLAG_CASE' ) ) {
 
178
  $sort_flags = SORT_STRING | SORT_FLAG_CASE;
179
  } else {
180
  $sort_flags = SORT_STRING;
181
  }
182
 
183
- sort( $this->data['php']['extensions'], $sort_flags );
 
 
 
 
 
 
184
 
185
  $this->data['php']['error_reporting'] = error_reporting();
 
186
 
187
  $this->data['wp'] = array(
188
  'version' => $wp_version,
@@ -229,6 +232,27 @@ class QM_Collector_Environment extends QM_Collector {
229
 
230
  }
231
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  protected static function get_current_user() {
233
 
234
  $php_u = null;
1
  <?php
2
+ /**
3
+ * Environment data collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Environment extends QM_Collector {
9
 
41
 
42
  }
43
 
44
+ protected static function get_error_levels( $error_reporting ) {
45
  $levels = array(
46
  'E_ERROR' => false,
47
  'E_WARNING' => false,
90
 
91
  foreach ( $dbq->db_objects as $id => $db ) {
92
 
93
+ if ( method_exists( $db, 'db_version' ) ) {
94
+ $server = $db->db_version();
95
+ // query_cache_* deprecated since MySQL 5.7.20
96
+ if ( version_compare( $server, '5.7.20', '>=' ) ) {
97
+ unset( $mysql_vars['query_cache_limit'], $mysql_vars['query_cache_size'], $mysql_vars['query_cache_type'] );
98
+ }
99
+ } else {
100
+ $server = null;
101
+ }
102
+
103
  $variables = $db->get_results( "
104
  SHOW VARIABLES
105
  WHERE Variable_name IN ( '" . implode( "', '", array_keys( $mysql_vars ) ) . "' )
116
  $extension = null;
117
  }
118
 
 
 
 
 
 
 
119
  if ( isset( $db->use_mysqli ) && $db->use_mysqli ) {
120
  $client = mysqli_get_client_version();
121
+ $info = mysqli_get_server_info( $db->dbh );
122
  } else {
123
  if ( preg_match( '|[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}|', mysql_get_client_info(), $matches ) ) {
124
  $client = $matches[0];
125
  } else {
126
  $client = null;
127
  }
128
+ $info = mysql_get_server_info( $db->dbh );
129
+ }
130
+
131
+ if ( false !== strpos( $info, 'MariaDB' ) ) {
132
+ $rdbms = 'MariaDB';
133
+ } else {
134
+ $rdbms = 'MySQL';
135
  }
136
 
137
  if ( $client ) {
142
  }
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,
163
  $this->data['php']['version'] = phpversion();
164
  $this->data['php']['sapi'] = php_sapi_name();
165
  $this->data['php']['user'] = self::get_current_user();
166
+ $this->data['php']['old'] = version_compare( $this->data['php']['version'], 7, '<' );
 
 
 
167
 
168
  foreach ( $this->php_vars as $setting ) {
169
  $this->data['php']['variables'][ $setting ]['after'] = ini_get( $setting );
170
  }
171
 
 
 
 
 
 
 
172
  if ( defined( 'SORT_FLAG_CASE' ) ) {
173
+ // phpcs:ignore PHPCompatibility.PHP.NewConstants
174
  $sort_flags = SORT_STRING | SORT_FLAG_CASE;
175
  } else {
176
  $sort_flags = SORT_STRING;
177
  }
178
 
179
+ if ( is_callable( 'get_loaded_extensions' ) ) {
180
+ $extensions = get_loaded_extensions();
181
+ sort( $extensions, $sort_flags );
182
+ $this->data['php']['extensions'] = array_combine( $extensions, array_map( array( $this, 'get_extension_version' ), $extensions ) );
183
+ } else {
184
+ $this->data['php']['extensions'] = array();
185
+ }
186
 
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,
232
 
233
  }
234
 
235
+ public function get_extension_version( $extension ) {
236
+ // Nothing is simple in PHP. The exif and mysqlnd extensions (and probably others) add a bunch of
237
+ // crap to their version number, so we need to pluck out the first numeric value in the string.
238
+ $version = phpversion( $extension );
239
+
240
+ if ( ! $version ) {
241
+ return $version;
242
+ }
243
+
244
+ $parts = explode( ' ', $version );
245
+
246
+ foreach ( $parts as $part ) {
247
+ if ( is_numeric( $part[0] ) ) {
248
+ $version = $part;
249
+ break;
250
+ }
251
+ }
252
+
253
+ return $version;
254
+ }
255
+
256
  protected static function get_current_user() {
257
 
258
  $php_u = null;
collectors/hooks.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Hooks extends QM_Collector {
18
 
@@ -30,12 +21,6 @@ class QM_Collector_Hooks extends QM_Collector {
30
  self::$hide_qm = self::hide_qm();
31
  self::$hide_core = ( defined( 'QM_HIDE_CORE_HOOKS' ) && QM_HIDE_CORE_HOOKS );
32
 
33
- if ( is_admin() and ( $admin = QM_Collectors::get( 'admin' ) ) ) {
34
- $this->data['screen'] = $admin->data['base'];
35
- } else {
36
- $this->data['screen'] = '';
37
- }
38
-
39
  $hooks = $all_parts = $components = array();
40
 
41
  if ( has_filter( 'all' ) ) {
@@ -65,6 +50,16 @@ class QM_Collector_Hooks extends QM_Collector {
65
 
66
  }
67
 
 
 
 
 
 
 
 
 
 
 
68
  public static function process_action( $name, array $wp_filter, $hide_qm = false, $hide_core = false ) {
69
 
70
  $actions = $components = array();
@@ -91,6 +86,9 @@ class QM_Collector_Hooks extends QM_Collector {
91
  $components[ $callback['component']->name ] = $callback['component']->name;
92
  }
93
 
 
 
 
94
  $actions[] = array(
95
  'priority' => $priority,
96
  'callback' => $callback,
@@ -113,9 +111,5 @@ class QM_Collector_Hooks extends QM_Collector {
113
 
114
  }
115
 
116
- function register_qm_collector_hooks( array $collectors, QueryMonitor $qm ) {
117
- $collectors['hooks'] = new QM_Collector_Hooks;
118
- return $collectors;
119
- }
120
-
121
- add_filter( 'qm/collectors', 'register_qm_collector_hooks', 20, 2 );
1
  <?php
2
+ /**
3
+ * Hooks and actions collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Hooks extends QM_Collector {
9
 
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
 
26
  if ( has_filter( 'all' ) ) {
50
 
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'];
58
+ } else {
59
+ $this->data['screen'] = '';
60
+ }
61
+ }
62
+
63
  public static function process_action( $name, array $wp_filter, $hide_qm = false, $hide_core = false ) {
64
 
65
  $actions = $components = array();
86
  $components[ $callback['component']->name ] = $callback['component']->name;
87
  }
88
 
89
+ // This isn't used and takes up a ton of memory:
90
+ unset( $callback['function'] );
91
+
92
  $actions[] = array(
93
  'priority' => $priority,
94
  'callback' => $callback,
111
 
112
  }
113
 
114
+ # Load early to catch all hooks
115
+ QM_Collectors::add( new QM_Collector_Hooks );
 
 
 
 
collectors/http.php CHANGED
@@ -1,22 +1,15 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_HTTP extends QM_Collector {
18
 
19
  public $id = 'http';
 
 
20
 
21
  public function name() {
22
  return __( 'HTTP API Requests', 'query-monitor' );
@@ -30,6 +23,11 @@ class QM_Collector_HTTP extends QM_Collector {
30
  add_filter( 'pre_http_request', array( $this, 'filter_pre_http_request' ), 99, 3 );
31
  add_action( 'http_api_debug', array( $this, 'action_http_api_debug' ), 99, 5 );
32
 
 
 
 
 
 
33
  }
34
 
35
  /**
@@ -119,6 +117,22 @@ class QM_Collector_HTTP extends QM_Collector {
119
 
120
  }
121
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  /**
123
  * Log an HTTP response.
124
  *
@@ -138,6 +152,11 @@ class QM_Collector_HTTP extends QM_Collector {
138
  'pre_http_request'
139
  ) );
140
  }
 
 
 
 
 
141
  }
142
 
143
  public function process() {
@@ -185,6 +204,9 @@ class QM_Collector_HTTP extends QM_Collector {
185
  $this->data['errors']['alert'][] = $key;
186
  }
187
  $http['type'] = __( 'Error', 'query-monitor' );
 
 
 
188
  } else {
189
  $http['type'] = intval( wp_remote_retrieve_response_code( $http['response'] ) );
190
  if ( $http['type'] >= 400 ) {
@@ -193,6 +215,19 @@ class QM_Collector_HTTP extends QM_Collector {
193
  }
194
 
195
  $http['ltime'] = ( $http['end'] - $http['start'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  $this->data['ltime'] += $http['ltime'];
197
 
198
  $http['component'] = $http['trace']->get_component();
1
  <?php
2
+ /**
3
+ * HTTP API request collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_HTTP extends QM_Collector {
9
 
10
  public $id = 'http';
11
+ private $transport = null;
12
+ private $info = null;
13
 
14
  public function name() {
15
  return __( 'HTTP API Requests', 'query-monitor' );
23
  add_filter( 'pre_http_request', array( $this, 'filter_pre_http_request' ), 99, 3 );
24
  add_action( 'http_api_debug', array( $this, 'action_http_api_debug' ), 99, 5 );
25
 
26
+ add_action( 'requests-curl.before_request', array( $this, 'action_curl_before_request' ), 99 );
27
+ add_action( 'requests-curl.after_request', array( $this, 'action_curl_after_request' ), 99, 2 );
28
+ add_action( 'requests-fsockopen.before_request', array( $this, 'action_fsockopen_before_request' ), 99 );
29
+ add_action( 'requests-fsockopen.after_request', array( $this, 'action_fsockopen_after_request' ), 99, 2 );
30
+
31
  }
32
 
33
  /**
117
 
118
  }
119
 
120
+ public function action_curl_before_request() {
121
+ $this->transport = 'curl';
122
+ }
123
+
124
+ public function action_curl_after_request( $headers, array $info = null ) {
125
+ $this->info = $info;
126
+ }
127
+
128
+ public function action_fsockopen_before_request() {
129
+ $this->transport = 'fsockopen';
130
+ }
131
+
132
+ public function action_fsockopen_after_request( $headers, array $info = null ) {
133
+ $this->info = $info;
134
+ }
135
+
136
  /**
137
  * Log an HTTP response.
138
  *
152
  'pre_http_request'
153
  ) );
154
  }
155
+
156
+ $this->data['http'][ $args['_qm_key'] ]['info'] = $this->info;
157
+ $this->data['http'][ $args['_qm_key'] ]['transport'] = $this->transport;
158
+ $this->info = null;
159
+ $this->transport = null;
160
  }
161
 
162
  public function process() {
204
  $this->data['errors']['alert'][] = $key;
205
  }
206
  $http['type'] = __( 'Error', 'query-monitor' );
207
+ } elseif ( ! $http['args']['blocking'] ) {
208
+ /* translators: A non-blocking HTTP API request */
209
+ $http['type'] = __( 'Non-blocking', 'query-monitor' );
210
  } else {
211
  $http['type'] = intval( wp_remote_retrieve_response_code( $http['response'] ) );
212
  if ( $http['type'] >= 400 ) {
215
  }
216
 
217
  $http['ltime'] = ( $http['end'] - $http['start'] );
218
+
219
+ if ( isset( $http['info'] ) ) {
220
+ if ( isset( $http['info']['total_time'] ) ) {
221
+ $http['ltime'] = $http['info']['total_time'];
222
+ }
223
+
224
+ if ( ! empty( $http['info']['url'] ) ) {
225
+ if ( rtrim( $http['url'], '/' ) !== rtrim( $http['info']['url'], '/' ) ) {
226
+ $http['redirected_to'] = $http['info']['url'];
227
+ }
228
+ }
229
+ }
230
+
231
  $this->data['ltime'] += $http['ltime'];
232
 
233
  $http['component'] = $http['trace']->get_component();
collectors/languages.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Languages extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * Language and locale collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Languages extends QM_Collector {
9
 
collectors/overview.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Overview extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * General overview collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Overview extends QM_Collector {
9
 
collectors/php_errors.php CHANGED
@@ -1,35 +1,14 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
-
17
- # E_DEPRECATED and E_USER_DEPRECATED were introduced in PHP 5.3 so we need to use back-compat constants that work on 5.2.
18
- if ( defined( 'E_DEPRECATED' ) ) {
19
- define( 'QM_E_DEPRECATED', E_DEPRECATED );
20
- } else {
21
- define( 'QM_E_DEPRECATED', 0 );
22
- }
23
-
24
- if ( defined( 'E_USER_DEPRECATED' ) ) {
25
- define( 'QM_E_USER_DEPRECATED', E_USER_DEPRECATED );
26
- } else {
27
- define( 'QM_E_USER_DEPRECATED', 0 );
28
- }
29
 
30
  class QM_Collector_PHP_Errors extends QM_Collector {
31
 
32
  public $id = 'php_errors';
 
33
  private $error_reporting = null;
34
  private $display_errors = null;
35
  private static $unexpected_error;
@@ -74,8 +53,8 @@ class QM_Collector_PHP_Errors extends QM_Collector {
74
  $type = 'strict';
75
  break;
76
 
77
- case QM_E_DEPRECATED:
78
- case QM_E_USER_DEPRECATED:
79
  $type = 'deprecated';
80
  break;
81
 
@@ -89,9 +68,11 @@ class QM_Collector_PHP_Errors extends QM_Collector {
89
  return false;
90
  }
91
 
 
 
92
  if ( 0 === error_reporting() && 0 !== $this->error_reporting ) {
93
  // This is most likely an @-suppressed error
94
- $type .= '-suppressed';
95
  }
96
 
97
  if ( ! isset( self::$unexpected_error ) ) {
@@ -120,10 +101,10 @@ class QM_Collector_PHP_Errors extends QM_Collector {
120
 
121
  $filename = QM_Util::standard_dir( $file, '' );
122
 
123
- if ( isset( $this->data['errors'][ $type ][ $key ] ) ) {
124
- $this->data['errors'][ $type ][ $key ]->calls++;
125
  } else {
126
- $this->data['errors'][ $type ][ $key ] = (object) array(
127
  'errno' => $errno,
128
  'type' => $type,
129
  'message' => $message,
@@ -188,6 +169,191 @@ class QM_Collector_PHP_Errors extends QM_Collector {
188
  restore_error_handler();
189
  }
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  }
192
 
193
  # Load early to catch early errors
1
  <?php
2
+ /**
3
+ * PHP error collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_PHP_Errors extends QM_Collector {
9
 
10
  public $id = 'php_errors';
11
+ public $types = array();
12
  private $error_reporting = null;
13
  private $display_errors = null;
14
  private static $unexpected_error;
53
  $type = 'strict';
54
  break;
55
 
56
+ case E_DEPRECATED:
57
+ case E_USER_DEPRECATED:
58
  $type = 'deprecated';
59
  break;
60
 
68
  return false;
69
  }
70
 
71
+ $error_group = 'errors';
72
+
73
  if ( 0 === error_reporting() && 0 !== $this->error_reporting ) {
74
  // This is most likely an @-suppressed error
75
+ $error_group = 'suppressed';
76
  }
77
 
78
  if ( ! isset( self::$unexpected_error ) ) {
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,
169
  restore_error_handler();
170
  }
171
 
172
+ /**
173
+ * Runs post-processing on the collected errors and updates the
174
+ * errors collected in the data->errors property.
175
+ *
176
+ * Any unreportable errors are placed in the data->filtered_errors
177
+ * property.
178
+ */
179
+ public function process() {
180
+ $this->types = array(
181
+ 'errors' => array(
182
+ 'warning' => _x( 'Warning', 'PHP error level', 'query-monitor' ),
183
+ 'notice' => _x( 'Notice', 'PHP error level', 'query-monitor' ),
184
+ 'strict' => _x( 'Strict', 'PHP error level', 'query-monitor' ),
185
+ 'deprecated' => _x( 'Deprecated', 'PHP error level', 'query-monitor' ),
186
+ ),
187
+ 'suppressed' => array(
188
+ 'warning' => _x( 'Warning (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
189
+ 'notice' => _x( 'Notice (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
190
+ 'strict' => _x( 'Strict (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
191
+ 'deprecated' => _x( 'Deprecated (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
192
+ ),
193
+ 'silenced' => array(
194
+ 'warning' => _x( 'Warning (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
195
+ 'notice' => _x( 'Notice (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
196
+ 'strict' => _x( 'Strict (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
197
+ 'deprecated' => _x( 'Deprecated (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
198
+ ),
199
+ );
200
+ $components = array();
201
+
202
+ if ( ! empty( $this->data ) && ! empty( $this->data['errors'] ) ) {
203
+ /**
204
+ * Filters the levels used for reported PHP errors on a per-component basis.
205
+ *
206
+ * Error levels can be specified in order to silence certain error levels from
207
+ * plugins or the current theme. Most commonly, you may wish to use this filter
208
+ * in order to silence annoying notices from third party plugins that you do not
209
+ * have control over.
210
+ *
211
+ * Silenced errors will still appear in Query Monitor's output, but will not
212
+ * cause highlighting to appear in the top level admin toolbar.
213
+ *
214
+ * For example, to show all errors in the 'foo' plugin except PHP notices use:
215
+ *
216
+ * add_filter( 'qm/collect/php_error_levels', function( array $levels ) {
217
+ * $levels['plugin']['foo'] = ( E_ALL & ~E_NOTICE );
218
+ * return $levels;
219
+ * } );
220
+ *
221
+ * Errors from themes, WordPress core, and other components can also be filtered:
222
+ *
223
+ * add_filter( 'qm/collect/php_error_levels', function( array $levels ) {
224
+ * $levels['theme']['stylesheet'] = ( E_WARNING & E_USER_WARNING );
225
+ * $levels['theme']['template'] = ( E_WARNING & E_USER_WARNING );
226
+ * $levels['core']['core'] = ( 0 );
227
+ * return $levels;
228
+ * } );
229
+ *
230
+ * Any component which doesn't have an error level specified via this filter is
231
+ * assumed to have the default level of `E_ALL`, which shows all errors.
232
+ *
233
+ * Valid PHP error level bitmasks are supported for each component, including `0`
234
+ * to silence all errors from a component. See the PHP documentation on error
235
+ * reporting for more info: http://php.net/manual/en/function.error-reporting.php
236
+ *
237
+ * @param int[] $levels The error levels used for each component.
238
+ */
239
+ $levels = apply_filters( 'qm/collect/php_error_levels', array() );
240
+
241
+ /**
242
+ * Controls whether silenced PHP errors are hidden entirely by Query Monitor.
243
+ *
244
+ * To hide silenced errors, use:
245
+ *
246
+ * add_filter( 'qm/collect/hide_silenced_php_errors', '__return_true' );
247
+ *
248
+ * @param bool $hide Whether to hide silenced PHP errors. Default false.
249
+ */
250
+ $this->hide_silenced_php_errors = apply_filters( 'qm/collect/hide_silenced_php_errors', false );
251
+
252
+ array_map( array( $this, 'filter_reportable_errors' ), $levels, array_keys( $levels ) );
253
+
254
+ foreach ( $this->types as $error_group => $error_types ) {
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
+ }
262
+ }
263
+ }
264
+ }
265
+
266
+ $this->data['components'] = $components;
267
+ }
268
+
269
+ /**
270
+ * Filters the reportable PHP errors using the table specified. Users can customize the levels
271
+ * using the `qm/collect/php_error_levels` filter.
272
+ *
273
+ * @param int[] $components The error levels keyed by component name.
274
+ * @param string $component_type The component type, for example 'plugin' or 'theme'.
275
+ */
276
+ public function filter_reportable_errors( array $components, $component_type ) {
277
+ $all_errors = $this->data['errors'];
278
+
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
+
289
+ unset( $this->data['errors'][ $error_level ][ $error_id ] );
290
+
291
+ if ( $this->hide_silenced_php_errors ) {
292
+ continue;
293
+ }
294
+
295
+ $this->data['silenced'][ $error_level ][ $error_id ] = $error;
296
+ }
297
+ }
298
+ }
299
+
300
+ $this->data['errors'] = array_filter( $this->data['errors'] );
301
+ }
302
+
303
+ /**
304
+ * Checks if the file path is within the specified plugin. This is
305
+ * used to scope an error's file path to a plugin.
306
+ *
307
+ * @param string $plugin_name The name of the plugin
308
+ * @param string $file_path The full path to the file
309
+ * @return bool
310
+ */
311
+ public function is_affected_component( $component, $component_type, $component_context ) {
312
+ if ( empty( $component ) ) {
313
+ return false;
314
+ }
315
+ return ( $component->type === $component_type && $component->context === $component_context );
316
+ }
317
+
318
+ /**
319
+ * Checks if the error number specified is viewable based on the
320
+ * flags specified.
321
+ *
322
+ * @param int $error_no The errno from PHP
323
+ * @param int $flags The config flags specified by users
324
+ * @return int Truthy int value if reportable else 0.
325
+ *
326
+ * Eg:- If a plugin had the config flags,
327
+ *
328
+ * E_ALL & ~E_NOTICE
329
+ *
330
+ * then,
331
+ *
332
+ * is_reportable_error( E_NOTICE, E_ALL & ~E_NOTICE ) is false
333
+ * is_reportable_error( E_WARNING, E_ALL & ~E_NOTICE ) is true
334
+ *
335
+ * If the $flag is null, all errors are assumed to be
336
+ * reportable by default.
337
+ */
338
+ public function is_reportable_error( $error_no, $flags ) {
339
+ if ( ! is_null( $flags ) ) {
340
+ $result = $error_no & $flags;
341
+ } else {
342
+ $result = 1;
343
+ }
344
+
345
+ return (bool) $result;
346
+ }
347
+
348
+ /**
349
+ * For testing purposes only. Sets the errors property manually.
350
+ * Needed to test the filter since the data property is protected.
351
+ *
352
+ * @param array $errors The list of errors
353
+ */
354
+ public function set_php_errors( $errors ) {
355
+ $this->data['errors'] = $errors;
356
+ }
357
  }
358
 
359
  # Load early to catch early errors
collectors/redirects.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Redirects extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * HTTP redirect collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Redirects extends QM_Collector {
9
 
collectors/request.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Request extends QM_Collector {
18
 
@@ -24,7 +15,7 @@ class QM_Collector_Request extends QM_Collector {
24
 
25
  public function process() {
26
 
27
- global $wp, $wp_query, $current_blog, $current_site;
28
 
29
  $qo = get_queried_object();
30
  $user = wp_get_current_user();
@@ -32,7 +23,7 @@ class QM_Collector_Request extends QM_Collector {
32
  if ( $user->exists() ) {
33
  $user_title = sprintf(
34
  /* translators: %d: User ID */
35
- __( 'Current user: #%d', 'query-monitor' ),
36
  $user->ID
37
  );
38
  } else {
@@ -46,10 +37,10 @@ class QM_Collector_Request extends QM_Collector {
46
  );
47
 
48
  if ( is_multisite() ) {
49
- $this->data['multisite']['current_blog'] = array(
50
  'title' => sprintf(
51
- /* translators: %d: Blog ID */
52
- __( 'Current blog: #%d', 'query-monitor' ),
53
  $current_blog->blog_id
54
  ),
55
  'data' => $current_blog,
@@ -57,10 +48,10 @@ class QM_Collector_Request extends QM_Collector {
57
  }
58
 
59
  if ( QM_Util::is_multi_network() ) {
60
- $this->data['multisite']['current_site'] = array(
61
  'title' => sprintf(
62
- /* translators: %d: Site ID */
63
- __( 'Current site: #%d', 'query-monitor' ),
64
  $current_site->id
65
  ),
66
  'data' => $current_site,
@@ -69,7 +60,10 @@ class QM_Collector_Request extends QM_Collector {
69
 
70
  if ( is_admin() ) {
71
  if ( isset( $_SERVER['REQUEST_URI'] ) ) {
72
- $this->data['request']['request'] = wp_unslash( $_SERVER['REQUEST_URI'] ); // @codingStandardsIgnoreLine
 
 
 
73
  } else {
74
  $this->data['request']['request'] = '';
75
  }
@@ -117,7 +111,7 @@ class QM_Collector_Request extends QM_Collector {
117
 
118
  switch ( true ) {
119
 
120
- case is_null( $qo ):
121
  // Nada
122
  break;
123
 
@@ -167,7 +161,7 @@ class QM_Collector_Request extends QM_Collector {
167
 
168
  }
169
 
170
- if ( ! is_null( $qo ) ) {
171
  $this->data['queried_object']['data'] = $qo;
172
  }
173
 
@@ -177,6 +171,19 @@ class QM_Collector_Request extends QM_Collector {
177
  $this->data['request_method'] = '';
178
  }
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  }
181
 
182
  }
1
  <?php
2
+ /**
3
+ * Request collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Request extends QM_Collector {
9
 
15
 
16
  public function process() {
17
 
18
+ global $wp, $wp_query, $current_blog, $current_site, $wp_rewrite;
19
 
20
  $qo = get_queried_object();
21
  $user = wp_get_current_user();
23
  if ( $user->exists() ) {
24
  $user_title = sprintf(
25
  /* translators: %d: User ID */
26
+ __( 'Current User: #%d', 'query-monitor' ),
27
  $user->ID
28
  );
29
  } else {
37
  );
38
 
39
  if ( is_multisite() ) {
40
+ $this->data['multisite']['current_site'] = array(
41
  'title' => sprintf(
42
+ /* translators: %d: Multisite site ID */
43
+ __( 'Current Site: #%d', 'query-monitor' ),
44
  $current_blog->blog_id
45
  ),
46
  'data' => $current_blog,
48
  }
49
 
50
  if ( QM_Util::is_multi_network() ) {
51
+ $this->data['multisite']['current_network'] = array(
52
  'title' => sprintf(
53
+ /* translators: %d: Multisite network ID */
54
+ __( 'Current Network: #%d', 'query-monitor' ),
55
  $current_site->id
56
  ),
57
  'data' => $current_site,
60
 
61
  if ( is_admin() ) {
62
  if ( isset( $_SERVER['REQUEST_URI'] ) ) {
63
+ $home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' );
64
+ $request = wp_unslash( $_SERVER['REQUEST_URI'] ); // @codingStandardsIgnoreLine
65
+
66
+ $this->data['request']['request'] = str_replace( "/{$home_path}/", '', $request );
67
  } else {
68
  $this->data['request']['request'] = '';
69
  }
111
 
112
  switch ( true ) {
113
 
114
+ case ! is_object( $qo ):
115
  // Nada
116
  break;
117
 
161
 
162
  }
163
 
164
+ if ( $qo ) {
165
  $this->data['queried_object']['data'] = $qo;
166
  }
167
 
171
  $this->data['request_method'] = '';
172
  }
173
 
174
+ if ( is_admin() || QM_Util::is_async() || empty( $wp_rewrite->rules ) ) {
175
+ return;
176
+ }
177
+
178
+ $matching = array();
179
+
180
+ foreach ( $wp_rewrite->rules as $match => $query ) {
181
+ if ( preg_match( "#^{$match}#", $this->data['request']['request'] ) ) {
182
+ $matching[ $match ] = $query;
183
+ }
184
+ }
185
+
186
+ $this->data['matching_rewrites'] = $matching;
187
  }
188
 
189
  }
collectors/rewrites.php DELETED
@@ -1,63 +0,0 @@
1
- <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
-
17
- class QM_Collector_Rewrites extends QM_Collector {
18
-
19
- public $id = 'rewrites';
20
-
21
- public function name() {
22
- return __( 'Rewrite Rules', 'query-monitor' );
23
- }
24
-
25
- public function process() {
26
-
27
- global $wp_rewrite;
28
-
29
- if ( is_admin() or QM_Util::is_async() ) {
30
- return;
31
- }
32
-
33
- if ( ! $request = QM_Collectors::get( 'request' ) ) {
34
- return;
35
- }
36
-
37
- if ( empty( $wp_rewrite->rules ) ) {
38
- return;
39
- }
40
-
41
- $req = $request->data['request']['request'];
42
- $matching = array();
43
-
44
- foreach ( $wp_rewrite->rules as $match => $query ) {
45
- if ( preg_match( "#^{$match}#", $req ) ) {
46
- $matching[ $match ] = $query;
47
- }
48
- }
49
-
50
- $this->data['matching'] = $matching;
51
-
52
- }
53
-
54
- }
55
-
56
- function register_qm_collector_rewrites( array $collectors, QueryMonitor $qm ) {
57
- $collectors['rewrites'] = new QM_Collector_Rewrites;
58
- return $collectors;
59
- }
60
-
61
- if ( ! is_admin() ) {
62
- add_filter( 'qm/collectors', 'register_qm_collector_rewrites', 11, 2 );
63
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
collectors/theme.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Theme extends QM_Collector {
18
 
1
  <?php
2
+ /**
3
+ * Template and theme collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Theme extends QM_Collector {
9
 
collectors/timing.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Timing and profiling collector.
4
+ *
5
+ * @package query-monitor
6
+ */
7
+
8
+ class QM_Collector_Timing extends QM_Collector {
9
+
10
+ public $id = 'timing';
11
+ private $track_timer = array();
12
+ private $start = array();
13
+ private $stop = array();
14
+ private $laps = array();
15
+
16
+ public function name() {
17
+ return __( 'Timing', 'query-monitor' );
18
+ }
19
+
20
+ public function __construct() {
21
+ parent::__construct();
22
+ add_action( 'qm/start', array( $this, 'action_function_time_start' ), 10, 1 );
23
+ add_action( 'qm/stop', array( $this, 'action_function_time_stop' ), 10, 1 );
24
+ add_action( 'qm/lap', array( $this, 'action_function_time_lap' ), 10, 2 );
25
+ }
26
+
27
+ public function action_function_time_start( $function ) {
28
+ $this->track_timer[ $function ] = new QM_Timer;
29
+ $this->start[ $function ] = $this->track_timer[ $function ]->start();
30
+ }
31
+
32
+ public function action_function_time_stop( $function ) {
33
+ if ( ! isset( $this->track_timer[ $function ] ) ) {
34
+ $trace = new QM_Backtrace;
35
+ $this->data['warning'][] = array(
36
+ 'function' => $function,
37
+ 'message' => __( 'Timer not started', 'query-monitor' ),
38
+ 'trace' => $trace,
39
+ );
40
+ return;
41
+ }
42
+ $this->stop[ $function ] = $this->track_timer[ $function ]->stop();
43
+ $this->calculate_time( $function );
44
+ }
45
+
46
+ public function action_function_time_lap( $function, $name = null ) {
47
+ if ( ! isset( $this->track_timer[ $function ] ) ) {
48
+ $trace = new QM_Backtrace;
49
+ $this->data['warning'][] = array(
50
+ 'function' => $function,
51
+ 'message' => __( 'Timer not started', 'query-monitor' ),
52
+ 'trace' => $trace,
53
+ );
54
+ return;
55
+ }
56
+ $this->track_timer[ $function ]->lap( $name );
57
+ }
58
+
59
+ public function calculate_time( $function ) {
60
+ $trace = $this->track_timer[ $function ]->get_trace();
61
+ $function_time = $this->track_timer[ $function ]->get_time();
62
+ $function_memory = $this->track_timer[ $function ]->get_memory();
63
+ $function_laps = $this->track_timer[ $function ]->get_laps();
64
+
65
+ $this->data['timing'][] = array(
66
+ 'function' => $function,
67
+ 'function_time' => $function_time,
68
+ 'function_memory' => $function_memory,
69
+ 'laps' => $function_laps,
70
+ 'trace' => $trace,
71
+ );
72
+ }
73
+
74
+ public function process() {
75
+ foreach ( $this->start as $function => $value ) {
76
+ if ( ! isset( $this->stop[ $function ] ) ) {
77
+ $trace = $this->track_timer[ $function ]->get_trace();
78
+ $this->data['warning'][] = array(
79
+ 'function' => $function,
80
+ 'message' => __( 'Timer not stopped', 'query-monitor' ),
81
+ 'trace' => $trace,
82
+ );
83
+ }
84
+ }
85
+ }
86
+
87
+ }
88
+
89
+ # Load early in case a plugin is setting the function to be checked when it initialises instead of after the `plugins_loaded` hook
90
+ QM_Collectors::add( new QM_Collector_Timing );
collectors/transients.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Collector_Transients extends QM_Collector {
18
 
@@ -44,7 +35,7 @@ class QM_Collector_Transients extends QM_Collector {
44
 
45
  public function setted_transient( $transient, $type, $value, $expiration ) {
46
  $trace = new QM_Backtrace( array(
47
- 'ignore_items' => 1, # Ignore the action_setted_(site|blog)_transient method
48
  ) );
49
  $this->data['trans'][] = array(
50
  'transient' => $transient,
1
  <?php
2
+ /**
3
+ * Transient storage collector.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Collector_Transients extends QM_Collector {
9
 
35
 
36
  public function setted_transient( $transient, $type, $value, $expiration ) {
37
  $trace = new QM_Backtrace( array(
38
+ 'ignore_frames' => 1, # Ignore the action_setted_(site|blog)_transient method
39
  ) );
40
  $this->data['trans'][] = array(
41
  'transient' => $transient,
composer.json CHANGED
@@ -1,9 +1,9 @@
1
  {
2
  "name" : "johnbillion/query-monitor",
3
- "description": "WordPress plugin for monitoring database queries, hooks, conditionals, HTTP requests, query vars, environment, redirects, and more.",
4
  "homepage" : "https://github.com/johnbillion/query-monitor/",
5
  "type" : "wordpress-plugin",
6
- "license" : "GPL-2.0+",
7
  "authors" : [
8
  {
9
  "name" : "John Blackbourn",
@@ -19,8 +19,9 @@
19
  "composer/installers": "~1.0"
20
  },
21
  "require-dev" : {
 
22
  "wimg/php-compatibility": "^8",
23
- "wp-coding-standards/wpcs": "^0.13",
24
- "phpunit/phpunit": "~5.7"
25
  }
26
  }
1
  {
2
  "name" : "johnbillion/query-monitor",
3
+ "description": "The Developer Tools panel for WordPress.",
4
  "homepage" : "https://github.com/johnbillion/query-monitor/",
5
  "type" : "wordpress-plugin",
6
+ "license" : "GPL-2.0-or-later",
7
  "authors" : [
8
  {
9
  "name" : "John Blackbourn",
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
  }
dispatchers/AJAX.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Dispatcher_AJAX extends QM_Dispatcher {
18
 
1
  <?php
2
+ /**
3
+ * Ajax request dispatcher.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Dispatcher_AJAX extends QM_Dispatcher {
9
 
dispatchers/Html.php CHANGED
@@ -1,24 +1,19 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Dispatcher_Html extends QM_Dispatcher {
18
 
19
  public $id = 'html';
20
  public $did_footer = false;
21
 
 
 
 
 
22
  public function __construct( QM_Plugin $qm ) {
23
 
24
  add_action( 'admin_bar_menu', array( $this, 'action_admin_bar_menu' ), 999 );
@@ -32,7 +27,6 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
32
  add_action( 'admin_footer', array( $this, 'action_footer' ) );
33
  add_action( 'login_footer', array( $this, 'action_footer' ) );
34
  add_action( 'embed_footer', array( $this, 'action_footer' ) );
35
- add_action( 'amp_post_template_footer', array( $this, 'action_footer' ) );
36
  add_action( 'gp_footer', array( $this, 'action_footer' ) );
37
 
38
  parent::__construct( $qm );
@@ -97,14 +91,14 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
97
  $wp_admin_bar->add_menu( array(
98
  'id' => 'query-monitor',
99
  'title' => esc_html( $title ),
100
- 'href' => '#qm',
101
  ) );
102
 
103
  $wp_admin_bar->add_menu( array(
104
  'parent' => 'query-monitor',
105
  'id' => 'query-monitor-placeholder',
106
  'title' => esc_html( $title ),
107
- 'href' => '#qm',
108
  ) );
109
 
110
  }
@@ -119,15 +113,12 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
119
  define( 'DONOTCACHEPAGE', 1 );
120
  }
121
 
122
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
123
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
124
- add_action( 'login_enqueue_scripts', array( $this, 'enqueue_assets' ) );
125
- add_action( 'enqueue_embed_scripts', array( $this, 'enqueue_assets' ) );
126
  add_action( 'send_headers', 'nocache_headers' );
127
 
128
- add_action( 'amp_post_template_head', array( $this, 'enqueue_assets' ) );
129
- add_action( 'amp_post_template_head', array( $this, 'manually_print_assets' ), 11 );
130
-
131
  add_action( 'gp_head', array( $this, 'manually_print_assets' ), 11 );
132
 
133
  }
@@ -142,37 +133,42 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
142
  }
143
 
144
  public function enqueue_assets() {
145
-
146
  global $wp_locale, $wp_version;
147
 
 
 
 
 
 
 
 
 
148
  wp_enqueue_style(
149
  'query-monitor',
150
  $this->qm->plugin_url( 'assets/query-monitor.css' ),
151
- null,
152
  $this->qm->plugin_ver( 'assets/query-monitor.css' )
153
  );
154
  wp_enqueue_script(
155
  'query-monitor',
156
  $this->qm->plugin_url( 'assets/query-monitor.js' ),
157
- array( 'jquery' ),
158
  $this->qm->plugin_ver( 'assets/query-monitor.js' ),
159
- true
160
  );
161
  wp_localize_script(
162
  'query-monitor',
163
- 'qm_locale',
164
- (array) $wp_locale
165
  );
166
  wp_localize_script(
167
  'query-monitor',
168
  'qm_l10n',
169
  array(
170
- 'ajax_error' => __( 'PHP Error in AJAX Response', 'query-monitor' ),
171
- 'infinitescroll_paused' => __( 'Infinite Scroll has been paused by Query Monitor', 'query-monitor' ),
172
- 'ajaxurl' => admin_url( 'admin-ajax.php' ),
173
  'auth_nonce' => array(
174
- 'on' => wp_create_nonce( 'qm-auth-on' ),
175
- 'off' => wp_create_nonce( 'qm-auth-off' ),
176
  ),
177
  )
178
  );
@@ -197,8 +193,13 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
197
  $this->before_output();
198
 
199
  /* @var QM_Output_Html[] */
200
- foreach ( $this->get_outputters( 'html' ) as $id => $output ) {
 
 
 
201
  $output->output();
 
 
202
  }
203
 
204
  $this->after_output();
@@ -213,6 +214,10 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
213
  require_once $file;
214
  }
215
 
 
 
 
 
216
  $class = array(
217
  'qm-no-js',
218
  );
@@ -226,68 +231,126 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
226
  $class[] = 'qm-peek';
227
  }
228
 
229
- echo '<div id="qm" class="' . implode( ' ', array_map( 'esc_attr', $class ) ) . '">';
230
- echo '<div id="qm-wrapper">';
 
 
 
 
 
 
 
 
231
  echo '<div id="qm-title">';
232
- echo '<p>' . esc_html__( 'Query Monitor', 'query-monitor' ) . '</p>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  echo '</div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
 
235
  }
236
 
237
  protected function after_output() {
238
 
239
- echo '<div class="qm qm-half qm-clear" id="qm-authentication">';
240
- echo '<table cellspacing="0">';
241
- echo '<thead>';
242
- echo '<tr>';
243
- echo '<th>' . esc_html__( 'Authentication', 'query-monitor' ) . '</th>';
244
- echo '</tr>';
245
- echo '</thead>';
246
- echo '<tbody>';
247
 
248
  if ( ! self::user_verified() ) {
249
 
250
- echo '<tr>';
251
- echo '<td>' . 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' ) . '</td>';
252
- echo '</tr>';
253
- echo '<tr>';
254
- echo '<td><a href="#" class="qm-auth" data-action="on">' . esc_html__( 'Set authentication cookie', 'query-monitor' ) . '</a></td>';
255
- echo '</tr>';
256
 
257
  } else {
258
 
259
- echo '<tr>';
260
- echo '<td>' . esc_html__( 'You currently have an authentication cookie which allows you to view Query Monitor output.', 'query-monitor' ) . '</td>';
261
- echo '</tr>';
262
- echo '<tr>';
263
- echo '<td><a href="#" class="qm-auth" data-action="off">' . esc_html__( 'Clear authentication cookie', 'query-monitor' ) . '</a></td>';
264
- echo '</tr>';
265
 
266
  }
267
 
268
- echo '</tbody>';
269
- echo '</table>';
270
- echo '</div>';
271
-
272
  echo '</div>';
273
  echo '</div>';
274
 
275
- $json = array(
276
- 'menu' => $this->js_admin_bar_menu(),
277
- 'ajax_errors' => array(), # @TODO move this into the php_errors collector
278
- );
279
 
280
  echo '<script type="text/javascript">' . "\n\n";
281
- echo 'var qm = ' . json_encode( $json ) . ';' . "\n\n";
282
  ?>
283
  if ( ( 'undefined' === typeof QM_i18n ) || ( 'undefined' === typeof jQuery ) || ! jQuery ) {
284
- document.getElementById( 'qm' ).style.display = 'block';
 
 
 
 
 
 
 
 
285
  } else if ( ! document.getElementById( 'wpadminbar' ) ) {
286
- document.getElementById( 'qm' ).className += ' qm-peek';
287
  }
288
  <?php
289
  echo '</script>' . "\n\n";
 
 
 
 
 
 
 
 
 
 
 
 
290
 
 
291
  }
292
 
293
  public function js_admin_bar_menu() {
@@ -312,7 +375,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
312
  'sub' => array(),
313
  );
314
 
315
- foreach ( apply_filters( 'qm/output/menus', array() ) as $menu ) {
316
  $admin_bar_menu['sub'][ $menu['id'] ] = $menu;
317
  }
318
 
1
  <?php
2
+ /**
3
+ * General HTML request dispatcher.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Dispatcher_Html extends QM_Dispatcher {
9
 
10
  public $id = 'html';
11
  public $did_footer = false;
12
 
13
+ protected $outputters = array();
14
+ protected $admin_bar_menu = array();
15
+ protected $panel_menu = array();
16
+
17
  public function __construct( QM_Plugin $qm ) {
18
 
19
  add_action( 'admin_bar_menu', array( $this, 'action_admin_bar_menu' ), 999 );
27
  add_action( 'admin_footer', array( $this, 'action_footer' ) );
28
  add_action( 'login_footer', array( $this, 'action_footer' ) );
29
  add_action( 'embed_footer', array( $this, 'action_footer' ) );
 
30
  add_action( 'gp_footer', array( $this, 'action_footer' ) );
31
 
32
  parent::__construct( $qm );
91
  $wp_admin_bar->add_menu( array(
92
  'id' => 'query-monitor',
93
  'title' => esc_html( $title ),
94
+ 'href' => '#qm-overview',
95
  ) );
96
 
97
  $wp_admin_bar->add_menu( array(
98
  'parent' => 'query-monitor',
99
  'id' => 'query-monitor-placeholder',
100
  'title' => esc_html( $title ),
101
+ 'href' => '#qm-overview',
102
  ) );
103
 
104
  }
113
  define( 'DONOTCACHEPAGE', 1 );
114
  }
115
 
116
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
117
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
118
+ add_action( 'login_enqueue_scripts', array( $this, 'enqueue_assets' ), -999 );
119
+ add_action( 'enqueue_embed_scripts', array( $this, 'enqueue_assets' ), -999 );
120
  add_action( 'send_headers', 'nocache_headers' );
121
 
 
 
 
122
  add_action( 'gp_head', array( $this, 'manually_print_assets' ), 11 );
123
 
124
  }
133
  }
134
 
135
  public function enqueue_assets() {
 
136
  global $wp_locale, $wp_version;
137
 
138
+ $deps = array(
139
+ 'jquery-core',
140
+ );
141
+
142
+ if ( defined( 'QM_NO_JQUERY' ) && QM_NO_JQUERY ) {
143
+ $deps = array();
144
+ }
145
+
146
  wp_enqueue_style(
147
  'query-monitor',
148
  $this->qm->plugin_url( 'assets/query-monitor.css' ),
149
+ array( 'dashicons' ),
150
  $this->qm->plugin_ver( 'assets/query-monitor.css' )
151
  );
152
  wp_enqueue_script(
153
  'query-monitor',
154
  $this->qm->plugin_url( 'assets/query-monitor.js' ),
155
+ $deps,
156
  $this->qm->plugin_ver( 'assets/query-monitor.js' ),
157
+ false
158
  );
159
  wp_localize_script(
160
  'query-monitor',
161
+ 'qm_number_format',
162
+ $wp_locale->number_format
163
  );
164
  wp_localize_script(
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' ),
171
+ 'off' => wp_create_nonce( 'qm-auth-off' ),
172
  ),
173
  )
174
  );
193
  $this->before_output();
194
 
195
  /* @var QM_Output_Html[] */
196
+ foreach ( $this->outputters as $id => $output ) {
197
+ $timer = new QM_Timer;
198
+ $timer->start();
199
+
200
  $output->output();
201
+
202
+ $output->set_timer( $timer->stop() );
203
  }
204
 
205
  $this->after_output();
214
  require_once $file;
215
  }
216
 
217
+ $this->outputters = $this->get_outputters( 'html' );
218
+ $this->admin_bar_menu = apply_filters( 'qm/output/menus', array() );
219
+ $this->panel_menu = apply_filters( 'qm/output/panel_menus', $this->admin_bar_menu );
220
+
221
  $class = array(
222
  'qm-no-js',
223
  );
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
237
+ );
238
+
239
+ echo '<script type="text/javascript">' . "\n\n";
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">';
247
+ echo '<select>';
248
+
249
+ printf(
250
+ '<option value="%1$s">%2$s</option>',
251
+ '#qm-overview',
252
+ esc_html__( 'Overview', 'query-monitor' )
253
+ );
254
+
255
+ foreach ( $this->panel_menu as $menu ) {
256
+ printf(
257
+ '<option value="%1$s">%2$s</option>',
258
+ esc_attr( $menu['href'] ),
259
+ esc_html( $menu['title'] )
260
+ );
261
+ }
262
+ echo '</select>';
263
+
264
  echo '</div>';
265
+ echo '<div class="qm-title-button"><button class="qm-button-container-settings"><span class="screen-reader-text">' . esc_html__( 'Settings', 'query-monitor' ) . '</span><span class="dashicons dashicons-admin-generic" aria-hidden="true"></span></button></div>';
266
+ echo '<div class="qm-title-button"><button class="qm-button-container-pin"><span class="screen-reader-text">' . esc_html__( 'Pin Panel Open', 'query-monitor' ) . '</span><span class="dashicons dashicons-admin-post" aria-hidden="true"></span></button></div>';
267
+ echo '<div class="qm-title-button"><button class="qm-button-container-close"><span class="screen-reader-text">' . esc_html__( 'Close Panel', 'query-monitor' ) . '</span><span class="dashicons dashicons-no-alt" aria-hidden="true"></span></button></div>';
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
+ );
286
+ }
287
+
288
+ echo '</ul>';
289
+ echo '</div>'; // #qm-panel-menu
290
+
291
+ echo '<div id="qm-panels">';
292
 
293
  }
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
322
 
323
  echo '<script type="text/javascript">' . "\n\n";
 
324
  ?>
325
  if ( ( 'undefined' === typeof QM_i18n ) || ( 'undefined' === typeof jQuery ) || ! jQuery ) {
326
+ /* Fallback for worst case scenario */
327
+ document.getElementById( 'query-monitor' ).className += ' qm-broken';
328
+ console.error( document.getElementById( 'qm-broken' ).textContent );
329
+ var menu_item = document.getElementById( 'wp-admin-bar-query-monitor' );
330
+ if ( menu_item ) {
331
+ menu_item.addEventListener( 'click', function() {
332
+ document.getElementById( 'query-monitor' ).className += ' qm-show';
333
+ } );
334
+ }
335
  } else if ( ! document.getElementById( 'wpadminbar' ) ) {
336
+ document.getElementById( 'query-monitor' ).className += ' qm-peek';
337
  }
338
  <?php
339
  echo '</script>' . "\n\n";
340
+ echo '<!-- End of Query Monitor output -->' . "\n\n";
341
+
342
+ }
343
+
344
+ protected static function size( $var ) {
345
+ $start_memory = memory_get_usage();
346
+
347
+ try {
348
+ $var = unserialize( serialize( $var ) ); // @codingStandardsIgnoreLine
349
+ } catch ( Exception $e ) {
350
+ return $e;
351
+ }
352
 
353
+ return memory_get_usage() - $start_memory - ( PHP_INT_SIZE * 8 );
354
  }
355
 
356
  public function js_admin_bar_menu() {
375
  'sub' => array(),
376
  );
377
 
378
+ foreach ( $this->admin_bar_menu as $menu ) {
379
  $admin_bar_menu['sub'][ $menu['id'] ] = $menu;
380
  }
381
 
dispatchers/REST.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Dispatcher_REST extends QM_Dispatcher {
18
 
1
  <?php
2
+ /**
3
+ * REST API request dispatcher.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Dispatcher_REST extends QM_Dispatcher {
9
 
dispatchers/Redirect.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Dispatcher_Redirect extends QM_Dispatcher {
18
 
1
  <?php
2
+ /**
3
+ * HTTP redirect dispatcher.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Dispatcher_Redirect extends QM_Dispatcher {
9
 
output/Headers.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  abstract class QM_Output_Headers extends QM_Output {
18
 
1
  <?php
2
+ /**
3
+ * Abstract output class for HTTP headers.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  abstract class QM_Output_Headers extends QM_Output {
9
 
output/Html.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  abstract class QM_Output_Html extends QM_Output {
18
 
@@ -37,7 +28,7 @@ abstract class QM_Output_Html extends QM_Output {
37
 
38
  public static function output_inner( $vars ) {
39
 
40
- echo '<table cellspacing="0" class="qm-inner">';
41
 
42
  foreach ( $vars as $key => $value ) {
43
  echo '<tr>';
@@ -97,7 +88,9 @@ abstract class QM_Output_Html extends QM_Output {
97
  'prepend' => array(),
98
  ), $args );
99
 
100
- if ( 'component' === $name ) {
 
 
101
  $args['prepend']['non-core'] = __( 'Non-Core', 'query-monitor' );
102
  }
103
 
@@ -105,7 +98,8 @@ abstract class QM_Output_Html extends QM_Output {
105
 
106
  $filter_id = 'qm-filter-' . $this->collector->id . '-' . $name;
107
 
108
- $out = '<label for="' . esc_attr( $filter_id ) . '">' . esc_html( $label ) . '</label>';
 
109
  $out .= '<select id="' . esc_attr( $filter_id ) . '" class="qm-filter" data-filter="' . esc_attr( $name ) . '" data-highlight="' . esc_attr( $args['highlight'] ) . '">';
110
  $out .= '<option value="">' . esc_html_x( 'All', '"All" option for filters', 'query-monitor' ) . '</option>';
111
 
@@ -120,6 +114,7 @@ abstract class QM_Output_Html extends QM_Output {
120
  }
121
 
122
  $out .= '</select>';
 
123
 
124
  return $out;
125
 
@@ -128,15 +123,23 @@ abstract class QM_Output_Html extends QM_Output {
128
  /**
129
  * Returns the column sorter controls. Safe for output.
130
  *
 
 
 
131
  * @return string Markup for the column sorter controls.
132
  */
133
- protected function build_sorter() {
134
- $out = '<span class="qm-sort-controls">';
135
- /* translators: Button for sorting table columns in ascending order */
136
- $out .= '<button class="qm-sort qm-sort-asc"><span class="screen-reader-text">' . esc_html__( 'Ascending', 'query-monitor' ) . '</span></button>';
137
- /* translators: Button for sorting table columns in descending order */
138
- $out .= '<button class="qm-sort qm-sort-desc"><span class="screen-reader-text">' . esc_html__( 'Descending', 'query-monitor' ) . '</span></button>';
 
139
  $out .= '</span>';
 
 
 
 
140
  return $out;
141
  }
142
 
@@ -145,8 +148,8 @@ abstract class QM_Output_Html extends QM_Output {
145
  *
146
  * @return string Markup for the column sorter controls.
147
  */
148
- protected function build_toggler() {
149
- $out = '<button class="qm-toggle" data-on="+" data-off="-">+</button>';
150
  return $out;
151
  }
152
 
@@ -171,10 +174,13 @@ abstract class QM_Output_Html extends QM_Output {
171
  $sql = esc_html( $sql );
172
  $sql = trim( $sql );
173
 
174
- $regex = 'ADD|AFTER|ALTER|AND|BEGIN|COMMIT|CREATE|DESCRIBE|DELETE|DROP|ELSE|END|EXCEPT|FROM|GROUP|HAVING|INNER|INSERT|INTERSECT|LEFT|LIMIT|ON|OR|ORDER|OUTER|REPLACE|RIGHT|ROLLBACK|SELECT|SET|SHOW|START|THEN|TRUNCATE|UNION|UPDATE|USING|VALUES|WHEN|WHERE|XOR';
175
- $sql = preg_replace( '# (' . $regex . ') #', '<br>$1 ', $sql );
 
 
 
176
 
177
- return $sql;
178
 
179
  }
180
 
@@ -217,19 +223,64 @@ abstract class QM_Output_Html extends QM_Output {
217
  * Netbeans: http://simonwheatley.co.uk/2012/08/clickable-stack-traces-with-netbeans/
218
  * `nbopen://%f:%l`
219
  *
220
- * @param string $text The display text, such as a function name or file name.
221
- * @param string $file The full file path and name.
222
- * @param int $line Optional. A line number, if appropriate.
 
223
  * @return string The fully formatted file link or file name, safe for output.
224
  */
225
- public static function output_filename( $text, $file, $line = 0 ) {
226
 
227
  if ( empty( $file ) ) {
228
- return esc_html( $text );
 
 
 
 
229
  }
230
 
231
  $link_line = ( $line ) ? $line : 1;
232
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  if ( ! isset( self::$file_link_format ) ) {
234
  $format = ini_get( 'xdebug.file_link_format' );
235
  $format = apply_filters( 'qm/output/file_link_format', $format );
@@ -240,21 +291,16 @@ abstract class QM_Output_Html extends QM_Output {
240
  }
241
  }
242
 
243
- if ( false === self::$file_link_format ) {
244
- $fallback = QM_Util::standard_dir( $file, '' );
245
- if ( $line ) {
246
- $fallback .= ':' . $line;
247
- }
248
- $return = esc_html( $text );
249
- if ( $fallback !== $text ) {
250
- $return .= '<br><span class="qm-info qm-supplemental">' . esc_html( $fallback ) . '</span>';
251
- }
252
- return $return;
253
- }
254
 
255
- $link = sprintf( self::$file_link_format, urlencode( $file ), intval( $link_line ) );
256
- return sprintf( '<a href="%s">%s</a>', esc_attr( $link ), esc_html( $text ) );
 
 
257
 
 
 
258
  }
259
 
260
  }
1
  <?php
2
+ /**
3
+ * Abstract output class for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  abstract class QM_Output_Html extends QM_Output {
9
 
28
 
29
  public static function output_inner( $vars ) {
30
 
31
+ echo '<table class="qm-inner">';
32
 
33
  foreach ( $vars as $key => $value ) {
34
  echo '<tr>';
88
  'prepend' => array(),
89
  ), $args );
90
 
91
+ $core = __( 'Core', 'query-monitor' );
92
+
93
+ if ( 'component' === $name && isset( $values[ $core ] ) ) {
94
  $args['prepend']['non-core'] = __( 'Non-Core', 'query-monitor' );
95
  }
96
 
98
 
99
  $filter_id = 'qm-filter-' . $this->collector->id . '-' . $name;
100
 
101
+ $out = '<div class="qm-filter-container">';
102
+ $out .= '<label for="' . esc_attr( $filter_id ) . '">' . esc_html( $label ) . '</label>';
103
  $out .= '<select id="' . esc_attr( $filter_id ) . '" class="qm-filter" data-filter="' . esc_attr( $name ) . '" data-highlight="' . esc_attr( $args['highlight'] ) . '">';
104
  $out .= '<option value="">' . esc_html_x( 'All', '"All" option for filters', 'query-monitor' ) . '</option>';
105
 
114
  }
115
 
116
  $out .= '</select>';
117
+ $out .= '</div>';
118
 
119
  return $out;
120
 
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
 
148
  *
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
 
174
  $sql = esc_html( $sql );
175
  $sql = trim( $sql );
176
 
177
+ $regex = 'ADD|AFTER|ALTER|AND|BEGIN|COMMIT|CREATE|DELETE|DESCRIBE|DO|DROP|ELSE|END|EXCEPT|EXPLAIN|FROM|GROUP|HAVING|INNER|INSERT|INTERSECT|LEFT|LIMIT|ON|OR|ORDER|OUTER|RENAME|REPLACE|RIGHT|ROLLBACK|SELECT|SET|SHOW|START|THEN|TRUNCATE|UNION|UPDATE|USE|USING|VALUES|WHEN|WHERE|XOR';
178
+ $sql = preg_replace( '# (' . $regex . ') #', '<br> $1 ', $sql );
179
+
180
+ $keywords = '\b(?:ACTION|ADD|AFTER|ALTER|AND|ASC|AS|AUTO_INCREMENT|BEGIN|BETWEEN|BIGINT|BINARY|BIT|BLOB|BOOLEAN|BOOL|BREAK|BY|CASE|COLLATE|COLUMNS?|COMMIT|CONTINUE|CREATE|DATA(?:BASES?)?|DATE(?:TIME)?|DECIMAL|DECLARE|DEC|DEFAULT|DELAYED|DELETE|DESCRIBE|DESC|DISTINCT|DOUBLE|DO|DROP|DUPLICATE|ELSE|END|ENUM|EXCEPT|EXISTS|EXPLAIN|FIELDS|FLOAT|FOREIGN|FOR|FROM|FULL|FUNCTION|GROUP|HAVING|IF|IGNORE|INDEX|INNER|INSERT|INTEGER|INTERSECT|INTERVAL|INTO|INT|IN|IS|JOIN|KEYS?|LEFT|LIKE|LIMIT|LONG(?:BLOB|TEXT)|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|NOT|NO|NULLIF|ON|ORDER|OR|OUTER|PRIMARY|PROC(?:EDURE)?|REGEXP|RENAME|REPLACE|RIGHT|RLIKE|ROLLBACK|SCHEMA|SELECT|SET|SHOW|SMALLINT|START|TABLES?|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TRUNCATE|UNION|UNIQUE|UNSIGNED|UPDATE|USE|USING|VALUES?|VAR(?:BINARY|CHAR)|WHEN|WHERE|WHILE|XOR)\b';
181
+ $sql = preg_replace( '#' . $keywords . '#', '<b>$0</b>', $sql );
182
 
183
+ return '<code>' . $sql . '</code>';
184
 
185
  }
186
 
223
  * Netbeans: http://simonwheatley.co.uk/2012/08/clickable-stack-traces-with-netbeans/
224
  * `nbopen://%f:%l`
225
  *
226
+ * @param string $text The display text, such as a function name or file name.
227
+ * @param string $file The full file path and name.
228
+ * @param int $line Optional. A line number, if appropriate.
229
+ * @param bool $is_filename Optional. Is the text a plain file name? Default false.
230
  * @return string The fully formatted file link or file name, safe for output.
231
  */
232
+ public static function output_filename( $text, $file, $line = 0, $is_filename = false ) {
233
 
234
  if ( empty( $file ) ) {
235
+ if ( $is_filename ) {
236
+ return esc_html( $text );
237
+ } else {
238
+ return '<code>' . esc_html( $text ) . '</code>';
239
+ }
240
  }
241
 
242
  $link_line = ( $line ) ? $line : 1;
243
 
244
+ if ( ! self::has_clickable_links() ) {
245
+ $fallback = QM_Util::standard_dir( $file, '' );
246
+ if ( $line ) {
247
+ $fallback .= ':' . $line;
248
+ }
249
+ if ( $is_filename ) {
250
+ $return = esc_html( $text );
251
+ } else {
252
+ $return = '<code>' . esc_html( $text ) . '</code>';
253
+ }
254
+ if ( $fallback !== $text ) {
255
+ $return .= '<br><span class="qm-info qm-supplemental">' . esc_html( $fallback ) . '</span>';
256
+ }
257
+ return $return;
258
+ }
259
+
260
+ $map = self::get_file_path_map();
261
+
262
+ if ( ! empty( $map ) ) {
263
+ foreach ( $map as $from => $to ) {
264
+ $file = str_replace( $from, $to, $file );
265
+ }
266
+ }
267
+
268
+ $link = sprintf( self::get_file_link_format(), rawurlencode( $file ), intval( $link_line ) );
269
+
270
+ if ( $is_filename ) {
271
+ $format = '<a href="%s" class="qm-edit-link">%s</a>';
272
+ } else {
273
+ $format = '<a href="%s" class="qm-edit-link"><code>%s</code></a>';
274
+ }
275
+
276
+ return sprintf(
277
+ $format,
278
+ esc_attr( $link ),
279
+ esc_html( $text )
280
+ );
281
+ }
282
+
283
+ public static function get_file_link_format() {
284
  if ( ! isset( self::$file_link_format ) ) {
285
  $format = ini_get( 'xdebug.file_link_format' );
286
  $format = apply_filters( 'qm/output/file_link_format', $format );
291
  }
292
  }
293
 
294
+ return self::$file_link_format;
295
+ }
 
 
 
 
 
 
 
 
 
296
 
297
+ public static function get_file_path_map() {
298
+ // @TODO document this!
299
+ return apply_filters( 'qm/output/file_path_map', array() );
300
+ }
301
 
302
+ public static function has_clickable_links() {
303
+ return ( false !== self::get_file_link_format() );
304
  }
305
 
306
  }
output/headers/overview.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Headers_Overview extends QM_Output_Headers {
18
 
1
  <?php
2
+ /**
3
+ * General overview output for HTTP headers.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Headers_Overview extends QM_Output_Headers {
9
 
output/headers/php_errors.php CHANGED
@@ -1,19 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
-
17
  class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
18
 
19
  public function get_output() {
@@ -39,7 +29,7 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
39
  $output_error = array(
40
  'type' => $error->type,
41
  'message' => wp_strip_all_tags( $error->message ),
42
- 'file' => $error->file,
43
  'line' => $error->line,
44
  'stack' => $error->trace->get_stack(),
45
  'component' => $component->name,
1
  <?php
2
+ /**
3
+ * PHP error output for HTTP headers.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
 
7
  class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
8
 
9
  public function get_output() {
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,
output/headers/redirects.php CHANGED
@@ -1,19 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
-
17
  class QM_Output_Headers_Redirects extends QM_Output_Headers {
18
 
19
  public function get_output() {
1
  <?php
2
+ /**
3
+ * HTTP redirects output for HTTP headers.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
 
7
  class QM_Output_Headers_Redirects extends QM_Output_Headers {
8
 
9
  public function get_output() {
output/html/admin.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Admin extends QM_Output_Html {
18
 
@@ -29,63 +20,58 @@ class QM_Output_Html_Admin extends QM_Output_Html {
29
  return;
30
  }
31
 
32
- echo '<div class="qm qm-half" id="' . esc_attr( $this->collector->id() ) . '">';
33
- echo '<table cellspacing="0">';
34
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
 
 
 
 
35
  echo '<thead class="screen-reader-text">';
36
  echo '<tr>';
37
- echo '<th>' . esc_html__( 'Data', 'query-monitor' ) . '</th>';
38
  echo '<th>' . esc_html__( 'Property', 'query-monitor' ) . '</th>';
39
  echo '<th>' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
40
  echo '</tr>';
41
  echo '</thead>';
42
- echo '<tbody class="qm-group">';
43
-
44
- $first = true;
45
 
46
  foreach ( $data['current_screen'] as $key => $value ) {
47
  echo '<tr>';
48
-
49
- if ( $first ) {
50
- echo '<th class="qm-ltr" rowspan="' . count( $data['current_screen'] ) . '">get_current_screen()</th>';
51
- }
52
-
53
  echo '<td>' . esc_html( $key ) . '</td>';
54
  echo '<td>' . esc_html( $value ) . '</td>';
55
  echo '</tr>';
56
-
57
- $first = false;
58
  }
59
 
60
  echo '</tbody>';
 
 
61
 
62
- echo '<tbody>';
63
- echo '<tr>';
64
- echo '<th class="qm-ltr">$pagenow</th>';
65
- echo '<td colspan="2">' . esc_html( $data['pagenow'] ) . '</td>';
66
- echo '</tr>';
67
 
68
  if ( ! empty( $data['list_table'] ) ) {
69
 
70
- echo '<tr>';
71
- echo '<th rowspan="2">' . esc_html__( 'Column Filters', 'query-monitor' ) . '</th>';
72
- echo '<td colspan="2">' . $data['list_table_markup']['columns_filter'] . '</td>'; // WPCS: XSS ok;
73
- echo '</tr>';
74
- echo '<tr>';
75
- echo '<td colspan="2">' . $data['list_table_markup']['sortables_filter'] . '</td>'; // WPCS: XSS ok;
76
- echo '</tr>';
77
 
78
- echo '<tr>';
79
- echo '<th>' . esc_html__( 'Column Action', 'query-monitor' ) . '</th>';
80
- echo '<td colspan="2">' . $data['list_table_markup']['column_action'] . '</td>'; // WPCS: XSS ok;
81
- echo '</tr>';
 
 
 
 
 
 
 
82
 
83
  }
84
 
85
- echo '</tbody>';
86
- echo '</table>';
87
  echo '</div>';
88
-
89
  }
90
 
91
  }
1
  <?php
2
+ /**
3
+ * Admin screen output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Admin extends QM_Output_Html {
9
 
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
  }
44
 
45
  echo '</tbody>';
46
+ echo '</table>';
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
  }
output/html/assets.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Assets extends QM_Output_Html {
18
 
@@ -30,109 +21,119 @@ class QM_Output_Html_Assets extends QM_Output_Html {
30
  return;
31
  }
32
 
33
- echo '<div id="' . esc_attr( $this->collector->id() ) . '">';
34
-
35
  $position_labels = array(
36
  'missing' => __( 'Missing', 'query-monitor' ),
37
- 'broken' => __( 'Broken Dependencies', 'query-monitor' ),
38
  'header' => __( 'Header', 'query-monitor' ),
39
  'footer' => __( 'Footer', 'query-monitor' ),
40
  );
41
 
42
  $type_labels = array(
43
  'scripts' => array(
44
- 'singular' => __( 'Script', 'query-monitor' ),
 
45
  'plural' => __( 'Scripts', 'query-monitor' ),
46
  ),
47
  'styles' => array(
48
- 'singular' => __( 'Style', 'query-monitor' ),
 
49
  'plural' => __( 'Styles', 'query-monitor' ),
50
  ),
51
  );
52
 
53
  foreach ( $type_labels as $type => $type_label ) {
54
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '-' . esc_attr( $type ) . '">';
56
- echo '<table cellspacing="0">';
57
  echo '<caption>' . esc_html( $type_label['plural'] ) . '</caption>';
58
  echo '<thead>';
59
  echo '<tr>';
60
  echo '<th scope="col">' . esc_html__( 'Position', 'query-monitor' ) . '</th>';
61
- echo '<th scope="col">' . esc_html( $type_label['singular'] ) . '</th>';
 
 
 
 
 
 
 
 
 
62
  echo '<th scope="col">' . esc_html__( 'Dependencies', 'query-monitor' ) . '</th>';
63
  echo '<th scope="col">' . esc_html__( 'Dependents', 'query-monitor' ) . '</th>';
64
  echo '<th scope="col">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
65
  echo '</tr>';
66
  echo '</thead>';
67
 
68
- foreach ( array(
69
- 'missing',
70
- 'broken',
71
- 'header',
72
- 'footer',
73
- ) as $position ) {
74
- if ( isset( $data[ $position ][ $type ] ) ) {
75
- $this->dependency_rows( $data[ $position ][ $type ], $data['raw'][ $type ], $position_labels[ $position ], $type );
76
  }
77
  }
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  echo '</table>';
80
  echo '</div>';
81
 
82
  }
83
 
84
- echo '</div>';
85
-
86
  }
87
 
88
  protected function dependency_rows( array $handles, WP_Dependencies $dependencies, $label, $type ) {
 
89
 
90
- $first = true;
91
-
92
- if ( empty( $handles ) ) {
93
- echo '<tbody>';
94
- echo '<tr>';
95
- echo '<td class="qm-nowrap">' . esc_html( $label ) . '</td>';
96
- echo '<td colspan="5"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
97
- echo '</tr>';
98
- echo '</tbody>';
99
- return;
100
- }
101
 
102
- echo '<tbody class="qm-group">';
103
 
104
- foreach ( $handles as $handle ) {
105
 
106
  if ( in_array( $handle, $dependencies->done, true ) ) {
107
- echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '">';
 
108
  } else {
109
- echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" class="qm-warn">';
110
- }
111
-
112
- if ( $first ) {
113
- $rowspan = count( $handles );
114
- echo '<th scope="row" rowspan="' . esc_attr( $rowspan ) . '" class="qm-nowrap">' . esc_html( $label ) . '</th>';
115
  }
116
 
117
- $this->dependency_row( $dependencies->query( $handle ), $dependencies, $type );
118
 
119
  echo '</tr>';
120
-
121
- $first = false;
122
  }
123
-
124
- echo '</tbody>';
125
-
126
  }
127
 
128
- protected function dependency_row( _WP_Dependency $dependency, WP_Dependencies $dependencies, $type ) {
129
-
130
- if ( empty( $dependency->ver ) ) {
131
- $ver = '';
132
- } else {
133
- $ver = $dependency->ver;
134
- }
135
-
136
  $loader = rtrim( $type, 's' );
137
 
138
  /**
@@ -145,18 +146,43 @@ class QM_Output_Html_Assets extends QM_Output_Html {
145
  */
146
  $source = apply_filters( "{$loader}_loader_src", $dependency->src, $dependency->handle );
147
 
 
 
 
 
 
 
 
 
148
  if ( is_wp_error( $source ) ) {
149
  $src = $source->get_error_message();
150
  if ( ( $error_data = $source->get_error_data() ) && isset( $error_data['src'] ) ) {
151
  $src .= ' (' . $error_data['src'] . ')';
 
152
  }
153
  } elseif ( empty( $source ) ) {
154
  $src = '';
 
155
  } else {
156
  $src = $source;
157
  }
158
 
159
- $dependents = self::get_dependents( $dependency, $dependencies, $type );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  $deps = $dependency->deps;
161
  sort( $deps );
162
 
@@ -172,6 +198,7 @@ class QM_Output_Html_Assets extends QM_Output_Html {
172
  $highlight_deps = array_map( array( $this, '_prefix_type' ), $deps );
173
  $highlight_dependents = array_map( array( $this, '_prefix_type' ), $dependents );
174
 
 
175
  echo '<td class="qm-wrap qm-ltr">' . esc_html( $dependency->handle ) . '<br><span class="qm-info qm-supplemental">';
176
  if ( is_wp_error( $source ) ) {
177
  printf(
@@ -192,26 +219,6 @@ class QM_Output_Html_Assets extends QM_Output_Html {
192
  return $this->type . '-' . $val;
193
  }
194
 
195
- protected static function get_dependents( _WP_Dependency $dependency, WP_Dependencies $dependencies, $type ) {
196
-
197
- // @TODO move this into the collector
198
- $dependents = array();
199
- $handles = array_unique( array_merge( $dependencies->queue, $dependencies->done ) );
200
-
201
- foreach ( $handles as $handle ) {
202
- if ( $item = $dependencies->query( $handle ) ) {
203
- if ( in_array( $dependency->handle, $item->deps, true ) ) {
204
- $dependents[] = $handle;
205
- }
206
- }
207
- }
208
-
209
- sort( $dependents );
210
-
211
- return $dependents;
212
-
213
- }
214
-
215
  public function admin_class( array $class ) {
216
 
217
  $data = $this->collector->get_data();
1
  <?php
2
+ /**
3
+ * Scripts and styles output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Assets extends QM_Output_Html {
9
 
21
  return;
22
  }
23
 
 
 
24
  $position_labels = array(
25
  'missing' => __( 'Missing', 'query-monitor' ),
26
+ 'broken' => __( 'Missing Dependencies', 'query-monitor' ),
27
  'header' => __( 'Header', 'query-monitor' ),
28
  'footer' => __( 'Footer', 'query-monitor' ),
29
  );
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
  );
43
 
44
  foreach ( $type_labels as $type => $type_label ) {
45
 
46
+ $types = array();
47
+
48
+ foreach ( $position_labels as $position => $label ) {
49
+ if ( ! empty( $data[ $position ][ $type ] ) ) {
50
+ $types[ $position ] = $label;
51
+ }
52
+ }
53
+
54
+ $hosts = array(
55
+ __( 'Other', 'query-monitor' ),
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(
67
+ // phpcs:ignore WordPress.VIP.ValidatedSanitizedInput
68
+ 'local' => wp_unslash( $_SERVER['HTTP_HOST'] ),
69
+ ),
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>';
77
  echo '</tr>';
78
  echo '</thead>';
79
 
80
+ echo '<tbody>';
81
+
82
+ $total = 0;
83
+
84
+ foreach ( $position_labels as $position => $label ) {
85
+ if ( ! empty( $data[ $position ][ $type ] ) ) {
86
+ $this->dependency_rows( $data[ $position ][ $type ], $data['raw'][ $type ], $label, $type );
87
+ $total += count( $data[ $position ][ $type ] );
88
  }
89
  }
90
 
91
+ echo '</tbody>';
92
+
93
+ echo '<tfoot>';
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
  }
112
 
113
  protected function dependency_rows( array $handles, WP_Dependencies $dependencies, $label, $type ) {
114
+ foreach ( $handles as $handle ) {
115
 
116
+ $dependency = $dependencies->query( $handle );
 
 
 
 
 
 
 
 
 
 
117
 
118
+ list( $src, $host, $source, $local ) = $this->get_dependency_data( $dependency, $dependencies, $type );
119
 
120
+ $qm_host = ( $local ) ? 'local' : __( 'Other', 'query-monitor' );
121
 
122
  if ( in_array( $handle, $dependencies->done, true ) ) {
123
+ echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" data-qm-' . esc_attr( $type ) . '-host="' . esc_attr( $qm_host ) . '">';
124
+ echo '<td class="qm-nowrap">' . esc_html( $label ) . '</td>';
125
  } else {
126
+ echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" data-qm-' . esc_attr( $type ) . '-host="' . esc_attr( $qm_host ) . '" class="qm-warn">';
127
+ echo '<td class="qm-nowrap"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( $label ) . '</td>';
 
 
 
 
128
  }
129
 
130
+ $this->dependency_row( $dependency, $dependencies, $type );
131
 
132
  echo '</tr>';
 
 
133
  }
 
 
 
134
  }
135
 
136
+ protected function get_dependency_data( _WP_Dependency $dependency, WP_Dependencies $dependencies, $type ) {
 
 
 
 
 
 
 
137
  $loader = rtrim( $type, 's' );
138
 
139
  /**
146
  */
147
  $source = apply_filters( "{$loader}_loader_src", $dependency->src, $dependency->handle );
148
 
149
+ $host = (string) wp_parse_url( $source, PHP_URL_HOST );
150
+ // phpcs:ignore WordPress.VIP.ValidatedSanitizedInput
151
+ $http_host = wp_unslash( $_SERVER['HTTP_HOST'] );
152
+
153
+ if ( empty( $host ) && ! empty( $http_host ) ) {
154
+ $host = $http_host;
155
+ }
156
+
157
  if ( is_wp_error( $source ) ) {
158
  $src = $source->get_error_message();
159
  if ( ( $error_data = $source->get_error_data() ) && isset( $error_data['src'] ) ) {
160
  $src .= ' (' . $error_data['src'] . ')';
161
+ $host = (string) wp_parse_url( $error_data['src'], PHP_URL_HOST );
162
  }
163
  } elseif ( empty( $source ) ) {
164
  $src = '';
165
+ $host = '';
166
  } else {
167
  $src = $source;
168
  }
169
 
170
+ $local = ( $http_host === $host );
171
+
172
+ return array( $src, $host, $source, $local );
173
+ }
174
+
175
+ protected function dependency_row( _WP_Dependency $dependency, WP_Dependencies $dependencies, $type ) {
176
+
177
+ if ( empty( $dependency->ver ) ) {
178
+ $ver = '';
179
+ } else {
180
+ $ver = $dependency->ver;
181
+ }
182
+
183
+ list( $src, $host, $source, $local ) = $this->get_dependency_data( $dependency, $dependencies, $type );
184
+
185
+ $dependents = $this->collector->get_dependents( $dependency, $dependencies );
186
  $deps = $dependency->deps;
187
  sort( $deps );
188
 
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(
219
  return $this->type . '-' . $val;
220
  }
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  public function admin_class( array $class ) {
223
 
224
  $data = $this->collector->get_data();
output/html/caps.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Caps extends QM_Output_Html {
18
 
@@ -22,11 +13,30 @@ class QM_Output_Html_Caps extends QM_Output_Html {
22
  }
23
 
24
  public function output() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  $data = $this->collector->get_data();
27
 
28
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
29
- echo '<table cellspacing="0">';
30
 
31
  if ( ! empty( $data['caps'] ) ) {
32
 
@@ -40,21 +50,21 @@ class QM_Output_Html_Caps extends QM_Output_Html {
40
 
41
  echo '<thead>';
42
  echo '<tr>';
43
- echo '<th scope="col">';
44
  echo $this->build_filter( 'name', $data['parts'], __( 'Capability Check', 'query-monitor' ) ); // WPCS: XSS ok;
45
  echo '</th>';
46
 
47
  if ( $show_user ) {
48
- echo '<th scope="col">';
49
  echo $this->build_filter( 'user', $data['users'], __( 'User', 'query-monitor' ) ); // WPCS: XSS ok;
50
  echo '</th>';
51
  }
52
 
53
- echo '<th scope="col">';
54
  echo $this->build_filter( 'result', $results, __( 'Result', 'query-monitor' ) ); // WPCS: XSS ok;
55
  echo '</th>';
56
  echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
57
- echo '<th scope="col">';
58
  echo $this->build_filter( 'component', $data['components'], __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
59
  echo '</th>';
60
  echo '</tr>';
@@ -95,7 +105,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
95
  }
96
 
97
  printf( // WPCS: XSS ok.
98
- '<td class="qm-ltr qm-nowrap">%s</td>',
99
  $name
100
  );
101
 
@@ -106,7 +116,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
106
  );
107
  }
108
 
109
- $result = ( $row['result'] ) ? '<span class="qm-true">true&nbsp;&#x2713;</span>' : '<span class="qm-false">false</span>';
110
  printf( // WPCS: XSS ok.
111
  '<td class="qm-ltr qm-nowrap">%s</td>',
112
  $result
@@ -143,7 +153,7 @@ class QM_Output_Html_Caps extends QM_Output_Html {
143
  $caller = array_pop( $stack );
144
 
145
  if ( ! empty( $stack ) ) {
146
- echo $this->build_toggler(); // WPCS: XSS ok;
147
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
148
  }
149
 
@@ -161,6 +171,23 @@ class QM_Output_Html_Caps extends QM_Output_Html {
161
 
162
  echo '</tbody>';
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  } else {
165
 
166
  echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
1
  <?php
2
+ /**
3
+ * User capability checks output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Caps extends QM_Output_Html {
9
 
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' ),
25
+ '<code>wp-config.php</code>'
26
+ );
27
+ echo '</p>';
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
 
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
 
63
+ echo '<th scope="col" class="qm-filterable-column">';
64
  echo $this->build_filter( 'result', $results, __( 'Result', 'query-monitor' ) ); // WPCS: XSS ok;
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>';
105
  }
106
 
107
  printf( // WPCS: XSS ok.
108
+ '<td class="qm-ltr qm-nowrap"><code>%s</code></td>',
109
  $name
110
  );
111
 
116
  );
117
  }
118
 
119
+ $result = ( $row['result'] ) ? '<span class="qm-true">true&nbsp;&#x2713;</span>' : 'false';
120
  printf( // WPCS: XSS ok.
121
  '<td class="qm-ltr qm-nowrap">%s</td>',
122
  $result
153
  $caller = array_pop( $stack );
154
 
155
  if ( ! empty( $stack ) ) {
156
+ echo self::build_toggler(); // WPCS: XSS ok;
157
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
158
  }
159
 
171
 
172
  echo '</tbody>';
173
 
174
+ echo '<tfoot>';
175
+
176
+ $colspan = ( $show_user ) ? 5 : 4;
177
+
178
+ echo '<tr>';
179
+ printf(
180
+ '<td colspan="%1$d">%2$s</td>',
181
+ esc_attr( $colspan ),
182
+ esc_html( sprintf(
183
+ /* translators: %s: Number of user capability checks */
184
+ __( 'Total Checks: %s', 'query-monitor' ),
185
+ number_format_i18n( count( $data['caps'] ) )
186
+ ) )
187
+ );
188
+ echo '</tr>';
189
+ echo '</tfoot>';
190
+
191
  } else {
192
 
193
  echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
output/html/conditionals.php CHANGED
@@ -1,70 +1,42 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Conditionals extends QM_Output_Html {
18
 
19
  public function __construct( QM_Collector $collector ) {
20
  parent::__construct( $collector );
21
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 1000 );
 
22
  }
23
 
24
  public function output() {
25
-
26
  $data = $this->collector->get_data();
27
 
28
- $cols = 6;
29
- $i = 0;
30
 
31
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
32
- echo '<table cellspacing="0">';
33
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
34
- echo '<tbody>';
35
 
36
  foreach ( $data['conds']['true'] as $cond ) {
37
- $i++;
38
- if ( 1 === $i % $cols ) {
39
- echo '<tr>';
40
- }
41
- echo '<td class="qm-ltr qm-true">' . esc_html( $cond ) . '()&nbsp;&#x2713;</td>';
42
- if ( 0 === $i % $cols ) {
43
- echo '</tr>';
44
- }
45
  }
46
 
47
- foreach ( $data['conds']['false'] as $cond ) {
48
- $i++;
49
- if ( 1 === $i % $cols ) {
50
- echo '<tr>';
51
- }
52
- echo '<td class="qm-ltr qm-false">' . esc_html( $cond ) . '()</td>';
53
- if ( 0 === $i % $cols ) {
54
- echo '</tr>';
55
- }
56
- }
57
 
58
- $fill = ( $cols - ( $i % $cols ) );
59
- if ( $fill && ( $fill !== $cols ) ) {
60
- echo '<td colspan="' . absint( $fill ) . '">&nbsp;</td>';
61
- echo '</tr>';
62
  }
63
 
64
- echo '</tbody>';
65
- echo '</table>';
66
  echo '</div>';
67
-
 
68
  }
69
 
70
  public function admin_menu( array $menu ) {
@@ -72,7 +44,7 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
72
  $data = $this->collector->get_data();
73
 
74
  foreach ( $data['conds']['true'] as $cond ) {
75
- $menu[] = $this->menu( array(
76
  'title' => esc_html( $cond . '()' ),
77
  'id' => 'query-monitor-conditionals-' . esc_attr( $cond ),
78
  'meta' => array(
@@ -85,6 +57,24 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
85
 
86
  }
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  }
89
 
90
  function register_qm_output_html_conditionals( array $output, QM_Collectors $collectors ) {
1
  <?php
2
+ /**
3
+ * Template conditionals output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Conditionals extends QM_Output_Html {
9
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 1000 );
13
+ add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 1000 );
14
  }
15
 
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>';
 
 
 
 
 
 
 
27
  }
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 ) {
44
  $data = $this->collector->get_data();
45
 
46
  foreach ( $data['conds']['true'] as $cond ) {
47
+ $menu[ "conditionals-{$cond}" ] = $this->menu( array(
48
  'title' => esc_html( $cond . '()' ),
49
  'id' => 'query-monitor-conditionals-' . esc_attr( $cond ),
50
  'meta' => array(
57
 
58
  }
59
 
60
+ public function panel_menu( array $menu ) {
61
+
62
+ $data = $this->collector->get_data();
63
+
64
+ foreach ( $data['conds']['true'] as $cond ) {
65
+ unset( $menu[ "conditionals-{$cond}" ] );
66
+ }
67
+
68
+ $menu['conditionals'] = $this->menu( array(
69
+ 'title' => esc_html__( 'Conditionals', 'query-monitor' ),
70
+ 'id' => 'query-monitor-conditionals',
71
+ ) );
72
+
73
+ return $menu;
74
+
75
+ }
76
+
77
+
78
  }
79
 
80
  function register_qm_output_html_conditionals( array $output, QM_Collectors $collectors ) {
output/html/db_callers.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_DB_Callers extends QM_Output_Html {
18
 
@@ -30,30 +21,27 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
30
  }
31
 
32
  $total_time = 0;
33
- $span = count( $data['types'] ) + 2;
34
-
35
- echo '<div class="qm qm-half" id="' . esc_attr( $this->collector->id() ) . '">';
36
- echo '<table cellspacing="0" class="qm-sortable">';
37
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
38
- echo '<thead>';
39
- echo '<tr>';
40
- echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
41
-
42
- foreach ( $data['types'] as $type_name => $type_count ) {
43
- echo '<th scope="col" class="qm-num qm-ltr">';
44
- echo esc_html( $type_name );
45
- echo $this->build_sorter(); // WPCS: XSS ok;
46
- echo '</th>';
47
- }
48
 
49
- echo '<th scope="col" class="qm-num qm-sorted-desc">';
50
- esc_html_e( 'Time', 'query-monitor' );
51
- echo $this->build_sorter(); // WPCS: XSS ok;
52
- echo '</th>';
53
- echo '</tr>';
54
- echo '</thead>';
55
 
56
  if ( ! empty( $data['times'] ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  echo '<tbody>';
59
 
@@ -62,7 +50,7 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
62
  $stime = number_format_i18n( $row['ltime'], 4 );
63
 
64
  echo '<tr>';
65
- echo '<th scope="row" class="qm-ltr"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="' . esc_attr( $row['caller'] ) . '">' . esc_html( $row['caller'] ) . '</a></th>';
66
 
67
  foreach ( $data['types'] as $type_name => $type_count ) {
68
  if ( isset( $row['types'][ $type_name ] ) ) {
@@ -83,7 +71,7 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
83
  $total_stime = number_format_i18n( $total_time, 4 );
84
 
85
  echo '<tr>';
86
- echo '<td>' . esc_html__( 'Total', 'query-monitor' ) . '</td>';
87
 
88
  foreach ( $data['types'] as $type_name => $type_count ) {
89
  echo '<td class="qm-num">' . esc_html( number_format_i18n( $type_count ) ) . '</td>';
@@ -93,18 +81,16 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
93
  echo '</tr>';
94
 
95
  echo '</tfoot>';
 
96
 
97
  } else {
98
 
99
- echo '<tbody>';
100
- echo '<tr>';
101
- echo '<td colspan="3" style="text-align:center !important"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
102
- echo '</tr>';
103
- echo '</tbody>';
104
 
105
  }
106
 
107
- echo '</table>';
108
  echo '</div>';
109
 
110
  }
1
  <?php
2
+ /**
3
+ * Database query calling function output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_DB_Callers extends QM_Output_Html {
9
 
21
  }
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>';
44
+ echo '</thead>';
45
 
46
  echo '<tbody>';
47
 
50
  $stime = number_format_i18n( $row['ltime'], 4 );
51
 
52
  echo '<tr>';
53
+ echo '<td class="qm-ltr"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="' . esc_attr( $row['caller'] ) . '"><code>' . esc_html( $row['caller'] ) . '</code></a></td>';
54
 
55
  foreach ( $data['types'] as $type_name => $type_count ) {
56
  if ( isset( $row['types'][ $type_name ] ) ) {
71
  $total_stime = number_format_i18n( $total_time, 4 );
72
 
73
  echo '<tr>';
74
+ echo '<td>&nbsp;</td>';
75
 
76
  foreach ( $data['types'] as $type_name => $type_count ) {
77
  echo '<td class="qm-num">' . esc_html( number_format_i18n( $type_count ) ) . '</td>';
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
  }
output/html/db_components.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_DB_Components extends QM_Output_Html {
18
 
@@ -25,102 +16,82 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
25
 
26
  $data = $this->collector->get_data();
27
 
28
- if ( empty( $data['types'] ) ) {
29
  return;
30
  }
31
 
32
  $total_time = 0;
33
- $total_calls = 0;
34
  $span = count( $data['types'] ) + 2;
35
 
36
- echo '<div class="qm qm-half" id="' . esc_attr( $this->collector->id() ) . '">';
37
- echo '<table cellspacing="0" class="qm-sortable">';
38
  echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
39
  echo '<thead>';
40
 
41
- if ( ! empty( $data['times'] ) ) {
42
- echo '<tr>';
43
- echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
44
-
45
- foreach ( $data['types'] as $type_name => $type_count ) {
46
- echo '<th scope="col" class="qm-num">';
47
- echo esc_html( $type_name );
48
- echo $this->build_sorter(); // WPCS: XSS ok;
49
- echo '</th>';
50
- }
51
 
52
- echo '<th scope="col" class="qm-num qm-sorted-desc">';
53
- esc_html_e( 'Time', 'query-monitor' );
54
- echo $this->build_sorter(); // WPCS: XSS ok;
55
  echo '</th>';
56
- echo '</tr>';
57
  }
58
 
59
- echo '</thead>';
60
-
61
- if ( ! empty( $data['times'] ) ) {
62
-
63
- echo '<tbody>';
64
-
65
- foreach ( $data['times'] as $row ) {
66
- $total_time += $row['ltime'];
67
- $total_calls += $row['calls'];
68
-
69
- echo '<tr>';
70
- echo '<th scope="row"><a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="component" data-qm-value="' . esc_attr( $row['component'] ) . '">' . esc_html( $row['component'] ) . '</a></th>';
71
-
72
- foreach ( $data['types'] as $type_name => $type_count ) {
73
- if ( isset( $row['types'][ $type_name ] ) ) {
74
- echo '<td class="qm-num">' . esc_html( number_format_i18n( $row['types'][ $type_name ] ) ) . '</td>';
75
- } else {
76
- echo '<td class="qm-num">&nbsp;</td>';
77
- }
78
- }
79
-
80
- echo '<td class="qm-num" data-qm-sort-weight="' . esc_attr( $row['ltime'] ) . '">' . esc_html( number_format_i18n( $row['ltime'], 4 ) ) . '</td>';
81
- echo '</tr>';
82
 
83
- }
84
 
85
- echo '</tbody>';
86
- echo '<tfoot>';
87
 
88
- $total_stime = number_format_i18n( $total_time, 4 );
 
89
 
90
  echo '<tr>';
91
- echo '<td>' . esc_html__( 'Total', 'query-monitor' ) . '</td>';
92
 
93
  foreach ( $data['types'] as $type_name => $type_count ) {
94
- echo '<td class="qm-num">' . esc_html( number_format_i18n( $type_count ) ) . '</td>';
 
 
 
 
95
  }
96
 
97
- echo '<td class="qm-num">' . esc_html( $total_stime ) . '</td>';
98
  echo '</tr>';
99
- echo '</tfoot>';
100
 
101
- } else {
102
 
103
- echo '<tbody>';
104
- echo '<tr>';
105
- echo '<td colspan="' . esc_attr( $span ) . '" style="text-align:center !important">';
106
- echo '<em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em>';
107
- printf(
108
- '&nbsp;<span class="qm-info">(<a href="%s" target="_blank">%s</a>)</span>',
109
- 'https://github.com/johnbillion/query-monitor/wiki/db.php-Symlink',
110
- esc_html__( 'Help', 'query-monitor' )
111
- );
112
- echo '</td>';
113
- echo '</tr>';
114
- echo '</tbody>';
115
 
 
 
 
 
 
116
  }
117
 
 
 
 
 
118
  echo '</table>';
119
  echo '</div>';
120
 
121
  }
122
 
123
  public function admin_menu( array $menu ) {
 
 
 
 
 
124
 
125
  if ( $dbq = QM_Collectors::get( 'db_queries' ) ) {
126
  $dbq_data = $dbq->get_data();
1
  <?php
2
+ /**
3
+ * Database query calling component output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_DB_Components extends QM_Output_Html {
9
 
16
 
17
  $data = $this->collector->get_data();
18
 
19
+ if ( empty( $data['types'] ) || empty( $data['times'] ) ) {
20
  return;
21
  }
22
 
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>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
+ echo '</thead>';
46
 
47
+ echo '<tbody>';
 
48
 
49
+ foreach ( $data['times'] as $row ) {
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 ] ) ) {
57
+ echo '<td class="qm-num">' . esc_html( number_format_i18n( $row['types'][ $type_name ] ) ) . '</td>';
58
+ } else {
59
+ echo '<td class="qm-num">&nbsp;</td>';
60
+ }
61
  }
62
 
63
+ echo '<td class="qm-num" data-qm-sort-weight="' . esc_attr( $row['ltime'] ) . '">' . esc_html( number_format_i18n( $row['ltime'], 4 ) ) . '</td>';
64
  echo '</tr>';
 
65
 
66
+ }
67
 
68
+ echo '</tbody>';
69
+ echo '<tfoot>';
70
+
71
+ $total_stime = number_format_i18n( $total_time, 4 );
 
 
 
 
 
 
 
 
72
 
73
+ echo '<tr>';
74
+ echo '<td>&nbsp;</td>';
75
+
76
+ foreach ( $data['types'] as $type_name => $type_count ) {
77
+ echo '<td class="qm-num">' . esc_html( number_format_i18n( $type_count ) ) . '</td>';
78
  }
79
 
80
+ echo '<td class="qm-num">' . esc_html( $total_stime ) . '</td>';
81
+ echo '</tr>';
82
+ echo '</tfoot>';
83
+
84
  echo '</table>';
85
  echo '</div>';
86
 
87
  }
88
 
89
  public function admin_menu( array $menu ) {
90
+ $data = $this->collector->get_data();
91
+
92
+ if ( empty( $data['types'] ) || empty( $data['times'] ) ) {
93
+ return $menu;
94
+ }
95
 
96
  if ( $dbq = QM_Collectors::get( 'db_queries' ) ) {
97
  $dbq_data = $dbq->get_data();
output/html/db_dupes.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2015 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_DB_Dupes extends QM_Output_Html {
18
 
@@ -29,10 +20,8 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
29
  return;
30
  }
31
 
32
- $colspan = empty( $data['dupe_components'] ) ? 4 : 5;
33
-
34
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
35
- echo '<table cellspacing="0">';
36
  echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
37
  echo '<thead>';
38
 
@@ -73,7 +62,7 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
73
  echo '<td class="qm-row-caller qm-nowrap qm-ltr">';
74
  foreach ( $data['dupe_callers'][ $sql ] as $caller => $calls ) {
75
  printf(
76
- '<a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="%s">%s</a><br><span class="qm-info qm-supplemental">%s</span><br>',
77
  esc_attr( $caller ),
78
  esc_html( $caller ),
79
  esc_html( sprintf(
@@ -100,7 +89,7 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
100
  echo '<td class="qm-row-caller qm-nowrap qm-ltr">';
101
  foreach ( $data['dupe_sources'][ $sql ] as $source => $calls ) {
102
  printf(
103
- '%s<br><span class="qm-info qm-supplemental">%s</span><br>',
104
  esc_html( $source ),
105
  esc_html( sprintf(
106
  translate_nooped_plural( $call_text, $calls, 'query-monitor' ),
1
  <?php
2
+ /**
3
+ * Duplicate database query output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_DB_Dupes extends QM_Output_Html {
9
 
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
 
62
  echo '<td class="qm-row-caller qm-nowrap qm-ltr">';
63
  foreach ( $data['dupe_callers'][ $sql ] as $caller => $calls ) {
64
  printf(
65
+ '<a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="caller" data-qm-value="%s"><code>%s</code></a><br><span class="qm-info qm-supplemental">%s</span><br>',
66
  esc_attr( $caller ),
67
  esc_html( $caller ),
68
  esc_html( sprintf(
89
  echo '<td class="qm-row-caller qm-nowrap qm-ltr">';
90
  foreach ( $data['dupe_sources'][ $sql ] as $source => $calls ) {
91
  printf(
92
+ '<code>%s</code><br><span class="qm-info qm-supplemental">%s</span><br>',
93
  esc_html( $source ),
94
  esc_html( sprintf(
95
  translate_nooped_plural( $call_text, $calls, 'query-monitor' ),
output/html/db_queries.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_DB_Queries extends QM_Output_Html {
18
 
@@ -50,18 +41,24 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
50
 
51
  protected function output_empty_queries() {
52
 
53
- echo '<div class="qm qm-queries" id="' . esc_attr( $this->collector->id() ) . '-wpdb">';
54
- echo '<table cellspacing="0">';
55
  echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
56
  echo '<tbody>';
57
  echo '<tr>';
58
- echo '<td class="qm-warn">';
59
- printf(
60
- /* translators: 1: Name of PHP constant, 2: Value of PHP constant */
61
- esc_html__( 'No database queries were logged because the %1$s constant is set to %2$s', 'query-monitor' ),
62
- '<code>SAVEQUERIES</code>',
63
- '<code>false</code>'
64
- );
 
 
 
 
 
 
65
  echo '</td>';
66
  echo '</tr>';
67
  echo '</tbody>';
@@ -72,22 +69,22 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
72
 
73
  protected function output_error_queries( array $errors ) {
74
 
75
- echo '<div class="qm qm-queries" id="qm-query-errors">';
76
- echo '<table cellspacing="0">';
77
  echo '<caption>' . esc_html__( 'Database Errors', 'query-monitor' ) . '</caption>';
78
  echo '<thead>';
79
  echo '<tr>';
80
  echo '<th scope="col">' . esc_html__( 'Query', 'query-monitor' ) . '</th>';
81
- echo '<th scope="col">' . esc_html__( 'Call Stack', 'query-monitor' ) . '</th>';
82
  echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
83
- echo '<th scope="col">' . esc_html__( 'Error Code', 'query-monitor' ) . '</th>';
84
  echo '<th scope="col">' . esc_html__( 'Error Message', 'query-monitor' ) . '</th>';
 
85
  echo '</tr>';
86
  echo '</thead>';
87
  echo '<tbody>';
88
 
89
  foreach ( $errors as $row ) {
90
- $this->output_query_row( $row, array( 'sql', 'stack', 'component', 'errno', 'result' ) );
91
  }
92
 
93
  echo '</tbody>';
@@ -100,13 +97,13 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
100
 
101
  $dp = strlen( substr( strrchr( QM_DB_EXPENSIVE, '.' ), 1 ) );
102
 
103
- echo '<div class="qm qm-queries" id="qm-query-expensive">';
104
- echo '<table cellspacing="0">';
105
  echo '<caption>';
106
  printf(
107
  /* translators: %s: Database query time in seconds */
108
  esc_html__( 'Slow Database Queries (above %ss)', 'query-monitor' ),
109
- '<span class="qm-expensive">' . esc_html( number_format_i18n( QM_DB_EXPENSIVE, $dp ) ) . '</span>'
110
  );
111
  echo '</caption>';
112
  echo '<thead>';
@@ -138,7 +135,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
138
  }
139
 
140
  protected function output_queries( $name, stdClass $db, array $data ) {
141
-
142
  $span = 4;
143
 
144
  if ( $db->has_result ) {
@@ -148,13 +145,13 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
148
  $span++;
149
  }
150
 
151
- echo '<div class="qm qm-queries" id="' . esc_attr( $this->collector->id() . '-' . sanitize_title_with_dashes( $name ) ) . '">';
152
- echo '<table cellspacing="0" class="qm-sortable">';
153
- /* translators: %s: Name of database controller */
154
- echo '<caption>' . esc_html( sprintf( __( '%s Queries', 'query-monitor' ), $name ) ) . '</caption>';
155
- echo '<thead>';
156
 
157
  if ( ! empty( $db->rows ) ) {
 
 
 
 
158
 
159
  /**
160
  * Filter whether to show the QM extended query information prompt.
@@ -166,7 +163,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
166
  */
167
  if ( apply_filters( 'qm/show_extended_query_prompt', true ) && ! $db->has_trace && ( '$wpdb' === $name ) ) {
168
  echo '<tr>';
169
- echo '<td colspan="' . absint( $span ) . '" class="qm-warn"><span class="dashicons dashicons-warning"></span>';
170
  if ( file_exists( WP_CONTENT_DIR . '/db.php' ) ) {
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. A conflicting %1$s file is present. <a href="%2$s" target="_blank">See this wiki page for more information.</a>', 'query-monitor' );
@@ -184,7 +181,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
184
  'target' => array(),
185
  ),
186
  ) );
187
- echo '</td>';
188
  echo '</tr>';
189
  }
190
 
@@ -200,13 +197,13 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
200
  );
201
 
202
  echo '<tr>';
203
- echo '<th scope="col" class="qm-sorted-asc">&nbsp;';
204
  echo $this->build_sorter(); // WPCS: XSS ok;
205
  echo '</th>';
206
- echo '<th scope="col">';
207
  echo $this->build_filter( 'type', $types, __( 'Query', 'query-monitor' ), $args ); // WPCS: XSS ok;
208
  echo '</th>';
209
- echo '<th scope="col">';
210
 
211
  $prepend = array();
212
 
@@ -221,7 +218,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
221
  echo '</th>';
222
 
223
  if ( $db->has_trace ) {
224
- echo '<th scope="col">';
225
  echo $this->build_filter( 'component', wp_list_pluck( $data['component_times'], 'component' ), __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
226
  echo '</th>';
227
  }
@@ -232,23 +229,16 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
232
  } else {
233
  $class = '';
234
  }
235
- echo '<th scope="col" class="' . esc_attr( $class ) . '">';
236
- esc_html_e( 'Rows', 'query-monitor' );
237
- echo $this->build_sorter(); // WPCS: XSS ok.
238
  echo '</th>';
239
  }
240
 
241
- echo '<th scope="col" class="qm-num">';
242
- esc_html_e( 'Time', 'query-monitor' );
243
- echo $this->build_sorter(); // WPCS: XSS ok.
244
  echo '</th>';
245
  echo '</tr>';
246
-
247
- }
248
-
249
- echo '</thead>';
250
-
251
- if ( ! empty( $db->rows ) ) {
252
 
253
  echo '<tbody>';
254
 
@@ -283,18 +273,16 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
283
  echo '<td class="qm-num">' . esc_html( $total_stime ) . '</td>';
284
  echo '</tr>';
285
  echo '</tfoot>';
 
286
 
287
  } else {
288
 
289
- echo '<tbody>';
290
- echo '<tr>';
291
- echo '<td colspan="' . absint( $span ) . '" style="text-align:center !important"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
292
- echo '</tr>';
293
- echo '</tbody>';
294
 
295
  }
296
 
297
- echo '</table>';
298
  echo '</div>';
299
 
300
  }
@@ -309,12 +297,9 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
309
  if ( ! isset( $row['result'] ) ) {
310
  unset( $cols['result'], $cols['errno'] );
311
  }
312
- if ( ! isset( $row['stack'] ) ) {
313
- unset( $cols['stack'] );
314
- }
315
 
316
  $stime = number_format_i18n( $row['ltime'], 4 );
317
- $td = $this->collector->is_expensive( $row ) ? ' qm-expensive' : '';
318
 
319
  $sql = self::format_sql( $row['sql'] );
320
 
@@ -335,11 +320,13 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
335
  }
336
  } else {
337
 
338
- $caller_name = esc_html( $row['caller'] );
339
  $stack = explode( ', ', $row['stack'] );
340
  $stack = array_reverse( $stack );
341
  array_shift( $stack );
342
- $stack = array_map( 'esc_html', $stack );
 
 
343
 
344
  }
345
 
@@ -393,9 +380,9 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
393
 
394
  if ( isset( $cols['caller'] ) ) {
395
  echo "<td class='qm-row-caller qm-ltr qm-has-toggle qm-nowrap'><ol class='qm-toggler qm-numbered'>";
 
396
 
397
  if ( ! empty( $stack ) ) {
398
- echo $this->build_toggler(); // WPCS: XSS ok;
399
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
400
  }
401
 
@@ -428,18 +415,18 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
428
  }
429
  }
430
 
431
- if ( isset( $cols['errno'] ) && is_wp_error( $row['result'] ) ) {
432
- echo "<td class='qm-row-result qm-row-error'>" . esc_html( $row['result']->get_error_code() ) . "</td>\n";
433
- }
434
-
435
  if ( isset( $cols['result'] ) ) {
436
  if ( is_wp_error( $row['result'] ) ) {
437
- echo "<td class='qm-row-result qm-row-error'>" . esc_html( $row['result']->get_error_message() ) . "</td>\n";
438
  } else {
439
  echo "<td class='qm-row-result qm-num'>" . esc_html( $row['result'] ) . "</td>\n";
440
  }
441
  }
442
 
 
 
 
 
443
  if ( isset( $cols['time'] ) ) {
444
  echo '<td class="qm-num qm-row-time' . esc_attr( $td ) . '" data-qm-sort-weight="' . esc_attr( $row['ltime'] ) . '">' . esc_html( $stime ) . "</td>\n";
445
  }
@@ -520,7 +507,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
520
  'id' => esc_attr( sprintf( 'query-monitor-%s-db-%s', $this->collector->id(), sanitize_title_with_dashes( $name ) ) ),
521
  'title' => esc_html( sprintf(
522
  /* translators: %s: Name of database controller */
523
- __( 'Queries - %s', 'query-monitor' ),
524
  $name
525
  ) ),
526
  'href' => esc_attr( sprintf( '#%s-%s', $this->collector->id(), sanitize_title_with_dashes( $name ) ) ),
1
  <?php
2
+ /**
3
+ * Database query output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_DB_Queries extends QM_Output_Html {
9
 
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>';
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>';
78
+ echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
79
  echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
 
80
  echo '<th scope="col">' . esc_html__( 'Error Message', 'query-monitor' ) . '</th>';
81
+ echo '<th scope="col">' . esc_html__( 'Error Code', 'query-monitor' ) . '</th>';
82
  echo '</tr>';
83
  echo '</thead>';
84
  echo '<tbody>';
85
 
86
  foreach ( $errors as $row ) {
87
+ $this->output_query_row( $row, array( 'sql', 'caller', 'component', 'errno', 'result' ) );
88
  }
89
 
90
  echo '</tbody>';
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>';
135
  }
136
 
137
  protected function output_queries( $name, stdClass $db, array $data ) {
138
+ $this->query_row = 0;
139
  $span = 4;
140
 
141
  if ( $db->has_result ) {
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
  /**
157
  * Filter whether to show the QM extended query information prompt.
163
  */
164
  if ( apply_filters( 'qm/show_extended_query_prompt', true ) && ! $db->has_trace && ( '$wpdb' === $name ) ) {
165
  echo '<tr>';
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' );
181
  'target' => array(),
182
  ),
183
  ) );
184
+ echo '</th>';
185
  echo '</tr>';
186
  }
187
 
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;
205
  echo '</th>';
206
+ echo '<th scope="col" class="qm-filterable-column">';
207
 
208
  $prepend = array();
209
 
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
  }
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>';
241
+ echo '</thead>';
 
 
 
 
 
242
 
243
  echo '<tbody>';
244
 
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
  }
297
  if ( ! isset( $row['result'] ) ) {
298
  unset( $cols['result'], $cols['errno'] );
299
  }
 
 
 
300
 
301
  $stime = number_format_i18n( $row['ltime'], 4 );
302
+ $td = $this->collector->is_expensive( $row ) ? ' qm-warn' : '';
303
 
304
  $sql = self::format_sql( $row['sql'] );
305
 
320
  }
321
  } else {
322
 
323
+ $caller_name = '<code>' . esc_html( $row['caller'] ) . '</code>';
324
  $stack = explode( ', ', $row['stack'] );
325
  $stack = array_reverse( $stack );
326
  array_shift( $stack );
327
+ $stack = array_map( function( $item ) {
328
+ return '<code>' . esc_html( $item ) . '</code>';
329
+ }, $stack );
330
 
331
  }
332
 
380
 
381
  if ( isset( $cols['caller'] ) ) {
382
  echo "<td class='qm-row-caller qm-ltr qm-has-toggle qm-nowrap'><ol class='qm-toggler qm-numbered'>";
383
+ echo self::build_toggler(); // WPCS: XSS ok;
384
 
385
  if ( ! empty( $stack ) ) {
 
386
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
387
  }
388
 
415
  }
416
  }
417
 
 
 
 
 
418
  if ( isset( $cols['result'] ) ) {
419
  if ( is_wp_error( $row['result'] ) ) {
420
+ echo "<td class='qm-row-result qm-row-error'><span class='dashicons dashicons-warning' aria-hidden='true'></span>" . esc_html( $row['result']->get_error_message() ) . "</td>\n";
421
  } else {
422
  echo "<td class='qm-row-result qm-num'>" . esc_html( $row['result'] ) . "</td>\n";
423
  }
424
  }
425
 
426
+ if ( isset( $cols['errno'] ) && is_wp_error( $row['result'] ) ) {
427
+ echo "<td class='qm-row-result qm-row-error'>" . esc_html( $row['result']->get_error_code() ) . "</td>\n";
428
+ }
429
+
430
  if ( isset( $cols['time'] ) ) {
431
  echo '<td class="qm-num qm-row-time' . esc_attr( $td ) . '" data-qm-sort-weight="' . esc_attr( $row['ltime'] ) . '">' . esc_html( $stime ) . "</td>\n";
432
  }
507
  'id' => esc_attr( sprintf( 'query-monitor-%s-db-%s', $this->collector->id(), sanitize_title_with_dashes( $name ) ) ),
508
  'title' => esc_html( sprintf(
509
  /* translators: %s: Name of database controller */
510
+ __( 'Queries: %s', 'query-monitor' ),
511
  $name
512
  ) ),
513
  'href' => esc_attr( sprintf( '#%s-%s', $this->collector->id(), sanitize_title_with_dashes( $name ) ) ),
output/html/debug_bar.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Debug_Bar extends QM_Output_Html {
18
 
@@ -26,22 +17,11 @@ class QM_Output_Html_Debug_Bar extends QM_Output_Html {
26
  $target = get_class( $this->collector->get_panel() );
27
 
28
  echo '<div class="qm qm-debug-bar" id="' . esc_attr( $this->collector->id() ) . '">';
29
- echo '<table cellspacing="0">';
30
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
31
- echo '<tbody>';
32
-
33
- echo '<tr>';
34
- echo '<td>';
35
  echo '<div id="debug-menu-target-' . esc_attr( $target ) . '" class="debug-menu-target qm-debug-bar-output">';
36
 
37
  $this->collector->render();
38
 
39
  echo '</div>';
40
- echo '</td>';
41
- echo '</tr>';
42
-
43
- echo '</tbody>';
44
- echo '</table>';
45
  echo '</div>';
46
 
47
  }
1
  <?php
2
+ /**
3
+ * 'Debug Bar' output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Debug_Bar extends QM_Output_Html {
9
 
17
  $target = 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
  }
output/html/environment.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Environment extends QM_Output_Html {
18
 
@@ -25,22 +16,34 @@ class QM_Output_Html_Environment extends QM_Output_Html {
25
 
26
  $data = $this->collector->get_data();
27
 
28
- echo '<div id="' . esc_attr( $this->collector->id() ) . '">';
 
29
 
30
- echo '<div class="qm qm-third">';
31
- echo '<table cellspacing="0">';
32
- echo '<caption>PHP</caption>';
33
- echo '<thead class="screen-reader-text">';
34
- echo '<tr>';
35
- echo '<th scope="col">' . esc_html__( 'Property', 'query-monitor' ) . '</th>';
36
- echo '<th scope="col">' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
37
- echo '</tr>';
38
- echo '</thead>';
39
  echo '<tbody>';
40
 
41
- echo '<tr>';
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  echo '<th scope="row">version</th>';
43
- echo '<td>' . esc_html( $data['php']['version'] ) . '</td>';
 
 
 
44
  echo '</tr>';
45
 
46
  echo '<tr>';
@@ -48,13 +51,6 @@ class QM_Output_Html_Environment extends QM_Output_Html {
48
  echo '<td>' . esc_html( $data['php']['sapi'] ) . '</td>';
49
  echo '</tr>';
50
 
51
- if ( isset( $data['php']['hhvm'] ) ) {
52
- echo '<tr>';
53
- echo '<th scope="row">hhvm</th>';
54
- echo '<td>' . esc_html( $data['php']['hhvm'] ) . '</td>';
55
- echo '</tr>';
56
- }
57
-
58
  echo '<tr>';
59
  echo '<th scope="row">user</th>';
60
  if ( ! empty( $data['php']['user'] ) ) {
@@ -68,7 +64,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
68
 
69
  echo '<tr>';
70
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
71
- echo '<td class="qm-wrap">';
72
  echo esc_html( $val['after'] );
73
 
74
  if ( $val['after'] !== $val['before'] ) {
@@ -86,10 +82,9 @@ class QM_Output_Html_Environment extends QM_Output_Html {
86
  echo '</tr>';
87
  }
88
 
89
- $error_levels = $this->collector->get_error_levels( $data['php']['error_reporting'] );
90
  $out = array();
91
 
92
- foreach ( $error_levels as $level => $reported ) {
93
  if ( $reported ) {
94
  $out[] = esc_html( $level ) . '&nbsp;&#x2713;';
95
  } else {
@@ -104,7 +99,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
104
  echo '<td class="qm-has-toggle qm-ltr"><div class="qm-toggler">';
105
 
106
  echo esc_html( $data['php']['error_reporting'] );
107
- echo $this->build_toggler(); // WPCS: XSS ok;
108
 
109
  echo '<div class="qm-toggled">';
110
  echo "<ul class='qm-supplemental'><li>{$error_levels}</li></ul>"; // WPCS: XSS ok.
@@ -116,14 +111,17 @@ class QM_Output_Html_Environment extends QM_Output_Html {
116
  if ( ! empty( $data['php']['extensions'] ) ) {
117
  echo '<tr>';
118
  echo '<th scope="row">' . esc_html__( 'Extensions', 'query-monitor' ) . '</th>';
119
- echo '<td class="qm-has-toggle qm-ltr"><div class="qm-toggler">';
120
 
121
- echo esc_html( number_format_i18n( count( $data['php']['extensions'] ) ) );
122
- echo $this->build_toggler(); // WPCS: XSS ok;
 
 
 
123
 
124
- echo '<div class="qm-toggled"><ul class="qm-supplemental"><li>';
125
- echo implode( '</li><li>', array_map( 'esc_html', $data['php']['extensions'] ) );
126
- echo '</li></ul></div>';
127
 
128
  echo '</div></td>';
129
  echo '</tr>';
@@ -131,6 +129,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
131
 
132
  echo '</tbody>';
133
  echo '</table>';
 
134
  echo '</div>';
135
 
136
  if ( isset( $data['db'] ) ) {
@@ -144,15 +143,10 @@ class QM_Output_Html_Environment extends QM_Output_Html {
144
  $name = sprintf( __( 'Database: %s', 'query-monitor' ), $id );
145
  }
146
 
147
- echo '<div class="qm qm-third">';
148
- echo '<table cellspacing="0">';
149
- echo '<caption>' . esc_html( $name ) . '</caption>';
150
- echo '<thead class="screen-reader-text">';
151
- echo '<tr>';
152
- echo '<th scope="col">' . esc_html__( 'Property', 'query-monitor' ) . '</th>';
153
- echo '<th scope="col">' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
154
- echo '</tr>';
155
- echo '</thead>';
156
  echo '<tbody>';
157
 
158
  foreach ( $db['info'] as $key => $value ) {
@@ -163,7 +157,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
163
  if ( ! isset( $value ) ) {
164
  echo '<td><span class="qm-warn">' . esc_html__( 'Unknown', 'query-monitor' ) . '</span></td>';
165
  } else {
166
- echo '<td class="qm-wrap">' . esc_html( $value ) . '</td>';
167
  }
168
 
169
  echo '</tr>';
@@ -177,8 +171,11 @@ class QM_Output_Html_Environment extends QM_Output_Html {
177
 
178
  foreach ( $db['variables'] as $setting ) {
179
 
 
180
  $key = $setting->Variable_name;
 
181
  $val = $setting->Value;
 
182
  $append = '';
183
  $show_warning = false;
184
 
@@ -191,7 +188,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
191
  if ( $show_warning ) {
192
  $append .= sprintf(
193
  '&nbsp;<span class="qm-info">(<a href="%s" target="_blank">%s</a>)</span>',
194
- esc_url( sprintf( $search, urlencode( $key ) ) ),
195
  esc_html__( 'Help', 'query-monitor' )
196
  );
197
  }
@@ -210,7 +207,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
210
  }
211
 
212
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
213
- echo '<td class="qm-wrap">';
214
  echo esc_html( $val );
215
  echo $append; // WPCS: XSS ok.
216
  echo '</td>';
@@ -223,55 +220,47 @@ class QM_Output_Html_Environment extends QM_Output_Html {
223
 
224
  echo '</tbody>';
225
  echo '</table>';
 
226
  echo '</div>';
227
 
228
  }
229
  }
230
 
231
- echo '<div class="qm qm-third" style="float:right !important">';
232
- echo '<table cellspacing="0">';
233
- echo '<caption>WordPress</caption>';
234
- echo '<thead class="screen-reader-text">';
235
- echo '<tr>';
236
- echo '<th scope="col">' . esc_html__( 'Property', 'query-monitor' ) . '</th>';
237
- echo '<th scope="col">' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
238
- echo '</tr>';
239
- echo '</thead>';
240
  echo '<tbody>';
241
 
242
  foreach ( $data['wp'] as $key => $val ) {
243
 
244
  echo '<tr>';
245
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
246
- echo '<td class="qm-wrap">' . esc_html( $val ) . '</td>';
247
  echo '</tr>';
248
 
249
  }
250
 
251
  echo '</tbody>';
252
  echo '</table>';
 
253
  echo '</div>';
254
 
255
- echo '<div class="qm qm-third">';
256
- echo '<table cellspacing="0">';
257
- echo '<caption>' . esc_html__( 'Server', 'query-monitor' ) . '</caption>';
258
- echo '<thead class="screen-reader-text">';
259
- echo '<tr>';
260
- echo '<th scope="col">' . esc_html__( 'Property', 'query-monitor' ) . '</th>';
261
- echo '<th scope="col">' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
262
- echo '</tr>';
263
- echo '</thead>';
264
  echo '<tbody>';
265
 
266
  echo '<tr>';
267
  echo '<th scope="row">' . esc_html__( 'software', 'query-monitor' ) . '</th>';
268
- echo '<td class="qm-wrap">' . esc_html( $data['server']['name'] ) . '</td>';
269
  echo '</tr>';
270
 
271
  echo '<tr>';
272
  echo '<th scope="row">' . esc_html__( 'version', 'query-monitor' ) . '</th>';
273
  if ( ! empty( $data['server']['version'] ) ) {
274
- echo '<td class="qm-wrap">' . esc_html( $data['server']['version'] ) . '</td>';
275
  } else {
276
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
277
  }
@@ -280,7 +269,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
280
  echo '<tr>';
281
  echo '<th scope="row">' . esc_html__( 'address', 'query-monitor' ) . '</th>';
282
  if ( ! empty( $data['server']['address'] ) ) {
283
- echo '<td class="qm-wrap">' . esc_html( $data['server']['address'] ) . '</td>';
284
  } else {
285
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
286
  }
@@ -288,7 +277,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
288
 
289
  echo '<tr>';
290
  echo '<th scope="row">' . esc_html__( 'host', 'query-monitor' ) . '</th>';
291
- echo '<td class="qm-wrap">' . esc_html( $data['server']['host'] ) . '</td>';
292
  echo '</tr>';
293
 
294
  echo '</tbody>';
@@ -296,7 +285,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
296
  echo '</div>';
297
 
298
  echo '</div>';
299
-
300
  }
301
 
302
  }
1
  <?php
2
+ /**
3
+ * Environment data output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Environment extends QM_Output_Html {
9
 
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>';
27
 
28
+ $append = '';
29
+ $class = '';
30
+ $php_warning = $data['php']['old'];
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
+ );
38
+ $class = 'qm-warn';
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.
46
+ echo '</td>';
47
  echo '</tr>';
48
 
49
  echo '<tr>';
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'] ) ) {
64
 
65
  echo '<tr>';
66
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
67
+ echo '<td>';
68
  echo esc_html( $val['after'] );
69
 
70
  if ( $val['after'] !== $val['before'] ) {
82
  echo '</tr>';
83
  }
84
 
 
85
  $out = array();
86
 
87
+ foreach ( $data['php']['error_levels'] as $level => $reported ) {
88
  if ( $reported ) {
89
  $out[] = esc_html( $level ) . '&nbsp;&#x2713;';
90
  } else {
99
  echo '<td class="qm-has-toggle qm-ltr"><div class="qm-toggler">';
100
 
101
  echo esc_html( $data['php']['error_reporting'] );
102
+ echo self::build_toggler(); // WPCS: XSS ok;
103
 
104
  echo '<div class="qm-toggled">';
105
  echo "<ul class='qm-supplemental'><li>{$error_levels}</li></ul>"; // WPCS: XSS ok.
111
  if ( ! empty( $data['php']['extensions'] ) ) {
112
  echo '<tr>';
113
  echo '<th scope="row">' . esc_html__( 'Extensions', 'query-monitor' ) . '</th>';
114
+ echo '<td class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
115
 
116
+ printf( // WPCS: XSS ok.
117
+ '<div class="qm-inner-toggle">%1$s %2$s</div>',
118
+ esc_html( number_format_i18n( count( $data['php']['extensions'] ) ) ),
119
+ self::build_toggler()
120
+ );
121
 
122
+ echo '<div class="qm-toggled">';
123
+ self::output_inner( $data['php']['extensions'] );
124
+ echo '</div>';
125
 
126
  echo '</div></td>';
127
  echo '</tr>';
129
 
130
  echo '</tbody>';
131
  echo '</table>';
132
+
133
  echo '</div>';
134
 
135
  if ( isset( $data['db'] ) ) {
143
  $name = sprintf( __( 'Database: %s', 'query-monitor' ), $id );
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 ) {
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>';
171
 
172
  foreach ( $db['variables'] as $setting ) {
173
 
174
+ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
175
  $key = $setting->Variable_name;
176
+ // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
177
  $val = $setting->Value;
178
+
179
  $append = '';
180
  $show_warning = false;
181
 
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
  );
194
  }
207
  }
208
 
209
  echo '<th scope="row">' . esc_html( $key ) . '</th>';
210
+ echo '<td>';
211
  echo esc_html( $val );
212
  echo $append; // WPCS: XSS ok.
213
  echo '</td>';
220
 
221
  echo '</tbody>';
222
  echo '</table>';
223
+
224
  echo '</div>';
225
 
226
  }
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>';
239
+ echo '<td>' . esc_html( $val ) . '</td>';
240
  echo '</tr>';
241
 
242
  }
243
 
244
  echo '</tbody>';
245
  echo '</table>';
246
+
247
  echo '</div>';
248
 
249
+ echo '<div class="qm-section">';
250
+ echo '<h2>' . esc_html( 'Server', 'query-monitor' ) . '</h2>';
251
+
252
+ echo '<table>';
 
 
 
 
 
253
  echo '<tbody>';
254
 
255
  echo '<tr>';
256
  echo '<th scope="row">' . esc_html__( 'software', 'query-monitor' ) . '</th>';
257
+ echo '<td>' . esc_html( $data['server']['name'] ) . '</td>';
258
  echo '</tr>';
259
 
260
  echo '<tr>';
261
  echo '<th scope="row">' . esc_html__( 'version', 'query-monitor' ) . '</th>';
262
  if ( ! empty( $data['server']['version'] ) ) {
263
+ echo '<td>' . esc_html( $data['server']['version'] ) . '</td>';
264
  } else {
265
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
266
  }
269
  echo '<tr>';
270
  echo '<th scope="row">' . esc_html__( 'address', 'query-monitor' ) . '</th>';
271
  if ( ! empty( $data['server']['address'] ) ) {
272
+ echo '<td>' . esc_html( $data['server']['address'] ) . '</td>';
273
  } else {
274
  echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
275
  }
277
 
278
  echo '<tr>';
279
  echo '<th scope="row">' . esc_html__( 'host', 'query-monitor' ) . '</th>';
280
+ echo '<td>' . esc_html( $data['server']['host'] ) . '</td>';
281
  echo '</tr>';
282
 
283
  echo '</tbody>';
285
  echo '</div>';
286
 
287
  echo '</div>';
288
+ echo '</div>';
289
  }
290
 
291
  }
output/html/hooks.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Hooks extends QM_Output_Html {
18
 
@@ -38,20 +29,24 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
38
  }
39
 
40
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
41
- echo '<table cellspacing="0">';
42
  echo '<caption class="screen-reader-text">' . esc_html__( 'Hooks', 'query-monitor' ) . '</caption>';
43
  echo '<thead>';
44
  echo '<tr>';
45
- echo '<th scope="col">';
46
  echo $this->build_filter( 'name', $data['parts'], __( 'Hook', 'query-monitor' ) ); // WPCS: XSS ok.
47
  echo '</th>';
48
- echo '<th scope="col" colspan="3">';
49
- echo $this->build_filter( 'component', $data['components'], __( 'Actions', 'query-monitor' ), 'subject' ); // WPCS: XSS ok.
 
 
50
  echo '</th>';
51
  echo '</tr>';
52
  echo '</thead>';
53
 
 
54
  self::output_hook_table( $data['hooks'], $screen );
 
55
 
56
  echo '</table>';
57
  echo '</div>';
@@ -59,11 +54,8 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
59
  }
60
 
61
  public static function output_hook_table( array $hooks, $screen = '' ) {
62
-
63
  foreach ( $hooks as $hook ) {
64
 
65
- echo '<tbody class="qm-group">';
66
-
67
  if ( ! empty( $screen ) ) {
68
 
69
  if ( false !== strpos( $hook['name'], $screen . '.php' ) ) {
@@ -115,8 +107,8 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
115
 
116
  if ( $first ) {
117
 
118
- echo '<th scope="row" rowspan="' . absint( $rowspan ) . '" class="qm-nowrap qm-ltr">';
119
- echo $hook_name; // WPCS: XSS ok.
120
  if ( 'all' === $hook['name'] ) {
121
  echo '<br><span class="qm-warn">';
122
  printf(
@@ -126,31 +118,47 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
126
  );
127
  echo '<span>';
128
  }
129
- echo '</th>';
 
 
130
 
 
 
 
 
131
  }
132
 
133
- echo '<td class="qm-num">' . intval( $action['priority'] ) . '</td>';
134
- echo '<td class="qm-ltr qm-wrap">';
135
 
136
  if ( isset( $action['callback']['file'] ) ) {
137
- echo self::output_filename( $action['callback']['name'], $action['callback']['file'], $action['callback']['line'] ); // WPCS: XSS ok.
 
 
 
 
 
 
 
 
 
 
 
138
  } else {
139
- echo esc_html( $action['callback']['name'] );
 
140
  }
141
 
142
  if ( isset( $action['callback']['error'] ) ) {
143
- echo '<br><span class="qm-warn">';
144
  echo esc_html( sprintf(
145
  /* translators: %s: Error message text */
146
  __( 'Error: %s', 'query-monitor' ),
147
  $action['callback']['error']->get_error_message()
148
  ) );
149
- echo '<span>';
150
  }
151
 
152
  echo '</td>';
153
- echo '<td class="qm-nowrap">';
154
  echo esc_html( $component );
155
  echo '</td>';
156
  echo '</tr>';
@@ -159,14 +167,13 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
159
  } else {
160
  echo "<tr{$attr}>"; // WPCS: XSS ok.
161
  echo '<th scope="row" class="qm-ltr">';
162
- echo $hook_name; // WPCS: XSS ok.
163
  echo '</th>';
164
- echo '<td colspan="3">&nbsp;</td>';
 
 
165
  echo '</tr>';
166
  }
167
-
168
- echo '</tbody>';
169
-
170
  }
171
 
172
  }
1
  <?php
2
+ /**
3
+ * Hooks and actions output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Hooks extends QM_Output_Html {
9
 
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>';
46
 
47
+ echo '<tbody>';
48
  self::output_hook_table( $data['hooks'], $screen );
49
+ echo '</tbody>';
50
 
51
  echo '</table>';
52
  echo '</div>';
54
  }
55
 
56
  public static function output_hook_table( array $hooks, $screen = '' ) {
 
57
  foreach ( $hooks as $hook ) {
58
 
 
 
59
  if ( ! empty( $screen ) ) {
60
 
61
  if ( false !== strpos( $hook['name'], $screen . '.php' ) ) {
107
 
108
  if ( $first ) {
109
 
110
+ echo '<th scope="row" rowspan="' . absint( $rowspan ) . '" class="qm-nowrap qm-ltr"><span class="qm-sticky">';
111
+ echo '<code>' . $hook_name . '</code>'; // WPCS: XSS ok.
112
  if ( 'all' === $hook['name'] ) {
113
  echo '<br><span class="qm-warn">';
114
  printf(
118
  );
119
  echo '<span>';
120
  }
121
+ echo '</span></th>';
122
+
123
+ }
124
 
125
+ if ( isset( $action['callback']['error'] ) ) {
126
+ $class = ' qm-warn';
127
+ } else {
128
+ $class = '';
129
  }
130
 
131
+ echo '<td class="qm-num' . esc_attr( $class ) . '">' . intval( $action['priority'] ) . '</td>';
 
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 {
139
+ echo '<td class="qm-nowrap qm-ltr qm-has-toggle' . esc_attr( $class ) . '"><ol class="qm-toggler">';
140
+ echo self::build_toggler(); // WPCS: XSS ok;
141
+ echo '<li>';
142
+ echo self::output_filename( $action['callback']['name'], $action['callback']['file'], $action['callback']['line'] ); // WPCS: XSS ok.
143
+ echo '</li>';
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
 
151
  if ( isset( $action['callback']['error'] ) ) {
152
+ echo '<br>';
153
  echo esc_html( sprintf(
154
  /* translators: %s: Error message text */
155
  __( 'Error: %s', 'query-monitor' ),
156
  $action['callback']['error']->get_error_message()
157
  ) );
 
158
  }
159
 
160
  echo '</td>';
161
+ echo '<td class="qm-nowrap' . esc_attr( $class ) . '">';
162
  echo esc_html( $component );
163
  echo '</td>';
164
  echo '</tr>';
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>';
175
  echo '</tr>';
176
  }
 
 
 
177
  }
178
 
179
  }
output/html/http.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_HTTP extends QM_Output_Html {
18
 
@@ -29,7 +20,6 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
29
  $total_time = 0;
30
 
31
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
32
- echo '<table cellspacing="0" class="qm-sortable">';
33
 
34
  $vars = array();
35
 
@@ -40,27 +30,29 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
40
  }
41
 
42
  if ( ! empty( $data['http'] ) ) {
 
43
 
44
  echo '<caption class="screen-reader-text">' . esc_html__( 'HTTP API Calls', 'query-monitor' ) . '</caption>';
45
 
46
  echo '<thead>';
47
  echo '<tr>';
48
- echo '<th scope="col" class="qm-sorted-asc">&nbsp;';
49
  echo $this->build_sorter(); // WPCS: XSS ok.
50
  echo '</th>';
51
- echo '<th scope="col">' . esc_html__( 'HTTP Request', 'query-monitor' ) . '</th>';
52
- echo '<th scope="col">';
 
53
  echo $this->build_filter( 'type', array_keys( $data['types'] ), __( 'Status', 'query-monitor' ) ); // WPCS: XSS ok.
54
  echo '</th>';
55
  echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
56
- echo '<th scope="col">';
57
  echo $this->build_filter( 'component', wp_list_pluck( $data['component_times'], 'component' ), __( 'Component', 'query-monitor' ) ); // WPCS: XSS ok.
58
  echo '</th>';
59
- echo '<th scope="col" class="qm-num">' . esc_html__( 'Timeout', 'query-monitor' );
60
- echo $this->build_sorter(); // WPCS: XSS ok.
61
  echo '</th>';
62
- echo '<th scope="col" class="qm-num">' . esc_html__( 'Time', 'query-monitor' );
63
- echo $this->build_sorter(); // WPCS: XSS ok.
64
  echo '</th>';
65
  echo '</tr>';
66
  echo '</thead>';
@@ -72,16 +64,18 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
72
  $ltime = $row['ltime'];
73
  $i++;
74
  $is_error = false;
75
-
76
  $row_attr = array();
 
77
 
78
  if ( is_wp_error( $row['response'] ) ) {
79
  $response = $row['response']->get_error_message();
80
  $is_error = true;
 
 
 
81
  } else {
82
  $code = wp_remote_retrieve_response_code( $row['response'] );
83
  $msg = wp_remote_retrieve_response_message( $row['response'] );
84
- $css = '';
85
 
86
  if ( intval( $code ) >= 400 ) {
87
  $is_error = true;
@@ -95,26 +89,18 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
95
  $css = 'qm-warn';
96
  }
97
 
98
- $method = esc_html( $row['args']['method'] );
99
-
100
- if ( empty( $row['args']['blocking'] ) ) {
101
- $method .= '<br><span class="qm-info">' . esc_html( sprintf(
102
- /* translators: A non-blocking HTTP API request. %s: Relevant argument name */
103
- __( '(Non-blocking request: %s)', 'query-monitor' ),
104
- 'blocking=false'
105
- ) ) . '</span>';
106
- }
107
-
108
  $url = self::format_url( $row['url'] );
 
109
 
110
  if ( 'https' === parse_url( $row['url'], PHP_URL_SCHEME ) ) {
111
  if ( empty( $row['args']['sslverify'] ) && empty( $row['args']['local'] ) ) {
112
- $method .= '<br><span class="qm-warn">' . esc_html( sprintf(
113
  /* translators: An HTTP API request has disabled certificate verification. 1: Relevant argument name */
114
- __( '(Certificate verification disabled: %s)', 'query-monitor' ),
115
  'sslverify=false'
116
- ) ) . '</span>';
117
- } elseif ( ! $is_error ) {
 
118
  $url = preg_replace( '|^https:|', '<span class="qm-true">https</span>:', $url );
119
  }
120
  }
@@ -123,9 +109,33 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
123
 
124
  $stack = array();
125
  $filtered_trace = $row['trace']->get_display_trace();
126
- array_pop( $filtered_trace ); // remove WP_Http->request()
127
- array_pop( $filtered_trace ); // remove WP_Http->{$method}()
128
- array_pop( $filtered_trace ); // remove wp_remote_{$method}()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
  foreach ( $filtered_trace as $item ) {
131
  $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
@@ -152,22 +162,99 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
152
  '<td class="qm-num">%s</td>',
153
  intval( $i )
154
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  printf( // WPCS: XSS ok.
156
- '<td class="qm-url qm-ltr qm-wrap">%s<br>%s</td>',
157
- $method,
158
  $url
159
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  printf(
161
- '<td>%s</td>',
162
- esc_html( $response )
163
  );
164
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
166
 
167
  $caller = array_pop( $stack );
168
 
169
  if ( ! empty( $stack ) ) {
170
- echo $this->build_toggler(); // WPCS: XSS ok;
171
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
172
  }
173
 
@@ -204,38 +291,27 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
204
 
205
  echo '<tr>';
206
  printf(
207
- '<td colspan="6">%s</td>',
 
 
 
 
 
208
  implode( '<br>', array_map( 'esc_html', $vars ) )
209
  );
210
  echo '<td class="qm-num">' . esc_html( $total_stime ) . '</td>';
211
  echo '</tr>';
212
  echo '</tfoot>';
 
213
 
214
  } else {
215
 
216
- echo '<thead>';
217
- echo '<tr>';
218
- echo '<th scope="col">' . esc_html__( 'HTTP Requests', 'query-monitor' ) . '</th>';
219
- echo '</tr>';
220
- echo '</thead>';
221
-
222
- echo '<tbody>';
223
- echo '<tr>';
224
- echo '<td style="text-align:center !important"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
225
- echo '</tr>';
226
- if ( ! empty( $vars ) ) {
227
- echo '<tr>';
228
- printf(
229
- '<td>%s</td>',
230
- implode( '<br>', array_map( 'esc_html', $vars ) )
231
- );
232
- echo '</tr>';
233
- }
234
- echo '</tbody>';
235
 
236
  }
237
 
238
- echo '</table>';
239
  echo '</div>';
240
 
241
  }
@@ -275,7 +351,8 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
275
 
276
  if ( isset( $data['errors']['alert'] ) ) {
277
  $args['meta']['classname'] = 'qm-alert';
278
- } elseif ( isset( $data['errors']['warning'] ) ) {
 
279
  $args['meta']['classname'] = 'qm-warning';
280
  }
281
 
1
  <?php
2
+ /**
3
+ * HTTP API request output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_HTTP extends QM_Output_Html {
9
 
20
  $total_time = 0;
21
 
22
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
 
23
 
24
  $vars = array();
25
 
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>';
64
  $ltime = $row['ltime'];
65
  $i++;
66
  $is_error = false;
 
67
  $row_attr = array();
68
+ $css = '';
69
 
70
  if ( is_wp_error( $row['response'] ) ) {
71
  $response = $row['response']->get_error_message();
72
  $is_error = true;
73
+ } elseif ( ! $row['args']['blocking'] ) {
74
+ /* translators: A non-blocking HTTP API request */
75
+ $response = __( 'Non-blocking', 'query-monitor' );
76
  } else {
77
  $code = wp_remote_retrieve_response_code( $row['response'] );
78
  $msg = wp_remote_retrieve_response_message( $row['response'] );
 
79
 
80
  if ( intval( $code ) >= 400 ) {
81
  $is_error = true;
89
  $css = 'qm-warn';
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
92
  $url = self::format_url( $row['url'] );
93
+ $info = '';
94
 
95
  if ( 'https' === parse_url( $row['url'], PHP_URL_SCHEME ) ) {
96
  if ( empty( $row['args']['sslverify'] ) && empty( $row['args']['local'] ) ) {
97
+ $info .= '<span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>' . esc_html( sprintf(
98
  /* translators: An HTTP API request has disabled certificate verification. 1: Relevant argument name */
99
+ __( 'Certificate verification disabled (%s)', 'query-monitor' ),
100
  'sslverify=false'
101
+ ) ) . '</span><br>';
102
+ $url = preg_replace( '|^https:|', '<span class="qm-warn">https</span>:', $url );
103
+ } elseif ( ! $is_error && $row['args']['blocking'] ) {
104
  $url = preg_replace( '|^https:|', '<span class="qm-true">https</span>:', $url );
105
  }
106
  }
109
 
110
  $stack = array();
111
  $filtered_trace = $row['trace']->get_display_trace();
112
+
113
+ $filtered_trace = array_filter( $filtered_trace, function( $item ) {
114
+ // @TODO This should happen during collection.
115
+ if ( isset( $item['class'] ) ) {
116
+ return ! in_array( $item['class'], array(
117
+ 'WP_Http',
118
+ ), true );
119
+ }
120
+
121
+ if ( isset( $item['function'] ) ) {
122
+ return ! in_array( $item['function'], array(
123
+ 'wp_safe_remote_request',
124
+ 'wp_safe_remote_get',
125
+ 'wp_safe_remote_post',
126
+ 'wp_safe_remote_head',
127
+ 'wp_remote_request',
128
+ 'wp_remote_get',
129
+ 'wp_remote_post',
130
+ 'wp_remote_head',
131
+ 'wp_remote_fopen',
132
+ 'download_url',
133
+ 'wpcom_vip_file_get_contents',
134
+ ), true );
135
+ }
136
+
137
+ return true;
138
+ } );
139
 
140
  foreach ( $filtered_trace as $item ) {
141
  $stack[] = self::output_filename( $item['display'], $item['calling_file'], $item['calling_line'] );
162
  '<td class="qm-num">%s</td>',
163
  intval( $i )
164
  );
165
+ printf(
166
+ '<td>%s</td>',
167
+ esc_html( $row['args']['method'] )
168
+ );
169
+
170
+ if ( ! empty( $row['redirected_to'] ) ) {
171
+ $url .= sprintf(
172
+ '<br><span class="qm-warn">%1$s</span><br>%2$s',
173
+ /* translators: An HTTP API request redirected to another URL */
174
+ __( 'Redirected to:', 'query-monitor' ),
175
+ self::format_url( $row['redirected_to'] )
176
+ );
177
+ }
178
+
179
  printf( // WPCS: XSS ok.
180
+ '<td class="qm-url qm-ltr qm-wrap">%s%s</td>',
181
+ $info,
182
  $url
183
  );
184
+
185
+ echo '<td class="qm-has-toggle"><div class="qm-toggler">';
186
+ if ( $is_error ) {
187
+ echo '<span class="dashicons dashicons-warning" aria-hidden="true"></span>';
188
+ }
189
+ echo esc_html( $response );
190
+ echo self::build_toggler(); // WPCS: XSS ok;
191
+
192
+ echo '<ul class="qm-toggled">';
193
+ $transport = sprintf(
194
+ /* translators: %s HTTP API transport name */
195
+ __( 'HTTP API Transport: %s', 'query-monitor' ),
196
+ $row['transport']
197
+ );
198
  printf(
199
+ '<li><span class="qm-info qm-supplemental">%s</span></li>',
200
+ esc_html( $transport )
201
  );
202
 
203
+ if ( ! empty( $row['info'] ) ) {
204
+ $time_fields = array(
205
+ 'namelookup_time' => __( 'DNS Resolution Time', 'query-monitor' ),
206
+ 'connect_time' => __( 'Connection Time', 'query-monitor' ),
207
+ 'starttransfer_time' => __( 'Transfer Start Time (TTFB)', 'query-monitor' ),
208
+ );
209
+ foreach ( $time_fields as $key => $value ) {
210
+ if ( ! isset( $row['info'][ $key ] ) ) {
211
+ continue;
212
+ }
213
+ printf(
214
+ '<li><span class="qm-info qm-supplemental">%1$s: %2$s</span></li>',
215
+ esc_html( $value ),
216
+ esc_html( number_format_i18n( $row['info'][ $key ], 4 ) )
217
+ );
218
+ }
219
+
220
+ $size_fields = array(
221
+ 'size_download' => __( 'Response Size', 'query-monitor' ),
222
+ );
223
+ foreach ( $size_fields as $key => $value ) {
224
+ if ( ! isset( $row['info'][ $key ] ) ) {
225
+ continue;
226
+ }
227
+ printf(
228
+ '<li><span class="qm-info qm-supplemental">%1$s: %2$s</span></li>',
229
+ esc_html( $value ),
230
+ esc_html( size_format( $row['info'][ $key ] ) )
231
+ );
232
+ }
233
+
234
+ $other_fields = array(
235
+ 'content_type' => __( 'Response Content Type', 'query-monitor' ),
236
+ 'primary_ip' => __( 'IP Address', 'query-monitor' ),
237
+ );
238
+ foreach ( $other_fields as $key => $value ) {
239
+ if ( ! isset( $row['info'][ $key ] ) ) {
240
+ continue;
241
+ }
242
+ printf(
243
+ '<li><span class="qm-info qm-supplemental">%1$s: %2$s</span></li>',
244
+ esc_html( $value ),
245
+ esc_html( $row['info'][ $key ] )
246
+ );
247
+ }
248
+ }
249
+ echo '</ul>';
250
+ echo '</td>';
251
+
252
  echo '<td class="qm-has-toggle qm-nowrap qm-ltr"><ol class="qm-toggler qm-numbered">';
253
 
254
  $caller = array_pop( $stack );
255
 
256
  if ( ! empty( $stack ) ) {
257
+ echo self::build_toggler(); // WPCS: XSS ok;
258
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
259
  }
260
 
291
 
292
  echo '<tr>';
293
  printf(
294
+ '<td colspan="7">%1$s<br>%2$s</td>',
295
+ esc_html( sprintf(
296
+ /* translators: %s: Number of HTTP API requests */
297
+ __( 'Total Requests: %s', 'query-monitor' ),
298
+ number_format_i18n( count( $data['http'] ) )
299
+ ) ),
300
  implode( '<br>', array_map( 'esc_html', $vars ) )
301
  );
302
  echo '<td class="qm-num">' . esc_html( $total_stime ) . '</td>';
303
  echo '</tr>';
304
  echo '</tfoot>';
305
+ echo '</table>';
306
 
307
  } else {
308
 
309
+ echo '<div class="qm-none">';
310
+ echo '<p>' . esc_html__( 'None', 'query-monitor' ) . '</p>';
311
+ echo '</div>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
 
313
  }
314
 
 
315
  echo '</div>';
316
 
317
  }
351
 
352
  if ( isset( $data['errors']['alert'] ) ) {
353
  $args['meta']['classname'] = 'qm-alert';
354
+ }
355
+ if ( isset( $data['errors']['warning'] ) ) {
356
  $args['meta']['classname'] = 'qm-warning';
357
  }
358
 
output/html/languages.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Languages extends QM_Output_Html {
18
 
@@ -32,7 +23,7 @@ class QM_Output_Html_Languages extends QM_Output_Html {
32
  }
33
 
34
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
35
- echo '<table cellspacing="0">';
36
  echo '<caption>' . esc_html( sprintf(
37
  /* translators: %s: Name of current language */
38
  __( 'Language Setting: %s', 'query-monitor' ),
@@ -42,27 +33,34 @@ class QM_Output_Html_Languages extends QM_Output_Html {
42
  echo '<tr>';
43
  echo '<th>' . esc_html__( 'Text Domain', 'query-monitor' ) . '</th>';
44
  echo '<th>' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
45
- echo '<th colspan="2">' . esc_html__( 'MO File', 'query-monitor' ) . '</th>';
 
46
  echo '</tr>';
47
  echo '</thead>';
48
 
49
  $not_found_class = ( substr( $data['locale'], 0, 3 ) === 'en_' ) ? '' : 'qm-warn';
50
 
51
- foreach ( $data['languages'] as $textdomain => $mofiles ) {
52
- $first = true;
53
-
54
- echo '<tbody class="qm-group">';
55
 
 
56
  foreach ( $mofiles as $mofile ) {
57
  echo '<tr>';
58
 
59
- if ( $first ) {
60
- echo '<th class="qm-ltr" rowspan="' . count( $mofiles ) . '">' . esc_html( $mofile['domain'] ) . '</th>';
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
 
63
- echo '<td class="qm-nowrap qm-ltr">';
64
- echo self::output_filename( $mofile['caller']['display'], $mofile['caller']['file'], $mofile['caller']['line'] ); // WPCS: XSS ok.
65
- echo '</td>';
66
  echo '<td class="qm-ltr">';
67
  echo esc_html( QM_Util::standard_dir( $mofile['mofile'], '' ) );
68
  echo '</td>';
@@ -80,11 +78,10 @@ class QM_Output_Html_Languages extends QM_Output_Html {
80
  echo '</tr>';
81
  $first = false;
82
  }
83
-
84
- echo '</tbody>';
85
-
86
  }
87
 
 
 
88
  echo '</table>';
89
  echo '</div>';
90
 
1
  <?php
2
+ /**
3
+ * Language and locale output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Languages extends QM_Output_Html {
9
 
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' ),
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
 
41
  $not_found_class = ( substr( $data['locale'], 0, 3 ) === 'en_' ) ? '' : 'qm-warn';
42
 
43
+ echo '<tbody>';
 
 
 
44
 
45
+ foreach ( $data['languages'] as $textdomain => $mofiles ) {
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">';
53
+ echo self::output_filename( $mofile['caller']['display'], $mofile['caller']['file'], $mofile['caller']['line'] ); // WPCS: XSS ok.
54
+ echo '</td>';
55
+ } else {
56
+ echo '<td class="qm-nowrap qm-ltr qm-has-toggle"><ol class="qm-toggler">';
57
+ echo self::build_toggler(); // WPCS: XSS ok;
58
+ echo '<li>';
59
+ echo self::output_filename( $mofile['caller']['display'], $mofile['caller']['file'], $mofile['caller']['line'] ); // WPCS: XSS ok.
60
+ echo '</li>';
61
+ echo '</ol></td>';
62
  }
63
 
 
 
 
64
  echo '<td class="qm-ltr">';
65
  echo esc_html( QM_Util::standard_dir( $mofile['mofile'], '' ) );
66
  echo '</td>';
78
  echo '</tr>';
79
  $first = false;
80
  }
 
 
 
81
  }
82
 
83
+ echo '</tbody>';
84
+
85
  echo '</table>';
86
  echo '</div>';
87
 
output/html/overview.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Overview extends QM_Output_Html {
18
 
@@ -22,7 +13,6 @@ class QM_Output_Html_Overview extends QM_Output_Html {
22
  }
23
 
24
  public function output() {
25
-
26
  $data = $this->collector->get_data();
27
 
28
  $db_query_num = null;
@@ -46,39 +36,40 @@ class QM_Output_Html_Overview extends QM_Output_Html {
46
  }
47
  }
48
 
49
- echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
50
- echo '<table cellspacing="0">';
51
- echo '<caption class="screen-reader-text">' . esc_html( $this->collector->name() ) . '</caption>';
52
- echo '<thead>';
53
- echo '<tr>';
54
- echo '<th scope="col">' . esc_html__( 'Page generation time', 'query-monitor' ) . '</th>';
55
- echo '<th scope="col">' . esc_html__( 'Peak memory usage', 'query-monitor' ) . '</th>';
56
- if ( isset( $db_query_num ) ) {
57
- echo '<th scope="col">' . esc_html__( 'Database query time', 'query-monitor' ) . '</th>';
58
- echo '<th scope="col">' . esc_html__( 'Database queries', 'query-monitor' ) . '</th>';
59
- }
60
- echo '<th scope="col">' . esc_html__( 'Object cache', 'query-monitor' ) . '</th>';
61
- echo '</tr>';
62
- echo '</thead>';
63
 
64
- echo '<tbody>';
65
- echo '<tr>';
66
- echo '<td>';
 
 
 
 
 
 
 
 
 
 
67
  echo esc_html( number_format_i18n( $data['time_taken'], 4 ) );
68
  echo '<br><span class="qm-info">';
69
  echo esc_html( sprintf(
70
- /* translators: 1: Percentage of time limit used, 2: Time limit in seconds*/
71
  __( '%1$s%% of %2$ss limit', 'query-monitor' ),
72
  number_format_i18n( $data['time_usage'], 1 ),
73
  number_format_i18n( $data['time_limit'] )
74
  ) );
75
  echo '</span>';
76
- echo '</td>';
 
 
 
 
 
77
 
78
  if ( empty( $data['memory'] ) ) {
79
- echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
80
  } else {
81
- echo '<td>';
82
  echo esc_html( sprintf(
83
  /* translators: %s: Memory used in kilobytes */
84
  __( '%s kB', 'query-monitor' ),
@@ -86,40 +77,50 @@ class QM_Output_Html_Overview extends QM_Output_Html {
86
  ) );
87
  echo '<br><span class="qm-info">';
88
  echo esc_html( sprintf(
89
- /* translators: 1: Percentage of memory limit used, 2: Memory limit in kilobytes*/
90
  __( '%1$s%% of %2$s kB limit', 'query-monitor' ),
91
  number_format_i18n( $data['memory_usage'], 1 ),
92
  number_format_i18n( $data['memory_limit'] / 1024 )
93
  ) );
94
  echo '</span>';
95
- echo '</td>';
96
  }
97
 
 
 
 
98
  if ( isset( $db_query_num ) ) {
99
- echo '<td>';
 
 
100
  echo esc_html( number_format_i18n( $db_queries_data['total_time'], 4 ) );
101
- echo '</td>';
102
- echo '<td>';
 
 
 
 
103
 
104
  if ( ! isset( $db_query_num['SELECT'] ) || count( $db_query_num ) > 1 ) {
105
  foreach ( $db_query_num as $type_name => $type_count ) {
106
- $db_query_types[] = sprintf(
107
- '<a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="type" data-qm-value="%1$s">%2$s</a>: %3$s',
108
  esc_attr( $type_name ),
109
  esc_html( $type_name ),
110
  esc_html( number_format_i18n( $type_count ) )
111
  );
112
  }
113
-
114
- echo implode( '<br>', $db_query_types ) . '<br>'; // WPCS: XSS ok;
115
  }
116
 
117
  echo esc_html__( 'Total', 'query-monitor' ) . ': ' . esc_html( number_format_i18n( $db_queries_data['total_qs'] ) );
118
 
119
- echo '</td>';
 
120
  }
121
 
122
- echo '<td>';
 
 
 
123
  if ( isset( $cache_hit_percentage ) ) {
124
  echo esc_html( sprintf(
125
  /* translators: 1: Cache hit rate percentage, 2: number of cache hits, 3: number of cache misses */
@@ -135,30 +136,30 @@ class QM_Output_Html_Overview extends QM_Output_Html {
135
  esc_html__( 'Why is this value 100%?', 'query-monitor' )
136
  );
137
  }
138
- echo '<br><span class="qm-info">';
139
  if ( $cache_data['ext_object_cache'] ) {
 
140
  printf(
141
  '<a href="%s">%s</a>',
142
  esc_url( network_admin_url( 'plugins.php?plugin_status=dropins' ) ),
143
  esc_html__( 'External object cache in use', 'query-monitor' )
144
  );
 
145
  } else {
 
146
  echo esc_html__( 'External object cache not in use', 'query-monitor' );
 
147
  }
148
- echo '</span>';
149
  } else {
150
  echo '<span class="qm-info">';
151
  echo esc_html__( 'Object cache information is not available', 'query-monitor' );
152
  echo '</span>';
153
  }
154
- echo '</td>';
155
-
156
- echo '</tr>';
157
- echo '</tbody>';
158
 
159
- echo '</table>';
160
  echo '</div>';
161
 
 
 
162
  }
163
 
164
  public function admin_title( array $title ) {
1
  <?php
2
+ /**
3
+ * General overview output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Overview extends QM_Output_Html {
9
 
13
  }
14
 
15
  public function output() {
 
16
  $data = $this->collector->get_data();
17
 
18
  $db_query_num = null;
36
  }
37
  }
38
 
39
+ $qm_broken = __( 'A JavaScript problem on the page is preventing Query Monitor from working correctly. jQuery may have been blocked from loading.', 'query-monitor' );
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
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'] ) ) {
71
+ esc_html_e( 'Unknown', 'query-monitor' );
72
  } else {
 
73
  echo esc_html( sprintf(
74
  /* translators: %s: Memory used in kilobytes */
75
  __( '%s kB', 'query-monitor' ),
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>';
89
+ echo '</div>';
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 ) {
104
  foreach ( $db_query_num as $type_name => $type_count ) {
105
+ printf(
106
+ '<a href="#" class="qm-filter-trigger" data-qm-target="db_queries-wpdb" data-qm-filter="type" data-qm-value="%1$s">%2$s: %3$s</a><br>',
107
  esc_attr( $type_name ),
108
  esc_html( $type_name ),
109
  esc_html( number_format_i18n( $type_count ) )
110
  );
111
  }
 
 
112
  }
113
 
114
  echo esc_html__( 'Total', 'query-monitor' ) . ': ' . esc_html( number_format_i18n( $db_queries_data['total_qs'] ) );
115
 
116
+ echo '</p>';
117
+ echo '</div>';
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 ) ) {
125
  echo esc_html( sprintf(
126
  /* translators: 1: Cache hit rate percentage, 2: number of cache hits, 3: number of cache misses */
136
  esc_html__( 'Why is this value 100%?', 'query-monitor' )
137
  );
138
  }
 
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">';
154
  echo esc_html__( 'Object cache information is not available', 'query-monitor' );
155
  echo '</span>';
156
  }
 
 
 
 
157
 
158
+ echo '</p>';
159
  echo '</div>';
160
 
161
+ echo '</div>';
162
+ echo '</div>';
163
  }
164
 
165
  public function admin_title( array $title ) {
output/html/php_errors.php CHANGED
@@ -1,24 +1,16 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_PHP_Errors extends QM_Output_Html {
18
 
19
  public function __construct( QM_Collector $collector ) {
20
  parent::__construct( $collector );
21
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 10 );
 
22
  add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
23
  }
24
 
@@ -26,56 +18,74 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
26
 
27
  $data = $this->collector->get_data();
28
 
29
- if ( empty( $data['errors'] ) ) {
30
  return;
31
  }
32
 
33
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
34
- echo '<table cellspacing="0">';
35
  echo '<caption class="screen-reader-text">' . esc_html( 'PHP Errors', 'query-monitor' ) . '</caption>';
36
  echo '<thead>';
37
  echo '<tr>';
38
- echo '<th scope="col" colspan="2">' . esc_html__( 'PHP Error', 'query-monitor' ) . '</th>';
 
39
  echo '<th scope="col" class="qm-num">' . esc_html__( 'Count', 'query-monitor' ) . '</th>';
40
  echo '<th scope="col">' . esc_html__( 'Location', 'query-monitor' ) . '</th>';
41
- echo '<th scope="col">' . esc_html__( 'Call Stack', 'query-monitor' ) . '</th>';
42
- echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
 
 
43
  echo '</tr>';
44
  echo '</thead>';
45
 
46
- $types = array(
47
- 'warning' => _x( 'Warning', 'PHP error level', 'query-monitor' ),
48
- 'notice' => _x( 'Notice', 'PHP error level', 'query-monitor' ),
49
- 'strict' => _x( 'Strict', 'PHP error level', 'query-monitor' ),
50
- 'deprecated' => _x( 'Deprecated', 'PHP error level', 'query-monitor' ),
51
- 'warning-suppressed' => _x( 'Warning (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
52
- 'notice-suppressed' => _x( 'Notice (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
53
- 'strict-suppressed' => _x( 'Strict (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
54
- 'deprecated-suppressed' => _x( 'Deprecated (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
55
- );
56
 
57
- foreach ( $types as $type => $title ) {
 
58
 
59
- if ( isset( $data['errors'][ $type ] ) ) {
60
 
61
- echo '<tbody class="qm-group">';
62
- echo '<tr class="qm-php-error qm-php-error-' . esc_attr( $type ) . '">';
63
- echo '<th scope="row" rowspan="' . count( $data['errors'][ $type ] ) . '"><span class="dashicons dashicons-warning"></span>' . esc_html( $title ) . '</th>';
64
- $first = true;
65
 
66
- foreach ( $data['errors'][ $type ] as $error ) {
 
 
 
67
 
68
- if ( ! $first ) {
69
- echo '<tr class="qm-php-error qm-php-error-' . esc_attr( $type ) . '">';
70
  }
71
 
72
- $component = $error->trace->get_component();
73
- $message = wp_strip_all_tags( $error->message );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
  echo '<td class="qm-ltr">' . esc_html( $message ) . '</td>';
76
  echo '<td class="qm-num">' . esc_html( number_format_i18n( $error->calls ) ) . '</td>';
77
  echo '<td class="qm-ltr">';
78
- echo self::output_filename( $error->filename . ':' . $error->line, $error->file, $error->line ); // WPCS: XSS ok.
79
  echo '</td>';
80
 
81
  $stack = array();
@@ -95,9 +105,18 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
95
  }
96
  }
97
 
98
- echo '<td class="qm-row-caller qm-row-stack qm-nowrap qm-ltr"><ol class="qm-numbered"><li>';
99
- echo implode( '</li><li>', $stack ); // WPCS: XSS ok.
100
- echo '</li></ol></td>';
 
 
 
 
 
 
 
 
 
101
 
102
  if ( $component ) {
103
  echo '<td class="qm-nowrap">' . esc_html( $component->name ) . '</td>';
@@ -106,15 +125,12 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
106
  }
107
 
108
  echo '</tr>';
109
-
110
- $first = false;
111
-
112
  }
113
-
114
- echo '</tbody>';
115
  }
116
  }
117
 
 
118
  echo '</table>';
119
  echo '</div>';
120
 
@@ -137,48 +153,93 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
137
  public function admin_menu( array $menu ) {
138
 
139
  $data = $this->collector->get_data();
 
140
 
141
  $types = array(
142
- /* translators: %s: Number of PHP warnings */
143
- 'warning' => _x( 'Warnings (%s)', 'PHP error level', 'query-monitor' ),
144
- /* translators: %s: Number of PHP notices */
145
- 'notice' => _x( 'Notices (%s)', 'PHP error level', 'query-monitor' ),
146
- /* translators: %s: Number of strict PHP errors */
147
- 'strict' => _x( 'Stricts (%s)', 'PHP error level', 'query-monitor' ),
148
  /* translators: %s: Number of deprecated PHP errors */
149
- 'deprecated' => _x( 'Deprecated (%s)', 'PHP error level', 'query-monitor' ),
 
 
 
 
 
 
150
  );
151
 
 
 
 
152
  foreach ( $types as $type => $label ) {
153
 
154
  $count = 0;
 
155
 
156
- if ( isset( $data['errors'][ "{$type}-suppressed" ] ) ) {
157
- $key = "{$type}-suppressed";
158
- $count = count( $data['errors'][ $key ] );
 
 
 
 
159
  }
160
  if ( isset( $data['errors'][ $type ] ) ) {
 
161
  $key = $type;
162
- $count += count( $data['errors'][ $key ] );
163
  }
164
 
165
- if ( ! $count ) {
166
  continue;
167
  }
168
 
169
- $menu[] = $this->menu( array(
170
- 'id' => "query-monitor-{$key}s",
171
- 'title' => esc_html( sprintf(
172
- $label,
 
 
 
173
  number_format_i18n( $count )
174
- ) ),
175
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  }
177
 
 
 
 
 
178
  return $menu;
179
 
180
  }
181
 
 
 
 
 
 
 
 
 
182
  }
183
 
184
  function register_qm_output_html_php_errors( array $output, QM_Collectors $collectors ) {
1
  <?php
2
+ /**
3
+ * PHP error output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_PHP_Errors extends QM_Output_Html {
9
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 10 );
13
+ add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 10 );
14
  add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
15
  }
16
 
18
 
19
  $data = $this->collector->get_data();
20
 
21
+ if ( empty( $data['errors'] ) && empty( $data['silenced'] ) && empty( $data['suppressed'] ) ) {
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>';
40
 
41
+ echo '<tbody>';
 
 
 
 
 
 
 
 
 
42
 
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';
57
  }
58
 
59
+ $attr = '';
60
+
61
+ foreach ( $row_attr as $a => $v ) {
62
+ $attr .= ' ' . $a . '="' . esc_attr( $v ) . '"';
63
+ }
64
+
65
+ $is_warning = ( 'errors' === $error_group && 'warning' === $type );
66
+
67
+ if ( $is_warning ) {
68
+ $class = 'qm-warn';
69
+ } else {
70
+ $class = '';
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>';
78
+ } else {
79
+ echo '<span class="dashicons" aria-hidden="true"></span>';
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();
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;
113
+ if ( ! empty( $stack ) ) {
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
 
121
  if ( $component ) {
122
  echo '<td class="qm-nowrap">' . esc_html( $component->name ) . '</td>';
125
  }
126
 
127
  echo '</tr>';
 
 
 
128
  }
129
+ }
 
130
  }
131
  }
132
 
133
+ echo '</tbody>';
134
  echo '</table>';
135
  echo '</div>';
136
 
153
  public function admin_menu( array $menu ) {
154
 
155
  $data = $this->collector->get_data();
156
+ $menu_label = array();
157
 
158
  $types = array(
 
 
 
 
 
 
159
  /* translators: %s: Number of deprecated PHP errors */
160
+ 'deprecated' => _nx_noop( '%s Deprecated', '%s Deprecated', 'PHP error level', 'query-monitor' ),
161
+ /* translators: %s: Number of strict PHP errors */
162
+ 'strict' => _nx_noop( '%s Strict', '%s Stricts', 'PHP error level', 'query-monitor' ),
163
+ /* translators: %s: Number of PHP notices */
164
+ 'notice' => _nx_noop( '%s Notice', '%s Notices', 'PHP error level', 'query-monitor' ),
165
+ /* translators: %s: Number of PHP warnings */
166
+ 'warning' => _nx_noop( '%s Warning', '%s Warnings', 'PHP error level', 'query-monitor' ),
167
  );
168
 
169
+ $key = 'quiet';
170
+ $generic = false;
171
+
172
  foreach ( $types as $type => $label ) {
173
 
174
  $count = 0;
175
+ $has_errors = false;
176
 
177
+ if ( isset( $data['suppressed'][ $type ] ) ) {
178
+ $has_errors = true;
179
+ $generic = true;
180
+ }
181
+ if ( isset( $data['silenced'][ $type ] ) ) {
182
+ $has_errors = true;
183
+ $generic = true;
184
  }
185
  if ( isset( $data['errors'][ $type ] ) ) {
186
+ $has_errors = true;
187
  $key = $type;
188
+ $count += array_sum( wp_list_pluck( $data['errors'][ $type ], 'calls' ) );
189
  }
190
 
191
+ if ( ! $has_errors ) {
192
  continue;
193
  }
194
 
195
+ if ( $count ) {
196
+ $label = sprintf(
197
+ translate_nooped_plural(
198
+ $label,
199
+ $count,
200
+ 'query-monitor'
201
+ ),
202
  number_format_i18n( $count )
203
+ );
204
+ $menu_label[] = $label;
205
+ }
206
+ }
207
+
208
+ if ( empty( $menu_label ) && ! $generic ) {
209
+ return $menu;
210
+ }
211
+
212
+ /* translators: %s: Number of PHP errors */
213
+ $title = __( 'PHP Errors (%s)', 'query-monitor' );
214
+
215
+ /* translators: used between list items, there is a space after the comma */
216
+ $sep = __( ', ', 'query-monitor' );
217
+
218
+ if ( count( $menu_label ) ) {
219
+ $title = sprintf(
220
+ $title,
221
+ implode( $sep, array_reverse( $menu_label ) )
222
+ );
223
+ } else {
224
+ $title = __( 'PHP Errors', 'query-monitor' );
225
  }
226
 
227
+ $menu['php_errors'] = $this->menu( array(
228
+ 'id' => "query-monitor-{$key}s",
229
+ 'title' => $title,
230
+ ) );
231
  return $menu;
232
 
233
  }
234
 
235
+ public function panel_menu( array $menu ) {
236
+ if ( isset( $menu['php_errors'] ) ) {
237
+ $menu['php_errors']['title'] = __( 'PHP Errors', 'query-monitor' );
238
+ }
239
+
240
+ return $menu;
241
+ }
242
+
243
  }
244
 
245
  function register_qm_output_html_php_errors( array $output, QM_Collectors $collectors ) {
output/html/request.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Request extends QM_Output_Html {
18
 
@@ -27,16 +18,8 @@ class QM_Output_Html_Request extends QM_Output_Html {
27
 
28
  $db_queries = QM_Collectors::get( 'db_queries' );
29
 
30
- echo '<div class="qm qm-half" id="' . esc_attr( $this->collector->id() ) . '">';
31
- echo '<table cellspacing="0">';
32
- echo '<caption class="screen-reader-text">' . esc_html( $this->collector->name() ) . '</caption>';
33
- echo '<thead class="screen-reader-text">';
34
- echo '<tr>';
35
- echo '<th scope="col">' . esc_html__( 'Property', 'query-monitor' ) . '</th>';
36
- echo '<th scope="col" colspan="2">' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
37
- echo '</tr>';
38
- echo '</thead>';
39
- echo '<tbody>';
40
 
41
  foreach ( array(
42
  'request' => __( 'Request', 'query-monitor' ),
@@ -44,8 +27,7 @@ class QM_Output_Html_Request extends QM_Output_Html {
44
  'matched_query' => __( 'Matched Query', 'query-monitor' ),
45
  'query_string' => __( 'Query String', 'query-monitor' ),
46
  ) as $item => $name ) {
47
-
48
- if ( ! isset( $data['request'][ $item ] ) ) {
49
  continue;
50
  }
51
 
@@ -59,43 +41,59 @@ class QM_Output_Html_Request extends QM_Output_Html {
59
  $value = '<em>' . esc_html__( 'none', 'query-monitor' ) . '</em>';
60
  }
61
 
62
- echo '<tr>';
63
- echo '<th>' . esc_html( $name ) . '</th>';
64
- echo '<td colspan="2" class="qm-ltr qm-wrap">' . $value . '</td>'; // WPCS: XSS ok.
65
- echo '</tr>';
66
  }
67
 
68
- echo '</tbody>';
 
 
69
 
70
- $rowspan = isset( $data['qvars'] ) ? count( $data['qvars'] ) : 1;
 
 
 
71
 
72
- echo '<tbody class="qm-group">';
73
- echo '<tr>';
74
- echo '<th rowspan="' . absint( $rowspan ) . '">';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  esc_html_e( 'Query Vars', 'query-monitor' );
76
 
77
  if ( $db_queries ) {
78
  $db_queries_data = $db_queries->get_data();
79
  if ( ! empty( $db_queries_data['dbs']['$wpdb']->has_main_query ) ) {
80
- echo '<br>';
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 '</th>';
89
 
90
  if ( ! empty( $data['qvars'] ) ) {
91
 
92
- $first = true;
93
 
94
  foreach ( $data['qvars'] as $var => $value ) {
95
 
96
- if ( ! $first ) {
97
- echo '<tr>';
98
- }
99
 
100
  if ( isset( $data['plugin_qvars'][ $var ] ) ) {
101
  echo '<td class="qm-ltr"><span class="qm-current">' . esc_html( $var ) . '</span></td>';
@@ -113,111 +111,62 @@ class QM_Output_Html_Request extends QM_Output_Html {
113
 
114
  echo '</tr>';
115
 
116
- $first = false;
117
-
118
  }
 
 
119
  } else {
120
 
121
- echo '<td colspan="2"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
122
- echo '</tr>';
123
 
124
  }
125
 
126
- echo '</tbody>';
127
-
128
- if ( ! empty( $data['queried_object'] ) ) {
129
 
130
- echo '<tbody class="qm-group">';
131
- echo '<tr>';
132
- echo '<th>' . esc_html__( 'Queried Object', 'query-monitor' ) . '</th>';
133
- echo '<td colspan="2" class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
134
 
 
135
  printf( // WPCS: XSS ok.
136
- '<div class="qm-inner-toggle">%1$s (%2$s) %3$s</div>',
137
  esc_html( $data['queried_object']['title'] ),
138
- esc_html( get_class( $data['queried_object']['data'] ) ),
139
- $this->build_toggler()
140
  );
141
-
142
- echo '<div class="qm-toggled">';
143
- self::output_inner( $data['queried_object']['data'] );
144
- echo '</div>';
145
-
146
- echo '</div></td>';
147
- echo '</tr>';
148
- echo '</tbody>';
149
-
150
  }
151
 
152
- echo '<tbody class="qm-group">';
153
- echo '<tr>';
154
- echo '<th>' . esc_html__( 'User', 'query-monitor' ) . '</th>';
155
 
156
- if ( $data['user']['data'] ) {
157
- echo '<td colspan="2" class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
158
 
 
159
  printf( // WPCS: XSS ok.
160
- '<div class="qm-inner-toggle">%1$s %2$s</div>',
161
- esc_html( $data['user']['title'] ),
162
- $this->build_toggler()
163
  );
164
-
165
- echo '<div class="qm-toggled">';
166
- self::output_inner( $data['user']['data'] );
167
- echo '</div>';
168
-
169
- echo '</div></td>';
170
  } else {
171
- echo '<td colspan="2">';
172
- esc_html_e( 'No current user', 'query-monitor' );
173
- echo '</td>';
174
  }
175
 
176
- echo '</tr>';
177
-
178
- echo '</tbody>';
179
 
180
  if ( ! empty( $data['multisite'] ) ) {
181
-
182
- $rowspan = count( $data['multisite'] );
183
-
184
- echo '<tbody class="qm-group">';
185
- echo '<tr>';
186
- echo '<th rowspan="' . absint( $rowspan ) . '">' . esc_html__( 'Multisite', 'query-monitor' ) . '</th>';
187
-
188
- $first = true;
189
 
190
  foreach ( $data['multisite'] as $var => $value ) {
191
-
192
- if ( ! $first ) {
193
- echo '<tr>';
194
- }
195
-
196
- echo '<td colspan="2" class="qm-has-inner qm-has-toggle qm-ltr"><div class="qm-toggler">';
197
-
198
  printf( // WPCS: XSS ok.
199
- '<div class="qm-inner-toggle">%1$s %2$s</div>',
200
- esc_html( $value['title'] ),
201
- $this->build_toggler()
202
  );
203
-
204
- echo '<div class="qm-toggled">';
205
- self::output_inner( $value['data'] );
206
- echo '</div>';
207
-
208
- echo '</div></td>';
209
-
210
- echo '</tr>';
211
-
212
- $first = false;
213
-
214
  }
215
- echo '</tbody>';
 
216
  }
217
 
218
- echo '</table>';
219
  echo '</div>';
220
-
221
  }
222
 
223
  public function admin_menu( array $menu ) {
1
  <?php
2
+ /**
3
+ * Request data output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Request extends QM_Output_Html {
9
 
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' ),
27
  'matched_query' => __( 'Matched Query', 'query-monitor' ),
28
  'query_string' => __( 'Query String', 'query-monitor' ),
29
  ) as $item => $name ) {
30
+ if ( is_admin() && ! isset( $data['request'][ $item ] ) ) {
 
31
  continue;
32
  }
33
 
41
  $value = '<em>' . esc_html__( 'none', 'query-monitor' ) . '</em>';
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
  }
49
 
50
+ echo '</div>';
51
+
52
+ echo '<div class="qm-boxed qm-boxed-wrap">';
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 ) {
60
+ $query = str_replace( 'index.php?', '', $query );
61
+
62
+ echo '<tr>';
63
+ echo '<td class="qm-ltr"><code>' . esc_html( $rule ) . '</code></td>';
64
+ echo '<td class="qm-ltr"><code>';
65
+ echo self::format_url( $query ); // WPCS: XSS ok.
66
+ echo '</code></td>';
67
+ echo '</tr>';
68
+ }
69
+
70
+ echo '</table>';
71
+ echo '</div>';
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>';
93
 
94
  foreach ( $data['qvars'] as $var => $value ) {
95
 
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>';
111
 
112
  echo '</tr>';
113
 
 
 
114
  }
115
+ echo '</table>';
116
+
117
  } else {
118
 
119
+ echo '<p><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></p>';
 
120
 
121
  }
122
 
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.
130
+ '<p>%1$s (%2$s)</p>',
131
  esc_html( $data['queried_object']['title'] ),
132
+ esc_html( get_class( $data['queried_object']['data'] ) )
 
133
  );
134
+ } else {
135
+ echo '<p><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></p>';
 
 
 
 
 
 
 
136
  }
137
 
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.
145
+ '<p>%1$s</p>',
146
+ esc_html( $data['user']['title'] )
 
147
  );
 
 
 
 
 
 
148
  } else {
149
+ echo '<p><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></p>';
 
 
150
  }
151
 
152
+ echo '</div>';
 
 
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.
160
+ '<p>%1$s</p>',
161
+ esc_html( $value['title'] )
 
162
  );
 
 
 
 
 
 
 
 
 
 
 
163
  }
164
+
165
+ echo '</div>';
166
  }
167
 
 
168
  echo '</div>';
169
+ echo '</div>';
170
  }
171
 
172
  public function admin_menu( array $menu ) {
output/html/rewrites.php DELETED
@@ -1,77 +0,0 @@
1
- <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
-
17
- class QM_Output_Html_Rewrites extends QM_Output_Html {
18
-
19
- public function __construct( QM_Collector $collector ) {
20
- parent::__construct( $collector );
21
- add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 55 );
22
- }
23
-
24
- public function output() {
25
-
26
- $data = $this->collector->get_data();
27
-
28
- echo '<div class="qm qm-half" id="' . esc_attr( $this->collector->id() ) . '">';
29
- echo '<table cellspacing="0">';
30
-
31
- echo '<caption>' . esc_html__( 'All Matching Rewrite Rules', 'query-monitor' ) . '</caption>';
32
- echo '<thead class="screen-reader-text">';
33
- echo '<tr>';
34
- echo '<th scope="col">' . esc_html__( 'Rule', 'query-monitor' ) . '</th>';
35
- echo '<th scope="col">' . esc_html__( 'Query', 'query-monitor' ) . '</th>';
36
- echo '</tr>';
37
- echo '</thead>';
38
-
39
- echo '<tbody>';
40
-
41
- if ( ! empty( $data['matching'] ) ) {
42
- foreach ( $data['matching'] as $rule => $query ) {
43
-
44
- $query = str_replace( 'index.php?', '', $query );
45
-
46
- echo '<tr>';
47
- echo '<td class="qm-ltr">' . esc_html( $rule ) . '</td>';
48
- echo '<td class="qm-ltr">';
49
- echo self::format_url( $query ); // WPCS: XSS ok.
50
- echo '</td>';
51
- echo '</tr>';
52
-
53
- }
54
- } else {
55
-
56
- echo '<tr>';
57
- echo '<td colspan="2"><em>' . esc_html__( 'None', 'query-monitor' ) . '</em></td>';
58
- echo '</tr>';
59
-
60
- }
61
-
62
- echo '</tbody>';
63
- echo '</table>';
64
- echo '</div>';
65
-
66
- }
67
-
68
- }
69
-
70
- function register_qm_output_html_rewrites( array $output, QM_Collectors $collectors ) {
71
- if ( $collector = QM_Collectors::get( 'rewrites' ) ) {
72
- $output['rewrites'] = new QM_Output_Html_Rewrites( $collector );
73
- }
74
- return $output;
75
- }
76
-
77
- add_filter( 'qm/outputter/html', 'register_qm_output_html_rewrites', 65, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
output/html/theme.php CHANGED
@@ -1,71 +1,52 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Theme extends QM_Output_Html {
18
 
19
  public function __construct( QM_Collector $collector ) {
20
  parent::__construct( $collector );
21
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 60 );
 
22
  }
23
 
24
  public function output() {
25
-
26
  $data = $this->collector->get_data();
27
 
28
  if ( empty( $data['stylesheet'] ) ) {
29
  return;
30
  }
31
 
32
- echo '<div class="qm qm-half" id="' . esc_attr( $this->collector->id() ) . '">';
33
- echo '<table cellspacing="0">';
34
- echo '<caption>' . esc_html( $this->collector->name() ) . '</caption>';
35
- echo '<thead>';
36
- echo '<tr class="screen-reader-text">';
37
- echo '<th scope="col">' . esc_html__( 'Data', 'query-monitor' ) . '</th>';
38
- echo '<th scope="col">' . esc_html__( 'Value', 'query-monitor' ) . '</th>';
39
- echo '</tr>';
40
- echo '</thead>';
41
- echo '<tbody>';
42
 
43
- echo '<tr>';
44
- echo '<th scope="row">' . esc_html__( 'Template File', 'query-monitor' ) . '</th>';
45
 
46
  if ( ! empty( $data['template_path'] ) ) {
47
  if ( $data['is_child_theme'] ) {
48
- echo '<td class="qm-ltr">' . self::output_filename( $data['theme_template_file'], $data['template_path'] ) . '</td>'; // WPCS: XSS ok.
49
  } else {
50
- echo '<td class="qm-ltr">' . self::output_filename( $data['template_file'], $data['template_path'] ) . '</td>'; // WPCS: XSS ok.
51
  }
52
  } else {
53
- echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
54
  }
55
 
56
- echo '</tr>';
57
 
58
  if ( ! empty( $data['template_hierarchy'] ) ) {
59
-
60
- echo '<tr>';
61
- echo '<th scope="row">' . esc_html__( 'Template Hierarchy', 'query-monitor' ) . '</th>';
62
- echo '<td class="qm-ltr qm-wrap"><ol class="qm-numbered"><li>' . implode( '</li><li>', array_map( 'esc_html', $data['template_hierarchy'] ) ) . '</li></ol></td>';
63
- echo '</tr>';
64
-
65
  }
66
 
67
- echo '<tr>';
68
- echo '<th scope="row">' . esc_html__( 'Template Parts', 'query-monitor' ) . '</th>';
69
 
70
  if ( ! empty( $data['template_parts'] ) ) {
71
 
@@ -75,67 +56,60 @@ class QM_Output_Html_Theme extends QM_Output_Html {
75
  $parts = $data['template_parts'];
76
  }
77
 
78
- echo '<td class="qm-ltr"><ul>';
79
 
80
  foreach ( $parts as $filename => $display ) {
81
- echo '<li>' . self::output_filename( $display, $filename ) . '</li>'; // WPCS: XSS ok.
82
  }
83
 
84
- echo '</ul></td>';
85
 
86
  } else {
87
- echo '<td><em>' . esc_html__( 'None', 'query-monitor' ) . '</em></td>';
88
  }
89
 
90
- echo '</tr>';
91
 
92
  if ( ! empty( $data['timber_files'] ) ) {
93
- echo '<tr>';
94
- echo '<th scope="row">' . esc_html__( 'Timber Files', 'query-monitor' ) . '</th>';
95
- echo '<td class="qm-ltr"><ul>';
96
 
97
  foreach ( $data['timber_files'] as $filename ) {
98
- echo '<li>' . esc_html( $filename ) . '</li>'; // WPCS: XSS ok.
99
  }
100
 
101
- echo '</ul></td>';
102
- echo '</tr>';
103
  }
104
 
105
- echo '<tr>';
106
- if ( $data['is_child_theme'] ) {
107
- echo '<th scope="row">' . esc_html__( 'Child Theme', 'query-monitor' ) . '</th>';
108
- } else {
109
- echo '<th scope="row">' . esc_html__( 'Theme', 'query-monitor' ) . '</th>';
110
- }
111
- echo '<td class="qm-ltr">' . esc_html( $data['stylesheet'] ) . '</td>';
112
- echo '</tr>';
113
 
114
  if ( $data['is_child_theme'] ) {
115
- echo '<tr>';
116
- echo '<th scope="row">' . esc_html__( 'Parent Theme', 'query-monitor' ) . '</th>';
117
- echo '<td class="qm-ltr">' . esc_html( $data['template'] ) . '</td>';
118
- echo '</tr>';
119
  }
120
 
 
 
121
  if ( ! empty( $data['body_class'] ) ) {
 
122
 
123
- echo '<tr>';
124
- echo '<th scope="row">' . esc_html__( 'Body Classes', 'query-monitor' ) . '</th>';
125
- echo '<td class="qm-ltr"><ul>';
126
 
127
  foreach ( $data['body_class'] as $class ) {
128
  echo '<li>' . esc_html( $class ) . '</li>';
129
  }
130
 
131
- echo '</ul></td>';
132
- echo '</tr>';
133
  }
134
 
135
- echo '</tbody>';
136
- echo '</table>';
137
  echo '</div>';
138
-
139
  }
140
 
141
  public function admin_menu( array $menu ) {
@@ -143,7 +117,7 @@ class QM_Output_Html_Theme extends QM_Output_Html {
143
  $data = $this->collector->get_data();
144
 
145
  if ( isset( $data['template_file'] ) ) {
146
- $menu[] = $this->menu( array(
147
  'title' => esc_html( sprintf(
148
  /* translators: %s: Template file name */
149
  __( 'Template: %s', 'query-monitor' ),
@@ -155,10 +129,18 @@ class QM_Output_Html_Theme extends QM_Output_Html {
155
 
156
  }
157
 
 
 
 
 
 
 
 
 
158
  }
159
 
160
  function register_qm_output_html_theme( array $output, QM_Collectors $collectors ) {
161
- if ( $collector = QM_Collectors::get( 'theme' ) ) {
162
  $output['theme'] = new QM_Output_Html_Theme( $collector );
163
  }
164
  return $output;
1
  <?php
2
+ /**
3
+ * Template and theme output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Theme extends QM_Output_Html {
9
 
10
  public function __construct( QM_Collector $collector ) {
11
  parent::__construct( $collector );
12
  add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 60 );
13
+ add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 60 );
14
  }
15
 
16
  public function output() {
 
17
  $data = $this->collector->get_data();
18
 
19
  if ( empty( $data['stylesheet'] ) ) {
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'] ) {
31
+ echo '<p class="qm-ltr">' . self::output_filename( $data['theme_template_file'], $data['template_path'], 0, true ) . '</p>'; // WPCS: XSS ok.
32
  } else {
33
+ echo '<p class="qm-ltr">' . self::output_filename( $data['template_file'], $data['template_path'], 0, true ) . '</p>'; // WPCS: XSS ok.
34
  }
35
  } else {
36
+ echo '<p><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></p>';
37
  }
38
 
39
+ echo '</div>';
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
 
56
  $parts = $data['template_parts'];
57
  }
58
 
59
+ echo '<ul class="qm-ltr">';
60
 
61
  foreach ( $parts as $filename => $display ) {
62
+ echo '<li>' . self::output_filename( $display, $filename, 0, true ) . '</li>'; // WPCS: XSS ok.
63
  }
64
 
65
+ echo '</ul>';
66
 
67
  } else {
68
+ echo '<p><em>' . esc_html__( 'None', 'query-monitor' ) . '</em></p>';
69
  }
70
 
71
+ echo '</div>';
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 ) {
79
+ echo '<li>' . esc_html( $filename ) . '</li>';
80
  }
81
 
82
+ echo '</ul>';
83
+ echo '</div>';
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'] ) {
91
+ echo '<h3>' . esc_html__( 'Parent Theme:', 'query-monitor' ) . '</h3>';
92
+ echo '<p>' . esc_html( $data['template'] ) . '</p>';
 
 
93
  }
94
 
95
+ echo '</div>';
96
+
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 ) {
104
  echo '<li>' . esc_html( $class ) . '</li>';
105
  }
106
 
107
+ echo '</ul>';
108
+ echo '</div>';
109
  }
110
 
 
 
111
  echo '</div>';
112
+ echo '</div>';
113
  }
114
 
115
  public function admin_menu( array $menu ) {
117
  $data = $this->collector->get_data();
118
 
119
  if ( isset( $data['template_file'] ) ) {
120
+ $menu['theme'] = $this->menu( array(
121
  'title' => esc_html( sprintf(
122
  /* translators: %s: Template file name */
123
  __( 'Template: %s', 'query-monitor' ),
129
 
130
  }
131
 
132
+ public function panel_menu( array $menu ) {
133
+ if ( isset( $menu['theme'] ) ) {
134
+ $menu['theme']['title'] = __( 'Template', 'query-monitor' );
135
+ }
136
+
137
+ return $menu;
138
+ }
139
+
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;
output/html/timing.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Timing and profiling output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
7
+
8
+ class QM_Output_Html_Timing extends QM_Output_Html {
9
+
10
+ public function __construct( QM_Collector $collector ) {
11
+ parent::__construct( $collector );
12
+ add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 15 );
13
+ }
14
+
15
+ public function output() {
16
+
17
+ $data = $this->collector->get_data();
18
+
19
+ if ( empty( $data['timing'] ) && empty( $data['warning'] ) ) {
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>';
30
+ echo '<th scope="col">' . esc_html__( 'Tracked Function', 'query-monitor' ) . '</th>';
31
+ echo '<th scope="col" class="qm-num">' . esc_html__( 'Time', 'query-monitor' ) . '</th>';
32
+ echo '<th scope="col" class="qm-num">' . esc_html__( 'Memory', 'query-monitor' ) . '</th>';
33
+ echo '<th scope="col">' . esc_html__( 'Component', 'query-monitor' ) . '</th>';
34
+ echo '</tr>';
35
+ echo '</thead>';
36
+
37
+ echo '<tbody>';
38
+ if ( ! empty( $data['timing'] ) ) {
39
+ foreach ( $data['timing'] as $row ) {
40
+
41
+ $component = $row['trace']->get_component();
42
+ $trace = $row['trace']->get_filtered_trace();
43
+ $file = self::output_filename( $row['function'], $trace[0]['file'], $trace[0]['line'] );
44
+
45
+ echo '<tr>';
46
+
47
+ if ( self::has_clickable_links() ) {
48
+ echo '<td class="qm-ltr">';
49
+ echo $file; // WPCS: XSS ok.
50
+ echo '</td>';
51
+ } else {
52
+ echo '<td class="qm-ltr qm-has-toggle"><ol class="qm-toggler">';
53
+ echo self::build_toggler(); // WPCS: XSS ok;
54
+ echo '<li>';
55
+ echo $file; // WPCS: XSS ok.
56
+ echo '</li>';
57
+ echo '</ol></td>';
58
+ }
59
+
60
+ printf(
61
+ '<td class="qm-num">%s</td>',
62
+ esc_html( number_format_i18n( $row['function_time'] * 1000, 4 ) )
63
+ );
64
+
65
+ $mem = sprintf(
66
+ /* translators: %s: Approximate memory used in kilobytes */
67
+ __( '~%s kB', 'query-monitor' ),
68
+ number_format_i18n( $row['function_memory'] / 1024 )
69
+ );
70
+ printf(
71
+ '<td class="qm-num">%s</td>',
72
+ esc_html( $mem )
73
+ );
74
+ printf(
75
+ '<td class="qm-nowrap">%s</td>',
76
+ esc_html( $component->name )
77
+ );
78
+
79
+ echo '</tr>';
80
+
81
+ }
82
+ }
83
+ if ( ! empty( $data['warning'] ) ) {
84
+ foreach ( $data['warning'] as $row ) {
85
+ $component = $row['trace']->get_component();
86
+ $trace = $row['trace']->get_filtered_trace();
87
+ $file = self::output_filename( $row['function'], $trace[0]['file'], $trace[0]['line'] );
88
+
89
+ echo '<tr class="qm-warn">';
90
+ if ( self::has_clickable_links() ) {
91
+ echo '<td class="qm-ltr">';
92
+ echo $file; // WPCS: XSS ok.
93
+ echo '</td>';
94
+ } else {
95
+ echo '<td class="qm-ltr qm-has-toggle"><ol class="qm-toggler">';
96
+ echo self::build_toggler(); // WPCS: XSS ok;
97
+ echo '<li>';
98
+ echo $file; // WPCS: XSS ok.
99
+ echo '</li>';
100
+ echo '</ol></td>';
101
+ }
102
+
103
+ printf(
104
+ '<td colspan="2">%s</td>',
105
+ esc_html( $row['message'] )
106
+ );
107
+
108
+ printf(
109
+ '<td class="qm-nowrap">%s</td>',
110
+ esc_html( $component->name )
111
+ );
112
+ }
113
+ }
114
+
115
+ echo '</tbody>';
116
+ echo '</table>';
117
+ echo '</div>';
118
+
119
+ }
120
+
121
+ public function admin_menu( array $menu ) {
122
+ $data = $this->collector->get_data();
123
+
124
+ if ( ! empty( $data['timing'] ) || ! empty( $data['warning'] ) ) {
125
+ $count = 0;
126
+ if ( ! empty( $data['timing'] ) ) {
127
+ $count += count( $data['timing'] );
128
+ }
129
+ if ( ! empty( $data['warning'] ) ) {
130
+ $count += count( $data['warning'] );
131
+ }
132
+ /* translators: %s: Number of function timing results that are available */
133
+ $label = _n( 'Timings (%s)', 'Timings (%s)', $count, 'query-monitor' );
134
+ $menu[] = $this->menu( array(
135
+ 'title' => esc_html( sprintf(
136
+ $label,
137
+ number_format_i18n( $count )
138
+ ) ),
139
+ ) );
140
+ }
141
+
142
+ return $menu;
143
+ }
144
+
145
+ }
146
+
147
+ function register_qm_output_html_timing( array $output, QM_Collectors $collectors ) {
148
+ if ( $collector = QM_Collectors::get( 'timing' ) ) {
149
+ $output['timing'] = new QM_Output_Html_Timing( $collector );
150
+ }
151
+ return $output;
152
+ }
153
+
154
+ add_filter( 'qm/outputter/html', 'register_qm_output_html_timing', 15, 2 );
output/html/transients.php CHANGED
@@ -1,18 +1,9 @@
1
  <?php
2
- /*
3
- Copyright 2009-2017 John Blackbourn
4
-
5
- This program is free software; you can redistribute it and/or modify
6
- it under the terms of the GNU General Public License as published by
7
- the Free Software Foundation; either version 2 of the License, or
8
- (at your option) any later version.
9
-
10
- This program is distributed in the hope that it will be useful,
11
- but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- GNU General Public License for more details.
14
-
15
- */
16
 
17
  class QM_Output_Html_Transients extends QM_Output_Html {
18
 
@@ -26,10 +17,10 @@ class QM_Output_Html_Transients extends QM_Output_Html {
26
  $data = $this->collector->get_data();
27
 
28
  echo '<div class="qm" id="' . esc_attr( $this->collector->id() ) . '">';
29
- echo '<table cellspacing="0">';
30
 
31
  if ( ! empty( $data['trans'] ) ) {
32
 
 
33
  echo '<caption class="screen-reader-text">' . esc_html__( 'Transient Updates', 'query-monitor' ) . '</caption>';
34
 
35
  echo '<thead>';
@@ -57,7 +48,7 @@ class QM_Output_Html_Transients extends QM_Output_Html {
57
 
58
  echo '<tr>';
59
  printf(
60
- '<td class="qm-ltr">%s</td>',
61
  esc_html( $transient )
62
  );
63
  if ( is_multisite() ) {
@@ -98,7 +89,7 @@ class QM_Output_Html_Transients extends QM_Output_Html {
98
  $caller = array_pop( $stack );
99
 
100
  if ( ! empty( $stack ) ) {
101
- echo $this->build_toggler(); // WPCS: XSS ok;
102
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
103
  }
104
 
@@ -115,24 +106,16 @@ class QM_Output_Html_Transients extends QM_Output_Html {
115
  }
116
 
117
  echo '</tbody>';
 
118
 
119
  } else {
120
 
121
- echo '<thead>';
122
- echo '<tr>';
123
- echo '<th>' . esc_html__( 'Transient Updates', 'query-monitor' ) . '</th>';
124
- echo '</tr>';
125
- echo '</thead>';
126
-
127
- echo '<tbody>';
128
- echo '<tr>';
129
- echo '<td style="text-align:center !important"><em>' . esc_html__( 'none', 'query-monitor' ) . '</em></td>';
130
- echo '</tr>';
131
- echo '</tbody>';
132
 
133
  }
134
 
135
- echo '</table>';
136
  echo '</div>';
137
 
138
  }
1
  <?php
2
+ /**
3
+ * Transient storage output for HTML pages.
4
+ *
5
+ * @package query-monitor
6
+ */
 
 
 
 
 
 
 
 
 
7
 
8
  class QM_Output_Html_Transients extends QM_Output_Html {
9
 
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>';
48
 
49
  echo '<tr>';
50
  printf(
51
+ '<td class="qm-ltr"><code>%s</code></td>',
52
  esc_html( $transient )
53
  );
54
  if ( is_multisite() ) {
89
  $caller = array_pop( $stack );
90
 
91
  if ( ! empty( $stack ) ) {
92
+ echo self::build_toggler(); // WPCS: XSS ok;
93
  echo '<div class="qm-toggled"><li>' . implode( '</li><li>', $stack ) . '</li></div>'; // WPCS: XSS ok.
94
  }
95
 
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
  }
query-monitor.php CHANGED
@@ -5,17 +5,18 @@
5
  * @package query-monitor
6
  * @link https://github.com/johnbillion/query-monitor
7
  * @author John Blackbourn <john@johnblackbourn.com>
8
- * @copyright 2009-2017 John Blackbourn
9
  * @license GPL v2 or later
10
  *
11
- * Plugin Name: Query Monitor
12
- * Description: Monitoring of database queries, hooks, conditionals and more.
13
- * Version: 2.17.0
14
- * Plugin URI: https://github.com/johnbillion/query-monitor
15
- * Author: John Blackbourn
16
- * Author URI: https://johnblackbourn.com/
17
- * Text Domain: query-monitor
18
- * Domain Path: /languages/
 
19
  *
20
  * This program is free software; you can redistribute it and/or modify
21
  * it under the terms of the GNU General Public License as published by
@@ -32,13 +33,19 @@ defined( 'ABSPATH' ) or die();
32
 
33
  $qm_dir = dirname( __FILE__ );
34
 
 
 
35
  # No autoloaders for us. See https://github.com/johnbillion/query-monitor/issues/7
36
- foreach ( array( 'Plugin', 'Activation', 'Util' ) as $qm_class ) {
37
  require_once "{$qm_dir}/classes/{$qm_class}.php";
38
  }
39
 
40
  QM_Activation::init( __FILE__ );
41
 
 
 
 
 
42
  if ( defined( 'QM_DISABLED' ) and QM_DISABLED ) {
43
  return;
44
  }
@@ -54,7 +61,7 @@ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
54
  return;
55
  }
56
 
57
- foreach ( array( 'QueryMonitor', 'Backtrace', 'Collectors', 'Collector', 'Dispatchers', 'Dispatcher', 'Output' ) as $qm_class ) {
58
  require_once "{$qm_dir}/classes/{$qm_class}.php";
59
  }
60
 
5
  * @package query-monitor
6
  * @link https://github.com/johnbillion/query-monitor
7
  * @author John Blackbourn <john@johnblackbourn.com>
8
+ * @copyright 2009-2018 John Blackbourn
9
  * @license GPL v2 or later
10
  *
11
+ * Plugin Name: Query Monitor
12
+ * Description: The Developer Tools panel for WordPress.
13
+ * Version: 3.0.0
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
20
  *
21
  * This program is free software; you can redistribute it and/or modify
22
  * it under the terms of the GNU General Public License as published by
33
 
34
  $qm_dir = dirname( __FILE__ );
35
 
36
+ require_once "{$qm_dir}/classes/Plugin.php";
37
+
38
  # No autoloaders for us. See https://github.com/johnbillion/query-monitor/issues/7
39
+ foreach ( array( 'Activation', 'Util' ) as $qm_class ) {
40
  require_once "{$qm_dir}/classes/{$qm_class}.php";
41
  }
42
 
43
  QM_Activation::init( __FILE__ );
44
 
45
+ if ( ! QM_Plugin::php_version_met() ) {
46
+ return;
47
+ }
48
+
49
  if ( defined( 'QM_DISABLED' ) and QM_DISABLED ) {
50
  return;
51
  }
61
  return;
62
  }
63
 
64
+ foreach ( array( 'QueryMonitor', 'Backtrace', 'Collectors', 'Collector', 'Dispatchers', 'Dispatcher', 'Output', 'Timer' ) as $qm_class ) {
65
  require_once "{$qm_dir}/classes/{$qm_class}.php";
66
  }
67
 
readme.txt CHANGED
@@ -1,176 +1,148 @@
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: 2.17.0
7
- License: GPLv2 or later
8
-
9
- View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
10
-
11
- == Description ==
12
-
13
- Query Monitor is a debugging plugin for anyone developing with WordPress. It has some advanced features not available in other debugging plugins, including debugging of AJAX calls, REST API requests, redirects, and the ability to narrow down its output by plugin or theme.
14
-
15
- For complete information, please see [Query Monitor's GitHub repo](https://github.com/johnbillion/query-monitor).
16
-
17
- Here's an overview of what's shown:
18
-
19
- = Database Queries =
20
-
21
- * Shows all database queries performed on the current request
22
- * Shows affected rows and time for all queries
23
- * Shows notifications for slow queries, duplicate queries, and queries with errors
24
- * Filter queries by query type (`SELECT`, `UPDATE`, `DELETE`, etc)
25
- * Filter queries by component (WordPress core, Plugin X, Plugin Y, theme)
26
- * Filter queries by calling function
27
- * View aggregate query information grouped by component, calling function, and type
28
- * Super advanced: Supports multiple instances of wpdb on one page (more info in the FAQ)
29
-
30
- Filtering queries by component or calling function makes it easy to see which plugins, themes, or functions are making the most (or the slowest) database queries.
31
-
32
- = Hooks =
33
-
34
- * Shows all hooks fired on the current request, along with hooked actions, their priorities, and their components
35
- * Filter hooks by part of their name
36
- * Filter actions by component (WordPress core, Plugin X, Plugin Y, theme)
37
-
38
- = Theme =
39
-
40
- * Shows the template filename for the current request
41
- * Shows the complete template hierarchy for the current request (WordPress 4.7+)
42
- * Shows all template parts used on the current request
43
- * Shows the available body classes for the current request
44
- * Shows the active theme name
45
-
46
- = PHP Errors =
47
-
48
- * PHP errors (warnings, notices, stricts, and deprecated) are presented nicely along with their component and call stack
49
- * Shows an easily visible warning in the admin toolbar
50
-
51
- = Request =
52
-
53
- * Shows matched rewrite rules and associated query strings
54
- * Shows query vars for the current request, and highlights custom query vars
55
- * Shows the queried object details
56
- * Shows details of the current blog (multisite only) and current site (multi-network only)
57
-
58
- = Rewrite Rules =
59
-
60
- * Shows all matching rewrite rules for the current request
61
-
62
- = Scripts & Styles =
63
-
64
- * Shows all enqueued scripts and styles on the current request, along with their URL and version
65
- * Shows their dependencies and dependents, and displays an alert for any broken dependencies
66
-
67
- = Languages =
68
-
69
- * Shows language settings and text domains
70
- * Shows the MO files for each text domain and which ones were loaded or not
71
-
72
- = HTTP Requests =
73
-
74
- * Shows all HTTP requests performed on the current request (as long as they use WordPress' HTTP API)
75
- * Shows the response code, call stack, component, timeout, and time taken
76
- * Highlights erroneous responses, such as failed requests and anything without a `200` response code
77
-
78
- = User Capability Checks =
79
-
80
- * Shows every user capability check that is performed on the page, along with the result and any parameters passed along with the capability check.
81
-
82
- = Redirects =
83
-
84
- * 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
85
-
86
- = AJAX =
87
-
88
- 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.
89
-
90
- Currently this includes PHP errors and some overview information such as memory usage, but this will be built upon in future versions.
91
-
92
- = REST API =
93
-
94
- The response from an authenticated WordPress REST API (v2 or later) request will contain various debugging information in its headers, as long as the authenticated user has permission to view Query Monitor's output.
95
-
96
- Currently this includes PHP errors and some overview information such as memory usage, but this will be built upon in future versions.
97
-
98
- = Admin Screen =
99
-
100
- * Shows the correct names for custom column filters and actions on all admin screens that have a listing table
101
- * Shows the state of `get_current_screen()` and a few variables
102
-
103
- = Environment Information =
104
-
105
- * Shows various PHP information such as memory limit and error reporting levels
106
- * Highlights the fact when any of these are overridden at runtime
107
- * Shows various MySQL information, including caching and performance related configuration
108
- * Highlights the fact when any performance related configurations are not optimal
109
- * Shows various details about WordPress and the web server
110
- * Shows version numbers for all the things
111
-
112
- = Everything Else =
113
-
114
- * Shows any transients that were set, along with their timeout, component, and call stack
115
- * Shows all WordPress conditionals on the current request, highlighted nicely
116
- * Shows an overview at the top, including page generation time and memory limit as absolute values and as % of their respective limits
117
-
118
- = Authentication =
119
-
120
- By default, Query Monitor's output is only shown to Administrators on single-site installs, and Super Admins on Multisite installs.
121
-
122
- In addition to this, you can set an authentication cookie which allows you to view Query Monitor output when you're not logged in (or if you're logged in as a non-administrator). See the bottom of Query Monitor's output for details.
123
-
124
- == Screenshots ==
125
-
126
- 1. The admin toolbar menu showing an overview
127
- 2. Aggregate database queries by component
128
- 3. User capability checks with an active filter
129
- 4. Database queries complete with filter controls
130
- 5. Hooks and actions
131
- 6. HTTP requests (showing an HTTP error)
132
- 7. Aggregate database queries grouped by calling function
133
-
134
- == Frequently Asked Questions ==
135
-
136
- = Who can see Query Monitor's output? =
137
-
138
- By default, Query Monitor's output is only shown to Administrators on single-site installs, and Super Admins on Multisite installs.
139
-
140
- In addition to this, you can set an authentication cookie which allows you to view Query Monitor output when you're not logged in (or if you're logged in as a non-administrator). See the bottom of Query Monitor's output for details.
141
-
142
- = Does Query Monitor itself impact the page generation time or memory usage? =
143
-
144
- Short answer: Yes, but only a little.
145
-
146
- Long answer: Query Monitor has a small impact on page generation time because it hooks into a few places in WordPress in the same way that other plugins do. The impact is negligible.
147
-
148
- On pages that have an especially high number of database queries (in the hundreds), Query Monitor currently uses more memory than I would like it to. This is due to the amount of data that is captured in the stack trace for each query. I have been and will be working to continually reduce this.
149
-
150
- = Are there any add-on plugins for Query Monitor? =
151
-
152
- [A list of add-on plugins for Query Monitor can be found here.](https://github.com/johnbillion/query-monitor/wiki/Query-Monitor-Add-on-Plugins)
153
-
154
- In addition, Query Monitor transparently supports add-ons for the Debug Bar plugin. If you have any Debug Bar add-ons installed, just deactivate Debug Bar and the add-ons will show up in Query Monitor's menu.
155
-
156
- = Where can I suggest a new feature or report a bug? =
157
-
158
- Please use [the issue tracker on Query Monitor's GitHub repo](https://github.com/johnbillion/query-monitor/issues) as it's easier to keep track of issues there, rather than on the wordpress.org support forums.
159
-
160
- = Is Query Monitor available on WordPress.com VIP Go? =
161
-
162
- Yep! You just need to add `define( 'WPCOM_VIP_QM_ENABLE', true );` to your `vip-config/vip-config.php` file.
163
-
164
- (It's not available on standard WordPress.com VIP though.)
165
-
166
- = I'm using multiple instances of `wpdb`. How do I get my additional instances to show up in Query Monitor? =
167
-
168
- You'll need to hook into the `qm/collect/db_objects` filter and add an item to the array with your connection name as the key and the `wpdb` instance as the value. Your `wpdb` instance will then show up as a separate panel, and the query time and query count will show up separately in the admin toolbar menu. Aggregate information (queries by caller and component) will not be separated.
169
-
170
- = Do you accept donations? =
171
-
172
- No, I do not accept donations. If you like the plugin, I'd love for you to [leave a review](https://wordpress.org/support/view/plugin-reviews/query-monitor). Tell all your friends about the plugin too!
173
-
174
- == Changelog ==
175
-
176
- For Query Monitor's changelog, please see [the Releases page on GitHub](https://github.com/johnbillion/query-monitor/releases).
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.0
7
+ License: GPLv2 or later
8
+
9
+ Query Monitor is the Developer Tools panel for WordPress.
10
+
11
+ == Description ==
12
+
13
+ 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.
14
+
15
+ 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.
16
+
17
+ For complete information, please see [Query Monitor's GitHub repo](https://github.com/johnbillion/query-monitor).
18
+
19
+ Here's an overview of some of what's shown:
20
+
21
+ = Database Queries =
22
+
23
+ * Shows all database queries performed on the current request
24
+ * Shows notifications for slow queries, duplicate queries, and queries with errors
25
+ * Filter queries by query type (`SELECT`, `UPDATE`, `DELETE`, etc)
26
+ * Filter queries by component (WordPress core, Plugin X, Plugin Y, theme)
27
+ * Filter queries by calling function
28
+ * View aggregate query information grouped by component, calling function, and type
29
+ * Super advanced: Supports multiple instances of wpdb on one page (more info in the FAQ)
30
+
31
+ Filtering queries by component or calling function makes it easy to see which plugins, themes, or functions are making the most (or the slowest) database queries.
32
+
33
+ = Hooks =
34
+
35
+ * Shows all hooks fired on the current request, along with hooked actions, their priorities, and their components
36
+ * Filter actions by component (WordPress core, Plugin X, Plugin Y, theme)
37
+
38
+ = Theme =
39
+
40
+ * Shows the template filename for the current request
41
+ * Shows the complete template hierarchy for the current request (WordPress 4.7+)
42
+ * Shows all template parts used on the current request
43
+
44
+ = PHP Errors =
45
+
46
+ * PHP errors (warnings, notices, stricts, and deprecated) are presented nicely along with their component and call stack
47
+ * Shows an easily visible warning in the admin toolbar
48
+
49
+ = Request =
50
+
51
+ * Shows query vars for the current request, and highlights custom query vars
52
+ * Shows all matched rewrite rules and associated query strings
53
+
54
+ = Scripts & Styles =
55
+
56
+ * Shows all enqueued scripts and styles on the current request, along with their URL and version
57
+ * Shows their dependencies and dependents, and displays an alert for any broken dependencies
58
+
59
+ = Languages =
60
+
61
+ * Shows language settings and text domains
62
+ * Shows the MO files for each text domain and which ones were loaded or not
63
+
64
+ = HTTP Requests =
65
+
66
+ * Shows all HTTP requests performed on the current request (as long as they use WordPress' HTTP API)
67
+ * Shows the response code, call stack, component, timeout, and time taken
68
+ * Highlights erroneous responses, such as failed requests and anything without a `200` response code
69
+
70
+ = User Capability Checks =
71
+
72
+ * Shows every user capability check that is performed on the page, along with the result and any parameters passed along with the capability check.
73
+
74
+ = Redirects =
75
+
76
+ * 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
77
+
78
+ = AJAX =
79
+
80
+ 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.
81
+
82
+ Currently this includes PHP errors and some overview information such as memory usage, but this will be built upon in future versions.
83
+
84
+ = REST API =
85
+
86
+ The response from an authenticated WordPress REST API (v2 or later) request will contain various debugging information in its headers, as long as the authenticated user has permission to view Query Monitor's output.
87
+
88
+ Currently this includes PHP errors and some overview information such as memory usage, but this will be built upon in future versions.
89
+
90
+ = Authentication =
91
+
92
+ By default, Query Monitor's output is only shown to Administrators on single-site installs, and Super Admins on Multisite installs.
93
+
94
+ In addition to this, you can set an authentication cookie which allows you to view Query Monitor output when you're not logged in (or if you're logged in as a non-administrator). See the bottom of Query Monitor's output for details.
95
+
96
+ == Screenshots ==
97
+
98
+ 1. The admin toolbar menu showing an overview
99
+ 2. Aggregate database queries by component
100
+ 3. User capability checks with an active filter
101
+ 4. Database queries complete with filter controls
102
+ 5. Hooks and actions
103
+ 6. HTTP requests (showing an HTTP error)
104
+ 7. Aggregate database queries grouped by calling function
105
+
106
+ == Frequently Asked Questions ==
107
+
108
+ = Who can see Query Monitor's output? =
109
+
110
+ By default, Query Monitor's output is only shown to Administrators on single-site installs, and Super Admins on Multisite installs.
111
+
112
+ In addition to this, you can set an authentication cookie which allows you to view Query Monitor output when you're not logged in (or if you're logged in as a non-administrator). See the bottom of Query Monitor's output for details.
113
+
114
+ = Does Query Monitor itself impact the page generation time or memory usage? =
115
+
116
+ Short answer: Yes, but only a little.
117
+
118
+ Long answer: Query Monitor has a small impact on page generation time because it hooks into WordPress in the same way that other plugins do. The impact is low; typically between 10ms and 100ms depending on the complexity of your site.
119
+
120
+ Query Monitor's memory usage typically accounts for around 10% of the total memory used to generate the page.
121
+
122
+ = Are there any add-on plugins for Query Monitor? =
123
+
124
+ [A list of add-on plugins for Query Monitor can be found here.](https://github.com/johnbillion/query-monitor/wiki/Query-Monitor-Add-on-Plugins)
125
+
126
+ In addition, Query Monitor transparently supports add-ons for the Debug Bar plugin. If you have any Debug Bar add-ons installed, just deactivate Debug Bar and the add-ons will show up in Query Monitor's menu.
127
+
128
+ = Where can I suggest a new feature or report a bug? =
129
+
130
+ Please use [the issue tracker on Query Monitor's GitHub repo](https://github.com/johnbillion/query-monitor/issues) as it's easier to keep track of issues there, rather than on the wordpress.org support forums.
131
+
132
+ = Is Query Monitor available on WordPress.com VIP Go? =
133
+
134
+ Yep! You just need to add `define( 'WPCOM_VIP_QM_ENABLE', true );` to your `vip-config/vip-config.php` file.
135
+
136
+ (It's not available on standard WordPress.com VIP though.)
137
+
138
+ = I'm using multiple instances of `wpdb`. How do I get my additional instances to show up in Query Monitor? =
139
+
140
+ You'll need to hook into the `qm/collect/db_objects` filter and add an item to the array with your connection name as the key and the `wpdb` instance as the value. Your `wpdb` instance will then show up as a separate panel, and the query time and query count will show up separately in the admin toolbar menu. Aggregate information (queries by caller and component) will not be separated.
141
+
142
+ = Do you accept donations? =
143
+
144
+ No, I do not accept donations. If you like the plugin, I'd love for you to [leave a review](https://wordpress.org/support/view/plugin-reviews/query-monitor). Tell all your friends about the plugin too!
145
+
146
+ == Changelog ==
147
+
148
+ For Query Monitor's changelog, please see [the Releases page on GitHub](https://github.com/johnbillion/query-monitor/releases).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wp-content/db.php CHANGED
@@ -1,27 +1,16 @@
1
  <?php
2
- /*
3
- Plugin Name: Query Monitor Database Class
4
-
5
- *********************************************************************
6
-
7
- Ensure this file is symlinked to your wp-content directory to provide
8
- additional database query information in Query Monitor's output.
9
-
10
- *********************************************************************
11
-
12
- Copyright 2009-2017 John Blackbourn
13
-
14
- This program is free software; you can redistribute it and/or modify
15
- it under the terms of the GNU General Public License as published by
16
- the Free Software Foundation; either version 2 of the License, or
17
- (at your option) any later version.
18
-
19
- This program is distributed in the hope that it will be useful,
20
- but WITHOUT ANY WARRANTY; without even the implied warranty of
21
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
- GNU General Public License for more details.
23
-
24
- */
25
 
26
  defined( 'ABSPATH' ) or die();
27
 
@@ -42,6 +31,17 @@ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
42
 
43
  # No autoloaders for us. See https://github.com/johnbillion/query-monitor/issues/7
44
  $qm_dir = dirname( dirname( __FILE__ ) );
 
 
 
 
 
 
 
 
 
 
 
45
  $backtrace = "{$qm_dir}/classes/Backtrace.php";
46
  if ( ! is_readable( $backtrace ) ) {
47
  return;
@@ -105,9 +105,13 @@ class QM_DB extends wpdb {
105
 
106
  $i = $this->num_queries - 1;
107
  $this->queries[ $i ]['trace'] = new QM_Backtrace( array(
108
- 'ignore_items' => 1,
109
  ) );
110
 
 
 
 
 
111
  if ( $this->last_error ) {
112
  $code = 'qmdb';
113
  if ( $this->use_mysqli ) {
1
  <?php
2
+ /**
3
+ * Plugin Name: Query Monitor Database Class
4
+ *
5
+ * *********************************************************************
6
+ *
7
+ * Ensure this file is symlinked to your wp-content directory to provide
8
+ * additional database query information in Query Monitor's output.
9
+ *
10
+ * *********************************************************************
11
+ *
12
+ * @package query-monitor
13
+ */
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  defined( 'ABSPATH' ) or die();
16
 
31
 
32
  # No autoloaders for us. See https://github.com/johnbillion/query-monitor/issues/7
33
  $qm_dir = dirname( dirname( __FILE__ ) );
34
+ $plugin = "{$qm_dir}/classes/Plugin.php";
35
+
36
+ if ( ! is_readable( $plugin ) ) {
37
+ return;
38
+ }
39
+ require_once $plugin;
40
+
41
+ if ( ! QM_Plugin::php_version_met() ) {
42
+ return;
43
+ }
44
+
45
  $backtrace = "{$qm_dir}/classes/Backtrace.php";
46
  if ( ! is_readable( $backtrace ) ) {
47
  return;
105
 
106
  $i = $this->num_queries - 1;
107
  $this->queries[ $i ]['trace'] = new QM_Backtrace( array(
108
+ 'ignore_frames' => 1,
109
  ) );
110
 
111
+ if ( ! isset( $this->queries[ $i ][3] ) ) {
112
+ $this->queries[ $i ][3] = $this->time_start;
113
+ }
114
+
115
  if ( $this->last_error ) {
116
  $code = 'qmdb';
117
  if ( $this->use_mysqli ) {