Version Description
Download this release
Release Info
Developer | johnbillion |
Plugin | Query Monitor |
Version | 3.8.0 |
Comparing to | |
See all releases |
Code changes from version 3.7.1 to 3.8.0
- assets/query-monitor-dark.css +7 -6
- assets/query-monitor.css +7 -6
- assets/query-monitor.js +49 -43
- classes/Activation.php +26 -1
- classes/Backtrace.php +270 -117
- classes/CLI.php +10 -1
- classes/Collector.php +139 -12
- classes/Collectors.php +40 -1
- classes/Dispatcher.php +87 -5
- classes/Dispatchers.php +33 -1
- classes/Hook.php +11 -4
- classes/Output.php +17 -1
- classes/Plugin.php +25 -1
- classes/QM.php +48 -0
- classes/QueryMonitor.php +57 -23
- classes/Timer.php +86 -12
- classes/Util.php +162 -38
- classes/debug_bar.php +15 -0
- classes/debug_bar_panel.php +37 -2
- collectors/admin.php +33 -17
- collectors/assets.php +93 -38
- collectors/assets_scripts.php +14 -1
- collectors/assets_styles.php +11 -1
- collectors/block_editor.php +97 -18
- collectors/cache.php +17 -7
- collectors/caps.php +97 -57
- collectors/conditionals.php +13 -3
- collectors/db_callers.php +11 -1
- collectors/db_components.php +11 -1
- collectors/db_dupes.php +18 -9
- collectors/db_queries.php +93 -44
- collectors/debug_bar.php +35 -4
- collectors/environment.php +118 -59
- collectors/hooks.php +20 -8
- collectors/http.php +131 -46
- collectors/languages.php +64 -50
- collectors/logger.php +110 -21
- collectors/overview.php +25 -4
- collectors/php_errors.php +161 -77
- collectors/raw_request.php +25 -13
- collectors/redirects.php +32 -6
- collectors/request.php +31 -9
- collectors/theme.php +256 -64
- collectors/timing.php +91 -29
- collectors/transients.php +51 -30
- composer.json +77 -0
- dispatchers/AJAX.php +23 -1
- dispatchers/Html.php +206 -77
- dispatchers/REST.php +14 -1
- dispatchers/REST_Envelope.php +15 -4
- dispatchers/Redirect.php +15 -1
- dispatchers/WP_Die.php +35 -21
- output/Headers.php +7 -0
- output/Html.php +93 -25
- output/Raw.php +4 -5
- output/headers/overview.php +12 -2
- output/headers/php_errors.php +21 -11
- output/headers/redirects.php +12 -2
- output/html/admin.php +14 -1
- output/html/assets.php +54 -18
- output/html/assets_scripts.php +17 -3
- output/html/assets_styles.php +17 -3
- output/html/block_editor.php +40 -17
- output/html/caps.php +27 -10
- output/html/conditionals.php +26 -5
- output/html/db_callers.php +19 -2
- output/html/db_components.php +19 -2
- output/html/db_dupes.php +23 -2
- output/html/db_queries.php +93 -41
- output/html/debug_bar.php +16 -2
- output/html/environment.php +28 -13
- output/html/headers.php +30 -5
- output/html/hooks.php +23 -6
- output/html/http.php +36 -44
- output/html/languages.php +23 -2
- output/html/logger.php +54 -13
- output/html/overview.php +112 -44
- output/html/php_errors.php +47 -22
- output/html/request.php +24 -7
- output/html/theme.php +30 -10
- output/html/timing.php +24 -7
- output/html/transients.php +21 -4
- output/raw/cache.php +13 -2
- output/raw/conditionals.php +11 -0
- output/raw/db_queries.php +38 -10
- output/raw/http.php +14 -3
- output/raw/logger.php +13 -2
- output/raw/transients.php +12 -1
- query-monitor.php +5 -7
- readme.txt +24 -19
- wp-content/db.php +35 -29
assets/query-monitor-dark.css
CHANGED
@@ -234,6 +234,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
234 |
background: #23282d !important;
|
235 |
border-top: 1px solid #50626f !important;
|
236 |
bottom: 0 !important;
|
|
|
237 |
direction: ltr !important;
|
238 |
display: none;
|
239 |
left: 0 !important;
|
@@ -942,7 +943,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
942 |
#query-monitor-main .qm button.qm-filter-info:before {
|
943 |
left: unset !important;
|
944 |
right: 2px !important;
|
945 |
-
content: "
|
946 |
visibility: visible !important;
|
947 |
}
|
948 |
#query-monitor-main .qm a.qm-external-link:after,
|
@@ -955,14 +956,14 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
955 |
visibility: visible !important;
|
956 |
}
|
957 |
#query-monitor-main .qm button.qm-filter-trigger:after {
|
958 |
-
content: "
|
959 |
}
|
960 |
#query-monitor-main .qm a.qm-edit-link:after {
|
961 |
-
content: "
|
962 |
}
|
963 |
#query-monitor-main .qm a.qm-external-link:after,
|
964 |
#query-monitor-main .qm a.qm-link:after {
|
965 |
-
content: "
|
966 |
}
|
967 |
#query-monitor-main #qm-ajax-errors {
|
968 |
display: none;
|
@@ -1060,7 +1061,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
1060 |
width: 16px !important;
|
1061 |
}
|
1062 |
#query-monitor-main .qm .qm-sortable-column .qm-sort-arrow::before {
|
1063 |
-
content: "
|
1064 |
position: absolute !important;
|
1065 |
right: 0 !important;
|
1066 |
top: 4px !important;
|
@@ -1073,7 +1074,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
1073 |
color: #0073aa !important;
|
1074 |
}
|
1075 |
#query-monitor-main .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
|
1076 |
-
content: "
|
1077 |
}
|
1078 |
#query-monitor-main .qm button:focus,
|
1079 |
#query-monitor-main .qm a:focus,
|
234 |
background: #23282d !important;
|
235 |
border-top: 1px solid #50626f !important;
|
236 |
bottom: 0 !important;
|
237 |
+
contain: layout paint;
|
238 |
direction: ltr !important;
|
239 |
display: none;
|
240 |
left: 0 !important;
|
943 |
#query-monitor-main .qm button.qm-filter-info:before {
|
944 |
left: unset !important;
|
945 |
right: 2px !important;
|
946 |
+
content: "\f534" !important;
|
947 |
visibility: visible !important;
|
948 |
}
|
949 |
#query-monitor-main .qm a.qm-external-link:after,
|
956 |
visibility: visible !important;
|
957 |
}
|
958 |
#query-monitor-main .qm button.qm-filter-trigger:after {
|
959 |
+
content: "\f536" !important;
|
960 |
}
|
961 |
#query-monitor-main .qm a.qm-edit-link:after {
|
962 |
+
content: "\f464" !important;
|
963 |
}
|
964 |
#query-monitor-main .qm a.qm-external-link:after,
|
965 |
#query-monitor-main .qm a.qm-link:after {
|
966 |
+
content: "\f504" !important;
|
967 |
}
|
968 |
#query-monitor-main #qm-ajax-errors {
|
969 |
display: none;
|
1061 |
width: 16px !important;
|
1062 |
}
|
1063 |
#query-monitor-main .qm .qm-sortable-column .qm-sort-arrow::before {
|
1064 |
+
content: "\f140" !important;
|
1065 |
position: absolute !important;
|
1066 |
right: 0 !important;
|
1067 |
top: 4px !important;
|
1074 |
color: #0073aa !important;
|
1075 |
}
|
1076 |
#query-monitor-main .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
|
1077 |
+
content: "\f142" !important;
|
1078 |
}
|
1079 |
#query-monitor-main .qm button:focus,
|
1080 |
#query-monitor-main .qm a:focus,
|
assets/query-monitor.css
CHANGED
@@ -234,6 +234,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
234 |
background: #fff !important;
|
235 |
border-top: 1px solid #aaa !important;
|
236 |
bottom: 0 !important;
|
|
|
237 |
direction: ltr !important;
|
238 |
display: none;
|
239 |
left: 0 !important;
|
@@ -942,7 +943,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
942 |
#query-monitor-main .qm button.qm-filter-info:before {
|
943 |
left: unset !important;
|
944 |
right: 2px !important;
|
945 |
-
content: "
|
946 |
visibility: visible !important;
|
947 |
}
|
948 |
#query-monitor-main .qm a.qm-external-link:after,
|
@@ -955,14 +956,14 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
955 |
visibility: visible !important;
|
956 |
}
|
957 |
#query-monitor-main .qm button.qm-filter-trigger:after {
|
958 |
-
content: "
|
959 |
}
|
960 |
#query-monitor-main .qm a.qm-edit-link:after {
|
961 |
-
content: "
|
962 |
}
|
963 |
#query-monitor-main .qm a.qm-external-link:after,
|
964 |
#query-monitor-main .qm a.qm-link:after {
|
965 |
-
content: "
|
966 |
}
|
967 |
#query-monitor-main #qm-ajax-errors {
|
968 |
display: none;
|
@@ -1060,7 +1061,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
1060 |
width: 16px !important;
|
1061 |
}
|
1062 |
#query-monitor-main .qm .qm-sortable-column .qm-sort-arrow::before {
|
1063 |
-
content: "
|
1064 |
position: absolute !important;
|
1065 |
right: 0 !important;
|
1066 |
top: 4px !important;
|
@@ -1073,7 +1074,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
|
|
1073 |
color: #0073aa !important;
|
1074 |
}
|
1075 |
#query-monitor-main .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
|
1076 |
-
content: "
|
1077 |
}
|
1078 |
#query-monitor-main .qm button:focus,
|
1079 |
#query-monitor-main .qm a:focus,
|
234 |
background: #fff !important;
|
235 |
border-top: 1px solid #aaa !important;
|
236 |
bottom: 0 !important;
|
237 |
+
contain: layout paint;
|
238 |
direction: ltr !important;
|
239 |
display: none;
|
240 |
left: 0 !important;
|
943 |
#query-monitor-main .qm button.qm-filter-info:before {
|
944 |
left: unset !important;
|
945 |
right: 2px !important;
|
946 |
+
content: "\f534" !important;
|
947 |
visibility: visible !important;
|
948 |
}
|
949 |
#query-monitor-main .qm a.qm-external-link:after,
|
956 |
visibility: visible !important;
|
957 |
}
|
958 |
#query-monitor-main .qm button.qm-filter-trigger:after {
|
959 |
+
content: "\f536" !important;
|
960 |
}
|
961 |
#query-monitor-main .qm a.qm-edit-link:after {
|
962 |
+
content: "\f464" !important;
|
963 |
}
|
964 |
#query-monitor-main .qm a.qm-external-link:after,
|
965 |
#query-monitor-main .qm a.qm-link:after {
|
966 |
+
content: "\f504" !important;
|
967 |
}
|
968 |
#query-monitor-main #qm-ajax-errors {
|
969 |
display: none;
|
1061 |
width: 16px !important;
|
1062 |
}
|
1063 |
#query-monitor-main .qm .qm-sortable-column .qm-sort-arrow::before {
|
1064 |
+
content: "\f140" !important;
|
1065 |
position: absolute !important;
|
1066 |
right: 0 !important;
|
1067 |
top: 4px !important;
|
1074 |
color: #0073aa !important;
|
1075 |
}
|
1076 |
#query-monitor-main .qm .qm-sortable-column.qm-sorted-asc .qm-sort-arrow::before {
|
1077 |
+
content: "\f142" !important;
|
1078 |
}
|
1079 |
#query-monitor-main .qm button:focus,
|
1080 |
#query-monitor-main .qm a:focus,
|
assets/query-monitor.js
CHANGED
@@ -21,10 +21,10 @@ var QM_i18n = {
|
|
21 |
number = parseFloat( number );
|
22 |
|
23 |
var num_float = number.toFixed( decimals ),
|
24 |
-
num_int
|
25 |
-
num_str
|
26 |
-
fraction
|
27 |
-
o
|
28 |
|
29 |
if ( num_str.length > 3 ) {
|
30 |
for ( i = num_str.length; i > 3; i -= 3 ) {
|
@@ -48,18 +48,18 @@ var QM_i18n = {
|
|
48 |
if ( window.jQuery ) {
|
49 |
|
50 |
jQuery( function($) {
|
51 |
-
var toolbarHeight
|
52 |
-
var minheight
|
53 |
-
var maxheight
|
54 |
-
var minwidth
|
55 |
-
var maxwidth
|
56 |
-
var container
|
57 |
-
var body
|
58 |
-
var body_margin
|
59 |
-
var container_height_key
|
60 |
-
var container_pinned_key
|
61 |
var container_position_key = 'qm-container-position';
|
62 |
-
var container_width_key
|
63 |
|
64 |
if ( container.hasClass('qm-peek') ) {
|
65 |
minheight = 27;
|
@@ -145,12 +145,12 @@ if ( window.jQuery ) {
|
|
145 |
|
146 |
if ( selected_menu.length ) {
|
147 |
var selected_menu_top = selected_menu.position().top - 27;
|
148 |
-
var menu_height
|
149 |
-
var menu_scroll
|
150 |
selected_menu.closest('#qm-panel-menu > ul > li').addClass('qm-current-menu');
|
151 |
|
152 |
var selected_menu_off_bottom = ( selected_menu_top > ( menu_height ) );
|
153 |
-
var selected_menu_off_top
|
154 |
|
155 |
if ( selected_menu_off_bottom || selected_menu_off_top ) {
|
156 |
$('#qm-panel-menu').scrollTop( selected_menu_top + menu_scroll - ( menu_height / 2 ) + ( selected_menu.outerHeight() / 2 ) );
|
@@ -217,13 +217,13 @@ if ( window.jQuery ) {
|
|
217 |
container.find('.qm-filter').on('change',function(e){
|
218 |
|
219 |
var filter = $(this).attr('data-filter'),
|
220 |
-
table
|
221 |
-
tr
|
222 |
// Escape the following chars with a backslash before passing into jQ selectors: [ ] ( ) ' " \
|
223 |
-
val
|
224 |
-
total
|
225 |
hilite = $(this).attr('data-highlight'),
|
226 |
-
time
|
227 |
|
228 |
key = $(this).attr('id');
|
229 |
if ( val ) {
|
@@ -270,7 +270,7 @@ if ( window.jQuery ) {
|
|
270 |
});
|
271 |
|
272 |
container.find('.qm-filter').each(function () {
|
273 |
-
var key
|
274 |
var value = localStorage.getItem( key );
|
275 |
if ( value !== null ) {
|
276 |
// Escape the following chars with a backslash before passing into jQ selectors: [ ] ( ) ' " \
|
@@ -284,7 +284,7 @@ if ( window.jQuery ) {
|
|
284 |
|
285 |
container.find('.qm-filter-trigger').on('click',function(e){
|
286 |
var filter = $(this).data('qm-filter'),
|
287 |
-
value
|
288 |
target = $(this).data('qm-target');
|
289 |
$('#qm-' + target).find('.qm-filter').not('[data-filter="' + filter + '"]').val('').removeClass('qm-highlight').trigger('change');
|
290 |
$('#qm-' + target).find('[data-filter="' + filter + '"]').val(value).addClass('qm-highlight').trigger('change');
|
@@ -294,9 +294,9 @@ if ( window.jQuery ) {
|
|
294 |
});
|
295 |
|
296 |
container.find('.qm-toggle').on('click',function(e){
|
297 |
-
var el
|
298 |
var currentState = el.attr('aria-expanded');
|
299 |
-
var newState
|
300 |
if (currentState === 'true') {
|
301 |
newState = 'false';
|
302 |
}
|
@@ -323,7 +323,7 @@ if ( window.jQuery ) {
|
|
323 |
container.find('.qm-highlighter').on('mouseenter',function(e){
|
324 |
|
325 |
var subject = $(this).data('qm-highlight');
|
326 |
-
var table
|
327 |
|
328 |
if ( ! subject ) {
|
329 |
return;
|
@@ -408,7 +408,7 @@ if ( window.jQuery ) {
|
|
408 |
} );
|
409 |
|
410 |
$('.qm-auth').on('click',function(e){
|
411 |
-
var state
|
412 |
var action = ( 'off' === state ? 'on' : 'off' );
|
413 |
|
414 |
$.ajax(qm_l10n.ajaxurl,{
|
@@ -435,7 +435,7 @@ if ( window.jQuery ) {
|
|
435 |
editorSuccessIndicator.hide();
|
436 |
|
437 |
$('.qm-editor-button').on('click',function(e){
|
438 |
-
var state
|
439 |
var editor = $('#qm-editor-select').val();
|
440 |
|
441 |
$.ajax(qm_l10n.ajaxurl,{
|
@@ -468,8 +468,8 @@ if ( window.jQuery ) {
|
|
468 |
event.stopPropagation();
|
469 |
|
470 |
resizerHeight = $(this).outerHeight() - 1;
|
471 |
-
startY
|
472 |
-
startX
|
473 |
|
474 |
if ( ! container.hasClass('qm-show-right') ) {
|
475 |
$(document).on('mousemove touchmove', qm_do_resizer_drag_vertical);
|
@@ -537,11 +537,11 @@ if ( window.jQuery ) {
|
|
537 |
}
|
538 |
|
539 |
$(window).on('resize', function(){
|
540 |
-
var h
|
541 |
-
var w
|
542 |
|
543 |
maxheight = ( $(window).height() - toolbarHeight );
|
544 |
-
maxwidth
|
545 |
|
546 |
if ( h < minheight ) {
|
547 |
container.height( minheight );
|
@@ -616,21 +616,21 @@ if ( window.jQuery ) {
|
|
616 |
* Author: Gajus Kuizinas <g.kuizinas@anuary.com>
|
617 |
*/
|
618 |
(function ($) {
|
619 |
-
$.qm
|
620 |
$.qm.tableSort = function (settings) {
|
621 |
// @param object columns NodeList table colums.
|
622 |
// @param integer row_width defines the number of columns per row.
|
623 |
var table_to_array = function (columns, row_width) {
|
624 |
columns = Array.prototype.slice.call(columns, 0);
|
625 |
|
626 |
-
var rows
|
627 |
var row_index = 0;
|
628 |
|
629 |
for (var i = 0, j = columns.length; i < j; i += row_width) {
|
630 |
var row = [];
|
631 |
|
632 |
for (var k = 0; k < row_width; k++) {
|
633 |
-
var e
|
634 |
var data = e.dataset.qmSortWeight;
|
635 |
|
636 |
if (data === undefined) {
|
@@ -658,7 +658,7 @@ if ( window.jQuery ) {
|
|
658 |
var table = $(this);
|
659 |
|
660 |
table.find('.qm-sortable-column').on('click', function (e) {
|
661 |
-
var desc
|
662 |
var index = $(this).index();
|
663 |
|
664 |
table.find('thead th').removeClass('qm-sorted-asc qm-sorted-desc').attr('aria-sort','none');
|
@@ -670,8 +670,8 @@ if ( window.jQuery ) {
|
|
670 |
}
|
671 |
|
672 |
table.find('tbody').each(function () {
|
673 |
-
var tbody
|
674 |
-
var rows
|
675 |
var columns = this.querySelectorAll('th,td');
|
676 |
|
677 |
if (this.data_matrix === undefined) {
|
@@ -722,6 +722,7 @@ if ( window.jQuery ) {
|
|
722 |
|
723 |
window.addEventListener('load', function() {
|
724 |
var main = document.getElementById( 'query-monitor-main' );
|
|
|
725 |
var broken = document.getElementById( 'qm-broken' );
|
726 |
var menu_item = document.getElementById( 'wp-admin-bar-query-monitor' );
|
727 |
|
@@ -750,7 +751,12 @@ window.addEventListener('load', function() {
|
|
750 |
}
|
751 |
|
752 |
if ( ! main ) {
|
753 |
-
|
754 |
-
|
|
|
|
|
|
|
|
|
|
|
755 |
}
|
756 |
} );
|
21 |
number = parseFloat( number );
|
22 |
|
23 |
var num_float = number.toFixed( decimals ),
|
24 |
+
num_int = Math.floor( number ),
|
25 |
+
num_str = num_int.toString(),
|
26 |
+
fraction = num_float.substring( num_float.indexOf( '.' ) + 1, num_float.length ),
|
27 |
+
o = '';
|
28 |
|
29 |
if ( num_str.length > 3 ) {
|
30 |
for ( i = num_str.length; i > 3; i -= 3 ) {
|
48 |
if ( window.jQuery ) {
|
49 |
|
50 |
jQuery( function($) {
|
51 |
+
var toolbarHeight = $('#wpadminbar').length ? $('#wpadminbar').outerHeight() : 0;
|
52 |
+
var minheight = 100;
|
53 |
+
var maxheight = ( $(window).height() - toolbarHeight );
|
54 |
+
var minwidth = 300;
|
55 |
+
var maxwidth = $(window).width();
|
56 |
+
var container = $('#query-monitor-main');
|
57 |
+
var body = $('body');
|
58 |
+
var body_margin = body.css('margin-bottom');
|
59 |
+
var container_height_key = 'qm-container-height';
|
60 |
+
var container_pinned_key = 'qm-' + ( $('body').hasClass('wp-admin') ? 'admin' : 'front' ) + '-container-pinned';
|
61 |
var container_position_key = 'qm-container-position';
|
62 |
+
var container_width_key = 'qm-container-width';
|
63 |
|
64 |
if ( container.hasClass('qm-peek') ) {
|
65 |
minheight = 27;
|
145 |
|
146 |
if ( selected_menu.length ) {
|
147 |
var selected_menu_top = selected_menu.position().top - 27;
|
148 |
+
var menu_height = $('#qm-panel-menu').height();
|
149 |
+
var menu_scroll = $('#qm-panel-menu').scrollTop();
|
150 |
selected_menu.closest('#qm-panel-menu > ul > li').addClass('qm-current-menu');
|
151 |
|
152 |
var selected_menu_off_bottom = ( selected_menu_top > ( menu_height ) );
|
153 |
+
var selected_menu_off_top = ( selected_menu_top < 0 );
|
154 |
|
155 |
if ( selected_menu_off_bottom || selected_menu_off_top ) {
|
156 |
$('#qm-panel-menu').scrollTop( selected_menu_top + menu_scroll - ( menu_height / 2 ) + ( selected_menu.outerHeight() / 2 ) );
|
217 |
container.find('.qm-filter').on('change',function(e){
|
218 |
|
219 |
var filter = $(this).attr('data-filter'),
|
220 |
+
table = $(this).closest('table'),
|
221 |
+
tr = table.find('tbody tr[data-qm-' + filter + ']'),
|
222 |
// Escape the following chars with a backslash before passing into jQ selectors: [ ] ( ) ' " \
|
223 |
+
val = $(this).val().replace(/[[\]()'"\\]/g, "\\$&"),
|
224 |
+
total = tr.removeClass('qm-hide-' + filter).length,
|
225 |
hilite = $(this).attr('data-highlight'),
|
226 |
+
time = 0;
|
227 |
|
228 |
key = $(this).attr('id');
|
229 |
if ( val ) {
|
270 |
});
|
271 |
|
272 |
container.find('.qm-filter').each(function () {
|
273 |
+
var key = $(this).attr('id');
|
274 |
var value = localStorage.getItem( key );
|
275 |
if ( value !== null ) {
|
276 |
// Escape the following chars with a backslash before passing into jQ selectors: [ ] ( ) ' " \
|
284 |
|
285 |
container.find('.qm-filter-trigger').on('click',function(e){
|
286 |
var filter = $(this).data('qm-filter'),
|
287 |
+
value = $(this).data('qm-value'),
|
288 |
target = $(this).data('qm-target');
|
289 |
$('#qm-' + target).find('.qm-filter').not('[data-filter="' + filter + '"]').val('').removeClass('qm-highlight').trigger('change');
|
290 |
$('#qm-' + target).find('[data-filter="' + filter + '"]').val(value).addClass('qm-highlight').trigger('change');
|
294 |
});
|
295 |
|
296 |
container.find('.qm-toggle').on('click',function(e){
|
297 |
+
var el = $(this);
|
298 |
var currentState = el.attr('aria-expanded');
|
299 |
+
var newState = 'true';
|
300 |
if (currentState === 'true') {
|
301 |
newState = 'false';
|
302 |
}
|
323 |
container.find('.qm-highlighter').on('mouseenter',function(e){
|
324 |
|
325 |
var subject = $(this).data('qm-highlight');
|
326 |
+
var table = $(this).closest('table');
|
327 |
|
328 |
if ( ! subject ) {
|
329 |
return;
|
408 |
} );
|
409 |
|
410 |
$('.qm-auth').on('click',function(e){
|
411 |
+
var state = $('#qm-settings').data('qm-state');
|
412 |
var action = ( 'off' === state ? 'on' : 'off' );
|
413 |
|
414 |
$.ajax(qm_l10n.ajaxurl,{
|
435 |
editorSuccessIndicator.hide();
|
436 |
|
437 |
$('.qm-editor-button').on('click',function(e){
|
438 |
+
var state = $('#qm-settings').data('qm-state');
|
439 |
var editor = $('#qm-editor-select').val();
|
440 |
|
441 |
$.ajax(qm_l10n.ajaxurl,{
|
468 |
event.stopPropagation();
|
469 |
|
470 |
resizerHeight = $(this).outerHeight() - 1;
|
471 |
+
startY = container.outerHeight() + ( event.clientY || event.originalEvent.targetTouches[0].pageY );
|
472 |
+
startX = container.outerWidth() + ( event.clientX || event.originalEvent.targetTouches[0].pageX );
|
473 |
|
474 |
if ( ! container.hasClass('qm-show-right') ) {
|
475 |
$(document).on('mousemove touchmove', qm_do_resizer_drag_vertical);
|
537 |
}
|
538 |
|
539 |
$(window).on('resize', function(){
|
540 |
+
var h = container.height();
|
541 |
+
var w = container.width();
|
542 |
|
543 |
maxheight = ( $(window).height() - toolbarHeight );
|
544 |
+
maxwidth = $(window).width();
|
545 |
|
546 |
if ( h < minheight ) {
|
547 |
container.height( minheight );
|
616 |
* Author: Gajus Kuizinas <g.kuizinas@anuary.com>
|
617 |
*/
|
618 |
(function ($) {
|
619 |
+
$.qm = $.qm || {};
|
620 |
$.qm.tableSort = function (settings) {
|
621 |
// @param object columns NodeList table colums.
|
622 |
// @param integer row_width defines the number of columns per row.
|
623 |
var table_to_array = function (columns, row_width) {
|
624 |
columns = Array.prototype.slice.call(columns, 0);
|
625 |
|
626 |
+
var rows = [];
|
627 |
var row_index = 0;
|
628 |
|
629 |
for (var i = 0, j = columns.length; i < j; i += row_width) {
|
630 |
var row = [];
|
631 |
|
632 |
for (var k = 0; k < row_width; k++) {
|
633 |
+
var e = columns[i + k];
|
634 |
var data = e.dataset.qmSortWeight;
|
635 |
|
636 |
if (data === undefined) {
|
658 |
var table = $(this);
|
659 |
|
660 |
table.find('.qm-sortable-column').on('click', function (e) {
|
661 |
+
var desc = ! $(this).hasClass('qm-sorted-desc');
|
662 |
var index = $(this).index();
|
663 |
|
664 |
table.find('thead th').removeClass('qm-sorted-asc qm-sorted-desc').attr('aria-sort','none');
|
670 |
}
|
671 |
|
672 |
table.find('tbody').each(function () {
|
673 |
+
var tbody = $(this);
|
674 |
+
var rows = this.rows;
|
675 |
var columns = this.querySelectorAll('th,td');
|
676 |
|
677 |
if (this.data_matrix === undefined) {
|
722 |
|
723 |
window.addEventListener('load', function() {
|
724 |
var main = document.getElementById( 'query-monitor-main' );
|
725 |
+
var ceased = document.getElementById( 'query-monitor-ceased' );
|
726 |
var broken = document.getElementById( 'qm-broken' );
|
727 |
var menu_item = document.getElementById( 'wp-admin-bar-query-monitor' );
|
728 |
|
751 |
}
|
752 |
|
753 |
if ( ! main ) {
|
754 |
+
if ( ceased ) {
|
755 |
+
// QM was ceased
|
756 |
+
console.info( 'QM: collection and output was ceased' );
|
757 |
+
} else {
|
758 |
+
// QM's output has disappeared
|
759 |
+
console.error( 'QM error from JS: QM output does not exist' );
|
760 |
+
}
|
761 |
}
|
762 |
} );
|
classes/Activation.php
CHANGED
@@ -7,6 +7,9 @@
|
|
7 |
|
8 |
class QM_Activation extends QM_Plugin {
|
9 |
|
|
|
|
|
|
|
10 |
protected function __construct( $file ) {
|
11 |
|
12 |
# PHP version handling
|
@@ -16,7 +19,7 @@ class QM_Activation extends QM_Plugin {
|
|
16 |
}
|
17 |
|
18 |
# Filters
|
19 |
-
add_filter( 'pre_update_option_active_plugins',
|
20 |
add_filter( 'pre_update_site_option_active_sitewide_plugins', array( $this, 'filter_active_sitewide_plugins' ) );
|
21 |
|
22 |
# Activation and deactivation
|
@@ -28,6 +31,10 @@ class QM_Activation extends QM_Plugin {
|
|
28 |
|
29 |
}
|
30 |
|
|
|
|
|
|
|
|
|
31 |
public function activate( $sitewide = false ) {
|
32 |
$db = WP_CONTENT_DIR . '/db.php';
|
33 |
$create_symlink = defined( 'QM_DB_SYMLINK' ) ? QM_DB_SYMLINK : true;
|
@@ -44,6 +51,9 @@ class QM_Activation extends QM_Plugin {
|
|
44 |
|
45 |
}
|
46 |
|
|
|
|
|
|
|
47 |
public function deactivate() {
|
48 |
$admins = QM_Util::get_admins();
|
49 |
|
@@ -59,6 +69,10 @@ class QM_Activation extends QM_Plugin {
|
|
59 |
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
62 |
public function filter_active_plugins( $plugins ) {
|
63 |
|
64 |
// this needs to run on the cli too
|
@@ -76,6 +90,10 @@ class QM_Activation extends QM_Plugin {
|
|
76 |
|
77 |
}
|
78 |
|
|
|
|
|
|
|
|
|
79 |
public function filter_active_sitewide_plugins( $plugins ) {
|
80 |
|
81 |
if ( empty( $plugins ) ) {
|
@@ -98,6 +116,9 @@ class QM_Activation extends QM_Plugin {
|
|
98 |
|
99 |
}
|
100 |
|
|
|
|
|
|
|
101 |
public function php_notice() {
|
102 |
?>
|
103 |
<div id="qm_php_notice" class="notice notice-error">
|
@@ -115,6 +136,10 @@ class QM_Activation extends QM_Plugin {
|
|
115 |
<?php
|
116 |
}
|
117 |
|
|
|
|
|
|
|
|
|
118 |
public static function init( $file = null ) {
|
119 |
|
120 |
static $instance = null;
|
7 |
|
8 |
class QM_Activation extends QM_Plugin {
|
9 |
|
10 |
+
/**
|
11 |
+
* @param string $file
|
12 |
+
*/
|
13 |
protected function __construct( $file ) {
|
14 |
|
15 |
# PHP version handling
|
19 |
}
|
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' ) );
|
24 |
|
25 |
# Activation and deactivation
|
31 |
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @param bool $sitewide
|
36 |
+
* @return void
|
37 |
+
*/
|
38 |
public function activate( $sitewide = false ) {
|
39 |
$db = WP_CONTENT_DIR . '/db.php';
|
40 |
$create_symlink = defined( 'QM_DB_SYMLINK' ) ? QM_DB_SYMLINK : true;
|
51 |
|
52 |
}
|
53 |
|
54 |
+
/**
|
55 |
+
* @return void
|
56 |
+
*/
|
57 |
public function deactivate() {
|
58 |
$admins = QM_Util::get_admins();
|
59 |
|
69 |
|
70 |
}
|
71 |
|
72 |
+
/**
|
73 |
+
* @param array<int, string> $plugins
|
74 |
+
* @return array<int, string>
|
75 |
+
*/
|
76 |
public function filter_active_plugins( $plugins ) {
|
77 |
|
78 |
// this needs to run on the cli too
|
90 |
|
91 |
}
|
92 |
|
93 |
+
/**
|
94 |
+
* @param array<string, int> $plugins
|
95 |
+
* @return array<string, int>
|
96 |
+
*/
|
97 |
public function filter_active_sitewide_plugins( $plugins ) {
|
98 |
|
99 |
if ( empty( $plugins ) ) {
|
116 |
|
117 |
}
|
118 |
|
119 |
+
/**
|
120 |
+
* @return void
|
121 |
+
*/
|
122 |
public function php_notice() {
|
123 |
?>
|
124 |
<div id="qm_php_notice" class="notice notice-error">
|
136 |
<?php
|
137 |
}
|
138 |
|
139 |
+
/**
|
140 |
+
* @param string $file
|
141 |
+
* @return self
|
142 |
+
*/
|
143 |
public static function init( $file = null ) {
|
144 |
|
145 |
static $instance = null;
|
classes/Backtrace.php
CHANGED
@@ -5,83 +5,134 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
if ( ! class_exists( 'QM_Backtrace' ) ) {
|
11 |
class QM_Backtrace {
|
12 |
|
|
|
|
|
|
|
13 |
protected static $ignore_class = array(
|
14 |
-
'wpdb'
|
15 |
-
'
|
16 |
-
'
|
17 |
-
'
|
18 |
-
'
|
|
|
19 |
);
|
|
|
|
|
|
|
|
|
20 |
protected static $ignore_method = array();
|
|
|
|
|
|
|
|
|
21 |
protected static $ignore_func = array(
|
22 |
-
'include_once'
|
23 |
-
'require_once'
|
24 |
-
'include'
|
25 |
-
'require'
|
26 |
'call_user_func_array' => true,
|
27 |
-
'call_user_func'
|
28 |
-
'trigger_error'
|
29 |
-
'_doing_it_wrong'
|
30 |
'_deprecated_argument' => true,
|
31 |
-
'_deprecated_file'
|
32 |
'_deprecated_function' => true,
|
33 |
-
'dbDelta'
|
34 |
);
|
|
|
|
|
|
|
|
|
|
|
35 |
protected static $show_args = array(
|
36 |
-
'do_action'
|
37 |
-
'apply_filters'
|
38 |
-
'do_action_ref_array'
|
39 |
-
'apply_filters_ref_array'
|
40 |
-
'
|
|
|
|
|
41 |
'get_extended_template_part' => 2,
|
42 |
-
'
|
43 |
-
'
|
44 |
-
'
|
45 |
-
'
|
46 |
-
'
|
47 |
-
'
|
48 |
-
'
|
49 |
-
'
|
50 |
-
'
|
51 |
-
'
|
|
|
|
|
|
|
|
|
|
|
52 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
protected static $filtered = false;
|
54 |
-
protected $trace = null;
|
55 |
-
protected $filtered_trace = null;
|
56 |
-
protected $calling_line = 0;
|
57 |
-
protected $calling_file = '';
|
58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
public function __construct( array $args = array(), array $trace = null ) {
|
60 |
$this->trace = ( null === $trace ) ? debug_backtrace( false ) : $trace;
|
61 |
|
62 |
-
$args = array_merge( array(
|
63 |
-
'
|
64 |
-
'
|
|
|
|
|
|
|
65 |
), $args );
|
66 |
|
67 |
-
$this->
|
68 |
-
|
69 |
-
/**
|
70 |
-
* If error_handler() is in the trace, QM fails later when it tries
|
71 |
-
* to get $lowest['file'] in get_filtered_trace()
|
72 |
-
*/
|
73 |
-
if ( 'error_handler' === $this->trace[0]['function'] ) {
|
74 |
-
$this->ignore( 1 );
|
75 |
-
}
|
76 |
-
|
77 |
-
if ( $args['ignore_frames'] ) {
|
78 |
-
$this->ignore( $args['ignore_frames'] );
|
79 |
-
}
|
80 |
-
if ( $args['ignore_current_filter'] ) {
|
81 |
-
$this->ignore_current_filter();
|
82 |
-
}
|
83 |
-
|
84 |
-
foreach ( $this->trace as $k => $frame ) {
|
85 |
if ( ! isset( $frame['args'] ) ) {
|
86 |
continue;
|
87 |
}
|
@@ -98,11 +149,12 @@ class QM_Backtrace {
|
|
98 |
} else {
|
99 |
unset( $frame['args'] );
|
100 |
}
|
101 |
-
|
102 |
-
$this->trace[ $k ] = $frame;
|
103 |
}
|
104 |
}
|
105 |
|
|
|
|
|
|
|
106 |
public function get_stack() {
|
107 |
|
108 |
$trace = $this->get_filtered_trace();
|
@@ -112,6 +164,9 @@ class QM_Backtrace {
|
|
112 |
|
113 |
}
|
114 |
|
|
|
|
|
|
|
115 |
public function get_caller() {
|
116 |
|
117 |
$trace = $this->get_filtered_trace();
|
@@ -120,18 +175,25 @@ class QM_Backtrace {
|
|
120 |
|
121 |
}
|
122 |
|
|
|
|
|
|
|
123 |
public function get_component() {
|
|
|
|
|
|
|
124 |
|
125 |
$components = array();
|
126 |
|
127 |
-
foreach ( $this->
|
128 |
$component = self::get_frame_component( $frame );
|
129 |
|
130 |
if ( $component ) {
|
131 |
if ( 'plugin' === $component->type ) {
|
132 |
// If the component is a plugin then it can't be anything else,
|
133 |
// so short-circuit and return early.
|
134 |
-
|
|
|
135 |
}
|
136 |
|
137 |
$components[ $component->type ] = $component;
|
@@ -140,50 +202,72 @@ class QM_Backtrace {
|
|
140 |
|
141 |
foreach ( QM_Util::get_file_dirs() as $type => $dir ) {
|
142 |
if ( isset( $components[ $type ] ) ) {
|
143 |
-
|
|
|
144 |
}
|
145 |
}
|
146 |
|
147 |
-
|
148 |
-
|
|
|
|
|
|
|
149 |
}
|
150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
public static function get_frame_component( array $frame ) {
|
152 |
-
|
153 |
|
154 |
-
|
155 |
-
|
156 |
-
return null;
|
157 |
-
}
|
158 |
-
if ( ! method_exists( $frame['class'], $frame['function'] ) ) {
|
159 |
-
return null;
|
160 |
-
}
|
161 |
-
$ref = new ReflectionMethod( $frame['class'], $frame['function'] );
|
162 |
-
$file = $ref->getFileName();
|
163 |
-
} elseif ( isset( $frame['function'] ) && function_exists( $frame['function'] ) ) {
|
164 |
-
$ref = new ReflectionFunction( $frame['function'] );
|
165 |
-
$file = $ref->getFileName();
|
166 |
-
} elseif ( isset( $frame['file'] ) ) {
|
167 |
-
$file = $frame['file'];
|
168 |
-
} else {
|
169 |
return null;
|
170 |
}
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
175 |
return null;
|
176 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
}
|
178 |
|
|
|
|
|
|
|
179 |
public function get_trace() {
|
180 |
return $this->trace;
|
181 |
}
|
182 |
|
|
|
|
|
|
|
|
|
|
|
183 |
public function get_display_trace() {
|
184 |
return $this->get_filtered_trace();
|
185 |
}
|
186 |
|
|
|
|
|
|
|
187 |
public function get_filtered_trace() {
|
188 |
|
189 |
if ( ! isset( $this->filtered_trace ) ) {
|
@@ -192,13 +276,13 @@ class QM_Backtrace {
|
|
192 |
$trace = array_values( array_filter( $trace ) );
|
193 |
|
194 |
if ( empty( $trace ) && ! empty( $this->trace ) ) {
|
195 |
-
$lowest
|
196 |
-
$file
|
197 |
$lowest['calling_file'] = $lowest['file'];
|
198 |
$lowest['calling_line'] = $lowest['line'];
|
199 |
-
$lowest['function']
|
200 |
-
$lowest['display']
|
201 |
-
$lowest['id']
|
202 |
unset( $lowest['class'], $lowest['args'], $lowest['type'] );
|
203 |
$trace[0] = $lowest;
|
204 |
}
|
@@ -211,6 +295,53 @@ class QM_Backtrace {
|
|
211 |
|
212 |
}
|
213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
public function ignore( $num ) {
|
215 |
for ( $i = 0; $i < $num; $i++ ) {
|
216 |
unset( $this->trace[ $i ] );
|
@@ -219,16 +350,10 @@ class QM_Backtrace {
|
|
219 |
return $this;
|
220 |
}
|
221 |
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
$this->ignore( 3 ); # Ignore filter and action callbacks
|
227 |
-
}
|
228 |
-
}
|
229 |
-
|
230 |
-
}
|
231 |
-
|
232 |
public function filter_trace( array $frame ) {
|
233 |
|
234 |
if ( ! self::$filtered && function_exists( 'did_action' ) && did_action( 'plugins_loaded' ) ) {
|
@@ -241,7 +366,7 @@ class QM_Backtrace {
|
|
241 |
* @param bool[] $ignore_class Array of class names to ignore. The array keys are class names to ignore,
|
242 |
* the array values are whether to ignore the class or not (usually true).
|
243 |
*/
|
244 |
-
self::$ignore_class
|
245 |
|
246 |
/**
|
247 |
* Filters which class methods to ignore when constructing user-facing call stacks.
|
@@ -261,7 +386,17 @@ class QM_Backtrace {
|
|
261 |
* @param bool[] $ignore_func Array of function names to ignore. The array keys are function names to ignore,
|
262 |
* the array values are whether to ignore the function or not (usually true).
|
263 |
*/
|
264 |
-
self::$ignore_func
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
265 |
|
266 |
/**
|
267 |
* Filters the number of argument values to show for the given function name when constructing user-facing
|
@@ -273,53 +408,71 @@ class QM_Backtrace {
|
|
273 |
* array keys are function names, the array values are either integers or
|
274 |
* "dir" to specifically treat the function argument as a directory path.
|
275 |
*/
|
276 |
-
self::$show_args
|
277 |
|
278 |
self::$filtered = true;
|
279 |
|
280 |
}
|
281 |
|
282 |
$return = $frame;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
|
284 |
if ( isset( $frame['class'] ) ) {
|
285 |
-
if ( isset(
|
286 |
$return = null;
|
287 |
-
} elseif ( isset(
|
288 |
$return = null;
|
289 |
} elseif ( 0 === strpos( $frame['class'], 'QM' ) ) {
|
290 |
$return = null;
|
291 |
} else {
|
292 |
-
$return['id']
|
293 |
$return['display'] = QM_Util::shorten_fqn( $frame['class'] . $frame['type'] . $frame['function'] ) . '()';
|
294 |
}
|
295 |
} else {
|
296 |
-
if ( isset(
|
297 |
$return = null;
|
298 |
-
} elseif ( isset(
|
299 |
-
$show =
|
300 |
|
301 |
if ( 'dir' === $show ) {
|
302 |
if ( isset( $frame['args'][0] ) ) {
|
303 |
$arg = QM_Util::standard_dir( $frame['args'][0], '' );
|
304 |
-
$return['id']
|
305 |
$return['display'] = QM_Util::shorten_fqn( $frame['function'] ) . "('{$arg}')";
|
306 |
}
|
307 |
} else {
|
308 |
-
$args
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
|
|
|
|
|
|
|
|
315 |
}
|
316 |
}
|
|
|
|
|
317 |
}
|
318 |
-
$return['id'] = $frame['function'] . '()';
|
319 |
-
$return['display'] = QM_Util::shorten_fqn( $frame['function'] ) . '(' . implode( ',', $args ) . ')';
|
320 |
}
|
321 |
} else {
|
322 |
-
$return['id']
|
323 |
$return['display'] = QM_Util::shorten_fqn( $frame['function'] ) . '()';
|
324 |
}
|
325 |
}
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
if ( ! class_exists( 'QM_Backtrace' ) ) {
|
13 |
class QM_Backtrace {
|
14 |
|
15 |
+
/**
|
16 |
+
* @var array<string, bool>
|
17 |
+
*/
|
18 |
protected static $ignore_class = array(
|
19 |
+
'wpdb' => true,
|
20 |
+
'hyperdb' => true,
|
21 |
+
'QueryMonitor' => true,
|
22 |
+
'W3_Db' => true,
|
23 |
+
'Debug_Bar_PHP' => true,
|
24 |
+
'WP_Hook' => true,
|
25 |
);
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var array<string, bool>
|
29 |
+
*/
|
30 |
protected static $ignore_method = array();
|
31 |
+
|
32 |
+
/**
|
33 |
+
* @var array<string, bool>
|
34 |
+
*/
|
35 |
protected static $ignore_func = array(
|
36 |
+
'include_once' => true,
|
37 |
+
'require_once' => true,
|
38 |
+
'include' => true,
|
39 |
+
'require' => true,
|
40 |
'call_user_func_array' => true,
|
41 |
+
'call_user_func' => true,
|
42 |
+
'trigger_error' => true,
|
43 |
+
'_doing_it_wrong' => true,
|
44 |
'_deprecated_argument' => true,
|
45 |
+
'_deprecated_file' => true,
|
46 |
'_deprecated_function' => true,
|
47 |
+
'dbDelta' => true,
|
48 |
);
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @var array<string, int|string>
|
52 |
+
* @phpstan-var array<string, positive-int|'dir'>
|
53 |
+
*/
|
54 |
protected static $show_args = array(
|
55 |
+
'do_action' => 1,
|
56 |
+
'apply_filters' => 1,
|
57 |
+
'do_action_ref_array' => 1,
|
58 |
+
'apply_filters_ref_array' => 1,
|
59 |
+
'get_query_template' => 1,
|
60 |
+
'resolve_block_template' => 1,
|
61 |
+
'get_template_part' => 2,
|
62 |
'get_extended_template_part' => 2,
|
63 |
+
'ai_get_template_part' => 2,
|
64 |
+
'load_template' => 'dir',
|
65 |
+
'dynamic_sidebar' => 1,
|
66 |
+
'get_header' => 1,
|
67 |
+
'get_sidebar' => 1,
|
68 |
+
'get_footer' => 1,
|
69 |
+
'get_option' => 1,
|
70 |
+
'update_option' => 1,
|
71 |
+
'get_transient' => 1,
|
72 |
+
'set_transient' => 1,
|
73 |
+
'class_exists' => 2,
|
74 |
+
'current_user_can' => 3,
|
75 |
+
'user_can' => 4,
|
76 |
+
'current_user_can_for_blog' => 4,
|
77 |
+
'author_can' => 4,
|
78 |
);
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @var array<string, bool>
|
82 |
+
*/
|
83 |
+
protected static $ignore_hook = array();
|
84 |
+
|
85 |
+
/**
|
86 |
+
* @var bool
|
87 |
+
*/
|
88 |
protected static $filtered = false;
|
|
|
|
|
|
|
|
|
89 |
|
90 |
+
/**
|
91 |
+
* @var array<string, mixed[]>
|
92 |
+
*/
|
93 |
+
protected $args = array();
|
94 |
+
|
95 |
+
/**
|
96 |
+
* @var mixed[]|null
|
97 |
+
*/
|
98 |
+
protected $trace = null;
|
99 |
+
|
100 |
+
/**
|
101 |
+
* @var mixed[]|null
|
102 |
+
*/
|
103 |
+
protected $filtered_trace = null;
|
104 |
+
|
105 |
+
/**
|
106 |
+
* @var int
|
107 |
+
*/
|
108 |
+
protected $calling_line = 0;
|
109 |
+
|
110 |
+
/**
|
111 |
+
* @var string
|
112 |
+
*/
|
113 |
+
protected $calling_file = '';
|
114 |
+
|
115 |
+
/**
|
116 |
+
* @var stdClass|null
|
117 |
+
*/
|
118 |
+
protected $component = null;
|
119 |
+
|
120 |
+
/**
|
121 |
+
* @param array<string, mixed[]> $args
|
122 |
+
* @param mixed[] $trace
|
123 |
+
*/
|
124 |
public function __construct( array $args = array(), array $trace = null ) {
|
125 |
$this->trace = ( null === $trace ) ? debug_backtrace( false ) : $trace;
|
126 |
|
127 |
+
$this->args = array_merge( array(
|
128 |
+
'ignore_class' => array(),
|
129 |
+
'ignore_method' => array(),
|
130 |
+
'ignore_func' => array(),
|
131 |
+
'ignore_hook' => array(),
|
132 |
+
'show_args' => array(),
|
133 |
), $args );
|
134 |
|
135 |
+
foreach ( $this->trace as & $frame ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
if ( ! isset( $frame['args'] ) ) {
|
137 |
continue;
|
138 |
}
|
149 |
} else {
|
150 |
unset( $frame['args'] );
|
151 |
}
|
|
|
|
|
152 |
}
|
153 |
}
|
154 |
|
155 |
+
/**
|
156 |
+
* @return array<int, string>
|
157 |
+
*/
|
158 |
public function get_stack() {
|
159 |
|
160 |
$trace = $this->get_filtered_trace();
|
164 |
|
165 |
}
|
166 |
|
167 |
+
/**
|
168 |
+
* @return mixed[]
|
169 |
+
*/
|
170 |
public function get_caller() {
|
171 |
|
172 |
$trace = $this->get_filtered_trace();
|
175 |
|
176 |
}
|
177 |
|
178 |
+
/**
|
179 |
+
* @return stdClass
|
180 |
+
*/
|
181 |
public function get_component() {
|
182 |
+
if ( isset( $this->component ) ) {
|
183 |
+
return $this->component;
|
184 |
+
}
|
185 |
|
186 |
$components = array();
|
187 |
|
188 |
+
foreach ( $this->get_filtered_trace() as $frame ) {
|
189 |
$component = self::get_frame_component( $frame );
|
190 |
|
191 |
if ( $component ) {
|
192 |
if ( 'plugin' === $component->type ) {
|
193 |
// If the component is a plugin then it can't be anything else,
|
194 |
// so short-circuit and return early.
|
195 |
+
$this->component = $component;
|
196 |
+
return $this->component;
|
197 |
}
|
198 |
|
199 |
$components[ $component->type ] = $component;
|
202 |
|
203 |
foreach ( QM_Util::get_file_dirs() as $type => $dir ) {
|
204 |
if ( isset( $components[ $type ] ) ) {
|
205 |
+
$this->component = $components[ $type ];
|
206 |
+
return $this->component;
|
207 |
}
|
208 |
}
|
209 |
|
210 |
+
return (object) array(
|
211 |
+
'type' => 'unknown',
|
212 |
+
'name' => __( 'Unknown', 'query-monitor' ),
|
213 |
+
'context' => 'unknown',
|
214 |
+
);
|
215 |
}
|
216 |
|
217 |
+
/**
|
218 |
+
* Attempts to determine the component responsible for a given frame.
|
219 |
+
*
|
220 |
+
* @param mixed[] $frame A single frame from a trace.
|
221 |
+
* @return stdClass|null A stdClass object (ouch) representing the component, or null if
|
222 |
+
* the component cannot be determined.
|
223 |
+
*/
|
224 |
public static function get_frame_component( array $frame ) {
|
225 |
+
try {
|
226 |
|
227 |
+
if ( isset( $frame['class'] ) ) {
|
228 |
+
if ( ! class_exists( $frame['class'], false ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
return null;
|
230 |
}
|
231 |
+
if ( ! method_exists( $frame['class'], $frame['function'] ) ) {
|
232 |
+
return null;
|
233 |
+
}
|
234 |
+
$ref = new ReflectionMethod( $frame['class'], $frame['function'] );
|
235 |
+
$file = $ref->getFileName();
|
236 |
+
} elseif ( isset( $frame['function'] ) && function_exists( $frame['function'] ) ) {
|
237 |
+
$ref = new ReflectionFunction( $frame['function'] );
|
238 |
+
$file = $ref->getFileName();
|
239 |
+
} elseif ( isset( $frame['file'] ) ) {
|
240 |
+
$file = $frame['file'];
|
241 |
+
} else {
|
242 |
return null;
|
243 |
}
|
244 |
+
|
245 |
+
return QM_Util::get_file_component( $file );
|
246 |
+
|
247 |
+
} catch ( ReflectionException $e ) {
|
248 |
+
return null;
|
249 |
+
}
|
250 |
}
|
251 |
|
252 |
+
/**
|
253 |
+
* @return mixed[]
|
254 |
+
*/
|
255 |
public function get_trace() {
|
256 |
return $this->trace;
|
257 |
}
|
258 |
|
259 |
+
/**
|
260 |
+
* @deprecated Use the `::get_filtered_trace()` method instead.
|
261 |
+
*
|
262 |
+
* @return mixed[]
|
263 |
+
*/
|
264 |
public function get_display_trace() {
|
265 |
return $this->get_filtered_trace();
|
266 |
}
|
267 |
|
268 |
+
/**
|
269 |
+
* @return mixed[]
|
270 |
+
*/
|
271 |
public function get_filtered_trace() {
|
272 |
|
273 |
if ( ! isset( $this->filtered_trace ) ) {
|
276 |
$trace = array_values( array_filter( $trace ) );
|
277 |
|
278 |
if ( empty( $trace ) && ! empty( $this->trace ) ) {
|
279 |
+
$lowest = $this->trace[0];
|
280 |
+
$file = QM_Util::standard_dir( $lowest['file'], '' );
|
281 |
$lowest['calling_file'] = $lowest['file'];
|
282 |
$lowest['calling_line'] = $lowest['line'];
|
283 |
+
$lowest['function'] = $file;
|
284 |
+
$lowest['display'] = $file;
|
285 |
+
$lowest['id'] = $file;
|
286 |
unset( $lowest['class'], $lowest['args'], $lowest['type'] );
|
287 |
$trace[0] = $lowest;
|
288 |
}
|
295 |
|
296 |
}
|
297 |
|
298 |
+
/**
|
299 |
+
* @param array<int, string> $stack
|
300 |
+
* @return array<int, string>
|
301 |
+
*/
|
302 |
+
public static function get_filtered_stack( array $stack ) {
|
303 |
+
$trace = new self( array(), array() );
|
304 |
+
$return = array();
|
305 |
+
|
306 |
+
foreach ( $stack as $i => $item ) {
|
307 |
+
$frame = array(
|
308 |
+
'function' => $item,
|
309 |
+
);
|
310 |
+
|
311 |
+
if ( false !== strpos( $item, '->' ) ) {
|
312 |
+
list( $class, $function ) = explode( '->', $item );
|
313 |
+
$frame = array(
|
314 |
+
'class' => $class,
|
315 |
+
'type' => '->',
|
316 |
+
'function' => $function,
|
317 |
+
);
|
318 |
+
}
|
319 |
+
|
320 |
+
if ( false !== strpos( $item, '::' ) ) {
|
321 |
+
list( $class, $function ) = explode( '::', $item );
|
322 |
+
$frame = array(
|
323 |
+
'class' => $class,
|
324 |
+
'type' => '::',
|
325 |
+
'function' => $function,
|
326 |
+
);
|
327 |
+
}
|
328 |
+
|
329 |
+
$frame['args'] = array();
|
330 |
+
|
331 |
+
if ( $trace->filter_trace( $frame ) ) {
|
332 |
+
$return[] = $item;
|
333 |
+
}
|
334 |
+
}
|
335 |
+
|
336 |
+
return $return;
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* @deprecated Use the `ignore_class`, `ignore_method`, `ignore_func`, and `ignore_hook` arguments instead.
|
341 |
+
*
|
342 |
+
* @param int $num
|
343 |
+
* @return self
|
344 |
+
*/
|
345 |
public function ignore( $num ) {
|
346 |
for ( $i = 0; $i < $num; $i++ ) {
|
347 |
unset( $this->trace[ $i ] );
|
350 |
return $this;
|
351 |
}
|
352 |
|
353 |
+
/**
|
354 |
+
* @param mixed[] $frame
|
355 |
+
* @return mixed[]|null
|
356 |
+
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
357 |
public function filter_trace( array $frame ) {
|
358 |
|
359 |
if ( ! self::$filtered && function_exists( 'did_action' ) && did_action( 'plugins_loaded' ) ) {
|
366 |
* @param bool[] $ignore_class Array of class names to ignore. The array keys are class names to ignore,
|
367 |
* the array values are whether to ignore the class or not (usually true).
|
368 |
*/
|
369 |
+
self::$ignore_class = apply_filters( 'qm/trace/ignore_class', self::$ignore_class );
|
370 |
|
371 |
/**
|
372 |
* Filters which class methods to ignore when constructing user-facing call stacks.
|
386 |
* @param bool[] $ignore_func Array of function names to ignore. The array keys are function names to ignore,
|
387 |
* the array values are whether to ignore the function or not (usually true).
|
388 |
*/
|
389 |
+
self::$ignore_func = apply_filters( 'qm/trace/ignore_func', self::$ignore_func );
|
390 |
+
|
391 |
+
/**
|
392 |
+
* Filters which action and filter names to ignore when constructing user-facing call stacks.
|
393 |
+
*
|
394 |
+
* @since x.x.x
|
395 |
+
*
|
396 |
+
* @param bool[] $ignore_hook Array of hook names to ignore. The array keys are hook names to ignore,
|
397 |
+
* the array values are whether to ignore the hook or not (usually true).
|
398 |
+
*/
|
399 |
+
self::$ignore_hook = apply_filters( 'qm/trace/ignore_hook', self::$ignore_hook );
|
400 |
|
401 |
/**
|
402 |
* Filters the number of argument values to show for the given function name when constructing user-facing
|
408 |
* array keys are function names, the array values are either integers or
|
409 |
* "dir" to specifically treat the function argument as a directory path.
|
410 |
*/
|
411 |
+
self::$show_args = apply_filters( 'qm/trace/show_args', self::$show_args );
|
412 |
|
413 |
self::$filtered = true;
|
414 |
|
415 |
}
|
416 |
|
417 |
$return = $frame;
|
418 |
+
$ignore_class = array_filter( array_merge( self::$ignore_class, $this->args['ignore_class'] ) );
|
419 |
+
$ignore_method = array_filter( array_merge( self::$ignore_method, $this->args['ignore_method'] ) );
|
420 |
+
$ignore_func = array_filter( array_merge( self::$ignore_func, $this->args['ignore_func'] ) );
|
421 |
+
$ignore_hook = array_filter( array_merge( self::$ignore_hook, $this->args['ignore_hook'] ) );
|
422 |
+
$show_args = array_merge( self::$show_args, $this->args['show_args'] );
|
423 |
+
|
424 |
+
$hook_functions = array(
|
425 |
+
'apply_filters' => true,
|
426 |
+
'do_action' => true,
|
427 |
+
'apply_filters_ref_array' => true,
|
428 |
+
'do_action_ref_array' => true,
|
429 |
+
'apply_filters_deprecated' => true,
|
430 |
+
'do_action_deprecated' => true,
|
431 |
+
);
|
432 |
|
433 |
if ( isset( $frame['class'] ) ) {
|
434 |
+
if ( isset( $ignore_class[ $frame['class'] ] ) ) {
|
435 |
$return = null;
|
436 |
+
} elseif ( isset( $ignore_method[ $frame['class'] ][ $frame['function'] ] ) ) {
|
437 |
$return = null;
|
438 |
} elseif ( 0 === strpos( $frame['class'], 'QM' ) ) {
|
439 |
$return = null;
|
440 |
} else {
|
441 |
+
$return['id'] = $frame['class'] . $frame['type'] . $frame['function'] . '()';
|
442 |
$return['display'] = QM_Util::shorten_fqn( $frame['class'] . $frame['type'] . $frame['function'] ) . '()';
|
443 |
}
|
444 |
} else {
|
445 |
+
if ( isset( $ignore_func[ $frame['function'] ] ) ) {
|
446 |
$return = null;
|
447 |
+
} elseif ( isset( $show_args[ $frame['function'] ] ) ) {
|
448 |
+
$show = $show_args[ $frame['function'] ];
|
449 |
|
450 |
if ( 'dir' === $show ) {
|
451 |
if ( isset( $frame['args'][0] ) ) {
|
452 |
$arg = QM_Util::standard_dir( $frame['args'][0], '' );
|
453 |
+
$return['id'] = $frame['function'] . '()';
|
454 |
$return['display'] = QM_Util::shorten_fqn( $frame['function'] ) . "('{$arg}')";
|
455 |
}
|
456 |
} else {
|
457 |
+
if ( isset( $hook_functions[ $frame['function'] ] ) && isset( $frame['args'][0] ) && is_string( $frame['args'][0] ) && isset( $ignore_hook[ $frame['args'][0] ] ) ) {
|
458 |
+
$return = null;
|
459 |
+
} else {
|
460 |
+
$args = array();
|
461 |
+
for ( $i = 0; $i < $show; $i++ ) {
|
462 |
+
if ( isset( $frame['args'][ $i ] ) ) {
|
463 |
+
if ( is_string( $frame['args'][ $i ] ) ) {
|
464 |
+
$args[] = '\'' . $frame['args'][ $i ] . '\'';
|
465 |
+
} else {
|
466 |
+
$args[] = QM_Util::display_variable( $frame['args'][ $i ] );
|
467 |
+
}
|
468 |
}
|
469 |
}
|
470 |
+
$return['id'] = $frame['function'] . '()';
|
471 |
+
$return['display'] = QM_Util::shorten_fqn( $frame['function'] ) . '(' . implode( ',', $args ) . ')';
|
472 |
}
|
|
|
|
|
473 |
}
|
474 |
} else {
|
475 |
+
$return['id'] = $frame['function'] . '()';
|
476 |
$return['display'] = QM_Util::shorten_fqn( $frame['function'] ) . '()';
|
477 |
}
|
478 |
}
|
classes/CLI.php
CHANGED
@@ -7,6 +7,9 @@
|
|
7 |
|
8 |
class QM_CLI extends QM_Plugin {
|
9 |
|
|
|
|
|
|
|
10 |
protected function __construct( $file ) {
|
11 |
|
12 |
# Register command
|
@@ -19,6 +22,8 @@ class QM_CLI extends QM_Plugin {
|
|
19 |
|
20 |
/**
|
21 |
* Enable QM by creating the symlink for db.php
|
|
|
|
|
22 |
*/
|
23 |
public function enable() {
|
24 |
$drop_in = WP_CONTENT_DIR . '/db.php';
|
@@ -28,7 +33,7 @@ class QM_CLI extends QM_Plugin {
|
|
28 |
WP_CLI::success( "Query Monitor's wp-content/db.php is already in place" );
|
29 |
exit( 0 );
|
30 |
} else {
|
31 |
-
WP_CLI::error( 'Unknown wp-content/db.php
|
32 |
}
|
33 |
}
|
34 |
|
@@ -49,6 +54,10 @@ class QM_CLI extends QM_Plugin {
|
|
49 |
}
|
50 |
}
|
51 |
|
|
|
|
|
|
|
|
|
52 |
public static function init( $file = null ) {
|
53 |
|
54 |
static $instance = null;
|
7 |
|
8 |
class QM_CLI extends QM_Plugin {
|
9 |
|
10 |
+
/**
|
11 |
+
* @param string $file
|
12 |
+
*/
|
13 |
protected function __construct( $file ) {
|
14 |
|
15 |
# Register command
|
22 |
|
23 |
/**
|
24 |
* Enable QM by creating the symlink for db.php
|
25 |
+
*
|
26 |
+
* @return void
|
27 |
*/
|
28 |
public function enable() {
|
29 |
$drop_in = WP_CONTENT_DIR . '/db.php';
|
33 |
WP_CLI::success( "Query Monitor's wp-content/db.php is already in place" );
|
34 |
exit( 0 );
|
35 |
} else {
|
36 |
+
WP_CLI::error( 'Unknown wp-content/db.php is already in place' );
|
37 |
}
|
38 |
}
|
39 |
|
54 |
}
|
55 |
}
|
56 |
|
57 |
+
/**
|
58 |
+
* @param string $file
|
59 |
+
* @return self
|
60 |
+
*/
|
61 |
public static function init( $file = null ) {
|
62 |
|
63 |
static $instance = null;
|
classes/Collector.php
CHANGED
@@ -8,24 +8,67 @@
|
|
8 |
if ( ! class_exists( 'QM_Collector' ) ) {
|
9 |
abstract class QM_Collector {
|
10 |
|
|
|
|
|
|
|
11 |
protected $timer;
|
|
|
|
|
|
|
|
|
12 |
protected $data = array(
|
13 |
-
'types'
|
14 |
'component_times' => array(),
|
15 |
);
|
|
|
|
|
|
|
|
|
16 |
protected static $hide_qm = null;
|
17 |
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
public $concerned_constants = array();
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
public function __construct() {}
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
final public function id() {
|
26 |
return "qm-{$this->id}";
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
29 |
protected function log_type( $type ) {
|
30 |
|
31 |
if ( isset( $this->data['types'][ $type ] ) ) {
|
@@ -36,6 +79,11 @@ abstract class QM_Collector {
|
|
36 |
|
37 |
}
|
38 |
|
|
|
|
|
|
|
|
|
|
|
39 |
protected function maybe_log_dupe( $sql, $i ) {
|
40 |
|
41 |
$sql = str_replace( array( "\r\n", "\r", "\n" ), ' ', $sql );
|
@@ -48,13 +96,19 @@ abstract class QM_Collector {
|
|
48 |
|
49 |
}
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
protected function log_component( $component, $ltime, $type ) {
|
52 |
|
53 |
if ( ! isset( $this->data['component_times'][ $component->name ] ) ) {
|
54 |
$this->data['component_times'][ $component->name ] = array(
|
55 |
'component' => $component->name,
|
56 |
-
'ltime'
|
57 |
-
'types'
|
58 |
);
|
59 |
}
|
60 |
|
@@ -68,11 +122,18 @@ abstract class QM_Collector {
|
|
68 |
|
69 |
}
|
70 |
|
|
|
|
|
|
|
71 |
public static function timer_stop_float() {
|
72 |
global $timestart;
|
73 |
return microtime( true ) - $timestart;
|
74 |
}
|
75 |
|
|
|
|
|
|
|
|
|
76 |
public static function format_bool_constant( $constant ) {
|
77 |
// @TODO this should be in QM_Util
|
78 |
|
@@ -88,19 +149,36 @@ abstract class QM_Collector {
|
|
88 |
}
|
89 |
}
|
90 |
|
|
|
|
|
|
|
91 |
final public function get_data() {
|
92 |
return $this->data;
|
93 |
}
|
94 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
final public function set_id( $id ) {
|
96 |
$this->id = $id;
|
97 |
}
|
98 |
|
|
|
|
|
|
|
99 |
final public function process_concerns() {
|
100 |
global $wp_filter;
|
101 |
|
102 |
$tracked = array();
|
103 |
-
$id
|
104 |
|
105 |
/**
|
106 |
* Filters the concerned actions for the given panel.
|
@@ -152,14 +230,14 @@ abstract class QM_Collector {
|
|
152 |
|
153 |
foreach ( $concerned_actions as $action ) {
|
154 |
if ( has_action( $action ) ) {
|
155 |
-
$this->concerned_actions[ $action ] = QM_Hook::process( $action, $wp_filter, true,
|
156 |
}
|
157 |
$tracked[] = $action;
|
158 |
}
|
159 |
|
160 |
foreach ( $concerned_filters as $filter ) {
|
161 |
if ( has_filter( $filter ) ) {
|
162 |
-
$this->concerned_filters[ $filter ] = QM_Hook::process( $filter, $wp_filter, true,
|
163 |
}
|
164 |
$tracked[] = $filter;
|
165 |
}
|
@@ -181,7 +259,7 @@ abstract class QM_Collector {
|
|
181 |
$option
|
182 |
);
|
183 |
if ( has_filter( $filter ) ) {
|
184 |
-
$this->concerned_filters[ $filter ] = QM_Hook::process( $filter, $wp_filter, true,
|
185 |
}
|
186 |
$tracked[] = $filter;
|
187 |
}
|
@@ -201,10 +279,18 @@ abstract class QM_Collector {
|
|
201 |
$this->tracked_hooks = $tracked;
|
202 |
}
|
203 |
|
|
|
|
|
|
|
|
|
204 |
public function filter_concerns( $concerns ) {
|
205 |
return ! empty( $concerns['actions'] );
|
206 |
}
|
207 |
|
|
|
|
|
|
|
|
|
208 |
public static function format_user( WP_User $user_object ) {
|
209 |
$user = get_object_vars( $user_object->data );
|
210 |
unset(
|
@@ -216,10 +302,16 @@ abstract class QM_Collector {
|
|
216 |
return $user;
|
217 |
}
|
218 |
|
|
|
|
|
|
|
219 |
public static function enabled() {
|
220 |
return true;
|
221 |
}
|
222 |
|
|
|
|
|
|
|
223 |
public static function hide_qm() {
|
224 |
if ( ! defined( 'QM_HIDE_SELF' ) ) {
|
225 |
return false;
|
@@ -232,41 +324,76 @@ abstract class QM_Collector {
|
|
232 |
return self::$hide_qm;
|
233 |
}
|
234 |
|
|
|
|
|
|
|
|
|
235 |
public function filter_remove_qm( array $item ) {
|
236 |
-
|
237 |
-
return ( 'query-monitor' !== $component->context );
|
238 |
}
|
239 |
|
|
|
|
|
|
|
|
|
240 |
public function filter_dupe_items( $items ) {
|
241 |
return ( count( $items ) > 1 );
|
242 |
}
|
243 |
|
|
|
|
|
|
|
244 |
public function process() {}
|
245 |
|
|
|
|
|
|
|
246 |
public function post_process() {}
|
247 |
|
|
|
|
|
|
|
248 |
public function tear_down() {}
|
249 |
|
|
|
|
|
|
|
250 |
public function get_timer() {
|
251 |
return $this->timer;
|
252 |
}
|
253 |
|
|
|
|
|
|
|
|
|
254 |
public function set_timer( QM_Timer $timer ) {
|
255 |
$this->timer = $timer;
|
256 |
}
|
257 |
|
|
|
|
|
|
|
258 |
public function get_concerned_actions() {
|
259 |
return array();
|
260 |
}
|
261 |
|
|
|
|
|
|
|
262 |
public function get_concerned_filters() {
|
263 |
return array();
|
264 |
}
|
265 |
|
|
|
|
|
|
|
266 |
public function get_concerned_options() {
|
267 |
return array();
|
268 |
}
|
269 |
|
|
|
|
|
|
|
270 |
public function get_concerned_constants() {
|
271 |
return array();
|
272 |
}
|
8 |
if ( ! class_exists( 'QM_Collector' ) ) {
|
9 |
abstract class QM_Collector {
|
10 |
|
11 |
+
/**
|
12 |
+
* @var QM_Timer|null
|
13 |
+
*/
|
14 |
protected $timer;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var array<string, mixed>
|
18 |
+
*/
|
19 |
protected $data = array(
|
20 |
+
'types' => array(),
|
21 |
'component_times' => array(),
|
22 |
);
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var bool|null
|
26 |
+
*/
|
27 |
protected static $hide_qm = null;
|
28 |
|
29 |
+
/**
|
30 |
+
* @var array<string, array<string, mixed>>
|
31 |
+
*/
|
32 |
+
public $concerned_actions = array();
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @var array<string, array<string, mixed>>
|
36 |
+
*/
|
37 |
+
public $concerned_filters = array();
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var array<string, array<string, mixed>>
|
41 |
+
*/
|
42 |
public $concerned_constants = array();
|
43 |
+
|
44 |
+
/**
|
45 |
+
* @var array<int, string>
|
46 |
+
*/
|
47 |
+
public $tracked_hooks = array();
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @var string
|
51 |
+
*/
|
52 |
+
public $id = '';
|
53 |
|
54 |
public function __construct() {}
|
55 |
|
56 |
+
/**
|
57 |
+
* @return void
|
58 |
+
*/
|
59 |
+
public function set_up() {}
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @return string
|
63 |
+
*/
|
64 |
final public function id() {
|
65 |
return "qm-{$this->id}";
|
66 |
}
|
67 |
|
68 |
+
/**
|
69 |
+
* @param string $type
|
70 |
+
* @return void
|
71 |
+
*/
|
72 |
protected function log_type( $type ) {
|
73 |
|
74 |
if ( isset( $this->data['types'][ $type ] ) ) {
|
79 |
|
80 |
}
|
81 |
|
82 |
+
/**
|
83 |
+
* @param string $sql
|
84 |
+
* @param int $i
|
85 |
+
* @return void
|
86 |
+
*/
|
87 |
protected function maybe_log_dupe( $sql, $i ) {
|
88 |
|
89 |
$sql = str_replace( array( "\r\n", "\r", "\n" ), ' ', $sql );
|
96 |
|
97 |
}
|
98 |
|
99 |
+
/**
|
100 |
+
* @param stdClass $component
|
101 |
+
* @param float $ltime
|
102 |
+
* @param string $type
|
103 |
+
* @return void
|
104 |
+
*/
|
105 |
protected function log_component( $component, $ltime, $type ) {
|
106 |
|
107 |
if ( ! isset( $this->data['component_times'][ $component->name ] ) ) {
|
108 |
$this->data['component_times'][ $component->name ] = array(
|
109 |
'component' => $component->name,
|
110 |
+
'ltime' => 0,
|
111 |
+
'types' => array(),
|
112 |
);
|
113 |
}
|
114 |
|
122 |
|
123 |
}
|
124 |
|
125 |
+
/**
|
126 |
+
* @return float
|
127 |
+
*/
|
128 |
public static function timer_stop_float() {
|
129 |
global $timestart;
|
130 |
return microtime( true ) - $timestart;
|
131 |
}
|
132 |
|
133 |
+
/**
|
134 |
+
* @param string $constant
|
135 |
+
* @return string
|
136 |
+
*/
|
137 |
public static function format_bool_constant( $constant ) {
|
138 |
// @TODO this should be in QM_Util
|
139 |
|
149 |
}
|
150 |
}
|
151 |
|
152 |
+
/**
|
153 |
+
* @return array<string, mixed>
|
154 |
+
*/
|
155 |
final public function get_data() {
|
156 |
return $this->data;
|
157 |
}
|
158 |
|
159 |
+
/**
|
160 |
+
* @return void
|
161 |
+
*/
|
162 |
+
final public function discard_data() {
|
163 |
+
$this->data = array();
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @param string $id
|
168 |
+
* @return void
|
169 |
+
*/
|
170 |
final public function set_id( $id ) {
|
171 |
$this->id = $id;
|
172 |
}
|
173 |
|
174 |
+
/**
|
175 |
+
* @return void
|
176 |
+
*/
|
177 |
final public function process_concerns() {
|
178 |
global $wp_filter;
|
179 |
|
180 |
$tracked = array();
|
181 |
+
$id = $this->id;
|
182 |
|
183 |
/**
|
184 |
* Filters the concerned actions for the given panel.
|
230 |
|
231 |
foreach ( $concerned_actions as $action ) {
|
232 |
if ( has_action( $action ) ) {
|
233 |
+
$this->concerned_actions[ $action ] = QM_Hook::process( $action, $wp_filter, true, false );
|
234 |
}
|
235 |
$tracked[] = $action;
|
236 |
}
|
237 |
|
238 |
foreach ( $concerned_filters as $filter ) {
|
239 |
if ( has_filter( $filter ) ) {
|
240 |
+
$this->concerned_filters[ $filter ] = QM_Hook::process( $filter, $wp_filter, true, false );
|
241 |
}
|
242 |
$tracked[] = $filter;
|
243 |
}
|
259 |
$option
|
260 |
);
|
261 |
if ( has_filter( $filter ) ) {
|
262 |
+
$this->concerned_filters[ $filter ] = QM_Hook::process( $filter, $wp_filter, true, false );
|
263 |
}
|
264 |
$tracked[] = $filter;
|
265 |
}
|
279 |
$this->tracked_hooks = $tracked;
|
280 |
}
|
281 |
|
282 |
+
/**
|
283 |
+
* @param array<string, mixed> $concerns
|
284 |
+
* @return bool
|
285 |
+
*/
|
286 |
public function filter_concerns( $concerns ) {
|
287 |
return ! empty( $concerns['actions'] );
|
288 |
}
|
289 |
|
290 |
+
/**
|
291 |
+
* @param WP_User $user_object
|
292 |
+
* @return array<string, mixed>
|
293 |
+
*/
|
294 |
public static function format_user( WP_User $user_object ) {
|
295 |
$user = get_object_vars( $user_object->data );
|
296 |
unset(
|
302 |
return $user;
|
303 |
}
|
304 |
|
305 |
+
/**
|
306 |
+
* @return bool
|
307 |
+
*/
|
308 |
public static function enabled() {
|
309 |
return true;
|
310 |
}
|
311 |
|
312 |
+
/**
|
313 |
+
* @return bool
|
314 |
+
*/
|
315 |
public static function hide_qm() {
|
316 |
if ( ! defined( 'QM_HIDE_SELF' ) ) {
|
317 |
return false;
|
324 |
return self::$hide_qm;
|
325 |
}
|
326 |
|
327 |
+
/**
|
328 |
+
* @param array<string, mixed> $item
|
329 |
+
* @return bool
|
330 |
+
*/
|
331 |
public function filter_remove_qm( array $item ) {
|
332 |
+
return ( 'query-monitor' !== $item['component']->context );
|
|
|
333 |
}
|
334 |
|
335 |
+
/**
|
336 |
+
* @param mixed[] $items
|
337 |
+
* @return bool
|
338 |
+
*/
|
339 |
public function filter_dupe_items( $items ) {
|
340 |
return ( count( $items ) > 1 );
|
341 |
}
|
342 |
|
343 |
+
/**
|
344 |
+
* @return void
|
345 |
+
*/
|
346 |
public function process() {}
|
347 |
|
348 |
+
/**
|
349 |
+
* @return void
|
350 |
+
*/
|
351 |
public function post_process() {}
|
352 |
|
353 |
+
/**
|
354 |
+
* @return void
|
355 |
+
*/
|
356 |
public function tear_down() {}
|
357 |
|
358 |
+
/**
|
359 |
+
* @return QM_Timer|null
|
360 |
+
*/
|
361 |
public function get_timer() {
|
362 |
return $this->timer;
|
363 |
}
|
364 |
|
365 |
+
/**
|
366 |
+
* @param QM_Timer $timer
|
367 |
+
* @return void
|
368 |
+
*/
|
369 |
public function set_timer( QM_Timer $timer ) {
|
370 |
$this->timer = $timer;
|
371 |
}
|
372 |
|
373 |
+
/**
|
374 |
+
* @return array<int, string>
|
375 |
+
*/
|
376 |
public function get_concerned_actions() {
|
377 |
return array();
|
378 |
}
|
379 |
|
380 |
+
/**
|
381 |
+
* @return array<int, string>
|
382 |
+
*/
|
383 |
public function get_concerned_filters() {
|
384 |
return array();
|
385 |
}
|
386 |
|
387 |
+
/**
|
388 |
+
* @return array<int, string>
|
389 |
+
*/
|
390 |
public function get_concerned_options() {
|
391 |
return array();
|
392 |
}
|
393 |
|
394 |
+
/**
|
395 |
+
* @return array<int, string>
|
396 |
+
*/
|
397 |
public function get_concerned_constants() {
|
398 |
return array();
|
399 |
}
|
classes/Collectors.php
CHANGED
@@ -6,18 +6,37 @@
|
|
6 |
*/
|
7 |
|
8 |
if ( ! class_exists( 'QM_Collectors' ) ) {
|
|
|
|
|
|
|
9 |
class QM_Collectors implements IteratorAggregate {
|
10 |
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
private $processed = false;
|
13 |
|
|
|
|
|
|
|
14 |
public function getIterator() {
|
15 |
return new ArrayIterator( $this->items );
|
16 |
}
|
17 |
|
|
|
|
|
|
|
|
|
18 |
public static function add( QM_Collector $collector ) {
|
19 |
$collectors = self::init();
|
20 |
|
|
|
|
|
21 |
$collectors->items[ $collector->id ] = $collector;
|
22 |
}
|
23 |
|
@@ -35,6 +54,9 @@ class QM_Collectors implements IteratorAggregate {
|
|
35 |
return null;
|
36 |
}
|
37 |
|
|
|
|
|
|
|
38 |
public static function init() {
|
39 |
static $instance;
|
40 |
|
@@ -46,6 +68,9 @@ class QM_Collectors implements IteratorAggregate {
|
|
46 |
|
47 |
}
|
48 |
|
|
|
|
|
|
|
49 |
public function process() {
|
50 |
if ( $this->processed ) {
|
51 |
return;
|
@@ -70,5 +95,19 @@ class QM_Collectors implements IteratorAggregate {
|
|
70 |
$this->processed = true;
|
71 |
}
|
72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
}
|
74 |
}
|
6 |
*/
|
7 |
|
8 |
if ( ! class_exists( 'QM_Collectors' ) ) {
|
9 |
+
/**
|
10 |
+
* @implements \IteratorAggregate<string, QM_Collector>
|
11 |
+
*/
|
12 |
class QM_Collectors implements IteratorAggregate {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var array<string, QM_Collector>
|
16 |
+
*/
|
17 |
+
private $items = array();
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var boolean
|
21 |
+
*/
|
22 |
private $processed = false;
|
23 |
|
24 |
+
/**
|
25 |
+
* @return ArrayIterator<string, QM_Collector>
|
26 |
+
*/
|
27 |
public function getIterator() {
|
28 |
return new ArrayIterator( $this->items );
|
29 |
}
|
30 |
|
31 |
+
/**
|
32 |
+
* @param QM_Collector $collector
|
33 |
+
* @return void
|
34 |
+
*/
|
35 |
public static function add( QM_Collector $collector ) {
|
36 |
$collectors = self::init();
|
37 |
|
38 |
+
$collector->set_up();
|
39 |
+
|
40 |
$collectors->items[ $collector->id ] = $collector;
|
41 |
}
|
42 |
|
54 |
return null;
|
55 |
}
|
56 |
|
57 |
+
/**
|
58 |
+
* @return self
|
59 |
+
*/
|
60 |
public static function init() {
|
61 |
static $instance;
|
62 |
|
68 |
|
69 |
}
|
70 |
|
71 |
+
/**
|
72 |
+
* @return void
|
73 |
+
*/
|
74 |
public function process() {
|
75 |
if ( $this->processed ) {
|
76 |
return;
|
95 |
$this->processed = true;
|
96 |
}
|
97 |
|
98 |
+
/**
|
99 |
+
* @return void
|
100 |
+
*/
|
101 |
+
public static function cease() {
|
102 |
+
$collectors = self::init();
|
103 |
+
|
104 |
+
$collectors->processed = true;
|
105 |
+
|
106 |
+
/** @var QM_Collector $collector */
|
107 |
+
foreach ( $collectors as $collector ) {
|
108 |
+
$collector->tear_down();
|
109 |
+
$collector->discard_data();
|
110 |
+
}
|
111 |
+
}
|
112 |
}
|
113 |
}
|
classes/Dispatcher.php
CHANGED
@@ -11,7 +11,7 @@ abstract class QM_Dispatcher {
|
|
11 |
/**
|
12 |
* Outputter instances.
|
13 |
*
|
14 |
-
* @var QM_Output
|
15 |
*/
|
16 |
protected $outputters = array();
|
17 |
|
@@ -22,6 +22,16 @@ abstract class QM_Dispatcher {
|
|
22 |
*/
|
23 |
protected $qm;
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
public function __construct( QM_Plugin $qm ) {
|
26 |
$this->qm = $qm;
|
27 |
|
@@ -36,8 +46,14 @@ abstract class QM_Dispatcher {
|
|
36 |
|
37 |
}
|
38 |
|
|
|
|
|
|
|
39 |
abstract public function is_active();
|
40 |
|
|
|
|
|
|
|
41 |
final public function should_dispatch() {
|
42 |
|
43 |
$e = error_get_last();
|
@@ -72,6 +88,15 @@ abstract class QM_Dispatcher {
|
|
72 |
|
73 |
}
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
/**
|
76 |
* Processes and fetches the outputters for this dispatcher.
|
77 |
*
|
@@ -89,16 +114,20 @@ abstract class QM_Dispatcher {
|
|
89 |
*
|
90 |
* @since 2.8.0
|
91 |
*
|
92 |
-
* @param QM_Output
|
93 |
-
* @param QM_Collectors
|
94 |
*/
|
95 |
$this->outputters = apply_filters( "qm/outputter/{$outputter_id}", array(), $collectors );
|
96 |
|
97 |
return $this->outputters;
|
98 |
}
|
99 |
|
|
|
|
|
|
|
100 |
public function init() {
|
101 |
if ( ! self::user_can_view() ) {
|
|
|
102 |
return;
|
103 |
}
|
104 |
|
@@ -109,14 +138,21 @@ abstract class QM_Dispatcher {
|
|
109 |
add_action( 'send_headers', 'nocache_headers' );
|
110 |
}
|
111 |
|
|
|
|
|
|
|
112 |
protected function before_output() {
|
113 |
-
// nothing
|
114 |
}
|
115 |
|
|
|
|
|
|
|
116 |
protected function after_output() {
|
117 |
-
// nothing
|
118 |
}
|
119 |
|
|
|
|
|
|
|
120 |
public static function user_can_view() {
|
121 |
|
122 |
if ( ! did_action( 'plugins_loaded' ) ) {
|
@@ -131,6 +167,9 @@ abstract class QM_Dispatcher {
|
|
131 |
|
132 |
}
|
133 |
|
|
|
|
|
|
|
134 |
public static function user_verified() {
|
135 |
if ( isset( $_COOKIE[QM_COOKIE] ) ) { // phpcs:ignore
|
136 |
return self::verify_cookie( wp_unslash( $_COOKIE[QM_COOKIE] ) ); // phpcs:ignore
|
@@ -138,6 +177,9 @@ abstract class QM_Dispatcher {
|
|
138 |
return false;
|
139 |
}
|
140 |
|
|
|
|
|
|
|
141 |
public static function editor_cookie() {
|
142 |
if ( defined( 'QM_EDITOR_COOKIE' ) && isset( $_COOKIE[QM_EDITOR_COOKIE] ) ) { // phpcs:ignore
|
143 |
return $_COOKIE[QM_EDITOR_COOKIE]; // phpcs:ignore
|
@@ -145,6 +187,10 @@ abstract class QM_Dispatcher {
|
|
145 |
return '';
|
146 |
}
|
147 |
|
|
|
|
|
|
|
|
|
148 |
public static function verify_cookie( $value ) {
|
149 |
$old_user_id = wp_validate_auth_cookie( $value, 'logged_in' );
|
150 |
if ( $old_user_id ) {
|
@@ -153,5 +199,41 @@ abstract class QM_Dispatcher {
|
|
153 |
return false;
|
154 |
}
|
155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
}
|
157 |
}
|
11 |
/**
|
12 |
* Outputter instances.
|
13 |
*
|
14 |
+
* @var array<string, QM_Output> Array of outputters.
|
15 |
*/
|
16 |
protected $outputters = array();
|
17 |
|
22 |
*/
|
23 |
protected $qm;
|
24 |
|
25 |
+
/**
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
public $id = '';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @var bool
|
32 |
+
*/
|
33 |
+
protected $ceased = false;
|
34 |
+
|
35 |
public function __construct( QM_Plugin $qm ) {
|
36 |
$this->qm = $qm;
|
37 |
|
46 |
|
47 |
}
|
48 |
|
49 |
+
/**
|
50 |
+
* @return bool
|
51 |
+
*/
|
52 |
abstract public function is_active();
|
53 |
|
54 |
+
/**
|
55 |
+
* @return bool
|
56 |
+
*/
|
57 |
final public function should_dispatch() {
|
58 |
|
59 |
$e = error_get_last();
|
88 |
|
89 |
}
|
90 |
|
91 |
+
/**
|
92 |
+
* @return void
|
93 |
+
*/
|
94 |
+
public function cease() {
|
95 |
+
$this->ceased = true;
|
96 |
+
|
97 |
+
add_filter( "qm/dispatch/{$this->id}", '__return_false' );
|
98 |
+
}
|
99 |
+
|
100 |
/**
|
101 |
* Processes and fetches the outputters for this dispatcher.
|
102 |
*
|
114 |
*
|
115 |
* @since 2.8.0
|
116 |
*
|
117 |
+
* @param array<string, QM_Output> $outputters Array of outputters.
|
118 |
+
* @param QM_Collectors $collectors List of collectors.
|
119 |
*/
|
120 |
$this->outputters = apply_filters( "qm/outputter/{$outputter_id}", array(), $collectors );
|
121 |
|
122 |
return $this->outputters;
|
123 |
}
|
124 |
|
125 |
+
/**
|
126 |
+
* @return void
|
127 |
+
*/
|
128 |
public function init() {
|
129 |
if ( ! self::user_can_view() ) {
|
130 |
+
do_action( 'qm/cease' );
|
131 |
return;
|
132 |
}
|
133 |
|
138 |
add_action( 'send_headers', 'nocache_headers' );
|
139 |
}
|
140 |
|
141 |
+
/**
|
142 |
+
* @return void
|
143 |
+
*/
|
144 |
protected function before_output() {
|
|
|
145 |
}
|
146 |
|
147 |
+
/**
|
148 |
+
* @return void
|
149 |
+
*/
|
150 |
protected function after_output() {
|
|
|
151 |
}
|
152 |
|
153 |
+
/**
|
154 |
+
* @return bool
|
155 |
+
*/
|
156 |
public static function user_can_view() {
|
157 |
|
158 |
if ( ! did_action( 'plugins_loaded' ) ) {
|
167 |
|
168 |
}
|
169 |
|
170 |
+
/**
|
171 |
+
* @return bool
|
172 |
+
*/
|
173 |
public static function user_verified() {
|
174 |
if ( isset( $_COOKIE[QM_COOKIE] ) ) { // phpcs:ignore
|
175 |
return self::verify_cookie( wp_unslash( $_COOKIE[QM_COOKIE] ) ); // phpcs:ignore
|
177 |
return false;
|
178 |
}
|
179 |
|
180 |
+
/**
|
181 |
+
* @return string
|
182 |
+
*/
|
183 |
public static function editor_cookie() {
|
184 |
if ( defined( 'QM_EDITOR_COOKIE' ) && isset( $_COOKIE[QM_EDITOR_COOKIE] ) ) { // phpcs:ignore
|
185 |
return $_COOKIE[QM_EDITOR_COOKIE]; // phpcs:ignore
|
187 |
return '';
|
188 |
}
|
189 |
|
190 |
+
/**
|
191 |
+
* @param string $value
|
192 |
+
* @return bool
|
193 |
+
*/
|
194 |
public static function verify_cookie( $value ) {
|
195 |
$old_user_id = wp_validate_auth_cookie( $value, 'logged_in' );
|
196 |
if ( $old_user_id ) {
|
199 |
return false;
|
200 |
}
|
201 |
|
202 |
+
/**
|
203 |
+
* Attempts to switch to the given locale.
|
204 |
+
*
|
205 |
+
* This is a wrapper around `switch_to_locale()` which is safe to call at any point, even
|
206 |
+
* before the `$wp_locale_switcher` global is initialised or if the function does not exist.
|
207 |
+
*
|
208 |
+
* @param string $locale The locale.
|
209 |
+
* @return bool True on success, false on failure.
|
210 |
+
*/
|
211 |
+
public static function switch_to_locale( $locale ) {
|
212 |
+
global $wp_locale_switcher;
|
213 |
+
|
214 |
+
if ( function_exists( 'switch_to_locale' ) && ( $wp_locale_switcher instanceof WP_Locale_Switcher ) ) {
|
215 |
+
return switch_to_locale( $locale );
|
216 |
+
}
|
217 |
+
|
218 |
+
return false;
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Attempts to restore the previous locale.
|
223 |
+
*
|
224 |
+
* This is a wrapper around `restore_previous_locale()` which is safe to call at any point, even
|
225 |
+
* before the `$wp_locale_switcher` global is initialised or if the function does not exist.
|
226 |
+
*
|
227 |
+
* @return string|false Locale on success, false on error.
|
228 |
+
*/
|
229 |
+
public static function restore_previous_locale() {
|
230 |
+
global $wp_locale_switcher;
|
231 |
+
|
232 |
+
if ( function_exists( 'restore_previous_locale' ) && ( $wp_locale_switcher instanceof WP_Locale_Switcher ) ) {
|
233 |
+
return restore_previous_locale();
|
234 |
+
}
|
235 |
+
|
236 |
+
return false;
|
237 |
+
}
|
238 |
}
|
239 |
}
|
classes/Dispatchers.php
CHANGED
@@ -5,19 +5,36 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
|
|
|
|
|
|
8 |
class QM_Dispatchers implements IteratorAggregate {
|
9 |
|
|
|
|
|
|
|
10 |
private $items = array();
|
11 |
|
|
|
|
|
|
|
12 |
public function getIterator() {
|
13 |
return new ArrayIterator( $this->items );
|
14 |
}
|
15 |
|
|
|
|
|
|
|
|
|
16 |
public static function add( QM_Dispatcher $dispatcher ) {
|
17 |
-
$dispatchers
|
18 |
$dispatchers->items[ $dispatcher->id ] = $dispatcher;
|
19 |
}
|
20 |
|
|
|
|
|
|
|
|
|
21 |
public static function get( $id ) {
|
22 |
$dispatchers = self::init();
|
23 |
if ( isset( $dispatchers->items[ $id ] ) ) {
|
@@ -26,6 +43,21 @@ class QM_Dispatchers implements IteratorAggregate {
|
|
26 |
return false;
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
public static function init() {
|
30 |
static $instance;
|
31 |
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
/**
|
9 |
+
* @implements \IteratorAggregate<string, QM_Dispatcher>
|
10 |
+
*/
|
11 |
class QM_Dispatchers implements IteratorAggregate {
|
12 |
|
13 |
+
/**
|
14 |
+
* @var array<string, QM_Dispatcher>
|
15 |
+
*/
|
16 |
private $items = array();
|
17 |
|
18 |
+
/**
|
19 |
+
* @return ArrayIterator<string, QM_Dispatcher>
|
20 |
+
*/
|
21 |
public function getIterator() {
|
22 |
return new ArrayIterator( $this->items );
|
23 |
}
|
24 |
|
25 |
+
/**
|
26 |
+
* @param QM_Dispatcher $dispatcher
|
27 |
+
* @return void
|
28 |
+
*/
|
29 |
public static function add( QM_Dispatcher $dispatcher ) {
|
30 |
+
$dispatchers = self::init();
|
31 |
$dispatchers->items[ $dispatcher->id ] = $dispatcher;
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @param string $id
|
36 |
+
* @return QM_Dispatcher|false
|
37 |
+
*/
|
38 |
public static function get( $id ) {
|
39 |
$dispatchers = self::init();
|
40 |
if ( isset( $dispatchers->items[ $id ] ) ) {
|
43 |
return false;
|
44 |
}
|
45 |
|
46 |
+
/**
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
+
public static function cease() {
|
50 |
+
$dispatchers = self::init();
|
51 |
+
|
52 |
+
/** @var QM_Dispatcher $dispatcher */
|
53 |
+
foreach ( $dispatchers as $dispatcher ) {
|
54 |
+
$dispatcher->cease();
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @return self
|
60 |
+
*/
|
61 |
public static function init() {
|
62 |
static $instance;
|
63 |
|
classes/Hook.php
CHANGED
@@ -7,9 +7,16 @@
|
|
7 |
|
8 |
class QM_Hook {
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
public static function process( $name, array $wp_filter, $hide_qm = false, $hide_core = false ) {
|
11 |
|
12 |
-
$actions
|
13 |
$components = array();
|
14 |
|
15 |
if ( isset( $wp_filter[ $name ] ) ) {
|
@@ -49,9 +56,9 @@ class QM_Hook {
|
|
49 |
$parts = array_values( array_filter( preg_split( '#[_/.-]#', $name ) ) );
|
50 |
|
51 |
return array(
|
52 |
-
'name'
|
53 |
-
'actions'
|
54 |
-
'parts'
|
55 |
'components' => $components,
|
56 |
);
|
57 |
|
7 |
|
8 |
class QM_Hook {
|
9 |
|
10 |
+
/**
|
11 |
+
* @param string $name
|
12 |
+
* @param array<string, mixed> $wp_filter
|
13 |
+
* @param bool $hide_qm
|
14 |
+
* @param bool $hide_core
|
15 |
+
* @return mixed[]
|
16 |
+
*/
|
17 |
public static function process( $name, array $wp_filter, $hide_qm = false, $hide_core = false ) {
|
18 |
|
19 |
+
$actions = array();
|
20 |
$components = array();
|
21 |
|
22 |
if ( isset( $wp_filter[ $name ] ) ) {
|
56 |
$parts = array_values( array_filter( preg_split( '#[_/.-]#', $name ) ) );
|
57 |
|
58 |
return array(
|
59 |
+
'name' => $name,
|
60 |
+
'actions' => $actions,
|
61 |
+
'parts' => $parts,
|
62 |
'components' => $components,
|
63 |
);
|
64 |
|
classes/Output.php
CHANGED
@@ -18,7 +18,7 @@ abstract class QM_Output {
|
|
18 |
/**
|
19 |
* Timer instance.
|
20 |
*
|
21 |
-
* @var QM_Timer Timer.
|
22 |
*/
|
23 |
protected $timer;
|
24 |
|
@@ -26,20 +26,36 @@ abstract class QM_Output {
|
|
26 |
$this->collector = $collector;
|
27 |
}
|
28 |
|
|
|
|
|
|
|
29 |
abstract public function get_output();
|
30 |
|
|
|
|
|
|
|
31 |
public function output() {
|
32 |
// nothing
|
33 |
}
|
34 |
|
|
|
|
|
|
|
35 |
public function get_collector() {
|
36 |
return $this->collector;
|
37 |
}
|
38 |
|
|
|
|
|
|
|
39 |
final public function get_timer() {
|
40 |
return $this->timer;
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
43 |
final public function set_timer( QM_Timer $timer ) {
|
44 |
$this->timer = $timer;
|
45 |
}
|
18 |
/**
|
19 |
* Timer instance.
|
20 |
*
|
21 |
+
* @var QM_Timer|null Timer.
|
22 |
*/
|
23 |
protected $timer;
|
24 |
|
26 |
$this->collector = $collector;
|
27 |
}
|
28 |
|
29 |
+
/**
|
30 |
+
* @return mixed
|
31 |
+
*/
|
32 |
abstract public function get_output();
|
33 |
|
34 |
+
/**
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
public function output() {
|
38 |
// nothing
|
39 |
}
|
40 |
|
41 |
+
/**
|
42 |
+
* @return QM_Collector
|
43 |
+
*/
|
44 |
public function get_collector() {
|
45 |
return $this->collector;
|
46 |
}
|
47 |
|
48 |
+
/**
|
49 |
+
* @return QM_Timer|null
|
50 |
+
*/
|
51 |
final public function get_timer() {
|
52 |
return $this->timer;
|
53 |
}
|
54 |
|
55 |
+
/**
|
56 |
+
* @param QM_Timer $timer
|
57 |
+
* @return void
|
58 |
+
*/
|
59 |
final public function set_timer( QM_Timer $timer ) {
|
60 |
$this->timer = $timer;
|
61 |
}
|
classes/Plugin.php
CHANGED
@@ -8,11 +8,25 @@
|
|
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
|
|
|
|
|
16 |
*/
|
17 |
protected function __construct( $file ) {
|
18 |
$this->file = $file;
|
@@ -45,7 +59,7 @@ abstract class QM_Plugin {
|
|
45 |
* @return string Version
|
46 |
*/
|
47 |
final public function plugin_ver( $file ) {
|
48 |
-
return filemtime( $this->plugin_path( $file ) );
|
49 |
}
|
50 |
|
51 |
/**
|
@@ -59,6 +73,10 @@ abstract class QM_Plugin {
|
|
59 |
|
60 |
/**
|
61 |
* Populates and returns the current plugin info.
|
|
|
|
|
|
|
|
|
62 |
*/
|
63 |
private function _plugin( $item, $file = '' ) {
|
64 |
if ( ! array_key_exists( $item, $this->plugin ) ) {
|
@@ -77,6 +95,9 @@ abstract class QM_Plugin {
|
|
77 |
return $this->plugin[ $item ] . ltrim( $file, '/' );
|
78 |
}
|
79 |
|
|
|
|
|
|
|
80 |
public static function php_version_met() {
|
81 |
static $met = null;
|
82 |
|
@@ -87,6 +108,9 @@ abstract class QM_Plugin {
|
|
87 |
return $met;
|
88 |
}
|
89 |
|
|
|
|
|
|
|
90 |
public static function php_version_nope() {
|
91 |
printf(
|
92 |
'<div id="qm-php-nope" class="notice notice-error is-dismissible"><p>%s</p></div>',
|
8 |
if ( ! class_exists( 'QM_Plugin' ) ) {
|
9 |
abstract class QM_Plugin {
|
10 |
|
11 |
+
/**
|
12 |
+
* @var array<string, string>
|
13 |
+
*/
|
14 |
private $plugin = array();
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
public static $minimum_php_version = '5.3.6';
|
20 |
|
21 |
+
/**
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
public $file = '';
|
25 |
+
|
26 |
/**
|
27 |
* Class constructor
|
28 |
+
*
|
29 |
+
* @param string $file
|
30 |
*/
|
31 |
protected function __construct( $file ) {
|
32 |
$this->file = $file;
|
59 |
* @return string Version
|
60 |
*/
|
61 |
final public function plugin_ver( $file ) {
|
62 |
+
return (string) filemtime( $this->plugin_path( $file ) );
|
63 |
}
|
64 |
|
65 |
/**
|
73 |
|
74 |
/**
|
75 |
* Populates and returns the current plugin info.
|
76 |
+
*
|
77 |
+
* @param string $item
|
78 |
+
* @param string $file
|
79 |
+
* @return string
|
80 |
*/
|
81 |
private function _plugin( $item, $file = '' ) {
|
82 |
if ( ! array_key_exists( $item, $this->plugin ) ) {
|
95 |
return $this->plugin[ $item ] . ltrim( $file, '/' );
|
96 |
}
|
97 |
|
98 |
+
/**
|
99 |
+
* @return bool
|
100 |
+
*/
|
101 |
public static function php_version_met() {
|
102 |
static $met = null;
|
103 |
|
108 |
return $met;
|
109 |
}
|
110 |
|
111 |
+
/**
|
112 |
+
* @return void
|
113 |
+
*/
|
114 |
public static function php_version_nope() {
|
115 |
printf(
|
116 |
'<div id="qm-php-nope" class="notice notice-error is-dismissible"><p>%s</p></div>',
|
classes/QM.php
CHANGED
@@ -7,6 +7,11 @@
|
|
7 |
|
8 |
class QM {
|
9 |
|
|
|
|
|
|
|
|
|
|
|
10 |
public static function emergency( $message, array $context = array() ) {
|
11 |
/**
|
12 |
* Fires when an `emergency` level message is logged.
|
@@ -19,6 +24,11 @@ class QM {
|
|
19 |
do_action( 'qm/emergency', $message, $context );
|
20 |
}
|
21 |
|
|
|
|
|
|
|
|
|
|
|
22 |
public static function alert( $message, array $context = array() ) {
|
23 |
/**
|
24 |
* Fires when an `alert` level message is logged.
|
@@ -31,6 +41,11 @@ class QM {
|
|
31 |
do_action( 'qm/alert', $message, $context );
|
32 |
}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
34 |
public static function critical( $message, array $context = array() ) {
|
35 |
/**
|
36 |
* Fires when a `critical` level message is logged.
|
@@ -43,6 +58,11 @@ class QM {
|
|
43 |
do_action( 'qm/critical', $message, $context );
|
44 |
}
|
45 |
|
|
|
|
|
|
|
|
|
|
|
46 |
public static function error( $message, array $context = array() ) {
|
47 |
/**
|
48 |
* Fires when an `error` level message is logged.
|
@@ -55,6 +75,11 @@ class QM {
|
|
55 |
do_action( 'qm/error', $message, $context );
|
56 |
}
|
57 |
|
|
|
|
|
|
|
|
|
|
|
58 |
public static function warning( $message, array $context = array() ) {
|
59 |
/**
|
60 |
* Fires when a `warning` level message is logged.
|
@@ -67,6 +92,11 @@ class QM {
|
|
67 |
do_action( 'qm/warning', $message, $context );
|
68 |
}
|
69 |
|
|
|
|
|
|
|
|
|
|
|
70 |
public static function notice( $message, array $context = array() ) {
|
71 |
/**
|
72 |
* Fires when a `notice` level message is logged.
|
@@ -79,6 +109,11 @@ class QM {
|
|
79 |
do_action( 'qm/notice', $message, $context );
|
80 |
}
|
81 |
|
|
|
|
|
|
|
|
|
|
|
82 |
public static function info( $message, array $context = array() ) {
|
83 |
/**
|
84 |
* Fires when an `info` level message is logged.
|
@@ -91,6 +126,11 @@ class QM {
|
|
91 |
do_action( 'qm/info', $message, $context );
|
92 |
}
|
93 |
|
|
|
|
|
|
|
|
|
|
|
94 |
public static function debug( $message, array $context = array() ) {
|
95 |
/**
|
96 |
* Fires when a `debug` level message is logged.
|
@@ -103,7 +143,15 @@ class QM {
|
|
103 |
do_action( 'qm/debug', $message, $context );
|
104 |
}
|
105 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
public static function log( $level, $message, array $context = array() ) {
|
|
|
107 |
$logger = QM_Collectors::get( 'logger' );
|
108 |
$logger->log( $level, $message, $context );
|
109 |
}
|
7 |
|
8 |
class QM {
|
9 |
|
10 |
+
/**
|
11 |
+
* @param string $message
|
12 |
+
* @param array<string, mixed> $context
|
13 |
+
* @return void
|
14 |
+
*/
|
15 |
public static function emergency( $message, array $context = array() ) {
|
16 |
/**
|
17 |
* Fires when an `emergency` level message is logged.
|
24 |
do_action( 'qm/emergency', $message, $context );
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
+
* @param string $message
|
29 |
+
* @param array<string, mixed> $context
|
30 |
+
* @return void
|
31 |
+
*/
|
32 |
public static function alert( $message, array $context = array() ) {
|
33 |
/**
|
34 |
* Fires when an `alert` level message is logged.
|
41 |
do_action( 'qm/alert', $message, $context );
|
42 |
}
|
43 |
|
44 |
+
/**
|
45 |
+
* @param string $message
|
46 |
+
* @param array<string, mixed> $context
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
public static function critical( $message, array $context = array() ) {
|
50 |
/**
|
51 |
* Fires when a `critical` level message is logged.
|
58 |
do_action( 'qm/critical', $message, $context );
|
59 |
}
|
60 |
|
61 |
+
/**
|
62 |
+
* @param string $message
|
63 |
+
* @param array<string, mixed> $context
|
64 |
+
* @return void
|
65 |
+
*/
|
66 |
public static function error( $message, array $context = array() ) {
|
67 |
/**
|
68 |
* Fires when an `error` level message is logged.
|
75 |
do_action( 'qm/error', $message, $context );
|
76 |
}
|
77 |
|
78 |
+
/**
|
79 |
+
* @param string $message
|
80 |
+
* @param array<string, mixed> $context
|
81 |
+
* @return void
|
82 |
+
*/
|
83 |
public static function warning( $message, array $context = array() ) {
|
84 |
/**
|
85 |
* Fires when a `warning` level message is logged.
|
92 |
do_action( 'qm/warning', $message, $context );
|
93 |
}
|
94 |
|
95 |
+
/**
|
96 |
+
* @param string $message
|
97 |
+
* @param array<string, mixed> $context
|
98 |
+
* @return void
|
99 |
+
*/
|
100 |
public static function notice( $message, array $context = array() ) {
|
101 |
/**
|
102 |
* Fires when a `notice` level message is logged.
|
109 |
do_action( 'qm/notice', $message, $context );
|
110 |
}
|
111 |
|
112 |
+
/**
|
113 |
+
* @param string $message
|
114 |
+
* @param array<string, mixed> $context
|
115 |
+
* @return void
|
116 |
+
*/
|
117 |
public static function info( $message, array $context = array() ) {
|
118 |
/**
|
119 |
* Fires when an `info` level message is logged.
|
126 |
do_action( 'qm/info', $message, $context );
|
127 |
}
|
128 |
|
129 |
+
/**
|
130 |
+
* @param string $message
|
131 |
+
* @param array<string, mixed> $context
|
132 |
+
* @return void
|
133 |
+
*/
|
134 |
public static function debug( $message, array $context = array() ) {
|
135 |
/**
|
136 |
* Fires when a `debug` level message is logged.
|
143 |
do_action( 'qm/debug', $message, $context );
|
144 |
}
|
145 |
|
146 |
+
/**
|
147 |
+
* @param string $level
|
148 |
+
* @param string $message
|
149 |
+
* @param array<string, mixed> $context
|
150 |
+
* @phpstan-param QM_Collector_Logger::* $level
|
151 |
+
* @return void
|
152 |
+
*/
|
153 |
public static function log( $level, $message, array $context = array() ) {
|
154 |
+
/** @var QM_Collector_Logger */
|
155 |
$logger = QM_Collectors::get( 'logger' );
|
156 |
$logger->log( $level, $message, $context );
|
157 |
}
|
classes/QueryMonitor.php
CHANGED
@@ -7,29 +7,30 @@
|
|
7 |
|
8 |
class QueryMonitor extends QM_Plugin {
|
9 |
|
10 |
-
|
|
|
|
|
|
|
11 |
|
12 |
# Actions
|
13 |
add_action( 'plugins_loaded', array( $this, 'action_plugins_loaded' ) );
|
14 |
-
add_action( 'init',
|
15 |
-
add_action( 'members_register_caps',
|
16 |
add_action( 'members_register_cap_groups', array( $this, 'action_register_members_groups' ) );
|
|
|
17 |
|
18 |
# Filters
|
19 |
-
add_filter( 'user_has_cap',
|
20 |
-
add_filter( 'ure_built_in_wp_caps',
|
21 |
add_filter( 'ure_capabilities_groups_tree', array( $this, 'filter_ure_groups' ) );
|
22 |
add_filter( 'network_admin_plugin_action_links_query-monitor/query-monitor.php', array( $this, 'filter_plugin_action_links' ) );
|
23 |
-
add_filter( 'plugin_action_links_query-monitor/query-monitor.php',
|
24 |
add_filter( 'plugin_row_meta', array( $this, 'filter_plugin_row_meta' ), 10, 4 );
|
25 |
|
26 |
-
# Parent setup:
|
27 |
-
parent::__construct( $file );
|
28 |
-
|
29 |
# Load and register built-in collectors:
|
30 |
$collectors = array();
|
31 |
foreach ( glob( $this->plugin_path( 'collectors/*.php' ) ) as $file ) {
|
32 |
-
$key
|
33 |
$collectors[ $key ] = $file;
|
34 |
}
|
35 |
|
@@ -41,15 +42,19 @@ class QueryMonitor extends QM_Plugin {
|
|
41 |
* @param string[] $collectors Array of file paths to be loaded.
|
42 |
*/
|
43 |
foreach ( apply_filters( 'qm/built-in-collectors', $collectors ) as $file ) {
|
44 |
-
|
45 |
}
|
46 |
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
49 |
public function filter_plugin_action_links( array $actions ) {
|
50 |
return array_merge( array(
|
51 |
'settings' => '<a href="#qm-settings">' . esc_html__( 'Settings', 'query-monitor' ) . '</a>',
|
52 |
-
'add-ons'
|
53 |
), $actions );
|
54 |
}
|
55 |
|
@@ -85,7 +90,7 @@ class QueryMonitor extends QM_Plugin {
|
|
85 |
* @param bool[] $user_caps Array of key/value pairs where keys represent a capability name and boolean values
|
86 |
* represent whether the user has that capability.
|
87 |
* @param string[] $required_caps Required primitive capabilities for the requested capability.
|
88 |
-
* @param
|
89 |
* Arguments that accompany the requested capability check.
|
90 |
*
|
91 |
* @type string $0 Requested capability.
|
@@ -111,6 +116,9 @@ class QueryMonitor extends QM_Plugin {
|
|
111 |
return $user_caps;
|
112 |
}
|
113 |
|
|
|
|
|
|
|
114 |
public function action_plugins_loaded() {
|
115 |
// Hide QM itself from output by default:
|
116 |
if ( ! defined( 'QM_HIDE_SELF' ) ) {
|
@@ -131,7 +139,7 @@ class QueryMonitor extends QM_Plugin {
|
|
131 |
|
132 |
# Load dispatchers:
|
133 |
foreach ( glob( $this->plugin_path( 'dispatchers/*.php' ) ) as $file ) {
|
134 |
-
|
135 |
}
|
136 |
|
137 |
/**
|
@@ -148,10 +156,16 @@ class QueryMonitor extends QM_Plugin {
|
|
148 |
|
149 |
}
|
150 |
|
|
|
|
|
|
|
151 |
public function action_init() {
|
152 |
load_plugin_textdomain( 'query-monitor', false, dirname( $this->plugin_base() ) . '/languages' );
|
153 |
}
|
154 |
|
|
|
|
|
|
|
155 |
public static function symlink_warning() {
|
156 |
$db = WP_CONTENT_DIR . '/db.php';
|
157 |
trigger_error( sprintf(
|
@@ -165,14 +179,16 @@ class QueryMonitor extends QM_Plugin {
|
|
165 |
* Registers the Query Monitor user capability group for the Members plugin.
|
166 |
*
|
167 |
* @link https://wordpress.org/plugins/members/
|
|
|
|
|
168 |
*/
|
169 |
public function action_register_members_groups() {
|
170 |
members_register_cap_group( 'query_monitor', array(
|
171 |
-
'label'
|
172 |
-
'caps'
|
173 |
'view_query_monitor',
|
174 |
),
|
175 |
-
'icon'
|
176 |
'priority' => 30,
|
177 |
) );
|
178 |
}
|
@@ -181,6 +197,8 @@ class QueryMonitor extends QM_Plugin {
|
|
181 |
* Registers the View Query Monitor user capability for the Members plugin.
|
182 |
*
|
183 |
* @link https://wordpress.org/plugins/members/
|
|
|
|
|
184 |
*/
|
185 |
public function action_register_members_caps() {
|
186 |
members_register_cap( 'view_query_monitor', array(
|
@@ -194,14 +212,14 @@ class QueryMonitor extends QM_Plugin {
|
|
194 |
*
|
195 |
* @link https://wordpress.org/plugins/user-role-editor/
|
196 |
*
|
197 |
-
* @param array
|
198 |
-
* @return array
|
199 |
*/
|
200 |
public function filter_ure_groups( array $groups ) {
|
201 |
$groups['query_monitor'] = array(
|
202 |
'caption' => esc_html__( 'Query Monitor', 'query-monitor' ),
|
203 |
-
'parent'
|
204 |
-
'level'
|
205 |
);
|
206 |
|
207 |
return $groups;
|
@@ -212,8 +230,8 @@ class QueryMonitor extends QM_Plugin {
|
|
212 |
*
|
213 |
* @link https://wordpress.org/plugins/user-role-editor/
|
214 |
*
|
215 |
-
* @param array
|
216 |
-
* @return array
|
217 |
*/
|
218 |
public function filter_ure_caps( array $caps ) {
|
219 |
$caps['view_query_monitor'] = array(
|
@@ -224,6 +242,22 @@ class QueryMonitor extends QM_Plugin {
|
|
224 |
return $caps;
|
225 |
}
|
226 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
public static function init( $file = null ) {
|
228 |
|
229 |
static $instance = null;
|
7 |
|
8 |
class QueryMonitor extends QM_Plugin {
|
9 |
|
10 |
+
/**
|
11 |
+
* @return void
|
12 |
+
*/
|
13 |
+
public function set_up() {
|
14 |
|
15 |
# Actions
|
16 |
add_action( 'plugins_loaded', array( $this, 'action_plugins_loaded' ) );
|
17 |
+
add_action( 'init', array( $this, 'action_init' ) );
|
18 |
+
add_action( 'members_register_caps', array( $this, 'action_register_members_caps' ) );
|
19 |
add_action( 'members_register_cap_groups', array( $this, 'action_register_members_groups' ) );
|
20 |
+
add_action( 'qm/cease', array( $this, 'action_cease' ) );
|
21 |
|
22 |
# Filters
|
23 |
+
add_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 10, 4 );
|
24 |
+
add_filter( 'ure_built_in_wp_caps', array( $this, 'filter_ure_caps' ) );
|
25 |
add_filter( 'ure_capabilities_groups_tree', array( $this, 'filter_ure_groups' ) );
|
26 |
add_filter( 'network_admin_plugin_action_links_query-monitor/query-monitor.php', array( $this, 'filter_plugin_action_links' ) );
|
27 |
+
add_filter( 'plugin_action_links_query-monitor/query-monitor.php', array( $this, 'filter_plugin_action_links' ) );
|
28 |
add_filter( 'plugin_row_meta', array( $this, 'filter_plugin_row_meta' ), 10, 4 );
|
29 |
|
|
|
|
|
|
|
30 |
# Load and register built-in collectors:
|
31 |
$collectors = array();
|
32 |
foreach ( glob( $this->plugin_path( 'collectors/*.php' ) ) as $file ) {
|
33 |
+
$key = basename( $file, '.php' );
|
34 |
$collectors[ $key ] = $file;
|
35 |
}
|
36 |
|
42 |
* @param string[] $collectors Array of file paths to be loaded.
|
43 |
*/
|
44 |
foreach ( apply_filters( 'qm/built-in-collectors', $collectors ) as $file ) {
|
45 |
+
include_once $file;
|
46 |
}
|
47 |
|
48 |
}
|
49 |
|
50 |
+
/**
|
51 |
+
* @param array<string, string> $actions
|
52 |
+
* @return array<string, string>
|
53 |
+
*/
|
54 |
public function filter_plugin_action_links( array $actions ) {
|
55 |
return array_merge( array(
|
56 |
'settings' => '<a href="#qm-settings">' . esc_html__( 'Settings', 'query-monitor' ) . '</a>',
|
57 |
+
'add-ons' => '<a href="https://github.com/johnbillion/query-monitor/wiki/Query-Monitor-Add-on-Plugins">' . esc_html__( 'Add-ons', 'query-monitor' ) . '</a>',
|
58 |
), $actions );
|
59 |
}
|
60 |
|
90 |
* @param bool[] $user_caps Array of key/value pairs where keys represent a capability name and boolean values
|
91 |
* represent whether the user has that capability.
|
92 |
* @param string[] $required_caps Required primitive capabilities for the requested capability.
|
93 |
+
* @param mixed[] $args {
|
94 |
* Arguments that accompany the requested capability check.
|
95 |
*
|
96 |
* @type string $0 Requested capability.
|
116 |
return $user_caps;
|
117 |
}
|
118 |
|
119 |
+
/**
|
120 |
+
* @return void
|
121 |
+
*/
|
122 |
public function action_plugins_loaded() {
|
123 |
// Hide QM itself from output by default:
|
124 |
if ( ! defined( 'QM_HIDE_SELF' ) ) {
|
139 |
|
140 |
# Load dispatchers:
|
141 |
foreach ( glob( $this->plugin_path( 'dispatchers/*.php' ) ) as $file ) {
|
142 |
+
include_once $file;
|
143 |
}
|
144 |
|
145 |
/**
|
156 |
|
157 |
}
|
158 |
|
159 |
+
/**
|
160 |
+
* @return void
|
161 |
+
*/
|
162 |
public function action_init() {
|
163 |
load_plugin_textdomain( 'query-monitor', false, dirname( $this->plugin_base() ) . '/languages' );
|
164 |
}
|
165 |
|
166 |
+
/**
|
167 |
+
* @return void
|
168 |
+
*/
|
169 |
public static function symlink_warning() {
|
170 |
$db = WP_CONTENT_DIR . '/db.php';
|
171 |
trigger_error( sprintf(
|
179 |
* Registers the Query Monitor user capability group for the Members plugin.
|
180 |
*
|
181 |
* @link https://wordpress.org/plugins/members/
|
182 |
+
*
|
183 |
+
* @return void
|
184 |
*/
|
185 |
public function action_register_members_groups() {
|
186 |
members_register_cap_group( 'query_monitor', array(
|
187 |
+
'label' => __( 'Query Monitor', 'query-monitor' ),
|
188 |
+
'caps' => array(
|
189 |
'view_query_monitor',
|
190 |
),
|
191 |
+
'icon' => 'dashicons-admin-tools',
|
192 |
'priority' => 30,
|
193 |
) );
|
194 |
}
|
197 |
* Registers the View Query Monitor user capability for the Members plugin.
|
198 |
*
|
199 |
* @link https://wordpress.org/plugins/members/
|
200 |
+
*
|
201 |
+
* @return void
|
202 |
*/
|
203 |
public function action_register_members_caps() {
|
204 |
members_register_cap( 'view_query_monitor', array(
|
212 |
*
|
213 |
* @link https://wordpress.org/plugins/user-role-editor/
|
214 |
*
|
215 |
+
* @param array<string, array<string, mixed>> $groups Array of existing groups.
|
216 |
+
* @return array<string, array<string, mixed>> Updated array of groups.
|
217 |
*/
|
218 |
public function filter_ure_groups( array $groups ) {
|
219 |
$groups['query_monitor'] = array(
|
220 |
'caption' => esc_html__( 'Query Monitor', 'query-monitor' ),
|
221 |
+
'parent' => 'custom',
|
222 |
+
'level' => 2,
|
223 |
);
|
224 |
|
225 |
return $groups;
|
230 |
*
|
231 |
* @link https://wordpress.org/plugins/user-role-editor/
|
232 |
*
|
233 |
+
* @param array<string, array<string, mixed>> $caps Array of existing capabilities.
|
234 |
+
* @return array<string, array<string, mixed>> Updated array of capabilities.
|
235 |
*/
|
236 |
public function filter_ure_caps( array $caps ) {
|
237 |
$caps['view_query_monitor'] = array(
|
242 |
return $caps;
|
243 |
}
|
244 |
|
245 |
+
/**
|
246 |
+
* @return void
|
247 |
+
*/
|
248 |
+
public function action_cease() {
|
249 |
+
// iterate collectors, call tear_down
|
250 |
+
// discard all collected data
|
251 |
+
QM_Collectors::cease();
|
252 |
+
|
253 |
+
// remove dispatchers or prevent them from doing anything
|
254 |
+
QM_Dispatchers::cease();
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* @param string $file
|
259 |
+
* @return self
|
260 |
+
*/
|
261 |
public static function init( $file = null ) {
|
262 |
|
263 |
static $instance = null;
|
classes/Timer.php
CHANGED
@@ -7,44 +7,90 @@
|
|
7 |
|
8 |
class QM_Timer {
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
protected $start = null;
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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'
|
19 |
'memory' => memory_get_usage(),
|
20 |
-
'data'
|
21 |
);
|
22 |
return $this;
|
23 |
}
|
24 |
|
|
|
|
|
|
|
|
|
25 |
public function stop( array $data = null ) {
|
26 |
|
27 |
$this->end = array(
|
28 |
-
'time'
|
29 |
'memory' => memory_get_usage(),
|
30 |
-
'data'
|
31 |
);
|
32 |
|
33 |
return $this;
|
34 |
|
35 |
}
|
36 |
|
|
|
|
|
|
|
|
|
|
|
37 |
public function lap( array $data = null, $name = null ) {
|
38 |
|
39 |
$lap = array(
|
40 |
-
'time'
|
41 |
'memory' => memory_get_usage(),
|
42 |
-
'data'
|
43 |
);
|
44 |
|
45 |
if ( ! isset( $name ) ) {
|
46 |
-
|
47 |
-
|
|
|
|
|
|
|
48 |
} else {
|
49 |
$i = $name;
|
50 |
}
|
@@ -55,6 +101,9 @@ class QM_Timer {
|
|
55 |
|
56 |
}
|
57 |
|
|
|
|
|
|
|
58 |
public function get_laps() {
|
59 |
|
60 |
$laps = array();
|
@@ -62,11 +111,11 @@ class QM_Timer {
|
|
62 |
|
63 |
foreach ( $this->laps as $lap_id => $lap ) {
|
64 |
|
65 |
-
$lap['time_used']
|
66 |
$lap['memory_used'] = $lap['memory'] - $prev['memory'];
|
67 |
|
68 |
$laps[ $lap_id ] = $lap;
|
69 |
-
$prev
|
70 |
|
71 |
}
|
72 |
|
@@ -74,34 +123,59 @@ class QM_Timer {
|
|
74 |
|
75 |
}
|
76 |
|
|
|
|
|
|
|
77 |
public function get_time() {
|
78 |
return $this->end['time'] - $this->start['time'];
|
79 |
}
|
80 |
|
|
|
|
|
|
|
81 |
public function get_memory() {
|
82 |
return $this->end['memory'] - $this->start['memory'];
|
83 |
}
|
84 |
|
|
|
|
|
|
|
85 |
public function get_start_time() {
|
86 |
return $this->start['time'];
|
87 |
}
|
88 |
|
|
|
|
|
|
|
89 |
public function get_start_memory() {
|
90 |
return $this->start['memory'];
|
91 |
}
|
92 |
|
|
|
|
|
|
|
93 |
public function get_end_time() {
|
94 |
return $this->end['time'];
|
95 |
}
|
96 |
|
|
|
|
|
|
|
97 |
public function get_end_memory() {
|
98 |
return $this->end['memory'];
|
99 |
}
|
100 |
|
|
|
|
|
|
|
101 |
public function get_trace() {
|
102 |
return $this->trace;
|
103 |
}
|
104 |
|
|
|
|
|
|
|
|
|
105 |
public function end( array $data = null ) {
|
106 |
return $this->stop( $data );
|
107 |
}
|
7 |
|
8 |
class QM_Timer {
|
9 |
|
10 |
+
/**
|
11 |
+
* @var array<string, mixed>|null
|
12 |
+
* @phpstan-var array{
|
13 |
+
* time: float,
|
14 |
+
* memory: int,
|
15 |
+
* data: mixed[],
|
16 |
+
* }|null
|
17 |
+
*/
|
18 |
protected $start = null;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var array<string, mixed>|null
|
22 |
+
* @phpstan-var array{
|
23 |
+
* time: float,
|
24 |
+
* memory: int,
|
25 |
+
* data: mixed[],
|
26 |
+
* }|null
|
27 |
+
*/
|
28 |
+
protected $end = null;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @var QM_Backtrace|null
|
32 |
+
*/
|
33 |
protected $trace = null;
|
|
|
34 |
|
35 |
+
/**
|
36 |
+
* @var array<string, array<string, mixed>>
|
37 |
+
* @phpstan-var array<string, array{
|
38 |
+
* time: float,
|
39 |
+
* memory: int,
|
40 |
+
* data: mixed[],
|
41 |
+
* }>
|
42 |
+
*/
|
43 |
+
protected $laps = array();
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @param mixed[] $data
|
47 |
+
* @return self
|
48 |
+
*/
|
49 |
public function start( array $data = null ) {
|
50 |
$this->trace = new QM_Backtrace();
|
51 |
$this->start = array(
|
52 |
+
'time' => microtime( true ),
|
53 |
'memory' => memory_get_usage(),
|
54 |
+
'data' => $data,
|
55 |
);
|
56 |
return $this;
|
57 |
}
|
58 |
|
59 |
+
/**
|
60 |
+
* @param mixed[] $data
|
61 |
+
* @return self
|
62 |
+
*/
|
63 |
public function stop( array $data = null ) {
|
64 |
|
65 |
$this->end = array(
|
66 |
+
'time' => microtime( true ),
|
67 |
'memory' => memory_get_usage(),
|
68 |
+
'data' => $data,
|
69 |
);
|
70 |
|
71 |
return $this;
|
72 |
|
73 |
}
|
74 |
|
75 |
+
/**
|
76 |
+
* @param mixed[] $data
|
77 |
+
* @param string $name
|
78 |
+
* @return self
|
79 |
+
*/
|
80 |
public function lap( array $data = null, $name = null ) {
|
81 |
|
82 |
$lap = array(
|
83 |
+
'time' => microtime( true ),
|
84 |
'memory' => memory_get_usage(),
|
85 |
+
'data' => $data,
|
86 |
);
|
87 |
|
88 |
if ( ! isset( $name ) ) {
|
89 |
+
$i = sprintf(
|
90 |
+
/* translators: %s: Timing lap number */
|
91 |
+
__( 'Lap %s', 'query-monitor' ),
|
92 |
+
number_format_i18n( count( $this->laps ) + 1 )
|
93 |
+
);
|
94 |
} else {
|
95 |
$i = $name;
|
96 |
}
|
101 |
|
102 |
}
|
103 |
|
104 |
+
/**
|
105 |
+
* @return mixed[]
|
106 |
+
*/
|
107 |
public function get_laps() {
|
108 |
|
109 |
$laps = array();
|
111 |
|
112 |
foreach ( $this->laps as $lap_id => $lap ) {
|
113 |
|
114 |
+
$lap['time_used'] = $lap['time'] - $prev['time'];
|
115 |
$lap['memory_used'] = $lap['memory'] - $prev['memory'];
|
116 |
|
117 |
$laps[ $lap_id ] = $lap;
|
118 |
+
$prev = $lap;
|
119 |
|
120 |
}
|
121 |
|
123 |
|
124 |
}
|
125 |
|
126 |
+
/**
|
127 |
+
* @return float
|
128 |
+
*/
|
129 |
public function get_time() {
|
130 |
return $this->end['time'] - $this->start['time'];
|
131 |
}
|
132 |
|
133 |
+
/**
|
134 |
+
* @return int
|
135 |
+
*/
|
136 |
public function get_memory() {
|
137 |
return $this->end['memory'] - $this->start['memory'];
|
138 |
}
|
139 |
|
140 |
+
/**
|
141 |
+
* @return float
|
142 |
+
*/
|
143 |
public function get_start_time() {
|
144 |
return $this->start['time'];
|
145 |
}
|
146 |
|
147 |
+
/**
|
148 |
+
* @return int
|
149 |
+
*/
|
150 |
public function get_start_memory() {
|
151 |
return $this->start['memory'];
|
152 |
}
|
153 |
|
154 |
+
/**
|
155 |
+
* @return float
|
156 |
+
*/
|
157 |
public function get_end_time() {
|
158 |
return $this->end['time'];
|
159 |
}
|
160 |
|
161 |
+
/**
|
162 |
+
* @return int
|
163 |
+
*/
|
164 |
public function get_end_memory() {
|
165 |
return $this->end['memory'];
|
166 |
}
|
167 |
|
168 |
+
/**
|
169 |
+
* @return QM_Backtrace
|
170 |
+
*/
|
171 |
public function get_trace() {
|
172 |
return $this->trace;
|
173 |
}
|
174 |
|
175 |
+
/**
|
176 |
+
* @param mixed[] $data
|
177 |
+
* @return self
|
178 |
+
*/
|
179 |
public function end( array $data = null ) {
|
180 |
return $this->stop( $data );
|
181 |
}
|
classes/Util.php
CHANGED
@@ -8,14 +8,37 @@
|
|
8 |
if ( ! class_exists( 'QM_Util' ) ) {
|
9 |
class QM_Util {
|
10 |
|
|
|
|
|
|
|
11 |
protected static $file_components = array();
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
private function __construct() {}
|
18 |
|
|
|
|
|
|
|
|
|
19 |
public static function convert_hr_to_bytes( $size ) {
|
20 |
|
21 |
# Annoyingly, wp_convert_hr_to_bytes() is defined in a file that's only
|
@@ -37,13 +60,18 @@ class QM_Util {
|
|
37 |
|
38 |
}
|
39 |
|
|
|
|
|
|
|
|
|
|
|
40 |
public static function standard_dir( $dir, $path_replace = null ) {
|
41 |
|
42 |
$dir = self::normalize_path( $dir );
|
43 |
|
44 |
if ( is_string( $path_replace ) ) {
|
45 |
if ( ! self::$abspath ) {
|
46 |
-
self::$abspath
|
47 |
self::$contentpath = self::normalize_path( dirname( WP_CONTENT_DIR ) . '/' );
|
48 |
}
|
49 |
$dir = str_replace( array(
|
@@ -56,6 +84,10 @@ class QM_Util {
|
|
56 |
|
57 |
}
|
58 |
|
|
|
|
|
|
|
|
|
59 |
public static function normalize_path( $path ) {
|
60 |
if ( function_exists( 'wp_normalize_path' ) ) {
|
61 |
$path = wp_normalize_path( $path );
|
@@ -67,6 +99,9 @@ class QM_Util {
|
|
67 |
return $path;
|
68 |
}
|
69 |
|
|
|
|
|
|
|
70 |
public static function get_file_dirs() {
|
71 |
if ( empty( self::$file_dirs ) ) {
|
72 |
|
@@ -76,7 +111,10 @@ class QM_Util {
|
|
76 |
* Note that this filter is applied before QM adds its built-in list of components. This is
|
77 |
* so custom registered components take precedence during component detection.
|
78 |
*
|
79 |
-
* See the corresponding
|
|
|
|
|
|
|
80 |
*
|
81 |
* @since 3.6.0
|
82 |
*
|
@@ -84,10 +122,10 @@ class QM_Util {
|
|
84 |
*/
|
85 |
self::$file_dirs = apply_filters( 'qm/component_dirs', self::$file_dirs );
|
86 |
|
87 |
-
self::$file_dirs['plugin']
|
88 |
-
self::$file_dirs['mu-vendor']
|
89 |
-
self::$file_dirs['go-plugin']
|
90 |
-
self::$file_dirs['mu-plugin']
|
91 |
self::$file_dirs['vip-plugin'] = get_theme_root() . '/vip/plugins';
|
92 |
|
93 |
if ( defined( 'WPCOM_VIP_CLIENT_MU_PLUGIN_DIR' ) ) {
|
@@ -98,12 +136,12 @@ class QM_Util {
|
|
98 |
self::$file_dirs['altis-vendor'] = \Altis\ROOT_DIR . '/vendor';
|
99 |
}
|
100 |
|
101 |
-
self::$file_dirs['theme']
|
102 |
self::$file_dirs['stylesheet'] = get_stylesheet_directory();
|
103 |
-
self::$file_dirs['template']
|
104 |
-
self::$file_dirs['other']
|
105 |
-
self::$file_dirs['core']
|
106 |
-
self::$file_dirs['unknown']
|
107 |
|
108 |
foreach ( self::$file_dirs as $type => $dir ) {
|
109 |
self::$file_dirs[ $type ] = self::standard_dir( $dir );
|
@@ -113,11 +151,18 @@ class QM_Util {
|
|
113 |
return self::$file_dirs;
|
114 |
}
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
public static function get_file_component( $file ) {
|
117 |
|
118 |
# @TODO turn this into a class (eg QM_File_Component)
|
119 |
|
120 |
$file = self::standard_dir( $file );
|
|
|
121 |
|
122 |
if ( isset( self::$file_components[ $file ] ) ) {
|
123 |
return self::$file_components[ $file ];
|
@@ -195,14 +240,14 @@ class QM_Util {
|
|
195 |
case 'other':
|
196 |
// Anything else that's within the content directory should appear as
|
197 |
// `wp-content/{dir}` or `wp-content/{file}`
|
198 |
-
$name
|
199 |
-
$name
|
200 |
-
$parts
|
201 |
-
$name
|
202 |
$context = $file;
|
203 |
break;
|
204 |
case 'core':
|
205 |
-
$name = __( 'Core', 'query-monitor' );
|
206 |
break;
|
207 |
case 'unknown':
|
208 |
default:
|
@@ -213,7 +258,10 @@ class QM_Util {
|
|
213 |
*
|
214 |
* The dynamic portion of the hook name, `$type`, refers to the component identifier.
|
215 |
*
|
216 |
-
* See the corresponding
|
|
|
|
|
|
|
217 |
*
|
218 |
* @since 3.6.0
|
219 |
*
|
@@ -221,6 +269,25 @@ class QM_Util {
|
|
221 |
* @param string $file The full file path for the file within the component.
|
222 |
*/
|
223 |
$name = apply_filters( "qm/component_name/{$type}", $name, $file );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
break;
|
225 |
}
|
226 |
|
@@ -229,6 +296,10 @@ class QM_Util {
|
|
229 |
return self::$file_components[ $file ];
|
230 |
}
|
231 |
|
|
|
|
|
|
|
|
|
232 |
public static function populate_callback( array $callback ) {
|
233 |
|
234 |
if ( is_string( $callback['function'] ) && ( false !== strpos( $callback['function'], '::' ) ) ) {
|
@@ -246,10 +317,10 @@ class QM_Util {
|
|
246 |
|
247 |
if ( is_array( $callback['function'] ) ) {
|
248 |
if ( is_object( $callback['function'][0] ) ) {
|
249 |
-
$class
|
250 |
$access = '->';
|
251 |
} else {
|
252 |
-
$class
|
253 |
$access = '::';
|
254 |
}
|
255 |
|
@@ -257,7 +328,7 @@ class QM_Util {
|
|
257 |
$ref = new ReflectionMethod( $class, $callback['function'][1] );
|
258 |
} elseif ( is_object( $callback['function'] ) ) {
|
259 |
if ( is_a( $callback['function'], 'Closure' ) ) {
|
260 |
-
$ref
|
261 |
$file = self::standard_dir( $ref->getFileName(), '' );
|
262 |
if ( 0 === strpos( $file, '/' ) ) {
|
263 |
$file = basename( $ref->getFileName() );
|
@@ -300,8 +371,8 @@ class QM_Util {
|
|
300 |
$callback['component'] = self::get_file_component( $callback['file'] );
|
301 |
} else {
|
302 |
$callback['component'] = (object) array(
|
303 |
-
'type'
|
304 |
-
'name'
|
305 |
'context' => '',
|
306 |
);
|
307 |
}
|
@@ -315,6 +386,9 @@ class QM_Util {
|
|
315 |
|
316 |
}
|
317 |
|
|
|
|
|
|
|
318 |
public static function is_ajax() {
|
319 |
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
320 |
return true;
|
@@ -322,6 +396,9 @@ class QM_Util {
|
|
322 |
return false;
|
323 |
}
|
324 |
|
|
|
|
|
|
|
325 |
public static function is_async() {
|
326 |
if ( self::is_ajax() ) {
|
327 |
return true;
|
@@ -332,6 +409,9 @@ class QM_Util {
|
|
332 |
return false;
|
333 |
}
|
334 |
|
|
|
|
|
|
|
335 |
public static function get_admins() {
|
336 |
if ( is_multisite() ) {
|
337 |
return false;
|
@@ -340,6 +420,9 @@ class QM_Util {
|
|
340 |
}
|
341 |
}
|
342 |
|
|
|
|
|
|
|
343 |
public static function is_multi_network() {
|
344 |
global $wpdb;
|
345 |
|
@@ -361,6 +444,15 @@ class QM_Util {
|
|
361 |
return ( $num_sites > 1 );
|
362 |
}
|
363 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
364 |
public static function get_client_version( $client ) {
|
365 |
|
366 |
$client = intval( $client );
|
@@ -375,6 +467,10 @@ class QM_Util {
|
|
375 |
|
376 |
}
|
377 |
|
|
|
|
|
|
|
|
|
378 |
public static function get_query_type( $sql ) {
|
379 |
// Trim leading whitespace and brackets
|
380 |
$sql = ltrim( $sql, ' \t\n\r\0\x0B(' );
|
@@ -390,6 +486,10 @@ class QM_Util {
|
|
390 |
return $type;
|
391 |
}
|
392 |
|
|
|
|
|
|
|
|
|
393 |
public static function display_variable( $value ) {
|
394 |
if ( is_string( $value ) ) {
|
395 |
return $value;
|
@@ -404,44 +504,42 @@ class QM_Util {
|
|
404 |
|
405 |
case ( $value instanceof WP_Post ):
|
406 |
case ( $value instanceof WP_User ):
|
407 |
-
|
408 |
break;
|
409 |
|
410 |
case ( $value instanceof WP_Term ):
|
411 |
-
|
412 |
break;
|
413 |
|
414 |
case ( $value instanceof WP_Comment ):
|
415 |
-
|
416 |
break;
|
417 |
|
418 |
case ( $value instanceof WP_Error ):
|
419 |
-
|
420 |
break;
|
421 |
|
422 |
case ( $value instanceof WP_Role ):
|
423 |
case ( $value instanceof WP_Post_Type ):
|
424 |
case ( $value instanceof WP_Taxonomy ):
|
425 |
-
|
426 |
break;
|
427 |
|
428 |
case ( $value instanceof WP_Network ):
|
429 |
-
|
430 |
break;
|
431 |
|
432 |
case ( $value instanceof WP_Site ):
|
433 |
-
|
434 |
break;
|
435 |
|
436 |
case ( $value instanceof WP_Theme ):
|
437 |
-
|
438 |
-
break;
|
439 |
-
|
440 |
-
default:
|
441 |
-
return $class;
|
442 |
break;
|
443 |
|
444 |
}
|
|
|
|
|
445 |
} else {
|
446 |
return gettype( $value );
|
447 |
}
|
@@ -491,20 +589,40 @@ class QM_Util {
|
|
491 |
return $json;
|
492 |
}
|
493 |
|
|
|
|
|
|
|
|
|
494 |
public static function is_stringy( $data ) {
|
495 |
return ( is_string( $data ) || ( is_object( $data ) && method_exists( $data, '__toString' ) ) );
|
496 |
}
|
497 |
|
|
|
|
|
|
|
|
|
|
|
498 |
public static function sort( array &$array, $field ) {
|
499 |
self::$sort_field = $field;
|
500 |
usort( $array, array( __CLASS__, '_sort' ) );
|
501 |
}
|
502 |
|
|
|
|
|
|
|
|
|
|
|
503 |
public static function rsort( array &$array, $field ) {
|
504 |
self::$sort_field = $field;
|
505 |
usort( $array, array( __CLASS__, '_rsort' ) );
|
506 |
}
|
507 |
|
|
|
|
|
|
|
|
|
|
|
|
|
508 |
private static function _rsort( $a, $b ) {
|
509 |
$field = self::$sort_field;
|
510 |
|
@@ -515,6 +633,12 @@ class QM_Util {
|
|
515 |
}
|
516 |
}
|
517 |
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
private static function _sort( $a, $b ) {
|
519 |
$field = self::$sort_field;
|
520 |
|
8 |
if ( ! class_exists( 'QM_Util' ) ) {
|
9 |
class QM_Util {
|
10 |
|
11 |
+
/**
|
12 |
+
* @var array<string, stdClass>
|
13 |
+
*/
|
14 |
protected static $file_components = array();
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var array<string, string|null>
|
18 |
+
*/
|
19 |
+
protected static $file_dirs = array();
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var string|null
|
23 |
+
*/
|
24 |
+
protected static $abspath = null;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var string|null
|
28 |
+
*/
|
29 |
+
protected static $contentpath = null;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @var string|null
|
33 |
+
*/
|
34 |
+
protected static $sort_field = null;
|
35 |
|
36 |
private function __construct() {}
|
37 |
|
38 |
+
/**
|
39 |
+
* @param string $size
|
40 |
+
* @return float
|
41 |
+
*/
|
42 |
public static function convert_hr_to_bytes( $size ) {
|
43 |
|
44 |
# Annoyingly, wp_convert_hr_to_bytes() is defined in a file that's only
|
60 |
|
61 |
}
|
62 |
|
63 |
+
/**
|
64 |
+
* @param string $dir
|
65 |
+
* @param string $path_replace
|
66 |
+
* @return string
|
67 |
+
*/
|
68 |
public static function standard_dir( $dir, $path_replace = null ) {
|
69 |
|
70 |
$dir = self::normalize_path( $dir );
|
71 |
|
72 |
if ( is_string( $path_replace ) ) {
|
73 |
if ( ! self::$abspath ) {
|
74 |
+
self::$abspath = self::normalize_path( ABSPATH );
|
75 |
self::$contentpath = self::normalize_path( dirname( WP_CONTENT_DIR ) . '/' );
|
76 |
}
|
77 |
$dir = str_replace( array(
|
84 |
|
85 |
}
|
86 |
|
87 |
+
/**
|
88 |
+
* @param string $path
|
89 |
+
* @return string
|
90 |
+
*/
|
91 |
public static function normalize_path( $path ) {
|
92 |
if ( function_exists( 'wp_normalize_path' ) ) {
|
93 |
$path = wp_normalize_path( $path );
|
99 |
return $path;
|
100 |
}
|
101 |
|
102 |
+
/**
|
103 |
+
* @return array<string, string|null>
|
104 |
+
*/
|
105 |
public static function get_file_dirs() {
|
106 |
if ( empty( self::$file_dirs ) ) {
|
107 |
|
111 |
* Note that this filter is applied before QM adds its built-in list of components. This is
|
112 |
* so custom registered components take precedence during component detection.
|
113 |
*
|
114 |
+
* See also the corresponding filters:
|
115 |
+
*
|
116 |
+
* - `qm/component_context/{$type}`
|
117 |
+
* - `qm/component_name/{$type}`
|
118 |
*
|
119 |
* @since 3.6.0
|
120 |
*
|
122 |
*/
|
123 |
self::$file_dirs = apply_filters( 'qm/component_dirs', self::$file_dirs );
|
124 |
|
125 |
+
self::$file_dirs['plugin'] = WP_PLUGIN_DIR;
|
126 |
+
self::$file_dirs['mu-vendor'] = WPMU_PLUGIN_DIR . '/vendor';
|
127 |
+
self::$file_dirs['go-plugin'] = WPMU_PLUGIN_DIR . '/shared-plugins';
|
128 |
+
self::$file_dirs['mu-plugin'] = WPMU_PLUGIN_DIR;
|
129 |
self::$file_dirs['vip-plugin'] = get_theme_root() . '/vip/plugins';
|
130 |
|
131 |
if ( defined( 'WPCOM_VIP_CLIENT_MU_PLUGIN_DIR' ) ) {
|
136 |
self::$file_dirs['altis-vendor'] = \Altis\ROOT_DIR . '/vendor';
|
137 |
}
|
138 |
|
139 |
+
self::$file_dirs['theme'] = null;
|
140 |
self::$file_dirs['stylesheet'] = get_stylesheet_directory();
|
141 |
+
self::$file_dirs['template'] = get_template_directory();
|
142 |
+
self::$file_dirs['other'] = WP_CONTENT_DIR;
|
143 |
+
self::$file_dirs['core'] = ABSPATH;
|
144 |
+
self::$file_dirs['unknown'] = null;
|
145 |
|
146 |
foreach ( self::$file_dirs as $type => $dir ) {
|
147 |
self::$file_dirs[ $type ] = self::standard_dir( $dir );
|
151 |
return self::$file_dirs;
|
152 |
}
|
153 |
|
154 |
+
/**
|
155 |
+
* Attempts to determine the component responsible for a given file name.
|
156 |
+
*
|
157 |
+
* @param string $file An absolute file path.
|
158 |
+
* @return stdClass A stdClass object (ouch) representing the component.
|
159 |
+
*/
|
160 |
public static function get_file_component( $file ) {
|
161 |
|
162 |
# @TODO turn this into a class (eg QM_File_Component)
|
163 |
|
164 |
$file = self::standard_dir( $file );
|
165 |
+
$type = '';
|
166 |
|
167 |
if ( isset( self::$file_components[ $file ] ) ) {
|
168 |
return self::$file_components[ $file ];
|
240 |
case 'other':
|
241 |
// Anything else that's within the content directory should appear as
|
242 |
// `wp-content/{dir}` or `wp-content/{file}`
|
243 |
+
$name = self::standard_dir( $file );
|
244 |
+
$name = str_replace( dirname( self::$file_dirs['other'] ), '', $name );
|
245 |
+
$parts = explode( '/', trim( $name, '/' ) );
|
246 |
+
$name = $parts[0] . '/' . $parts[1];
|
247 |
$context = $file;
|
248 |
break;
|
249 |
case 'core':
|
250 |
+
$name = __( 'WordPress Core', 'query-monitor' );
|
251 |
break;
|
252 |
case 'unknown':
|
253 |
default:
|
258 |
*
|
259 |
* The dynamic portion of the hook name, `$type`, refers to the component identifier.
|
260 |
*
|
261 |
+
* See also the corresponding filters:
|
262 |
+
*
|
263 |
+
* - `qm/component_dirs`
|
264 |
+
* - `qm/component_context/{$type}`
|
265 |
*
|
266 |
* @since 3.6.0
|
267 |
*
|
269 |
* @param string $file The full file path for the file within the component.
|
270 |
*/
|
271 |
$name = apply_filters( "qm/component_name/{$type}", $name, $file );
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Filters the context for a custom or unknown component. The context is usually a
|
275 |
+
* representation of its type more specific to the individual component.
|
276 |
+
*
|
277 |
+
* The dynamic portion of the hook name, `$type`, refers to the component identifier.
|
278 |
+
*
|
279 |
+
* See also the corresponding filters:
|
280 |
+
*
|
281 |
+
* - `qm/component_dirs`
|
282 |
+
* - `qm/component_name/{$type}`
|
283 |
+
*
|
284 |
+
* @since 3.8.0
|
285 |
+
*
|
286 |
+
* @param string $context The context for the component.
|
287 |
+
* @param string $file The full file path for the file within the component.
|
288 |
+
* @param string $name The component name.
|
289 |
+
*/
|
290 |
+
$context = apply_filters( "qm/component_context/{$type}", $context, $file, $name );
|
291 |
break;
|
292 |
}
|
293 |
|
296 |
return self::$file_components[ $file ];
|
297 |
}
|
298 |
|
299 |
+
/**
|
300 |
+
* @param array<string, mixed> $callback
|
301 |
+
* @return array<string, mixed>
|
302 |
+
*/
|
303 |
public static function populate_callback( array $callback ) {
|
304 |
|
305 |
if ( is_string( $callback['function'] ) && ( false !== strpos( $callback['function'], '::' ) ) ) {
|
317 |
|
318 |
if ( is_array( $callback['function'] ) ) {
|
319 |
if ( is_object( $callback['function'][0] ) ) {
|
320 |
+
$class = get_class( $callback['function'][0] );
|
321 |
$access = '->';
|
322 |
} else {
|
323 |
+
$class = $callback['function'][0];
|
324 |
$access = '::';
|
325 |
}
|
326 |
|
328 |
$ref = new ReflectionMethod( $class, $callback['function'][1] );
|
329 |
} elseif ( is_object( $callback['function'] ) ) {
|
330 |
if ( is_a( $callback['function'], 'Closure' ) ) {
|
331 |
+
$ref = new ReflectionFunction( $callback['function'] );
|
332 |
$file = self::standard_dir( $ref->getFileName(), '' );
|
333 |
if ( 0 === strpos( $file, '/' ) ) {
|
334 |
$file = basename( $ref->getFileName() );
|
371 |
$callback['component'] = self::get_file_component( $callback['file'] );
|
372 |
} else {
|
373 |
$callback['component'] = (object) array(
|
374 |
+
'type' => 'php',
|
375 |
+
'name' => 'PHP',
|
376 |
'context' => '',
|
377 |
);
|
378 |
}
|
386 |
|
387 |
}
|
388 |
|
389 |
+
/**
|
390 |
+
* @return bool
|
391 |
+
*/
|
392 |
public static function is_ajax() {
|
393 |
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
394 |
return true;
|
396 |
return false;
|
397 |
}
|
398 |
|
399 |
+
/**
|
400 |
+
* @return bool
|
401 |
+
*/
|
402 |
public static function is_async() {
|
403 |
if ( self::is_ajax() ) {
|
404 |
return true;
|
409 |
return false;
|
410 |
}
|
411 |
|
412 |
+
/**
|
413 |
+
* @return WP_Role|false
|
414 |
+
*/
|
415 |
public static function get_admins() {
|
416 |
if ( is_multisite() ) {
|
417 |
return false;
|
420 |
}
|
421 |
}
|
422 |
|
423 |
+
/**
|
424 |
+
* @return bool
|
425 |
+
*/
|
426 |
public static function is_multi_network() {
|
427 |
global $wpdb;
|
428 |
|
444 |
return ( $num_sites > 1 );
|
445 |
}
|
446 |
|
447 |
+
/**
|
448 |
+
* @param int|string $client
|
449 |
+
* @return array<string, int>
|
450 |
+
* @phpstan-return array{
|
451 |
+
* major: int,
|
452 |
+
* minor: int,
|
453 |
+
* patch: int,
|
454 |
+
* }
|
455 |
+
*/
|
456 |
public static function get_client_version( $client ) {
|
457 |
|
458 |
$client = intval( $client );
|
467 |
|
468 |
}
|
469 |
|
470 |
+
/**
|
471 |
+
* @param string $sql
|
472 |
+
* @return string
|
473 |
+
*/
|
474 |
public static function get_query_type( $sql ) {
|
475 |
// Trim leading whitespace and brackets
|
476 |
$sql = ltrim( $sql, ' \t\n\r\0\x0B(' );
|
486 |
return $type;
|
487 |
}
|
488 |
|
489 |
+
/**
|
490 |
+
* @param mixed $value
|
491 |
+
* @return string|float|int
|
492 |
+
*/
|
493 |
public static function display_variable( $value ) {
|
494 |
if ( is_string( $value ) ) {
|
495 |
return $value;
|
504 |
|
505 |
case ( $value instanceof WP_Post ):
|
506 |
case ( $value instanceof WP_User ):
|
507 |
+
$class = sprintf( '%s (ID: %s)', $class, $value->ID );
|
508 |
break;
|
509 |
|
510 |
case ( $value instanceof WP_Term ):
|
511 |
+
$class = sprintf( '%s (term_id: %s)', $class, $value->term_id );
|
512 |
break;
|
513 |
|
514 |
case ( $value instanceof WP_Comment ):
|
515 |
+
$class = sprintf( '%s (comment_ID: %s)', $class, $value->comment_ID );
|
516 |
break;
|
517 |
|
518 |
case ( $value instanceof WP_Error ):
|
519 |
+
$class = sprintf( '%s (%s)', $class, $value->get_error_code() );
|
520 |
break;
|
521 |
|
522 |
case ( $value instanceof WP_Role ):
|
523 |
case ( $value instanceof WP_Post_Type ):
|
524 |
case ( $value instanceof WP_Taxonomy ):
|
525 |
+
$class = sprintf( '%s (%s)', $class, $value->name );
|
526 |
break;
|
527 |
|
528 |
case ( $value instanceof WP_Network ):
|
529 |
+
$class = sprintf( '%s (id: %s)', $class, $value->id );
|
530 |
break;
|
531 |
|
532 |
case ( $value instanceof WP_Site ):
|
533 |
+
$class = sprintf( '%s (blog_id: %s)', $class, $value->blog_id );
|
534 |
break;
|
535 |
|
536 |
case ( $value instanceof WP_Theme ):
|
537 |
+
$class = sprintf( '%s (%s)', $class, $value->get_stylesheet() );
|
|
|
|
|
|
|
|
|
538 |
break;
|
539 |
|
540 |
}
|
541 |
+
|
542 |
+
return $class;
|
543 |
} else {
|
544 |
return gettype( $value );
|
545 |
}
|
589 |
return $json;
|
590 |
}
|
591 |
|
592 |
+
/**
|
593 |
+
* @param mixed $data
|
594 |
+
* @return bool
|
595 |
+
*/
|
596 |
public static function is_stringy( $data ) {
|
597 |
return ( is_string( $data ) || ( is_object( $data ) && method_exists( $data, '__toString' ) ) );
|
598 |
}
|
599 |
|
600 |
+
/**
|
601 |
+
* @param mixed[] $array
|
602 |
+
* @param string $field
|
603 |
+
* @return void
|
604 |
+
*/
|
605 |
public static function sort( array &$array, $field ) {
|
606 |
self::$sort_field = $field;
|
607 |
usort( $array, array( __CLASS__, '_sort' ) );
|
608 |
}
|
609 |
|
610 |
+
/**
|
611 |
+
* @param mixed[] $array
|
612 |
+
* @param string $field
|
613 |
+
* @return void
|
614 |
+
*/
|
615 |
public static function rsort( array &$array, $field ) {
|
616 |
self::$sort_field = $field;
|
617 |
usort( $array, array( __CLASS__, '_rsort' ) );
|
618 |
}
|
619 |
|
620 |
+
/**
|
621 |
+
* @param array<string, mixed> $a
|
622 |
+
* @param array<string, mixed> $b
|
623 |
+
* @return int
|
624 |
+
* @phpstan-return -1|0|1
|
625 |
+
*/
|
626 |
private static function _rsort( $a, $b ) {
|
627 |
$field = self::$sort_field;
|
628 |
|
633 |
}
|
634 |
}
|
635 |
|
636 |
+
/**
|
637 |
+
* @param array<string, mixed> $a
|
638 |
+
* @param array<string, mixed> $b
|
639 |
+
* @return int
|
640 |
+
* @phpstan-return -1|0|1
|
641 |
+
*/
|
642 |
private static function _sort( $a, $b ) {
|
643 |
$field = self::$sort_field;
|
644 |
|
classes/debug_bar.php
CHANGED
@@ -6,6 +6,9 @@
|
|
6 |
*/
|
7 |
|
8 |
class Debug_Bar {
|
|
|
|
|
|
|
9 |
public $panels = array();
|
10 |
|
11 |
public function __construct() {
|
@@ -15,6 +18,9 @@ class Debug_Bar {
|
|
15 |
$this->init_panels();
|
16 |
}
|
17 |
|
|
|
|
|
|
|
18 |
public function enqueue() {
|
19 |
// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
|
20 |
wp_register_style( 'debug-bar', false, array(
|
@@ -33,6 +39,9 @@ class Debug_Bar {
|
|
33 |
do_action( 'debug_bar_enqueue_scripts' );
|
34 |
}
|
35 |
|
|
|
|
|
|
|
36 |
public function init_panels() {
|
37 |
require_once 'debug_bar_panel.php';
|
38 |
|
@@ -46,6 +55,9 @@ class Debug_Bar {
|
|
46 |
$this->panels = apply_filters( 'debug_bar_panels', array() );
|
47 |
}
|
48 |
|
|
|
|
|
|
|
49 |
public function ensure_ajaxurl() {
|
50 |
$dispatcher = QM_Dispatchers::get( 'html' );
|
51 |
|
@@ -58,6 +70,9 @@ class Debug_Bar {
|
|
58 |
}
|
59 |
}
|
60 |
|
|
|
|
|
|
|
61 |
public function Debug_Bar() {
|
62 |
self::__construct();
|
63 |
}
|
6 |
*/
|
7 |
|
8 |
class Debug_Bar {
|
9 |
+
/**
|
10 |
+
* @var Debug_Bar_Panel[]
|
11 |
+
*/
|
12 |
public $panels = array();
|
13 |
|
14 |
public function __construct() {
|
18 |
$this->init_panels();
|
19 |
}
|
20 |
|
21 |
+
/**
|
22 |
+
* @return void
|
23 |
+
*/
|
24 |
public function enqueue() {
|
25 |
// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
|
26 |
wp_register_style( 'debug-bar', false, array(
|
39 |
do_action( 'debug_bar_enqueue_scripts' );
|
40 |
}
|
41 |
|
42 |
+
/**
|
43 |
+
* @return void
|
44 |
+
*/
|
45 |
public function init_panels() {
|
46 |
require_once 'debug_bar_panel.php';
|
47 |
|
55 |
$this->panels = apply_filters( 'debug_bar_panels', array() );
|
56 |
}
|
57 |
|
58 |
+
/**
|
59 |
+
* @return void
|
60 |
+
*/
|
61 |
public function ensure_ajaxurl() {
|
62 |
$dispatcher = QM_Dispatchers::get( 'html' );
|
63 |
|
70 |
}
|
71 |
}
|
72 |
|
73 |
+
/**
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
public function Debug_Bar() {
|
77 |
self::__construct();
|
78 |
}
|
classes/debug_bar_panel.php
CHANGED
@@ -7,9 +7,19 @@
|
|
7 |
|
8 |
abstract class Debug_Bar_Panel {
|
9 |
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
public $_visible = true;
|
12 |
|
|
|
|
|
|
|
13 |
public function __construct( $title = '' ) {
|
14 |
$this->title( $title );
|
15 |
|
@@ -18,30 +28,47 @@ abstract class Debug_Bar_Panel {
|
|
18 |
return;
|
19 |
}
|
20 |
|
21 |
-
# @TODO convert to QM classes
|
22 |
add_filter( 'debug_bar_classes', array( $this, 'debug_bar_classes' ) );
|
23 |
}
|
24 |
|
25 |
/**
|
26 |
* Initializes the panel.
|
|
|
|
|
27 |
*/
|
28 |
public function init() {}
|
29 |
|
|
|
|
|
|
|
30 |
public function prerender() {}
|
31 |
|
32 |
/**
|
33 |
* Renders the panel.
|
|
|
|
|
34 |
*/
|
35 |
public function render() {}
|
36 |
|
|
|
|
|
|
|
37 |
public function is_visible() {
|
38 |
return $this->_visible;
|
39 |
}
|
40 |
|
|
|
|
|
|
|
|
|
41 |
public function set_visible( $visible ) {
|
42 |
$this->_visible = $visible;
|
43 |
}
|
44 |
|
|
|
|
|
|
|
|
|
45 |
public function title( $title = null ) {
|
46 |
if ( ! isset( $title ) ) {
|
47 |
return $this->_title;
|
@@ -49,10 +76,18 @@ abstract class Debug_Bar_Panel {
|
|
49 |
$this->_title = $title;
|
50 |
}
|
51 |
|
|
|
|
|
|
|
|
|
52 |
public function debug_bar_classes( $classes ) {
|
53 |
return $classes;
|
54 |
}
|
55 |
|
|
|
|
|
|
|
|
|
56 |
public function Debug_Bar_Panel( $title = '' ) {
|
57 |
self::__construct( $title );
|
58 |
}
|
7 |
|
8 |
abstract class Debug_Bar_Panel {
|
9 |
|
10 |
+
/**
|
11 |
+
* @var string
|
12 |
+
*/
|
13 |
+
public $_title = '';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var bool
|
17 |
+
*/
|
18 |
public $_visible = true;
|
19 |
|
20 |
+
/**
|
21 |
+
* @param string $title
|
22 |
+
*/
|
23 |
public function __construct( $title = '' ) {
|
24 |
$this->title( $title );
|
25 |
|
28 |
return;
|
29 |
}
|
30 |
|
|
|
31 |
add_filter( 'debug_bar_classes', array( $this, 'debug_bar_classes' ) );
|
32 |
}
|
33 |
|
34 |
/**
|
35 |
* Initializes the panel.
|
36 |
+
*
|
37 |
+
* @return false|void
|
38 |
*/
|
39 |
public function init() {}
|
40 |
|
41 |
+
/**
|
42 |
+
* @return void
|
43 |
+
*/
|
44 |
public function prerender() {}
|
45 |
|
46 |
/**
|
47 |
* Renders the panel.
|
48 |
+
*
|
49 |
+
* @return void
|
50 |
*/
|
51 |
public function render() {}
|
52 |
|
53 |
+
/**
|
54 |
+
* @return bool
|
55 |
+
*/
|
56 |
public function is_visible() {
|
57 |
return $this->_visible;
|
58 |
}
|
59 |
|
60 |
+
/**
|
61 |
+
* @param bool $visible
|
62 |
+
* @return void
|
63 |
+
*/
|
64 |
public function set_visible( $visible ) {
|
65 |
$this->_visible = $visible;
|
66 |
}
|
67 |
|
68 |
+
/**
|
69 |
+
* @param string|null $title
|
70 |
+
* @return string|void
|
71 |
+
*/
|
72 |
public function title( $title = null ) {
|
73 |
if ( ! isset( $title ) ) {
|
74 |
return $this->_title;
|
76 |
$this->_title = $title;
|
77 |
}
|
78 |
|
79 |
+
/**
|
80 |
+
* @param array<int, string> $classes
|
81 |
+
* @return array<int, string>
|
82 |
+
*/
|
83 |
public function debug_bar_classes( $classes ) {
|
84 |
return $classes;
|
85 |
}
|
86 |
|
87 |
+
/**
|
88 |
+
* @param string $title
|
89 |
+
* @return void
|
90 |
+
*/
|
91 |
public function Debug_Bar_Panel( $title = '' ) {
|
92 |
self::__construct( $title );
|
93 |
}
|
collectors/admin.php
CHANGED
@@ -5,12 +5,17 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Admin extends QM_Collector {
|
11 |
|
12 |
public $id = 'response';
|
13 |
|
|
|
|
|
|
|
14 |
public function get_concerned_actions() {
|
15 |
$actions = array(
|
16 |
'current_screen',
|
@@ -27,6 +32,9 @@ class QM_Collector_Admin extends QM_Collector {
|
|
27 |
return $actions;
|
28 |
}
|
29 |
|
|
|
|
|
|
|
30 |
public function get_concerned_filters() {
|
31 |
$filters = array();
|
32 |
|
@@ -38,6 +46,9 @@ class QM_Collector_Admin extends QM_Collector {
|
|
38 |
return $filters;
|
39 |
}
|
40 |
|
|
|
|
|
|
|
41 |
public function process() {
|
42 |
|
43 |
global $pagenow, $wp_list_table;
|
@@ -50,24 +61,24 @@ class QM_Collector_Admin extends QM_Collector {
|
|
50 |
$this->data['base'] = $pagenow;
|
51 |
}
|
52 |
|
53 |
-
$this->data['pagenow']
|
54 |
-
$this->data['typenow']
|
55 |
-
$this->data['taxnow']
|
56 |
-
$this->data['hook_suffix']
|
57 |
$this->data['current_screen'] = ( $current_screen ) ? get_object_vars( $current_screen ) : null;
|
58 |
|
59 |
$screens = array(
|
60 |
-
'edit'
|
61 |
-
'edit-comments'
|
62 |
-
'edit-tags'
|
63 |
-
'link-manager'
|
64 |
-
'plugins'
|
65 |
'plugins-network' => true,
|
66 |
-
'sites-network'
|
67 |
-
'themes-network'
|
68 |
-
'upload'
|
69 |
-
'users'
|
70 |
-
'users-network'
|
71 |
);
|
72 |
|
73 |
if ( ! empty( $this->data['current_screen'] ) && isset( $screens[ $this->data['current_screen']['base'] ] ) ) {
|
@@ -101,9 +112,9 @@ class QM_Collector_Admin extends QM_Collector {
|
|
101 |
$list_table['sortables'] = $this->data['current_screen']['id'];
|
102 |
|
103 |
$this->data['list_table'] = array(
|
104 |
-
'columns_filter'
|
105 |
'sortables_filter' => "manage_{$list_table['sortables']}_sortable_columns",
|
106 |
-
'column_action'
|
107 |
);
|
108 |
|
109 |
if ( ! empty( $wp_list_table ) ) {
|
@@ -115,6 +126,11 @@ class QM_Collector_Admin extends QM_Collector {
|
|
115 |
|
116 |
}
|
117 |
|
|
|
|
|
|
|
|
|
|
|
118 |
function register_qm_collector_admin( array $collectors, QueryMonitor $qm ) {
|
119 |
$collectors['response'] = new QM_Collector_Admin();
|
120 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Admin extends QM_Collector {
|
13 |
|
14 |
public $id = 'response';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return array<int, string>
|
18 |
+
*/
|
19 |
public function get_concerned_actions() {
|
20 |
$actions = array(
|
21 |
'current_screen',
|
32 |
return $actions;
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* @return array<int, string>
|
37 |
+
*/
|
38 |
public function get_concerned_filters() {
|
39 |
$filters = array();
|
40 |
|
46 |
return $filters;
|
47 |
}
|
48 |
|
49 |
+
/**
|
50 |
+
* @return void
|
51 |
+
*/
|
52 |
public function process() {
|
53 |
|
54 |
global $pagenow, $wp_list_table;
|
61 |
$this->data['base'] = $pagenow;
|
62 |
}
|
63 |
|
64 |
+
$this->data['pagenow'] = $pagenow;
|
65 |
+
$this->data['typenow'] = isset( $GLOBALS['typenow'] ) ? $GLOBALS['typenow'] : '';
|
66 |
+
$this->data['taxnow'] = isset( $GLOBALS['taxnow'] ) ? $GLOBALS['taxnow'] : '';
|
67 |
+
$this->data['hook_suffix'] = isset( $GLOBALS['hook_suffix'] ) ? $GLOBALS['hook_suffix'] : '';
|
68 |
$this->data['current_screen'] = ( $current_screen ) ? get_object_vars( $current_screen ) : null;
|
69 |
|
70 |
$screens = array(
|
71 |
+
'edit' => true,
|
72 |
+
'edit-comments' => true,
|
73 |
+
'edit-tags' => true,
|
74 |
+
'link-manager' => true,
|
75 |
+
'plugins' => true,
|
76 |
'plugins-network' => true,
|
77 |
+
'sites-network' => true,
|
78 |
+
'themes-network' => true,
|
79 |
+
'upload' => true,
|
80 |
+
'users' => true,
|
81 |
+
'users-network' => true,
|
82 |
);
|
83 |
|
84 |
if ( ! empty( $this->data['current_screen'] ) && isset( $screens[ $this->data['current_screen']['base'] ] ) ) {
|
112 |
$list_table['sortables'] = $this->data['current_screen']['id'];
|
113 |
|
114 |
$this->data['list_table'] = array(
|
115 |
+
'columns_filter' => "manage_{$list_table['columns']}_columns",
|
116 |
'sortables_filter' => "manage_{$list_table['sortables']}_sortable_columns",
|
117 |
+
'column_action' => "manage_{$list_table['column']}_custom_column",
|
118 |
);
|
119 |
|
120 |
if ( ! empty( $wp_list_table ) ) {
|
126 |
|
127 |
}
|
128 |
|
129 |
+
/**
|
130 |
+
* @param array<string, QM_Collector> $collectors
|
131 |
+
* @param QueryMonitor $qm
|
132 |
+
* @return array<string, QM_Collector>
|
133 |
+
*/
|
134 |
function register_qm_collector_admin( array $collectors, QueryMonitor $qm ) {
|
135 |
$collectors['response'] = new QM_Collector_Admin();
|
136 |
return $collectors;
|
collectors/assets.php
CHANGED
@@ -5,28 +5,56 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
abstract class QM_Collector_Assets extends QM_Collector {
|
11 |
|
12 |
-
|
13 |
-
|
|
|
|
|
|
|
14 |
add_action( 'admin_print_footer_scripts', array( $this, 'action_print_footer_scripts' ) );
|
15 |
-
add_action( 'wp_print_footer_scripts',
|
16 |
-
add_action( 'admin_head',
|
17 |
-
add_action( 'wp_head',
|
18 |
-
add_action( 'login_head',
|
19 |
-
add_action( 'embed_head',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
}
|
21 |
|
|
|
|
|
|
|
22 |
abstract public function get_dependency_type();
|
23 |
|
|
|
|
|
|
|
24 |
public function action_head() {
|
25 |
$type = $this->get_dependency_type();
|
26 |
|
27 |
$this->data['header'] = $GLOBALS[ "wp_{$type}" ]->done;
|
28 |
}
|
29 |
|
|
|
|
|
|
|
30 |
public function action_print_footer_scripts() {
|
31 |
if ( empty( $this->data['header'] ) ) {
|
32 |
return;
|
@@ -38,16 +66,20 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
38 |
|
39 |
}
|
40 |
|
|
|
|
|
|
|
41 |
public function process() {
|
42 |
if ( empty( $this->data['header'] ) && empty( $this->data['footer'] ) ) {
|
43 |
return;
|
44 |
}
|
45 |
|
46 |
-
$this->data['is_ssl']
|
47 |
-
$this->data['host']
|
48 |
$this->data['default_version'] = get_bloginfo( 'version' );
|
|
|
49 |
|
50 |
-
$home_url
|
51 |
$positions = array(
|
52 |
'missing',
|
53 |
'broken',
|
@@ -57,10 +89,10 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
57 |
|
58 |
$this->data['counts'] = array(
|
59 |
'missing' => 0,
|
60 |
-
'broken'
|
61 |
-
'header'
|
62 |
-
'footer'
|
63 |
-
'total'
|
64 |
);
|
65 |
|
66 |
$type = $this->get_dependency_type();
|
@@ -70,8 +102,8 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
70 |
$this->data[ $position ] = array();
|
71 |
}
|
72 |
}
|
73 |
-
$raw
|
74 |
-
$broken
|
75 |
$missing = array_values( array_diff( $raw->queue, array_keys( $raw->registered ) ) );
|
76 |
|
77 |
// A broken asset is one which has been deregistered without also being dequeued
|
@@ -104,7 +136,7 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
104 |
}
|
105 |
|
106 |
$all_dependencies = array();
|
107 |
-
$all_dependents
|
108 |
|
109 |
$missing_dependencies = array();
|
110 |
|
@@ -121,10 +153,10 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
121 |
}
|
122 |
|
123 |
$all_dependencies = array_merge( $all_dependencies, $dependency->deps );
|
124 |
-
$dependents
|
125 |
-
$all_dependents
|
126 |
|
127 |
-
list( $host, $source, $local ) = $this->get_dependency_data( $dependency );
|
128 |
|
129 |
if ( empty( $dependency->ver ) ) {
|
130 |
$ver = '';
|
@@ -137,7 +169,7 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
137 |
if ( is_wp_error( $source ) ) {
|
138 |
$display = $source->get_error_message();
|
139 |
} else {
|
140 |
-
$display = ltrim( str_replace( $home_url, '', remove_query_arg( 'ver', $source ) ), '/' );
|
141 |
}
|
142 |
|
143 |
$dependencies = $dependency->deps;
|
@@ -150,13 +182,14 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
150 |
}
|
151 |
|
152 |
$this->data['assets'][ $position ][ $handle ] = array(
|
153 |
-
'host'
|
154 |
-
'
|
155 |
-
'
|
156 |
-
'
|
157 |
-
'
|
158 |
-
'
|
159 |
-
'
|
|
|
160 |
'dependencies' => $dependencies,
|
161 |
);
|
162 |
|
@@ -178,12 +211,17 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
178 |
$this->data['missing_dependencies'] = $missing_dependencies;
|
179 |
}
|
180 |
|
|
|
|
|
|
|
|
|
|
|
181 |
protected static function get_broken_dependencies( _WP_Dependency $item, WP_Dependencies $dependencies ) {
|
182 |
$broken = array();
|
183 |
|
184 |
foreach ( $item->deps as $handle ) {
|
185 |
$dep = $dependencies->query( $handle );
|
186 |
-
if ( $dep ) {
|
187 |
$broken = array_merge( $broken, self::get_broken_dependencies( $dep, $dependencies ) );
|
188 |
} else {
|
189 |
$broken[] = $item->handle;
|
@@ -193,13 +231,18 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
193 |
return $broken;
|
194 |
}
|
195 |
|
|
|
|
|
|
|
|
|
|
|
196 |
public function get_dependents( _WP_Dependency $dependency, WP_Dependencies $dependencies ) {
|
197 |
$dependents = array();
|
198 |
-
$handles
|
199 |
|
200 |
foreach ( $handles as $handle ) {
|
201 |
$item = $dependencies->query( $handle );
|
202 |
-
if ( $item ) {
|
203 |
if ( in_array( $dependency->handle, $item->deps, true ) ) {
|
204 |
$dependents[] = $handle;
|
205 |
}
|
@@ -211,10 +254,19 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
211 |
return $dependents;
|
212 |
}
|
213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
public function get_dependency_data( _WP_Dependency $dependency ) {
|
215 |
-
$data
|
216 |
$loader = rtrim( $this->get_dependency_type(), 's' );
|
217 |
-
$src
|
218 |
|
219 |
if ( null === $dependency->ver ) {
|
220 |
$ver = '';
|
@@ -229,12 +281,15 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
229 |
/** This filter is documented in wp-includes/class.wp-scripts.php */
|
230 |
$source = apply_filters( "{$loader}_loader_src", $src, $dependency->handle );
|
231 |
|
232 |
-
$host
|
233 |
-
$scheme
|
|
|
234 |
$http_host = $data['host'];
|
|
|
235 |
|
236 |
if ( empty( $host ) && ! empty( $http_host ) ) {
|
237 |
$host = $http_host;
|
|
|
238 |
}
|
239 |
|
240 |
if ( $scheme && $data['is_ssl'] && ( 'https' !== $scheme ) && ( 'localhost' !== $host ) ) {
|
@@ -250,12 +305,12 @@ abstract class QM_Collector_Assets extends QM_Collector {
|
|
250 |
}
|
251 |
} elseif ( empty( $source ) ) {
|
252 |
$source = '';
|
253 |
-
$host
|
254 |
}
|
255 |
|
256 |
$local = ( $http_host === $host );
|
257 |
|
258 |
-
return array( $host, $source, $local );
|
259 |
}
|
260 |
|
261 |
}
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
abstract class QM_Collector_Assets extends QM_Collector {
|
13 |
|
14 |
+
/**
|
15 |
+
* @return void
|
16 |
+
*/
|
17 |
+
public function set_up() {
|
18 |
+
parent::set_up();
|
19 |
add_action( 'admin_print_footer_scripts', array( $this, 'action_print_footer_scripts' ) );
|
20 |
+
add_action( 'wp_print_footer_scripts', array( $this, 'action_print_footer_scripts' ) );
|
21 |
+
add_action( 'admin_head', array( $this, 'action_head' ), 9999 );
|
22 |
+
add_action( 'wp_head', array( $this, 'action_head' ), 9999 );
|
23 |
+
add_action( 'login_head', array( $this, 'action_head' ), 9999 );
|
24 |
+
add_action( 'embed_head', array( $this, 'action_head' ), 9999 );
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @return void
|
29 |
+
*/
|
30 |
+
public function tear_down() {
|
31 |
+
remove_action( 'admin_print_footer_scripts', array( $this, 'action_print_footer_scripts' ) );
|
32 |
+
remove_action( 'wp_print_footer_scripts', array( $this, 'action_print_footer_scripts' ) );
|
33 |
+
remove_action( 'admin_head', array( $this, 'action_head' ), 9999 );
|
34 |
+
remove_action( 'wp_head', array( $this, 'action_head' ), 9999 );
|
35 |
+
remove_action( 'login_head', array( $this, 'action_head' ), 9999 );
|
36 |
+
remove_action( 'embed_head', array( $this, 'action_head' ), 9999 );
|
37 |
+
|
38 |
+
parent::tear_down();
|
39 |
}
|
40 |
|
41 |
+
/**
|
42 |
+
* @return string
|
43 |
+
*/
|
44 |
abstract public function get_dependency_type();
|
45 |
|
46 |
+
/**
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
public function action_head() {
|
50 |
$type = $this->get_dependency_type();
|
51 |
|
52 |
$this->data['header'] = $GLOBALS[ "wp_{$type}" ]->done;
|
53 |
}
|
54 |
|
55 |
+
/**
|
56 |
+
* @return void
|
57 |
+
*/
|
58 |
public function action_print_footer_scripts() {
|
59 |
if ( empty( $this->data['header'] ) ) {
|
60 |
return;
|
66 |
|
67 |
}
|
68 |
|
69 |
+
/**
|
70 |
+
* @return void
|
71 |
+
*/
|
72 |
public function process() {
|
73 |
if ( empty( $this->data['header'] ) && empty( $this->data['footer'] ) ) {
|
74 |
return;
|
75 |
}
|
76 |
|
77 |
+
$this->data['is_ssl'] = is_ssl();
|
78 |
+
$this->data['host'] = wp_unslash( $_SERVER['HTTP_HOST'] );
|
79 |
$this->data['default_version'] = get_bloginfo( 'version' );
|
80 |
+
$this->data['port'] = (string) parse_url( $this->data['host'], PHP_URL_PORT );
|
81 |
|
82 |
+
$home_url = home_url();
|
83 |
$positions = array(
|
84 |
'missing',
|
85 |
'broken',
|
89 |
|
90 |
$this->data['counts'] = array(
|
91 |
'missing' => 0,
|
92 |
+
'broken' => 0,
|
93 |
+
'header' => 0,
|
94 |
+
'footer' => 0,
|
95 |
+
'total' => 0,
|
96 |
);
|
97 |
|
98 |
$type = $this->get_dependency_type();
|
102 |
$this->data[ $position ] = array();
|
103 |
}
|
104 |
}
|
105 |
+
$raw = $GLOBALS[ "wp_{$type}" ];
|
106 |
+
$broken = array_values( array_diff( $raw->queue, $raw->done ) );
|
107 |
$missing = array_values( array_diff( $raw->queue, array_keys( $raw->registered ) ) );
|
108 |
|
109 |
// A broken asset is one which has been deregistered without also being dequeued
|
136 |
}
|
137 |
|
138 |
$all_dependencies = array();
|
139 |
+
$all_dependents = array();
|
140 |
|
141 |
$missing_dependencies = array();
|
142 |
|
153 |
}
|
154 |
|
155 |
$all_dependencies = array_merge( $all_dependencies, $dependency->deps );
|
156 |
+
$dependents = $this->get_dependents( $dependency, $raw );
|
157 |
+
$all_dependents = array_merge( $all_dependents, $dependents );
|
158 |
|
159 |
+
list( $host, $source, $local, $port ) = $this->get_dependency_data( $dependency );
|
160 |
|
161 |
if ( empty( $dependency->ver ) ) {
|
162 |
$ver = '';
|
169 |
if ( is_wp_error( $source ) ) {
|
170 |
$display = $source->get_error_message();
|
171 |
} else {
|
172 |
+
$display = ltrim( str_replace( "{$home_url}/", '/', remove_query_arg( 'ver', $source ) ), '/' );
|
173 |
}
|
174 |
|
175 |
$dependencies = $dependency->deps;
|
182 |
}
|
183 |
|
184 |
$this->data['assets'][ $position ][ $handle ] = array(
|
185 |
+
'host' => $host,
|
186 |
+
'port' => $port,
|
187 |
+
'source' => $source,
|
188 |
+
'local' => $local,
|
189 |
+
'ver' => $ver,
|
190 |
+
'warning' => $warning,
|
191 |
+
'display' => $display,
|
192 |
+
'dependents' => $dependents,
|
193 |
'dependencies' => $dependencies,
|
194 |
);
|
195 |
|
211 |
$this->data['missing_dependencies'] = $missing_dependencies;
|
212 |
}
|
213 |
|
214 |
+
/**
|
215 |
+
* @param _WP_Dependency $item
|
216 |
+
* @param WP_Dependencies $dependencies
|
217 |
+
* @return array<int, string>
|
218 |
+
*/
|
219 |
protected static function get_broken_dependencies( _WP_Dependency $item, WP_Dependencies $dependencies ) {
|
220 |
$broken = array();
|
221 |
|
222 |
foreach ( $item->deps as $handle ) {
|
223 |
$dep = $dependencies->query( $handle );
|
224 |
+
if ( $dep instanceof _WP_Dependency ) {
|
225 |
$broken = array_merge( $broken, self::get_broken_dependencies( $dep, $dependencies ) );
|
226 |
} else {
|
227 |
$broken[] = $item->handle;
|
231 |
return $broken;
|
232 |
}
|
233 |
|
234 |
+
/**
|
235 |
+
* @param _WP_Dependency $dependency
|
236 |
+
* @param WP_Dependencies $dependencies
|
237 |
+
* @return array<int, string>
|
238 |
+
*/
|
239 |
public function get_dependents( _WP_Dependency $dependency, WP_Dependencies $dependencies ) {
|
240 |
$dependents = array();
|
241 |
+
$handles = array_unique( array_merge( $dependencies->queue, $dependencies->done ) );
|
242 |
|
243 |
foreach ( $handles as $handle ) {
|
244 |
$item = $dependencies->query( $handle );
|
245 |
+
if ( $item instanceof _WP_Dependency ) {
|
246 |
if ( in_array( $dependency->handle, $item->deps, true ) ) {
|
247 |
$dependents[] = $handle;
|
248 |
}
|
254 |
return $dependents;
|
255 |
}
|
256 |
|
257 |
+
/**
|
258 |
+
* @param _WP_Dependency $dependency
|
259 |
+
* @return array{
|
260 |
+
* 0: string,
|
261 |
+
* 1: string|WP_Error,
|
262 |
+
* 2: bool,
|
263 |
+
* 3: string,
|
264 |
+
* }
|
265 |
+
*/
|
266 |
public function get_dependency_data( _WP_Dependency $dependency ) {
|
267 |
+
$data = $this->get_data();
|
268 |
$loader = rtrim( $this->get_dependency_type(), 's' );
|
269 |
+
$src = $dependency->src;
|
270 |
|
271 |
if ( null === $dependency->ver ) {
|
272 |
$ver = '';
|
281 |
/** This filter is documented in wp-includes/class.wp-scripts.php */
|
282 |
$source = apply_filters( "{$loader}_loader_src", $src, $dependency->handle );
|
283 |
|
284 |
+
$host = (string) parse_url( $source, PHP_URL_HOST );
|
285 |
+
$scheme = (string) parse_url( $source, PHP_URL_SCHEME );
|
286 |
+
$port = (string) parse_url( $source, PHP_URL_PORT );
|
287 |
$http_host = $data['host'];
|
288 |
+
$http_port = $data['port'];
|
289 |
|
290 |
if ( empty( $host ) && ! empty( $http_host ) ) {
|
291 |
$host = $http_host;
|
292 |
+
$port = $http_port;
|
293 |
}
|
294 |
|
295 |
if ( $scheme && $data['is_ssl'] && ( 'https' !== $scheme ) && ( 'localhost' !== $host ) ) {
|
305 |
}
|
306 |
} elseif ( empty( $source ) ) {
|
307 |
$source = '';
|
308 |
+
$host = '';
|
309 |
}
|
310 |
|
311 |
$local = ( $http_host === $host );
|
312 |
|
313 |
+
return array( $host, $source, $local, $port );
|
314 |
}
|
315 |
|
316 |
}
|
collectors/assets_scripts.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Assets_Scripts extends QM_Collector_Assets {
|
11 |
|
@@ -15,6 +17,9 @@ class QM_Collector_Assets_Scripts extends QM_Collector_Assets {
|
|
15 |
return 'scripts';
|
16 |
}
|
17 |
|
|
|
|
|
|
|
18 |
public function get_concerned_actions() {
|
19 |
if ( is_admin() ) {
|
20 |
return array(
|
@@ -31,6 +36,9 @@ class QM_Collector_Assets_Scripts extends QM_Collector_Assets {
|
|
31 |
}
|
32 |
}
|
33 |
|
|
|
|
|
|
|
34 |
public function get_concerned_filters() {
|
35 |
return array(
|
36 |
'print_scripts_array',
|
@@ -40,6 +48,11 @@ class QM_Collector_Assets_Scripts extends QM_Collector_Assets {
|
|
40 |
}
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
function register_qm_collector_assets_scripts( array $collectors, QueryMonitor $qm ) {
|
44 |
$collectors['assets_scripts'] = new QM_Collector_Assets_Scripts();
|
45 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Assets_Scripts extends QM_Collector_Assets {
|
13 |
|
17 |
return 'scripts';
|
18 |
}
|
19 |
|
20 |
+
/**
|
21 |
+
* @return array<int, string>
|
22 |
+
*/
|
23 |
public function get_concerned_actions() {
|
24 |
if ( is_admin() ) {
|
25 |
return array(
|
36 |
}
|
37 |
}
|
38 |
|
39 |
+
/**
|
40 |
+
* @return array<int, string>
|
41 |
+
*/
|
42 |
public function get_concerned_filters() {
|
43 |
return array(
|
44 |
'print_scripts_array',
|
48 |
}
|
49 |
}
|
50 |
|
51 |
+
/**
|
52 |
+
* @param array<string, QM_Collector> $collectors
|
53 |
+
* @param QueryMonitor $qm
|
54 |
+
* @return array<string, QM_Collector>
|
55 |
+
*/
|
56 |
function register_qm_collector_assets_scripts( array $collectors, QueryMonitor $qm ) {
|
57 |
$collectors['assets_scripts'] = new QM_Collector_Assets_Scripts();
|
58 |
return $collectors;
|
collectors/assets_styles.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Assets_Styles extends QM_Collector_Assets {
|
11 |
|
@@ -15,6 +17,9 @@ class QM_Collector_Assets_Styles extends QM_Collector_Assets {
|
|
15 |
return 'styles';
|
16 |
}
|
17 |
|
|
|
|
|
|
|
18 |
public function get_concerned_filters() {
|
19 |
return array(
|
20 |
'print_styles_array',
|
@@ -24,6 +29,11 @@ class QM_Collector_Assets_Styles extends QM_Collector_Assets {
|
|
24 |
}
|
25 |
}
|
26 |
|
|
|
|
|
|
|
|
|
|
|
27 |
function register_qm_collector_assets_styles( array $collectors, QueryMonitor $qm ) {
|
28 |
$collectors['assets_styles'] = new QM_Collector_Assets_Styles();
|
29 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Assets_Styles extends QM_Collector_Assets {
|
13 |
|
17 |
return 'styles';
|
18 |
}
|
19 |
|
20 |
+
/**
|
21 |
+
* @return array<int, string>
|
22 |
+
*/
|
23 |
public function get_concerned_filters() {
|
24 |
return array(
|
25 |
'print_styles_array',
|
29 |
}
|
30 |
}
|
31 |
|
32 |
+
/**
|
33 |
+
* @param array<string, QM_Collector> $collectors
|
34 |
+
* @param QueryMonitor $qm
|
35 |
+
* @return array<string, QM_Collector>
|
36 |
+
*/
|
37 |
function register_qm_collector_assets_styles( array $collectors, QueryMonitor $qm ) {
|
38 |
$collectors['assets_styles'] = new QM_Collector_Assets_Styles();
|
39 |
return $collectors;
|
collectors/block_editor.php
CHANGED
@@ -5,36 +5,78 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Block_Editor extends QM_Collector {
|
11 |
|
12 |
public $id = 'block_editor';
|
13 |
|
|
|
|
|
|
|
14 |
protected $block_context = array();
|
|
|
|
|
|
|
|
|
15 |
protected $block_timing = array();
|
16 |
-
protected $block_timer = null;
|
17 |
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
-
add_filter( 'pre_render_block',
|
22 |
add_filter( 'render_block_context', array( $this, 'filter_render_block_context' ), -9999, 2 );
|
23 |
add_filter( 'render_block_data', array( $this, 'filter_render_block_data' ), -9999 );
|
24 |
-
add_filter( 'render_block',
|
25 |
}
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
public function get_concerned_filters() {
|
28 |
return array(
|
29 |
'allowed_block_types',
|
|
|
|
|
|
|
|
|
30 |
'block_parser_class',
|
31 |
'pre_render_block',
|
|
|
32 |
'render_block_context',
|
33 |
'render_block_data',
|
34 |
'render_block',
|
|
|
35 |
);
|
36 |
}
|
37 |
|
|
|
|
|
|
|
|
|
|
|
38 |
public function filter_pre_render_block( $pre_render, array $block ) {
|
39 |
if ( null !== $pre_render ) {
|
40 |
$this->block_timing[] = false;
|
@@ -43,12 +85,21 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
43 |
return $pre_render;
|
44 |
}
|
45 |
|
|
|
|
|
|
|
|
|
|
|
46 |
public function filter_render_block_context( array $context, array $block ) {
|
47 |
$this->block_context[] = $context;
|
48 |
|
49 |
return $context;
|
50 |
}
|
51 |
|
|
|
|
|
|
|
|
|
52 |
public function filter_render_block_data( array $block ) {
|
53 |
$this->block_timer = new QM_Timer();
|
54 |
$this->block_timer->start();
|
@@ -56,6 +107,11 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
56 |
return $block;
|
57 |
}
|
58 |
|
|
|
|
|
|
|
|
|
|
|
59 |
public function filter_render_block( $block_content, array $block ) {
|
60 |
if ( isset( $this->block_timer ) ) {
|
61 |
$this->block_timing[] = $this->block_timer->stop();
|
@@ -80,21 +136,25 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
80 |
return;
|
81 |
}
|
82 |
|
83 |
-
$this->data['post_has_blocks']
|
84 |
-
$this->data['post_blocks']
|
85 |
$this->data['all_dynamic_blocks'] = self::wp_get_dynamic_block_names();
|
86 |
-
$this->data['total_blocks']
|
87 |
-
$this->data['has_block_context']
|
88 |
-
$this->data['has_block_timing']
|
89 |
|
90 |
if ( $this->data['post_has_blocks'] ) {
|
91 |
$this->data['post_blocks'] = array_values( array_filter( array_map( array( $this, 'process_block' ), $this->data['post_blocks'] ) ) );
|
92 |
}
|
93 |
}
|
94 |
|
|
|
|
|
|
|
|
|
95 |
protected function process_block( array $block ) {
|
96 |
$context = array_shift( $this->block_context );
|
97 |
-
$timing
|
98 |
|
99 |
// Remove empty blocks caused by two consecutive line breaks in content
|
100 |
if ( ! $block['blockName'] && ! trim( $block['innerHTML'] ) ) {
|
@@ -104,11 +164,11 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
104 |
$this->data['total_blocks']++;
|
105 |
|
106 |
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
|
107 |
-
$dynamic
|
108 |
-
$callback
|
109 |
|
110 |
if ( $block_type && $block_type->is_dynamic() ) {
|
111 |
-
$dynamic
|
112 |
$callback = QM_Util::populate_callback( array(
|
113 |
'function' => $block_type->render_callback,
|
114 |
) );
|
@@ -116,10 +176,10 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
116 |
|
117 |
$timing = array_shift( $this->block_timing );
|
118 |
|
119 |
-
$block['dynamic']
|
120 |
-
$block['callback']
|
121 |
$block['innerHTML'] = trim( $block['innerHTML'] );
|
122 |
-
$block['size']
|
123 |
|
124 |
if ( $context ) {
|
125 |
$block['context'] = $context;
|
@@ -138,10 +198,17 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
138 |
return $block;
|
139 |
}
|
140 |
|
|
|
|
|
|
|
141 |
protected static function wp_block_editor_enabled() {
|
142 |
return ( function_exists( 'parse_blocks' ) || function_exists( 'gutenberg_parse_blocks' ) );
|
143 |
}
|
144 |
|
|
|
|
|
|
|
|
|
145 |
protected static function wp_has_blocks( $content ) {
|
146 |
if ( function_exists( 'has_blocks' ) ) {
|
147 |
return has_blocks( $content );
|
@@ -152,6 +219,10 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
152 |
return false;
|
153 |
}
|
154 |
|
|
|
|
|
|
|
|
|
155 |
protected static function wp_parse_blocks( $content ) {
|
156 |
if ( function_exists( 'parse_blocks' ) ) {
|
157 |
return parse_blocks( $content );
|
@@ -162,6 +233,9 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
162 |
return null;
|
163 |
}
|
164 |
|
|
|
|
|
|
|
165 |
protected static function wp_get_dynamic_block_names() {
|
166 |
if ( function_exists( 'get_dynamic_block_names' ) ) {
|
167 |
return get_dynamic_block_names();
|
@@ -172,6 +246,11 @@ class QM_Collector_Block_Editor extends QM_Collector {
|
|
172 |
|
173 |
}
|
174 |
|
|
|
|
|
|
|
|
|
|
|
175 |
function register_qm_collector_block_editor( array $collectors, QueryMonitor $qm ) {
|
176 |
$collectors['block_editor'] = new QM_Collector_Block_Editor();
|
177 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Block_Editor extends QM_Collector {
|
13 |
|
14 |
public $id = 'block_editor';
|
15 |
|
16 |
+
/**
|
17 |
+
* @var array<int, mixed[]>
|
18 |
+
*/
|
19 |
protected $block_context = array();
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var array<int, QM_Timer|false>
|
23 |
+
*/
|
24 |
protected $block_timing = array();
|
|
|
25 |
|
26 |
+
/**
|
27 |
+
* @var QM_Timer|null
|
28 |
+
*/
|
29 |
+
protected $block_timer = null;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* @return void
|
33 |
+
*/
|
34 |
+
public function set_up() {
|
35 |
+
parent::set_up();
|
36 |
|
37 |
+
add_filter( 'pre_render_block', array( $this, 'filter_pre_render_block' ), 9999, 2 );
|
38 |
add_filter( 'render_block_context', array( $this, 'filter_render_block_context' ), -9999, 2 );
|
39 |
add_filter( 'render_block_data', array( $this, 'filter_render_block_data' ), -9999 );
|
40 |
+
add_filter( 'render_block', array( $this, 'filter_render_block' ), 9999, 2 );
|
41 |
}
|
42 |
|
43 |
+
/**
|
44 |
+
* @return void
|
45 |
+
*/
|
46 |
+
public function tear_down() {
|
47 |
+
remove_filter( 'pre_render_block', array( $this, 'filter_pre_render_block' ), 9999 );
|
48 |
+
remove_filter( 'render_block_context', array( $this, 'filter_render_block_context' ), -9999 );
|
49 |
+
remove_filter( 'render_block_data', array( $this, 'filter_render_block_data' ), -9999 );
|
50 |
+
remove_filter( 'render_block', array( $this, 'filter_render_block' ), 9999 );
|
51 |
+
|
52 |
+
parent::tear_down();
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @return array<int, string>
|
57 |
+
*/
|
58 |
public function get_concerned_filters() {
|
59 |
return array(
|
60 |
'allowed_block_types',
|
61 |
+
'allowed_block_types_all',
|
62 |
+
'block_editor_settings_all',
|
63 |
+
'block_type_metadata',
|
64 |
+
'block_type_metadata_settings',
|
65 |
'block_parser_class',
|
66 |
'pre_render_block',
|
67 |
+
'register_block_type_args',
|
68 |
'render_block_context',
|
69 |
'render_block_data',
|
70 |
'render_block',
|
71 |
+
'use_widgets_block_editor',
|
72 |
);
|
73 |
}
|
74 |
|
75 |
+
/**
|
76 |
+
* @param string|null $pre_render
|
77 |
+
* @param mixed[] $block
|
78 |
+
* @return string|null
|
79 |
+
*/
|
80 |
public function filter_pre_render_block( $pre_render, array $block ) {
|
81 |
if ( null !== $pre_render ) {
|
82 |
$this->block_timing[] = false;
|
85 |
return $pre_render;
|
86 |
}
|
87 |
|
88 |
+
/**
|
89 |
+
* @param mixed[] $context
|
90 |
+
* @param mixed[] $block
|
91 |
+
* @return mixed[]
|
92 |
+
*/
|
93 |
public function filter_render_block_context( array $context, array $block ) {
|
94 |
$this->block_context[] = $context;
|
95 |
|
96 |
return $context;
|
97 |
}
|
98 |
|
99 |
+
/**
|
100 |
+
* @param mixed[] $block
|
101 |
+
* @return mixed[]
|
102 |
+
*/
|
103 |
public function filter_render_block_data( array $block ) {
|
104 |
$this->block_timer = new QM_Timer();
|
105 |
$this->block_timer->start();
|
107 |
return $block;
|
108 |
}
|
109 |
|
110 |
+
/**
|
111 |
+
* @param string $block_content
|
112 |
+
* @param mixed[] $block
|
113 |
+
* @return string
|
114 |
+
*/
|
115 |
public function filter_render_block( $block_content, array $block ) {
|
116 |
if ( isset( $this->block_timer ) ) {
|
117 |
$this->block_timing[] = $this->block_timer->stop();
|
136 |
return;
|
137 |
}
|
138 |
|
139 |
+
$this->data['post_has_blocks'] = self::wp_has_blocks( $content );
|
140 |
+
$this->data['post_blocks'] = self::wp_parse_blocks( $content );
|
141 |
$this->data['all_dynamic_blocks'] = self::wp_get_dynamic_block_names();
|
142 |
+
$this->data['total_blocks'] = 0;
|
143 |
+
$this->data['has_block_context'] = false;
|
144 |
+
$this->data['has_block_timing'] = false;
|
145 |
|
146 |
if ( $this->data['post_has_blocks'] ) {
|
147 |
$this->data['post_blocks'] = array_values( array_filter( array_map( array( $this, 'process_block' ), $this->data['post_blocks'] ) ) );
|
148 |
}
|
149 |
}
|
150 |
|
151 |
+
/**
|
152 |
+
* @param mixed[] $block
|
153 |
+
* @return mixed[]|null
|
154 |
+
*/
|
155 |
protected function process_block( array $block ) {
|
156 |
$context = array_shift( $this->block_context );
|
157 |
+
$timing = array_shift( $this->block_timing );
|
158 |
|
159 |
// Remove empty blocks caused by two consecutive line breaks in content
|
160 |
if ( ! $block['blockName'] && ! trim( $block['innerHTML'] ) ) {
|
164 |
$this->data['total_blocks']++;
|
165 |
|
166 |
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
|
167 |
+
$dynamic = false;
|
168 |
+
$callback = null;
|
169 |
|
170 |
if ( $block_type && $block_type->is_dynamic() ) {
|
171 |
+
$dynamic = true;
|
172 |
$callback = QM_Util::populate_callback( array(
|
173 |
'function' => $block_type->render_callback,
|
174 |
) );
|
176 |
|
177 |
$timing = array_shift( $this->block_timing );
|
178 |
|
179 |
+
$block['dynamic'] = $dynamic;
|
180 |
+
$block['callback'] = $callback;
|
181 |
$block['innerHTML'] = trim( $block['innerHTML'] );
|
182 |
+
$block['size'] = strlen( $block['innerHTML'] );
|
183 |
|
184 |
if ( $context ) {
|
185 |
$block['context'] = $context;
|
198 |
return $block;
|
199 |
}
|
200 |
|
201 |
+
/**
|
202 |
+
* @return bool
|
203 |
+
*/
|
204 |
protected static function wp_block_editor_enabled() {
|
205 |
return ( function_exists( 'parse_blocks' ) || function_exists( 'gutenberg_parse_blocks' ) );
|
206 |
}
|
207 |
|
208 |
+
/**
|
209 |
+
* @param string $content
|
210 |
+
* @return bool
|
211 |
+
*/
|
212 |
protected static function wp_has_blocks( $content ) {
|
213 |
if ( function_exists( 'has_blocks' ) ) {
|
214 |
return has_blocks( $content );
|
219 |
return false;
|
220 |
}
|
221 |
|
222 |
+
/**
|
223 |
+
* @param string $content
|
224 |
+
* @return mixed[]|null
|
225 |
+
*/
|
226 |
protected static function wp_parse_blocks( $content ) {
|
227 |
if ( function_exists( 'parse_blocks' ) ) {
|
228 |
return parse_blocks( $content );
|
233 |
return null;
|
234 |
}
|
235 |
|
236 |
+
/**
|
237 |
+
* @return string[]|null
|
238 |
+
*/
|
239 |
protected static function wp_get_dynamic_block_names() {
|
240 |
if ( function_exists( 'get_dynamic_block_names' ) ) {
|
241 |
return get_dynamic_block_names();
|
246 |
|
247 |
}
|
248 |
|
249 |
+
/**
|
250 |
+
* @param array<string, QM_Collector> $collectors
|
251 |
+
* @param QueryMonitor $qm
|
252 |
+
* @return array<string, QM_Collector>
|
253 |
+
*/
|
254 |
function register_qm_collector_block_editor( array $collectors, QueryMonitor $qm ) {
|
255 |
$collectors['block_editor'] = new QM_Collector_Block_Editor();
|
256 |
return $collectors;
|
collectors/cache.php
CHANGED
@@ -5,16 +5,21 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Cache extends QM_Collector {
|
11 |
|
12 |
public $id = 'cache';
|
13 |
|
|
|
|
|
|
|
14 |
public function process() {
|
15 |
global $wp_object_cache;
|
16 |
|
17 |
-
$this->data['has_object_cache']
|
18 |
$this->data['cache_hit_percentage'] = 0;
|
19 |
|
20 |
if ( is_object( $wp_object_cache ) ) {
|
@@ -79,13 +84,13 @@ class QM_Collector_Cache extends QM_Collector {
|
|
79 |
|
80 |
if ( function_exists( 'extension_loaded' ) ) {
|
81 |
$this->data['object_cache_extensions'] = array_map( 'extension_loaded', array(
|
82 |
-
'APCu'
|
83 |
-
'Memcache'
|
84 |
-
'Memcached'
|
85 |
-
'Redis'
|
86 |
) );
|
87 |
$this->data['opcode_cache_extensions'] = array_map( 'extension_loaded', array(
|
88 |
-
'APC'
|
89 |
'Zend OPcache' => 'Zend OPcache',
|
90 |
) );
|
91 |
} else {
|
@@ -98,6 +103,11 @@ class QM_Collector_Cache extends QM_Collector {
|
|
98 |
|
99 |
}
|
100 |
|
|
|
|
|
|
|
|
|
|
|
101 |
function register_qm_collector_cache( array $collectors, QueryMonitor $qm ) {
|
102 |
$collectors['cache'] = new QM_Collector_Cache();
|
103 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Cache extends QM_Collector {
|
13 |
|
14 |
public $id = 'cache';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
public function process() {
|
20 |
global $wp_object_cache;
|
21 |
|
22 |
+
$this->data['has_object_cache'] = (bool) wp_using_ext_object_cache();
|
23 |
$this->data['cache_hit_percentage'] = 0;
|
24 |
|
25 |
if ( is_object( $wp_object_cache ) ) {
|
84 |
|
85 |
if ( function_exists( 'extension_loaded' ) ) {
|
86 |
$this->data['object_cache_extensions'] = array_map( 'extension_loaded', array(
|
87 |
+
'APCu' => 'APCu',
|
88 |
+
'Memcache' => 'Memcache',
|
89 |
+
'Memcached' => 'Memcached',
|
90 |
+
'Redis' => 'Redis',
|
91 |
) );
|
92 |
$this->data['opcode_cache_extensions'] = array_map( 'extension_loaded', array(
|
93 |
+
'APC' => 'APC',
|
94 |
'Zend OPcache' => 'Zend OPcache',
|
95 |
) );
|
96 |
} else {
|
103 |
|
104 |
}
|
105 |
|
106 |
+
/**
|
107 |
+
* @param array<string, QM_Collector> $collectors
|
108 |
+
* @param QueryMonitor $qm
|
109 |
+
* @return array<string, QM_Collector>
|
110 |
+
*/
|
111 |
function register_qm_collector_cache( array $collectors, QueryMonitor $qm ) {
|
112 |
$collectors['cache'] = new QM_Collector_Cache();
|
113 |
return $collectors;
|
collectors/caps.php
CHANGED
@@ -5,14 +5,19 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Caps extends QM_Collector {
|
11 |
|
12 |
public $id = 'caps';
|
13 |
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
16 |
|
17 |
if ( ! self::enabled() ) {
|
18 |
return;
|
@@ -22,16 +27,35 @@ class QM_Collector_Caps extends QM_Collector {
|
|
22 |
add_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 9999, 4 );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
public static function enabled() {
|
26 |
return ( defined( 'QM_ENABLE_CAPS_PANEL' ) && QM_ENABLE_CAPS_PANEL );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
29 |
public function get_concerned_actions() {
|
30 |
return array(
|
31 |
'wp_roles_init',
|
32 |
);
|
33 |
}
|
34 |
|
|
|
|
|
|
|
35 |
public function get_concerned_filters() {
|
36 |
return array(
|
37 |
'map_meta_cap',
|
@@ -40,6 +64,9 @@ class QM_Collector_Caps extends QM_Collector {
|
|
40 |
);
|
41 |
}
|
42 |
|
|
|
|
|
|
|
43 |
public function get_concerned_options() {
|
44 |
$blog_prefix = $GLOBALS['wpdb']->get_blog_prefix();
|
45 |
|
@@ -48,6 +75,9 @@ class QM_Collector_Caps extends QM_Collector {
|
|
48 |
);
|
49 |
}
|
50 |
|
|
|
|
|
|
|
51 |
public function get_concerned_constants() {
|
52 |
return array(
|
53 |
'ALLOW_UNFILTERED_UPLOADS',
|
@@ -56,12 +86,6 @@ class QM_Collector_Caps extends QM_Collector {
|
|
56 |
);
|
57 |
}
|
58 |
|
59 |
-
public function tear_down() {
|
60 |
-
remove_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 9999 );
|
61 |
-
remove_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 9999 );
|
62 |
-
parent::tear_down();
|
63 |
-
}
|
64 |
-
|
65 |
/**
|
66 |
* Logs user capability checks.
|
67 |
*
|
@@ -69,7 +93,7 @@ class QM_Collector_Caps extends QM_Collector {
|
|
69 |
*
|
70 |
* @param bool[] $user_caps Concerned user's capabilities.
|
71 |
* @param string[] $caps Required primitive capabilities for the requested capability.
|
72 |
-
* @param
|
73 |
* Arguments that accompany the requested capability check.
|
74 |
*
|
75 |
* @type string $0 Requested capability.
|
@@ -79,7 +103,21 @@ class QM_Collector_Caps extends QM_Collector {
|
|
79 |
* @return bool[] Concerned user's capabilities.
|
80 |
*/
|
81 |
public function filter_user_has_cap( array $user_caps, array $caps, array $args ) {
|
82 |
-
$trace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
$result = true;
|
84 |
|
85 |
foreach ( $caps as $cap ) {
|
@@ -90,8 +128,9 @@ class QM_Collector_Caps extends QM_Collector {
|
|
90 |
}
|
91 |
|
92 |
$this->data['caps'][] = array(
|
93 |
-
'args'
|
94 |
-
'
|
|
|
95 |
'result' => $result,
|
96 |
);
|
97 |
|
@@ -106,7 +145,7 @@ class QM_Collector_Caps extends QM_Collector {
|
|
106 |
* @param string[] $required_caps Required primitive capabilities for the requested capability.
|
107 |
* @param string $cap Capability or meta capability being checked.
|
108 |
* @param int $user_id Concerned user ID.
|
109 |
-
* @param
|
110 |
* Arguments that accompany the requested capability check.
|
111 |
*
|
112 |
* @type mixed ...$0 Optional second and further parameters.
|
@@ -122,28 +161,46 @@ class QM_Collector_Caps extends QM_Collector {
|
|
122 |
return $required_caps;
|
123 |
}
|
124 |
|
125 |
-
$trace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
$result = ( ! in_array( 'do_not_allow', $required_caps, true ) );
|
127 |
|
128 |
array_unshift( $args, $user_id );
|
129 |
array_unshift( $args, $cap );
|
130 |
|
131 |
$this->data['caps'][] = array(
|
132 |
-
'args'
|
133 |
-
'
|
|
|
134 |
'result' => $result,
|
135 |
);
|
136 |
|
137 |
return $required_caps;
|
138 |
}
|
139 |
|
|
|
|
|
|
|
140 |
public function process() {
|
141 |
if ( empty( $this->data['caps'] ) ) {
|
142 |
return;
|
143 |
}
|
144 |
|
145 |
-
$all_parts
|
146 |
-
$all_users
|
147 |
$components = array();
|
148 |
|
149 |
$this->data['caps'] = array_values( array_filter( $this->data['caps'], array( $this, 'filter_remove_noise' ) ) );
|
@@ -159,53 +216,31 @@ class QM_Collector_Caps extends QM_Collector {
|
|
159 |
$name = '';
|
160 |
}
|
161 |
|
162 |
-
$
|
163 |
-
$filtered_trace = $cap['trace']->get_display_trace();
|
164 |
-
|
165 |
-
$last = end( $filtered_trace );
|
166 |
-
if ( isset( $last['function'] ) && 'map_meta_cap' === $last['function'] ) {
|
167 |
-
array_shift( $filtered_trace ); // remove the map_meta_cap() call
|
168 |
-
}
|
169 |
|
170 |
-
|
171 |
-
array_shift( $filtered_trace ); // remove the *_user_can() call
|
172 |
-
|
173 |
-
if ( ! count( $filtered_trace ) ) {
|
174 |
-
$responsible_name = QM_Util::standard_dir( $trace[1]['file'], '' ) . ':' . $trace[1]['line'];
|
175 |
-
|
176 |
-
$responsible_item = $trace[1];
|
177 |
-
$responsible_item['display'] = $responsible_name;
|
178 |
-
$responsible_item['calling_file'] = $trace[1]['file'];
|
179 |
-
$responsible_item['calling_line'] = $trace[1]['line'];
|
180 |
-
array_unshift( $filtered_trace, $responsible_item );
|
181 |
-
}
|
182 |
-
|
183 |
-
$component = $cap['trace']->get_component();
|
184 |
-
|
185 |
-
$this->data['caps'][ $i ]['filtered_trace'] = $filtered_trace;
|
186 |
-
$this->data['caps'][ $i ]['component'] = $component;
|
187 |
-
|
188 |
-
$parts = array_values( array_filter( preg_split( '#[_/-]#', $name ) ) );
|
189 |
$this->data['caps'][ $i ]['parts'] = $parts;
|
190 |
-
$this->data['caps'][ $i ]['name']
|
191 |
-
$this->data['caps'][ $i ]['user']
|
192 |
-
$this->data['caps'][ $i ]['args']
|
193 |
-
$all_parts
|
194 |
-
$all_users[]
|
195 |
-
$components[ $component->name ]
|
196 |
-
|
197 |
-
unset( $this->data['caps'][ $i ]['trace'] );
|
198 |
}
|
199 |
|
200 |
-
$this->data['parts']
|
201 |
-
$this->data['users']
|
202 |
$this->data['components'] = $components;
|
203 |
}
|
204 |
|
|
|
|
|
|
|
|
|
205 |
public function filter_remove_noise( array $cap ) {
|
206 |
-
$trace = $cap['
|
207 |
|
208 |
-
$exclude_files
|
209 |
ABSPATH . 'wp-admin/menu.php',
|
210 |
ABSPATH . 'wp-admin/includes/menu.php',
|
211 |
);
|
@@ -228,6 +263,11 @@ class QM_Collector_Caps extends QM_Collector {
|
|
228 |
|
229 |
}
|
230 |
|
|
|
|
|
|
|
|
|
|
|
231 |
function register_qm_collector_caps( array $collectors, QueryMonitor $qm ) {
|
232 |
$collectors['caps'] = new QM_Collector_Caps();
|
233 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Caps extends QM_Collector {
|
13 |
|
14 |
public $id = 'caps';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
+
public function set_up() {
|
20 |
+
parent::set_up();
|
21 |
|
22 |
if ( ! self::enabled() ) {
|
23 |
return;
|
27 |
add_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 9999, 4 );
|
28 |
}
|
29 |
|
30 |
+
/**
|
31 |
+
* @return void
|
32 |
+
*/
|
33 |
+
public function tear_down() {
|
34 |
+
remove_filter( 'user_has_cap', array( $this, 'filter_user_has_cap' ), 9999 );
|
35 |
+
remove_filter( 'map_meta_cap', array( $this, 'filter_map_meta_cap' ), 9999 );
|
36 |
+
|
37 |
+
parent::tear_down();
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @return bool
|
42 |
+
*/
|
43 |
public static function enabled() {
|
44 |
return ( defined( 'QM_ENABLE_CAPS_PANEL' ) && QM_ENABLE_CAPS_PANEL );
|
45 |
}
|
46 |
|
47 |
+
/**
|
48 |
+
* @return array<int, string>
|
49 |
+
*/
|
50 |
public function get_concerned_actions() {
|
51 |
return array(
|
52 |
'wp_roles_init',
|
53 |
);
|
54 |
}
|
55 |
|
56 |
+
/**
|
57 |
+
* @return array<int, string>
|
58 |
+
*/
|
59 |
public function get_concerned_filters() {
|
60 |
return array(
|
61 |
'map_meta_cap',
|
64 |
);
|
65 |
}
|
66 |
|
67 |
+
/**
|
68 |
+
* @return array<int, string>
|
69 |
+
*/
|
70 |
public function get_concerned_options() {
|
71 |
$blog_prefix = $GLOBALS['wpdb']->get_blog_prefix();
|
72 |
|
75 |
);
|
76 |
}
|
77 |
|
78 |
+
/**
|
79 |
+
* @return array<int, string>
|
80 |
+
*/
|
81 |
public function get_concerned_constants() {
|
82 |
return array(
|
83 |
'ALLOW_UNFILTERED_UPLOADS',
|
86 |
);
|
87 |
}
|
88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
/**
|
90 |
* Logs user capability checks.
|
91 |
*
|
93 |
*
|
94 |
* @param bool[] $user_caps Concerned user's capabilities.
|
95 |
* @param string[] $caps Required primitive capabilities for the requested capability.
|
96 |
+
* @param mixed[] $args {
|
97 |
* Arguments that accompany the requested capability check.
|
98 |
*
|
99 |
* @type string $0 Requested capability.
|
103 |
* @return bool[] Concerned user's capabilities.
|
104 |
*/
|
105 |
public function filter_user_has_cap( array $user_caps, array $caps, array $args ) {
|
106 |
+
$trace = new QM_Backtrace( array(
|
107 |
+
'ignore_hook' => array(
|
108 |
+
current_filter() => true,
|
109 |
+
),
|
110 |
+
'ignore_func' => array(
|
111 |
+
'current_user_can' => true,
|
112 |
+
'map_meta_cap' => true,
|
113 |
+
'user_can' => true,
|
114 |
+
),
|
115 |
+
'ignore_method' => array(
|
116 |
+
'WP_User' => array(
|
117 |
+
'has_cap' => true,
|
118 |
+
),
|
119 |
+
),
|
120 |
+
) );
|
121 |
$result = true;
|
122 |
|
123 |
foreach ( $caps as $cap ) {
|
128 |
}
|
129 |
|
130 |
$this->data['caps'][] = array(
|
131 |
+
'args' => $args,
|
132 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
133 |
+
'component' => $trace->get_component(),
|
134 |
'result' => $result,
|
135 |
);
|
136 |
|
145 |
* @param string[] $required_caps Required primitive capabilities for the requested capability.
|
146 |
* @param string $cap Capability or meta capability being checked.
|
147 |
* @param int $user_id Concerned user ID.
|
148 |
+
* @param mixed[] $args {
|
149 |
* Arguments that accompany the requested capability check.
|
150 |
*
|
151 |
* @type mixed ...$0 Optional second and further parameters.
|
161 |
return $required_caps;
|
162 |
}
|
163 |
|
164 |
+
$trace = new QM_Backtrace( array(
|
165 |
+
'ignore_hook' => array(
|
166 |
+
current_filter() => true,
|
167 |
+
),
|
168 |
+
'ignore_func' => array(
|
169 |
+
'current_user_can' => true,
|
170 |
+
'map_meta_cap' => true,
|
171 |
+
'user_can' => true,
|
172 |
+
),
|
173 |
+
'ignore_method' => array(
|
174 |
+
'WP_User' => array(
|
175 |
+
'has_cap' => true,
|
176 |
+
),
|
177 |
+
),
|
178 |
+
) );
|
179 |
$result = ( ! in_array( 'do_not_allow', $required_caps, true ) );
|
180 |
|
181 |
array_unshift( $args, $user_id );
|
182 |
array_unshift( $args, $cap );
|
183 |
|
184 |
$this->data['caps'][] = array(
|
185 |
+
'args' => $args,
|
186 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
187 |
+
'component' => $trace->get_component(),
|
188 |
'result' => $result,
|
189 |
);
|
190 |
|
191 |
return $required_caps;
|
192 |
}
|
193 |
|
194 |
+
/**
|
195 |
+
* @return void
|
196 |
+
*/
|
197 |
public function process() {
|
198 |
if ( empty( $this->data['caps'] ) ) {
|
199 |
return;
|
200 |
}
|
201 |
|
202 |
+
$all_parts = array();
|
203 |
+
$all_users = array();
|
204 |
$components = array();
|
205 |
|
206 |
$this->data['caps'] = array_values( array_filter( $this->data['caps'], array( $this, 'filter_remove_noise' ) ) );
|
216 |
$name = '';
|
217 |
}
|
218 |
|
219 |
+
$component = $cap['component'];
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
|
221 |
+
$parts = array_values( array_filter( preg_split( '#[_/-]#', $name ) ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
$this->data['caps'][ $i ]['parts'] = $parts;
|
223 |
+
$this->data['caps'][ $i ]['name'] = $name;
|
224 |
+
$this->data['caps'][ $i ]['user'] = $cap['args'][1];
|
225 |
+
$this->data['caps'][ $i ]['args'] = array_slice( $cap['args'], 2 );
|
226 |
+
$all_parts = array_merge( $all_parts, $parts );
|
227 |
+
$all_users[] = $cap['args'][1];
|
228 |
+
$components[ $component->name ] = $component->name;
|
|
|
|
|
229 |
}
|
230 |
|
231 |
+
$this->data['parts'] = array_values( array_unique( array_filter( $all_parts ) ) );
|
232 |
+
$this->data['users'] = array_values( array_unique( array_filter( $all_users ) ) );
|
233 |
$this->data['components'] = $components;
|
234 |
}
|
235 |
|
236 |
+
/**
|
237 |
+
* @param array<string, mixed> $cap
|
238 |
+
* @return bool
|
239 |
+
*/
|
240 |
public function filter_remove_noise( array $cap ) {
|
241 |
+
$trace = $cap['filtered_trace'];
|
242 |
|
243 |
+
$exclude_files = array(
|
244 |
ABSPATH . 'wp-admin/menu.php',
|
245 |
ABSPATH . 'wp-admin/includes/menu.php',
|
246 |
);
|
263 |
|
264 |
}
|
265 |
|
266 |
+
/**
|
267 |
+
* @param array<string, QM_Collector> $collectors
|
268 |
+
* @param QueryMonitor $qm
|
269 |
+
* @return array<string, QM_Collector>
|
270 |
+
*/
|
271 |
function register_qm_collector_caps( array $collectors, QueryMonitor $qm ) {
|
272 |
$collectors['caps'] = new QM_Collector_Caps();
|
273 |
return $collectors;
|
collectors/conditionals.php
CHANGED
@@ -5,12 +5,17 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Conditionals extends QM_Collector {
|
11 |
|
12 |
public $id = 'conditionals';
|
13 |
|
|
|
|
|
|
|
14 |
public function process() {
|
15 |
|
16 |
/**
|
@@ -71,9 +76,9 @@ class QM_Collector_Conditionals extends QM_Collector {
|
|
71 |
*/
|
72 |
$conds = apply_filters( 'query_monitor_conditionals', $conds );
|
73 |
|
74 |
-
$true
|
75 |
$false = array();
|
76 |
-
$na
|
77 |
|
78 |
foreach ( $conds as $cond ) {
|
79 |
if ( function_exists( $cond ) ) {
|
@@ -101,6 +106,11 @@ class QM_Collector_Conditionals extends QM_Collector {
|
|
101 |
|
102 |
}
|
103 |
|
|
|
|
|
|
|
|
|
|
|
104 |
function register_qm_collector_conditionals( array $collectors, QueryMonitor $qm ) {
|
105 |
$collectors['conditionals'] = new QM_Collector_Conditionals();
|
106 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Conditionals extends QM_Collector {
|
13 |
|
14 |
public $id = 'conditionals';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
public function process() {
|
20 |
|
21 |
/**
|
76 |
*/
|
77 |
$conds = apply_filters( 'query_monitor_conditionals', $conds );
|
78 |
|
79 |
+
$true = array();
|
80 |
$false = array();
|
81 |
+
$na = array();
|
82 |
|
83 |
foreach ( $conds as $cond ) {
|
84 |
if ( function_exists( $cond ) ) {
|
106 |
|
107 |
}
|
108 |
|
109 |
+
/**
|
110 |
+
* @param array<string, QM_Collector> $collectors
|
111 |
+
* @param QueryMonitor $qm
|
112 |
+
* @return array<string, QM_Collector>
|
113 |
+
*/
|
114 |
function register_qm_collector_conditionals( array $collectors, QueryMonitor $qm ) {
|
115 |
$collectors['conditionals'] = new QM_Collector_Conditionals();
|
116 |
return $collectors;
|
collectors/db_callers.php
CHANGED
@@ -5,12 +5,17 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_DB_Callers extends QM_Collector {
|
11 |
|
12 |
public $id = 'db_callers';
|
13 |
|
|
|
|
|
|
|
14 |
public function process() {
|
15 |
$dbq = QM_Collectors::get( 'db_queries' );
|
16 |
|
@@ -28,6 +33,11 @@ class QM_Collector_DB_Callers extends QM_Collector {
|
|
28 |
|
29 |
}
|
30 |
|
|
|
|
|
|
|
|
|
|
|
31 |
function register_qm_collector_db_callers( array $collectors, QueryMonitor $qm ) {
|
32 |
$collectors['db_callers'] = new QM_Collector_DB_Callers();
|
33 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_DB_Callers extends QM_Collector {
|
13 |
|
14 |
public $id = 'db_callers';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
public function process() {
|
20 |
$dbq = QM_Collectors::get( 'db_queries' );
|
21 |
|
33 |
|
34 |
}
|
35 |
|
36 |
+
/**
|
37 |
+
* @param array<string, QM_Collector> $collectors
|
38 |
+
* @param QueryMonitor $qm
|
39 |
+
* @return array<string, QM_Collector>
|
40 |
+
*/
|
41 |
function register_qm_collector_db_callers( array $collectors, QueryMonitor $qm ) {
|
42 |
$collectors['db_callers'] = new QM_Collector_DB_Callers();
|
43 |
return $collectors;
|
collectors/db_components.php
CHANGED
@@ -5,12 +5,17 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_DB_Components extends QM_Collector {
|
11 |
|
12 |
public $id = 'db_components';
|
13 |
|
|
|
|
|
|
|
14 |
public function process() {
|
15 |
$dbq = QM_Collectors::get( 'db_queries' );
|
16 |
|
@@ -28,6 +33,11 @@ class QM_Collector_DB_Components extends QM_Collector {
|
|
28 |
|
29 |
}
|
30 |
|
|
|
|
|
|
|
|
|
|
|
31 |
function register_qm_collector_db_components( array $collectors, QueryMonitor $qm ) {
|
32 |
$collectors['db_components'] = new QM_Collector_DB_Components();
|
33 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_DB_Components extends QM_Collector {
|
13 |
|
14 |
public $id = 'db_components';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
public function process() {
|
20 |
$dbq = QM_Collectors::get( 'db_queries' );
|
21 |
|
33 |
|
34 |
}
|
35 |
|
36 |
+
/**
|
37 |
+
* @param array<string, QM_Collector> $collectors
|
38 |
+
* @param QueryMonitor $qm
|
39 |
+
* @return array<string, QM_Collector>
|
40 |
+
*/
|
41 |
function register_qm_collector_db_components( array $collectors, QueryMonitor $qm ) {
|
42 |
$collectors['db_components'] = new QM_Collector_DB_Components();
|
43 |
return $collectors;
|
collectors/db_dupes.php
CHANGED
@@ -5,12 +5,17 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_DB_Dupes extends QM_Collector {
|
11 |
|
12 |
public $id = 'db_dupes';
|
13 |
|
|
|
|
|
|
|
14 |
public function process() {
|
15 |
$dbq = QM_Collectors::get( 'db_queries' );
|
16 |
|
@@ -27,9 +32,8 @@ class QM_Collector_DB_Dupes extends QM_Collector {
|
|
27 |
// Ignore dupes from `WP_Query->set_found_posts()`
|
28 |
unset( $this->data['dupes']['SELECT FOUND_ROWS()'] );
|
29 |
|
30 |
-
$stacks
|
31 |
-
$
|
32 |
-
$callers = array();
|
33 |
$components = array();
|
34 |
|
35 |
// Loop over all SQL queries that have dupes
|
@@ -39,8 +43,8 @@ class QM_Collector_DB_Dupes extends QM_Collector {
|
|
39 |
foreach ( $query_ids as $query_id ) {
|
40 |
|
41 |
if ( isset( $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['trace'] ) ) {
|
42 |
-
$trace
|
43 |
-
$stack
|
44 |
$component = $trace->get_component();
|
45 |
|
46 |
// Populate the component counts for this query
|
@@ -50,7 +54,7 @@ class QM_Collector_DB_Dupes extends QM_Collector {
|
|
50 |
$components[ $sql ][ $component->name ] = 1;
|
51 |
}
|
52 |
} else {
|
53 |
-
$stack =
|
54 |
}
|
55 |
|
56 |
// Populate the caller counts for this query
|
@@ -84,14 +88,19 @@ class QM_Collector_DB_Dupes extends QM_Collector {
|
|
84 |
}
|
85 |
|
86 |
if ( ! empty( $sources ) ) {
|
87 |
-
$this->data['dupe_sources']
|
88 |
-
$this->data['dupe_callers']
|
89 |
$this->data['dupe_components'] = $components;
|
90 |
}
|
91 |
|
92 |
}
|
93 |
}
|
94 |
|
|
|
|
|
|
|
|
|
|
|
95 |
function register_qm_collector_db_dupes( array $collectors, QueryMonitor $qm ) {
|
96 |
$collectors['db_dupes'] = new QM_Collector_DB_Dupes();
|
97 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_DB_Dupes extends QM_Collector {
|
13 |
|
14 |
public $id = 'db_dupes';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
public function process() {
|
20 |
$dbq = QM_Collectors::get( 'db_queries' );
|
21 |
|
32 |
// Ignore dupes from `WP_Query->set_found_posts()`
|
33 |
unset( $this->data['dupes']['SELECT FOUND_ROWS()'] );
|
34 |
|
35 |
+
$stacks = array();
|
36 |
+
$callers = array();
|
|
|
37 |
$components = array();
|
38 |
|
39 |
// Loop over all SQL queries that have dupes
|
43 |
foreach ( $query_ids as $query_id ) {
|
44 |
|
45 |
if ( isset( $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['trace'] ) ) {
|
46 |
+
$trace = $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['trace'];
|
47 |
+
$stack = wp_list_pluck( $trace->get_filtered_trace(), 'id' );
|
48 |
$component = $trace->get_component();
|
49 |
|
50 |
// Populate the component counts for this query
|
54 |
$components[ $sql ][ $component->name ] = 1;
|
55 |
}
|
56 |
} else {
|
57 |
+
$stack = $dbq->data['dbs']['$wpdb']->rows[ $query_id ]['stack'];
|
58 |
}
|
59 |
|
60 |
// Populate the caller counts for this query
|
88 |
}
|
89 |
|
90 |
if ( ! empty( $sources ) ) {
|
91 |
+
$this->data['dupe_sources'] = $sources;
|
92 |
+
$this->data['dupe_callers'] = $callers;
|
93 |
$this->data['dupe_components'] = $components;
|
94 |
}
|
95 |
|
96 |
}
|
97 |
}
|
98 |
|
99 |
+
/**
|
100 |
+
* @param array<string, QM_Collector> $collectors
|
101 |
+
* @param QueryMonitor $qm
|
102 |
+
* @return array<string, QM_Collector>
|
103 |
+
*/
|
104 |
function register_qm_collector_db_dupes( array $collectors, QueryMonitor $qm ) {
|
105 |
$collectors['db_dupes'] = new QM_Collector_DB_Dupes();
|
106 |
return $collectors;
|
collectors/db_queries.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
if ( ! defined( 'SAVEQUERIES' ) ) {
|
11 |
define( 'SAVEQUERIES', true );
|
@@ -20,9 +22,19 @@ if ( SAVEQUERIES && property_exists( $GLOBALS['wpdb'], 'save_queries' ) ) {
|
|
20 |
|
21 |
class QM_Collector_DB_Queries extends QM_Collector {
|
22 |
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
public $db_objects = array();
|
25 |
|
|
|
|
|
|
|
26 |
public function get_errors() {
|
27 |
if ( ! empty( $this->data['errors'] ) ) {
|
28 |
return $this->data['errors'];
|
@@ -30,6 +42,9 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
30 |
return false;
|
31 |
}
|
32 |
|
|
|
|
|
|
|
33 |
public function get_expensive() {
|
34 |
if ( ! empty( $this->data['expensive'] ) ) {
|
35 |
return $this->data['expensive'];
|
@@ -37,14 +52,21 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
37 |
return false;
|
38 |
}
|
39 |
|
|
|
|
|
|
|
|
|
40 |
public static function is_expensive( array $row ) {
|
41 |
return $row['ltime'] > QM_DB_EXPENSIVE;
|
42 |
}
|
43 |
|
|
|
|
|
|
|
44 |
public function process() {
|
45 |
-
$this->data['total_qs']
|
46 |
$this->data['total_time'] = 0;
|
47 |
-
$this->data['errors']
|
48 |
|
49 |
/**
|
50 |
* Filters the `wpdb` instances that are exposed to QM.
|
@@ -69,13 +91,19 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
69 |
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
protected function log_caller( $caller, $ltime, $type ) {
|
73 |
|
74 |
if ( ! isset( $this->data['times'][ $caller ] ) ) {
|
75 |
$this->data['times'][ $caller ] = array(
|
76 |
'caller' => $caller,
|
77 |
-
'ltime'
|
78 |
-
'types'
|
79 |
);
|
80 |
}
|
81 |
|
@@ -89,6 +117,11 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
89 |
|
90 |
}
|
91 |
|
|
|
|
|
|
|
|
|
|
|
92 |
public function process_db_object( $id, wpdb $db ) {
|
93 |
global $EZSQL_ERROR, $wp_the_query;
|
94 |
|
@@ -98,31 +131,44 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
98 |
return;
|
99 |
}
|
100 |
|
101 |
-
$rows
|
102 |
-
$types
|
103 |
$total_time = 0;
|
104 |
$has_result = false;
|
105 |
-
$has_trace
|
106 |
-
$i
|
107 |
-
$request
|
108 |
|
109 |
if ( method_exists( $db, 'remove_placeholder_escape' ) ) {
|
110 |
$request = $db->remove_placeholder_escape( $request );
|
111 |
}
|
112 |
|
113 |
-
foreach (
|
|
|
|
|
|
|
114 |
|
115 |
-
|
116 |
-
|
117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
}
|
119 |
|
120 |
-
|
121 |
-
|
122 |
-
$stack
|
123 |
-
|
124 |
-
|
125 |
-
$has_result = isset( $query['result'] );
|
126 |
|
127 |
if ( $has_result ) {
|
128 |
$result = $query['result'];
|
@@ -134,27 +180,25 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
134 |
|
135 |
if ( $has_trace ) {
|
136 |
|
137 |
-
$trace
|
138 |
-
$component
|
139 |
-
$caller
|
140 |
$caller_name = $caller['display'];
|
141 |
-
$caller
|
142 |
|
143 |
} else {
|
144 |
|
145 |
-
$trace
|
146 |
$component = null;
|
147 |
-
$callers
|
148 |
-
$
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
$caller_name = $caller;
|
154 |
-
}
|
155 |
}
|
156 |
|
157 |
-
$sql
|
158 |
$type = QM_Util::get_query_type( $sql );
|
159 |
|
160 |
$this->log_type( $type );
|
@@ -183,7 +227,7 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
183 |
$row = compact( 'caller', 'caller_name', 'sql', 'ltime', 'result', 'type', 'component', 'trace', 'is_main_query' );
|
184 |
|
185 |
if ( ! isset( $trace ) ) {
|
186 |
-
$row['stack'] = $
|
187 |
}
|
188 |
|
189 |
if ( is_wp_error( $result ) ) {
|
@@ -203,15 +247,15 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
203 |
// Fallback for displaying database errors when wp-content/db.php isn't in place
|
204 |
foreach ( $EZSQL_ERROR as $error ) {
|
205 |
$row = array(
|
206 |
-
'caller'
|
207 |
'caller_name' => null,
|
208 |
-
'stack'
|
209 |
-
'sql'
|
210 |
-
'ltime'
|
211 |
-
'result'
|
212 |
-
'type'
|
213 |
-
'component'
|
214 |
-
'trace'
|
215 |
'is_main_query' => false,
|
216 |
);
|
217 |
$this->data['errors'][] = $row;
|
@@ -235,6 +279,11 @@ class QM_Collector_DB_Queries extends QM_Collector {
|
|
235 |
|
236 |
}
|
237 |
|
|
|
|
|
|
|
|
|
|
|
238 |
function register_qm_collector_db_queries( array $collectors, QueryMonitor $qm ) {
|
239 |
$collectors['db_queries'] = new QM_Collector_DB_Queries();
|
240 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
if ( ! defined( 'SAVEQUERIES' ) ) {
|
13 |
define( 'SAVEQUERIES', true );
|
22 |
|
23 |
class QM_Collector_DB_Queries extends QM_Collector {
|
24 |
|
25 |
+
/**
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
public $id = 'db_queries';
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @var array<string, wpdb>
|
32 |
+
*/
|
33 |
public $db_objects = array();
|
34 |
|
35 |
+
/**
|
36 |
+
* @return mixed[]|false
|
37 |
+
*/
|
38 |
public function get_errors() {
|
39 |
if ( ! empty( $this->data['errors'] ) ) {
|
40 |
return $this->data['errors'];
|
42 |
return false;
|
43 |
}
|
44 |
|
45 |
+
/**
|
46 |
+
* @return mixed[]|false
|
47 |
+
*/
|
48 |
public function get_expensive() {
|
49 |
if ( ! empty( $this->data['expensive'] ) ) {
|
50 |
return $this->data['expensive'];
|
52 |
return false;
|
53 |
}
|
54 |
|
55 |
+
/**
|
56 |
+
* @param array<string, mixed> $row
|
57 |
+
* @return bool
|
58 |
+
*/
|
59 |
public static function is_expensive( array $row ) {
|
60 |
return $row['ltime'] > QM_DB_EXPENSIVE;
|
61 |
}
|
62 |
|
63 |
+
/**
|
64 |
+
* @return void
|
65 |
+
*/
|
66 |
public function process() {
|
67 |
+
$this->data['total_qs'] = 0;
|
68 |
$this->data['total_time'] = 0;
|
69 |
+
$this->data['errors'] = array();
|
70 |
|
71 |
/**
|
72 |
* Filters the `wpdb` instances that are exposed to QM.
|
91 |
|
92 |
}
|
93 |
|
94 |
+
/**
|
95 |
+
* @param string $caller
|
96 |
+
* @param float $ltime
|
97 |
+
* @param string $type
|
98 |
+
* @return void
|
99 |
+
*/
|
100 |
protected function log_caller( $caller, $ltime, $type ) {
|
101 |
|
102 |
if ( ! isset( $this->data['times'][ $caller ] ) ) {
|
103 |
$this->data['times'][ $caller ] = array(
|
104 |
'caller' => $caller,
|
105 |
+
'ltime' => 0,
|
106 |
+
'types' => array(),
|
107 |
);
|
108 |
}
|
109 |
|
117 |
|
118 |
}
|
119 |
|
120 |
+
/**
|
121 |
+
* @param string $id
|
122 |
+
* @param wpdb $db
|
123 |
+
* @return void
|
124 |
+
*/
|
125 |
public function process_db_object( $id, wpdb $db ) {
|
126 |
global $EZSQL_ERROR, $wp_the_query;
|
127 |
|
131 |
return;
|
132 |
}
|
133 |
|
134 |
+
$rows = array();
|
135 |
+
$types = array();
|
136 |
$total_time = 0;
|
137 |
$has_result = false;
|
138 |
+
$has_trace = false;
|
139 |
+
$i = 0;
|
140 |
+
$request = trim( $wp_the_query->request );
|
141 |
|
142 |
if ( method_exists( $db, 'remove_placeholder_escape' ) ) {
|
143 |
$request = $db->remove_placeholder_escape( $request );
|
144 |
}
|
145 |
|
146 |
+
foreach ( $db->queries as $query ) {
|
147 |
+
$has_trace = false;
|
148 |
+
$has_result = false;
|
149 |
+
$callers = array();
|
150 |
|
151 |
+
if ( isset( $query['query'], $query['elapsed'], $query['debug'] ) ) {
|
152 |
+
// WordPress.com VIP.
|
153 |
+
$sql = $query['query'];
|
154 |
+
$ltime = $query['elapsed'];
|
155 |
+
$stack = $query['debug'];
|
156 |
+
} else {
|
157 |
+
// Standard WP.
|
158 |
+
$sql = $query[0];
|
159 |
+
$ltime = $query[1];
|
160 |
+
$stack = $query[2];
|
161 |
+
|
162 |
+
// Query Monitor db.php drop-in.
|
163 |
+
$has_trace = isset( $query['trace'] );
|
164 |
+
$has_result = isset( $query['result'] );
|
165 |
}
|
166 |
|
167 |
+
// @TODO: decide what I want to do with this:
|
168 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
169 |
+
if ( false !== strpos( $stack, 'wp_admin_bar' ) && ! isset( $_REQUEST['qm_display_admin_bar'] ) ) {
|
170 |
+
continue;
|
171 |
+
}
|
|
|
172 |
|
173 |
if ( $has_result ) {
|
174 |
$result = $query['result'];
|
180 |
|
181 |
if ( $has_trace ) {
|
182 |
|
183 |
+
$trace = $query['trace'];
|
184 |
+
$component = $query['trace']->get_component();
|
185 |
+
$caller = $query['trace']->get_caller();
|
186 |
$caller_name = $caller['display'];
|
187 |
+
$caller = $caller['display'];
|
188 |
|
189 |
} else {
|
190 |
|
191 |
+
$trace = null;
|
192 |
$component = null;
|
193 |
+
$callers = array_reverse( explode( ',', $stack ) );
|
194 |
+
$callers = array_map( 'trim', $callers );
|
195 |
+
$callers = QM_Backtrace::get_filtered_stack( $callers );
|
196 |
+
$caller = reset( $callers );
|
197 |
+
$caller_name = $caller;
|
198 |
+
|
|
|
|
|
199 |
}
|
200 |
|
201 |
+
$sql = trim( $sql );
|
202 |
$type = QM_Util::get_query_type( $sql );
|
203 |
|
204 |
$this->log_type( $type );
|
227 |
$row = compact( 'caller', 'caller_name', 'sql', 'ltime', 'result', 'type', 'component', 'trace', 'is_main_query' );
|
228 |
|
229 |
if ( ! isset( $trace ) ) {
|
230 |
+
$row['stack'] = $callers;
|
231 |
}
|
232 |
|
233 |
if ( is_wp_error( $result ) ) {
|
247 |
// Fallback for displaying database errors when wp-content/db.php isn't in place
|
248 |
foreach ( $EZSQL_ERROR as $error ) {
|
249 |
$row = array(
|
250 |
+
'caller' => null,
|
251 |
'caller_name' => null,
|
252 |
+
'stack' => '',
|
253 |
+
'sql' => $error['query'],
|
254 |
+
'ltime' => 0,
|
255 |
+
'result' => new WP_Error( 'qmdb', $error['error_str'] ),
|
256 |
+
'type' => '',
|
257 |
+
'component' => false,
|
258 |
+
'trace' => null,
|
259 |
'is_main_query' => false,
|
260 |
);
|
261 |
$this->data['errors'][] = $row;
|
279 |
|
280 |
}
|
281 |
|
282 |
+
/**
|
283 |
+
* @param array<string, QM_Collector> $collectors
|
284 |
+
* @param QueryMonitor $qm
|
285 |
+
* @return array<string, QM_Collector>
|
286 |
+
*/
|
287 |
function register_qm_collector_db_queries( array $collectors, QueryMonitor $qm ) {
|
288 |
$collectors['db_queries'] = new QM_Collector_DB_Queries();
|
289 |
return $collectors;
|
collectors/debug_bar.php
CHANGED
@@ -5,35 +5,63 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
final class QM_Collector_Debug_Bar extends QM_Collector {
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
private $panel = null;
|
14 |
|
|
|
|
|
|
|
|
|
15 |
public function set_panel( Debug_Bar_Panel $panel ) {
|
16 |
$this->panel = $panel;
|
17 |
}
|
18 |
|
|
|
|
|
|
|
19 |
public function get_panel() {
|
20 |
return $this->panel;
|
21 |
}
|
22 |
|
|
|
|
|
|
|
23 |
public function process() {
|
24 |
$this->get_panel()->prerender();
|
25 |
}
|
26 |
|
|
|
|
|
|
|
27 |
public function is_visible() {
|
28 |
return $this->get_panel()->is_visible();
|
29 |
}
|
30 |
|
|
|
|
|
|
|
31 |
public function render() {
|
32 |
-
|
33 |
}
|
34 |
|
35 |
}
|
36 |
|
|
|
|
|
|
|
37 |
function register_qm_collectors_debug_bar() {
|
38 |
|
39 |
global $debug_bar;
|
@@ -43,7 +71,7 @@ function register_qm_collectors_debug_bar() {
|
|
43 |
}
|
44 |
|
45 |
$collectors = QM_Collectors::init();
|
46 |
-
$qm
|
47 |
|
48 |
require_once $qm->plugin_path( 'classes/debug_bar.php' );
|
49 |
|
@@ -71,6 +99,9 @@ function register_qm_collectors_debug_bar() {
|
|
71 |
|
72 |
}
|
73 |
|
|
|
|
|
|
|
74 |
function qm_debug_bar_being_activated() {
|
75 |
// phpcs:disable
|
76 |
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
final class QM_Collector_Debug_Bar extends QM_Collector {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
public $id = 'debug_bar';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var Debug_Bar_Panel|null
|
21 |
+
*/
|
22 |
private $panel = null;
|
23 |
|
24 |
+
/**
|
25 |
+
* @param Debug_Bar_Panel $panel
|
26 |
+
* @return void
|
27 |
+
*/
|
28 |
public function set_panel( Debug_Bar_Panel $panel ) {
|
29 |
$this->panel = $panel;
|
30 |
}
|
31 |
|
32 |
+
/**
|
33 |
+
* @return Debug_Bar_Panel|null
|
34 |
+
*/
|
35 |
public function get_panel() {
|
36 |
return $this->panel;
|
37 |
}
|
38 |
|
39 |
+
/**
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
public function process() {
|
43 |
$this->get_panel()->prerender();
|
44 |
}
|
45 |
|
46 |
+
/**
|
47 |
+
* @return bool
|
48 |
+
*/
|
49 |
public function is_visible() {
|
50 |
return $this->get_panel()->is_visible();
|
51 |
}
|
52 |
|
53 |
+
/**
|
54 |
+
* @return void
|
55 |
+
*/
|
56 |
public function render() {
|
57 |
+
$this->get_panel()->render();
|
58 |
}
|
59 |
|
60 |
}
|
61 |
|
62 |
+
/**
|
63 |
+
* @return void
|
64 |
+
*/
|
65 |
function register_qm_collectors_debug_bar() {
|
66 |
|
67 |
global $debug_bar;
|
71 |
}
|
72 |
|
73 |
$collectors = QM_Collectors::init();
|
74 |
+
$qm = QueryMonitor::init();
|
75 |
|
76 |
require_once $qm->plugin_path( 'classes/debug_bar.php' );
|
77 |
|
99 |
|
100 |
}
|
101 |
|
102 |
+
/**
|
103 |
+
* @return bool
|
104 |
+
*/
|
105 |
function qm_debug_bar_being_activated() {
|
106 |
// phpcs:disable
|
107 |
|
collectors/environment.php
CHANGED
@@ -5,11 +5,20 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Environment extends QM_Collector {
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
protected $php_vars = array(
|
14 |
'max_execution_time',
|
15 |
'memory_limit',
|
@@ -19,11 +28,13 @@ class QM_Collector_Environment extends QM_Collector {
|
|
19 |
'log_errors',
|
20 |
);
|
21 |
|
22 |
-
|
23 |
-
|
|
|
|
|
24 |
global $wpdb;
|
25 |
|
26 |
-
parent::
|
27 |
|
28 |
# If QM_DB is in place then we'll use the values which were
|
29 |
# caught early before any plugins had a chance to alter them
|
@@ -39,24 +50,28 @@ class QM_Collector_Environment extends QM_Collector {
|
|
39 |
|
40 |
}
|
41 |
|
|
|
|
|
|
|
|
|
42 |
protected static function get_error_levels( $error_reporting ) {
|
43 |
$levels = array(
|
44 |
-
'E_ERROR'
|
45 |
-
'E_WARNING'
|
46 |
-
'E_PARSE'
|
47 |
-
'E_NOTICE'
|
48 |
-
'E_CORE_ERROR'
|
49 |
-
'E_CORE_WARNING'
|
50 |
-
'E_COMPILE_ERROR'
|
51 |
-
'E_COMPILE_WARNING'
|
52 |
-
'E_USER_ERROR'
|
53 |
-
'E_USER_WARNING'
|
54 |
-
'E_USER_NOTICE'
|
55 |
-
'E_STRICT'
|
56 |
'E_RECOVERABLE_ERROR' => false,
|
57 |
-
'E_DEPRECATED'
|
58 |
-
'E_USER_DEPRECATED'
|
59 |
-
'E_ALL'
|
60 |
);
|
61 |
|
62 |
foreach ( $levels as $level => $reported ) {
|
@@ -71,20 +86,24 @@ class QM_Collector_Environment extends QM_Collector {
|
|
71 |
return $levels;
|
72 |
}
|
73 |
|
|
|
|
|
|
|
74 |
public function process() {
|
75 |
|
76 |
global $wp_version;
|
77 |
|
78 |
$mysql_vars = array(
|
79 |
-
'key_buffer_size'
|
80 |
-
'max_allowed_packet'
|
81 |
-
'max_connections'
|
82 |
-
'query_cache_limit'
|
83 |
-
'query_cache_size'
|
84 |
-
'query_cache_type'
|
85 |
'innodb_buffer_pool_size' => false, # The amount of memory allocated to the InnoDB buffer pool
|
86 |
);
|
87 |
|
|
|
88 |
$dbq = QM_Collectors::get( 'db_queries' );
|
89 |
|
90 |
if ( $dbq ) {
|
@@ -97,8 +116,6 @@ class QM_Collector_Environment extends QM_Collector {
|
|
97 |
if ( version_compare( $server, '5.7.20', '>=' ) ) {
|
98 |
unset( $mysql_vars['query_cache_limit'], $mysql_vars['query_cache_size'], $mysql_vars['query_cache_type'] );
|
99 |
}
|
100 |
-
} else {
|
101 |
-
$server = null;
|
102 |
}
|
103 |
|
104 |
$variables = $db->get_results( "
|
@@ -106,12 +123,15 @@ class QM_Collector_Environment extends QM_Collector {
|
|
106 |
WHERE Variable_name IN ( '" . implode( "', '", array_keys( $mysql_vars ) ) . "' )
|
107 |
" );
|
108 |
|
109 |
-
|
|
|
|
|
|
|
110 |
# Old mysql extension
|
111 |
$extension = 'mysql';
|
112 |
-
} elseif ( is_object( $
|
113 |
# mysqli or PDO
|
114 |
-
$extension = get_class( $
|
115 |
} else {
|
116 |
# Who knows?
|
117 |
$extension = null;
|
@@ -119,7 +139,7 @@ class QM_Collector_Environment extends QM_Collector {
|
|
119 |
|
120 |
if ( isset( $db->use_mysqli ) && $db->use_mysqli ) {
|
121 |
$client = mysqli_get_client_version();
|
122 |
-
$info
|
123 |
} else {
|
124 |
// Please do not report this code as a PHP 7 incompatibility. Observe the surrounding logic.
|
125 |
// phpcs:ignore
|
@@ -130,7 +150,7 @@ class QM_Collector_Environment extends QM_Collector {
|
|
130 |
}
|
131 |
// Please do not report this code as a PHP 7 incompatibility. Observe the surrounding logic.
|
132 |
// phpcs:ignore
|
133 |
-
$info = mysql_get_server_info( $
|
134 |
}
|
135 |
|
136 |
if ( $client ) {
|
@@ -140,18 +160,20 @@ class QM_Collector_Environment extends QM_Collector {
|
|
140 |
$client_version = null;
|
141 |
}
|
142 |
|
|
|
|
|
143 |
$info = array(
|
144 |
-
'server-version' => $
|
145 |
-
'extension'
|
146 |
'client-version' => $client_version,
|
147 |
-
'user'
|
148 |
-
'host'
|
149 |
-
'database'
|
150 |
);
|
151 |
|
152 |
$this->data['db'][ $id ] = array(
|
153 |
-
'info'
|
154 |
-
'vars'
|
155 |
'variables' => $variables,
|
156 |
);
|
157 |
|
@@ -159,9 +181,11 @@ class QM_Collector_Environment extends QM_Collector {
|
|
159 |
}
|
160 |
|
161 |
$this->data['php']['version'] = phpversion();
|
162 |
-
$this->data['php']['sapi']
|
163 |
-
$this->data['php']['user']
|
164 |
-
|
|
|
|
|
165 |
|
166 |
foreach ( $this->php_vars as $setting ) {
|
167 |
$this->data['php']['variables'][ $setting ]['after'] = ini_get( $setting );
|
@@ -174,7 +198,7 @@ class QM_Collector_Environment extends QM_Collector {
|
|
174 |
$sort_flags = SORT_STRING;
|
175 |
}
|
176 |
|
177 |
-
if (
|
178 |
$extensions = get_loaded_extensions();
|
179 |
sort( $extensions, $sort_flags );
|
180 |
$this->data['php']['extensions'] = array_combine( $extensions, array_map( array( $this, 'get_extension_version' ), $extensions ) );
|
@@ -183,18 +207,18 @@ class QM_Collector_Environment extends QM_Collector {
|
|
183 |
}
|
184 |
|
185 |
$this->data['php']['error_reporting'] = error_reporting();
|
186 |
-
$this->data['php']['error_levels']
|
187 |
-
|
188 |
-
$this->data['wp']['version']
|
189 |
-
$constants
|
190 |
-
'WP_DEBUG'
|
191 |
-
'WP_DEBUG_DISPLAY'
|
192 |
-
'WP_DEBUG_LOG'
|
193 |
-
'SCRIPT_DEBUG'
|
194 |
-
'WP_CACHE'
|
195 |
'CONCATENATE_SCRIPTS' => self::format_bool_constant( 'CONCATENATE_SCRIPTS' ),
|
196 |
-
'COMPRESS_SCRIPTS'
|
197 |
-
'COMPRESS_CSS'
|
198 |
'WP_ENVIRONMENT_TYPE' => self::format_bool_constant( 'WP_ENVIRONMENT_TYPE' ),
|
199 |
);
|
200 |
|
@@ -228,20 +252,25 @@ class QM_Collector_Environment extends QM_Collector {
|
|
228 |
}
|
229 |
|
230 |
$this->data['server'] = array(
|
231 |
-
'name'
|
232 |
'version' => $server_version,
|
233 |
'address' => $address,
|
234 |
-
'host'
|
235 |
-
'OS'
|
236 |
);
|
237 |
|
238 |
if ( function_exists( 'php_uname' ) ) {
|
239 |
$this->data['server']['host'] = php_uname( 'n' );
|
240 |
-
$this->data['server']['OS']
|
|
|
241 |
}
|
242 |
|
243 |
}
|
244 |
|
|
|
|
|
|
|
|
|
245 |
public function get_extension_version( $extension ) {
|
246 |
// Nothing is simple in PHP. The exif and mysqlnd extensions (and probably others) add a bunch of
|
247 |
// crap to their version number, so we need to pluck out the first numeric value in the string.
|
@@ -263,6 +292,31 @@ class QM_Collector_Environment extends QM_Collector {
|
|
263 |
return $version;
|
264 |
}
|
265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
protected static function get_current_user() {
|
267 |
|
268 |
$php_u = null;
|
@@ -304,6 +358,11 @@ class QM_Collector_Environment extends QM_Collector {
|
|
304 |
|
305 |
}
|
306 |
|
|
|
|
|
|
|
|
|
|
|
307 |
function register_qm_collector_environment( array $collectors, QueryMonitor $qm ) {
|
308 |
$collectors['environment'] = new QM_Collector_Environment();
|
309 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Environment extends QM_Collector {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
public $id = 'environment';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var array<int, string>
|
21 |
+
*/
|
22 |
protected $php_vars = array(
|
23 |
'max_execution_time',
|
24 |
'memory_limit',
|
28 |
'log_errors',
|
29 |
);
|
30 |
|
31 |
+
/**
|
32 |
+
* @return void
|
33 |
+
*/
|
34 |
+
public function set_up() {
|
35 |
global $wpdb;
|
36 |
|
37 |
+
parent::set_up();
|
38 |
|
39 |
# If QM_DB is in place then we'll use the values which were
|
40 |
# caught early before any plugins had a chance to alter them
|
50 |
|
51 |
}
|
52 |
|
53 |
+
/**
|
54 |
+
* @param int $error_reporting
|
55 |
+
* @return array<string, bool>
|
56 |
+
*/
|
57 |
protected static function get_error_levels( $error_reporting ) {
|
58 |
$levels = array(
|
59 |
+
'E_ERROR' => false,
|
60 |
+
'E_WARNING' => false,
|
61 |
+
'E_PARSE' => false,
|
62 |
+
'E_NOTICE' => false,
|
63 |
+
'E_CORE_ERROR' => false,
|
64 |
+
'E_CORE_WARNING' => false,
|
65 |
+
'E_COMPILE_ERROR' => false,
|
66 |
+
'E_COMPILE_WARNING' => false,
|
67 |
+
'E_USER_ERROR' => false,
|
68 |
+
'E_USER_WARNING' => false,
|
69 |
+
'E_USER_NOTICE' => false,
|
70 |
+
'E_STRICT' => false,
|
71 |
'E_RECOVERABLE_ERROR' => false,
|
72 |
+
'E_DEPRECATED' => false,
|
73 |
+
'E_USER_DEPRECATED' => false,
|
74 |
+
'E_ALL' => false,
|
75 |
);
|
76 |
|
77 |
foreach ( $levels as $level => $reported ) {
|
86 |
return $levels;
|
87 |
}
|
88 |
|
89 |
+
/**
|
90 |
+
* @return void
|
91 |
+
*/
|
92 |
public function process() {
|
93 |
|
94 |
global $wp_version;
|
95 |
|
96 |
$mysql_vars = array(
|
97 |
+
'key_buffer_size' => true, # Key cache size limit
|
98 |
+
'max_allowed_packet' => false, # Individual query size limit
|
99 |
+
'max_connections' => false, # Max number of client connections
|
100 |
+
'query_cache_limit' => true, # Individual query cache size limit
|
101 |
+
'query_cache_size' => true, # Total cache size limit
|
102 |
+
'query_cache_type' => 'ON', # Query cache on or off
|
103 |
'innodb_buffer_pool_size' => false, # The amount of memory allocated to the InnoDB buffer pool
|
104 |
);
|
105 |
|
106 |
+
/** @var QM_Collector_DB_Queries|null */
|
107 |
$dbq = QM_Collectors::get( 'db_queries' );
|
108 |
|
109 |
if ( $dbq ) {
|
116 |
if ( version_compare( $server, '5.7.20', '>=' ) ) {
|
117 |
unset( $mysql_vars['query_cache_limit'], $mysql_vars['query_cache_size'], $mysql_vars['query_cache_type'] );
|
118 |
}
|
|
|
|
|
119 |
}
|
120 |
|
121 |
$variables = $db->get_results( "
|
123 |
WHERE Variable_name IN ( '" . implode( "', '", array_keys( $mysql_vars ) ) . "' )
|
124 |
" );
|
125 |
|
126 |
+
/** @var mysqli|resource|false|null $dbh */
|
127 |
+
$dbh = $db->dbh;
|
128 |
+
|
129 |
+
if ( is_resource( $dbh ) ) {
|
130 |
# Old mysql extension
|
131 |
$extension = 'mysql';
|
132 |
+
} elseif ( is_object( $dbh ) ) {
|
133 |
# mysqli or PDO
|
134 |
+
$extension = get_class( $dbh );
|
135 |
} else {
|
136 |
# Who knows?
|
137 |
$extension = null;
|
139 |
|
140 |
if ( isset( $db->use_mysqli ) && $db->use_mysqli ) {
|
141 |
$client = mysqli_get_client_version();
|
142 |
+
$info = mysqli_get_server_info( $dbh );
|
143 |
} else {
|
144 |
// Please do not report this code as a PHP 7 incompatibility. Observe the surrounding logic.
|
145 |
// phpcs:ignore
|
150 |
}
|
151 |
// Please do not report this code as a PHP 7 incompatibility. Observe the surrounding logic.
|
152 |
// phpcs:ignore
|
153 |
+
$info = mysql_get_server_info( $dbh );
|
154 |
}
|
155 |
|
156 |
if ( $client ) {
|
160 |
$client_version = null;
|
161 |
}
|
162 |
|
163 |
+
$server_version = self::get_server_version( $db );
|
164 |
+
|
165 |
$info = array(
|
166 |
+
'server-version' => $server_version,
|
167 |
+
'extension' => $extension,
|
168 |
'client-version' => $client_version,
|
169 |
+
'user' => $db->dbuser,
|
170 |
+
'host' => $db->dbhost,
|
171 |
+
'database' => $db->dbname,
|
172 |
);
|
173 |
|
174 |
$this->data['db'][ $id ] = array(
|
175 |
+
'info' => $info,
|
176 |
+
'vars' => $mysql_vars,
|
177 |
'variables' => $variables,
|
178 |
);
|
179 |
|
181 |
}
|
182 |
|
183 |
$this->data['php']['version'] = phpversion();
|
184 |
+
$this->data['php']['sapi'] = php_sapi_name();
|
185 |
+
$this->data['php']['user'] = self::get_current_user();
|
186 |
+
|
187 |
+
// https://www.php.net/supported-versions.php
|
188 |
+
$this->data['php']['old'] = version_compare( $this->data['php']['version'], '7.4', '<' );
|
189 |
|
190 |
foreach ( $this->php_vars as $setting ) {
|
191 |
$this->data['php']['variables'][ $setting ]['after'] = ini_get( $setting );
|
198 |
$sort_flags = SORT_STRING;
|
199 |
}
|
200 |
|
201 |
+
if ( function_exists( 'get_loaded_extensions' ) ) {
|
202 |
$extensions = get_loaded_extensions();
|
203 |
sort( $extensions, $sort_flags );
|
204 |
$this->data['php']['extensions'] = array_combine( $extensions, array_map( array( $this, 'get_extension_version' ), $extensions ) );
|
207 |
}
|
208 |
|
209 |
$this->data['php']['error_reporting'] = error_reporting();
|
210 |
+
$this->data['php']['error_levels'] = self::get_error_levels( $this->data['php']['error_reporting'] );
|
211 |
+
|
212 |
+
$this->data['wp']['version'] = $wp_version;
|
213 |
+
$constants = array(
|
214 |
+
'WP_DEBUG' => self::format_bool_constant( 'WP_DEBUG' ),
|
215 |
+
'WP_DEBUG_DISPLAY' => self::format_bool_constant( 'WP_DEBUG_DISPLAY' ),
|
216 |
+
'WP_DEBUG_LOG' => self::format_bool_constant( 'WP_DEBUG_LOG' ),
|
217 |
+
'SCRIPT_DEBUG' => self::format_bool_constant( 'SCRIPT_DEBUG' ),
|
218 |
+
'WP_CACHE' => self::format_bool_constant( 'WP_CACHE' ),
|
219 |
'CONCATENATE_SCRIPTS' => self::format_bool_constant( 'CONCATENATE_SCRIPTS' ),
|
220 |
+
'COMPRESS_SCRIPTS' => self::format_bool_constant( 'COMPRESS_SCRIPTS' ),
|
221 |
+
'COMPRESS_CSS' => self::format_bool_constant( 'COMPRESS_CSS' ),
|
222 |
'WP_ENVIRONMENT_TYPE' => self::format_bool_constant( 'WP_ENVIRONMENT_TYPE' ),
|
223 |
);
|
224 |
|
252 |
}
|
253 |
|
254 |
$this->data['server'] = array(
|
255 |
+
'name' => $server[0],
|
256 |
'version' => $server_version,
|
257 |
'address' => $address,
|
258 |
+
'host' => null,
|
259 |
+
'OS' => null,
|
260 |
);
|
261 |
|
262 |
if ( function_exists( 'php_uname' ) ) {
|
263 |
$this->data['server']['host'] = php_uname( 'n' );
|
264 |
+
$this->data['server']['OS'] = php_uname( 's' ) . ' ' . php_uname( 'r' );
|
265 |
+
$this->data['server']['arch'] = php_uname( 'm' );
|
266 |
}
|
267 |
|
268 |
}
|
269 |
|
270 |
+
/**
|
271 |
+
* @param string $extension
|
272 |
+
* @return string
|
273 |
+
*/
|
274 |
public function get_extension_version( $extension ) {
|
275 |
// Nothing is simple in PHP. The exif and mysqlnd extensions (and probably others) add a bunch of
|
276 |
// crap to their version number, so we need to pluck out the first numeric value in the string.
|
292 |
return $version;
|
293 |
}
|
294 |
|
295 |
+
/**
|
296 |
+
* @param wpdb $db
|
297 |
+
* @return string
|
298 |
+
*/
|
299 |
+
protected static function get_server_version( wpdb $db ) {
|
300 |
+
$version = null;
|
301 |
+
|
302 |
+
if ( method_exists( $db, 'db_server_info' ) ) {
|
303 |
+
$version = $db->db_server_info();
|
304 |
+
}
|
305 |
+
|
306 |
+
if ( ! $version ) {
|
307 |
+
$version = $db->get_var( 'SELECT VERSION()' );
|
308 |
+
}
|
309 |
+
|
310 |
+
if ( ! $version ) {
|
311 |
+
$version = __( 'Unknown', 'query-monitor' );
|
312 |
+
}
|
313 |
+
|
314 |
+
return $version;
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* @return string
|
319 |
+
*/
|
320 |
protected static function get_current_user() {
|
321 |
|
322 |
$php_u = null;
|
358 |
|
359 |
}
|
360 |
|
361 |
+
/**
|
362 |
+
* @param array<string, QM_Collector> $collectors
|
363 |
+
* @param QueryMonitor $qm
|
364 |
+
* @return array<string, QM_Collector>
|
365 |
+
*/
|
366 |
function register_qm_collector_environment( array $collectors, QueryMonitor $qm ) {
|
367 |
$collectors['environment'] = new QM_Collector_Environment();
|
368 |
return $collectors;
|
collectors/hooks.php
CHANGED
@@ -5,22 +5,34 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Hooks extends QM_Collector {
|
11 |
|
|
|
|
|
|
|
12 |
public $id = 'hooks';
|
|
|
|
|
|
|
|
|
13 |
protected static $hide_core;
|
14 |
|
|
|
|
|
|
|
15 |
public function process() {
|
16 |
|
17 |
global $wp_actions, $wp_filter;
|
18 |
|
19 |
-
self::$hide_qm
|
20 |
self::$hide_core = ( defined( 'QM_HIDE_CORE_ACTIONS' ) && QM_HIDE_CORE_ACTIONS );
|
21 |
|
22 |
-
$hooks
|
23 |
-
$all_parts
|
24 |
$components = array();
|
25 |
|
26 |
if ( has_filter( 'all' ) ) {
|
@@ -39,16 +51,16 @@ class QM_Collector_Hooks extends QM_Collector {
|
|
39 |
|
40 |
foreach ( $hook_names as $name ) {
|
41 |
|
42 |
-
$hook
|
43 |
$hooks[] = $hook;
|
44 |
|
45 |
-
$all_parts
|
46 |
$components = array_merge( $components, $hook['components'] );
|
47 |
|
48 |
}
|
49 |
|
50 |
-
$this->data['hooks']
|
51 |
-
$this->data['parts']
|
52 |
$this->data['components'] = array_unique( array_filter( $components ) );
|
53 |
|
54 |
usort( $this->data['parts'], 'strcasecmp' );
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Hooks extends QM_Collector {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
public $id = 'hooks';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var bool
|
21 |
+
*/
|
22 |
protected static $hide_core;
|
23 |
|
24 |
+
/**
|
25 |
+
* @return void
|
26 |
+
*/
|
27 |
public function process() {
|
28 |
|
29 |
global $wp_actions, $wp_filter;
|
30 |
|
31 |
+
self::$hide_qm = self::hide_qm();
|
32 |
self::$hide_core = ( defined( 'QM_HIDE_CORE_ACTIONS' ) && QM_HIDE_CORE_ACTIONS );
|
33 |
|
34 |
+
$hooks = array();
|
35 |
+
$all_parts = array();
|
36 |
$components = array();
|
37 |
|
38 |
if ( has_filter( 'all' ) ) {
|
51 |
|
52 |
foreach ( $hook_names as $name ) {
|
53 |
|
54 |
+
$hook = QM_Hook::process( $name, $wp_filter, self::$hide_qm, self::$hide_core );
|
55 |
$hooks[] = $hook;
|
56 |
|
57 |
+
$all_parts = array_merge( $all_parts, $hook['parts'] );
|
58 |
$components = array_merge( $components, $hook['components'] );
|
59 |
|
60 |
}
|
61 |
|
62 |
+
$this->data['hooks'] = $hooks;
|
63 |
+
$this->data['parts'] = array_unique( array_filter( $all_parts ) );
|
64 |
$this->data['components'] = array_unique( array_filter( $components ) );
|
65 |
|
66 |
usort( $this->data['parts'], 'strcasecmp' );
|
collectors/http.php
CHANGED
@@ -5,31 +5,66 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_HTTP extends QM_Collector {
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
private $transport = null;
|
14 |
-
private $info = null;
|
15 |
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
-
parent::
|
19 |
|
20 |
add_filter( 'http_request_args', array( $this, 'filter_http_request_args' ), 9999, 2 );
|
21 |
-
add_filter( 'pre_http_request',
|
22 |
-
add_action( 'http_api_debug',
|
23 |
|
24 |
-
add_action( 'requests-curl.before_request',
|
25 |
-
add_action( 'requests-curl.after_request',
|
26 |
add_action( 'requests-fsockopen.before_request', array( $this, 'action_fsockopen_before_request' ), 9999 );
|
27 |
-
add_action( 'requests-fsockopen.after_request',
|
28 |
|
29 |
}
|
30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
public function get_concerned_actions() {
|
32 |
-
$actions
|
33 |
'http_api_curl',
|
34 |
'requests-multiple.request.complete',
|
35 |
'requests-request.progress',
|
@@ -61,6 +96,9 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
61 |
return $actions;
|
62 |
}
|
63 |
|
|
|
|
|
|
|
64 |
public function get_concerned_filters() {
|
65 |
return array(
|
66 |
'block_local_requests',
|
@@ -74,6 +112,9 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
74 |
);
|
75 |
}
|
76 |
|
|
|
|
|
|
|
77 |
public function get_concerned_constants() {
|
78 |
return array(
|
79 |
'WP_PROXY_HOST',
|
@@ -91,28 +132,52 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
91 |
*
|
92 |
* Used to log the request, and to add the logging key to the arguments array.
|
93 |
*
|
94 |
-
* @param array
|
95 |
-
* @param string
|
96 |
-
* @return array
|
97 |
*/
|
98 |
public function filter_http_request_args( array $args, $url ) {
|
99 |
-
$trace = new QM_Backtrace(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
if ( isset( $args['_qm_key'] ) ) {
|
101 |
// Something has triggered another HTTP request from within the `pre_http_request` filter
|
102 |
// (eg. WordPress Beta Tester does this). This allows for one level of nested queries.
|
103 |
$args['_qm_original_key'] = $args['_qm_key'];
|
104 |
-
$start
|
105 |
} else {
|
106 |
$start = microtime( true );
|
107 |
}
|
108 |
-
$key
|
109 |
$this->data['http'][ $key ] = array(
|
110 |
-
'url'
|
111 |
-
'args'
|
112 |
'start' => $start,
|
113 |
-
'
|
|
|
114 |
);
|
115 |
-
$args['_qm_key']
|
116 |
return $args;
|
117 |
}
|
118 |
|
@@ -123,10 +188,10 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
123 |
* $response should be one of boolean false, an array, or a `WP_Error`, but be aware that plugins
|
124 |
* which short-circuit the request using this filter may (incorrectly) return data of another type.
|
125 |
*
|
126 |
-
* @param bool|
|
127 |
-
* @param array
|
128 |
-
* @param string
|
129 |
-
* @return bool|
|
130 |
*/
|
131 |
public function filter_pre_http_request( $response, array $args, $url ) {
|
132 |
|
@@ -144,11 +209,12 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
144 |
/**
|
145 |
* Debugging action for the HTTP API.
|
146 |
*
|
147 |
-
* @param mixed
|
148 |
-
* @param string
|
149 |
-
* @param string
|
150 |
-
* @param array
|
151 |
-
* @param string
|
|
|
152 |
*/
|
153 |
public function action_http_api_debug( $response, $action, $class, $args, $url ) {
|
154 |
|
@@ -173,18 +239,34 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
173 |
|
174 |
}
|
175 |
|
|
|
|
|
|
|
176 |
public function action_curl_before_request() {
|
177 |
$this->transport = 'curl';
|
178 |
}
|
179 |
|
|
|
|
|
|
|
|
|
|
|
180 |
public function action_curl_after_request( $headers, array $info = null ) {
|
181 |
$this->info = $info;
|
182 |
}
|
183 |
|
|
|
|
|
|
|
184 |
public function action_fsockopen_before_request() {
|
185 |
$this->transport = 'fsockopen';
|
186 |
}
|
187 |
|
|
|
|
|
|
|
|
|
|
|
188 |
public function action_fsockopen_after_request( $headers, array $info = null ) {
|
189 |
$this->info = $info;
|
190 |
}
|
@@ -192,16 +274,17 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
192 |
/**
|
193 |
* Log an HTTP response.
|
194 |
*
|
195 |
-
* @param
|
196 |
-
* @param array
|
197 |
-
* @param string
|
|
|
198 |
*/
|
199 |
public function log_http_response( $response, array $args, $url ) {
|
200 |
-
$this->data['http'][ $args['_qm_key'] ]['end']
|
201 |
$this->data['http'][ $args['_qm_key'] ]['response'] = $response;
|
202 |
-
$this->data['http'][ $args['_qm_key'] ]['args']
|
203 |
if ( isset( $args['_qm_original_key'] ) ) {
|
204 |
-
$this->data['http'][ $args['_qm_original_key'] ]['end']
|
205 |
$this->data['http'][ $args['_qm_original_key'] ]['response'] = new WP_Error( 'http_request_not_executed', sprintf(
|
206 |
/* translators: %s: Hook name */
|
207 |
__( 'Request not executed due to a filter on %s', 'query-monitor' ),
|
@@ -209,12 +292,15 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
209 |
) );
|
210 |
}
|
211 |
|
212 |
-
$this->data['http'][ $args['_qm_key'] ]['info']
|
213 |
$this->data['http'][ $args['_qm_key'] ]['transport'] = $this->transport;
|
214 |
-
$this->info
|
215 |
$this->transport = null;
|
216 |
}
|
217 |
|
|
|
|
|
|
|
218 |
public function process() {
|
219 |
$this->data['ltime'] = 0;
|
220 |
|
@@ -241,7 +327,7 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
241 |
if ( ! isset( $http['response'] ) ) {
|
242 |
// Timed out
|
243 |
$http['response'] = new WP_Error( 'http_request_timed_out', __( 'Request timed out', 'query-monitor' ) );
|
244 |
-
$http['end']
|
245 |
}
|
246 |
|
247 |
if ( is_wp_error( $http['response'] ) ) {
|
@@ -260,18 +346,17 @@ class QM_Collector_HTTP extends QM_Collector {
|
|
260 |
|
261 |
$http['ltime'] = ( $http['end'] - $http['start'] );
|
262 |
|
263 |
-
if ( isset( $http['info'] ) ) {
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
|
|
268 |
}
|
269 |
}
|
270 |
|
271 |
$this->data['ltime'] += $http['ltime'];
|
272 |
|
273 |
-
$http['component'] = $http['trace']->get_component();
|
274 |
-
|
275 |
$host = (string) parse_url( $http['url'], PHP_URL_HOST );
|
276 |
|
277 |
$http['local'] = ( $host === $home_host );
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_HTTP extends QM_Collector {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
public $id = 'http';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var string|null
|
21 |
+
*/
|
22 |
private $transport = null;
|
|
|
23 |
|
24 |
+
/**
|
25 |
+
* @var mixed|null
|
26 |
+
*/
|
27 |
+
private $info = null;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return void
|
31 |
+
*/
|
32 |
+
public function set_up() {
|
33 |
|
34 |
+
parent::set_up();
|
35 |
|
36 |
add_filter( 'http_request_args', array( $this, 'filter_http_request_args' ), 9999, 2 );
|
37 |
+
add_filter( 'pre_http_request', array( $this, 'filter_pre_http_request' ), 9999, 3 );
|
38 |
+
add_action( 'http_api_debug', array( $this, 'action_http_api_debug' ), 9999, 5 );
|
39 |
|
40 |
+
add_action( 'requests-curl.before_request', array( $this, 'action_curl_before_request' ), 9999 );
|
41 |
+
add_action( 'requests-curl.after_request', array( $this, 'action_curl_after_request' ), 9999, 2 );
|
42 |
add_action( 'requests-fsockopen.before_request', array( $this, 'action_fsockopen_before_request' ), 9999 );
|
43 |
+
add_action( 'requests-fsockopen.after_request', array( $this, 'action_fsockopen_after_request' ), 9999, 2 );
|
44 |
|
45 |
}
|
46 |
|
47 |
+
/**
|
48 |
+
* @return void
|
49 |
+
*/
|
50 |
+
public function tear_down() {
|
51 |
+
remove_filter( 'http_request_args', array( $this, 'filter_http_request_args' ), 9999 );
|
52 |
+
remove_filter( 'pre_http_request', array( $this, 'filter_pre_http_request' ), 9999 );
|
53 |
+
remove_action( 'http_api_debug', array( $this, 'action_http_api_debug' ), 9999 );
|
54 |
+
|
55 |
+
remove_action( 'requests-curl.before_request', array( $this, 'action_curl_before_request' ), 9999 );
|
56 |
+
remove_action( 'requests-curl.after_request', array( $this, 'action_curl_after_request' ), 9999 );
|
57 |
+
remove_action( 'requests-fsockopen.before_request', array( $this, 'action_fsockopen_before_request' ), 9999 );
|
58 |
+
remove_action( 'requests-fsockopen.after_request', array( $this, 'action_fsockopen_after_request' ), 9999 );
|
59 |
+
|
60 |
+
parent::tear_down();
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* @return array<int, string>
|
65 |
+
*/
|
66 |
public function get_concerned_actions() {
|
67 |
+
$actions = array(
|
68 |
'http_api_curl',
|
69 |
'requests-multiple.request.complete',
|
70 |
'requests-request.progress',
|
96 |
return $actions;
|
97 |
}
|
98 |
|
99 |
+
/**
|
100 |
+
* @return array<int, string>
|
101 |
+
*/
|
102 |
public function get_concerned_filters() {
|
103 |
return array(
|
104 |
'block_local_requests',
|
112 |
);
|
113 |
}
|
114 |
|
115 |
+
/**
|
116 |
+
* @return array<int, string>
|
117 |
+
*/
|
118 |
public function get_concerned_constants() {
|
119 |
return array(
|
120 |
'WP_PROXY_HOST',
|
132 |
*
|
133 |
* Used to log the request, and to add the logging key to the arguments array.
|
134 |
*
|
135 |
+
* @param array<string, mixed> $args HTTP request arguments.
|
136 |
+
* @param string $url The request URL.
|
137 |
+
* @return array<string, mixed> HTTP request arguments.
|
138 |
*/
|
139 |
public function filter_http_request_args( array $args, $url ) {
|
140 |
+
$trace = new QM_Backtrace( array(
|
141 |
+
'ignore_hook' => array(
|
142 |
+
current_filter() => true,
|
143 |
+
),
|
144 |
+
'ignore_class' => array(
|
145 |
+
'WP_Http' => true,
|
146 |
+
),
|
147 |
+
'ignore_func' => array(
|
148 |
+
'wp_safe_remote_request' => true,
|
149 |
+
'wp_safe_remote_get' => true,
|
150 |
+
'wp_safe_remote_post' => true,
|
151 |
+
'wp_safe_remote_head' => true,
|
152 |
+
'wp_remote_request' => true,
|
153 |
+
'wp_remote_get' => true,
|
154 |
+
'wp_remote_post' => true,
|
155 |
+
'wp_remote_head' => true,
|
156 |
+
'wp_remote_fopen' => true,
|
157 |
+
'download_url' => true,
|
158 |
+
'vip_safe_wp_remote_get' => true,
|
159 |
+
'vip_safe_wp_remote_request' => true,
|
160 |
+
'wpcom_vip_file_get_contents' => true,
|
161 |
+
),
|
162 |
+
) );
|
163 |
+
|
164 |
if ( isset( $args['_qm_key'] ) ) {
|
165 |
// Something has triggered another HTTP request from within the `pre_http_request` filter
|
166 |
// (eg. WordPress Beta Tester does this). This allows for one level of nested queries.
|
167 |
$args['_qm_original_key'] = $args['_qm_key'];
|
168 |
+
$start = $this->data['http'][ $args['_qm_key'] ]['start'];
|
169 |
} else {
|
170 |
$start = microtime( true );
|
171 |
}
|
172 |
+
$key = microtime( true ) . $url;
|
173 |
$this->data['http'][ $key ] = array(
|
174 |
+
'url' => $url,
|
175 |
+
'args' => $args,
|
176 |
'start' => $start,
|
177 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
178 |
+
'component' => $trace->get_component(),
|
179 |
);
|
180 |
+
$args['_qm_key'] = $key;
|
181 |
return $args;
|
182 |
}
|
183 |
|
188 |
* $response should be one of boolean false, an array, or a `WP_Error`, but be aware that plugins
|
189 |
* which short-circuit the request using this filter may (incorrectly) return data of another type.
|
190 |
*
|
191 |
+
* @param bool|mixed[]|WP_Error $response The preemptive HTTP response. Default false.
|
192 |
+
* @param array<string, mixed> $args HTTP request arguments.
|
193 |
+
* @param string $url The request URL.
|
194 |
+
* @return bool|mixed[]|WP_Error The preemptive HTTP response.
|
195 |
*/
|
196 |
public function filter_pre_http_request( $response, array $args, $url ) {
|
197 |
|
209 |
/**
|
210 |
* Debugging action for the HTTP API.
|
211 |
*
|
212 |
+
* @param mixed $response A parameter which varies depending on $action.
|
213 |
+
* @param string $action The debug action. Currently one of 'response' or 'transports_list'.
|
214 |
+
* @param string $class The HTTP transport class name.
|
215 |
+
* @param array<string, mixed> $args HTTP request arguments.
|
216 |
+
* @param string $url The request URL.
|
217 |
+
* @return void
|
218 |
*/
|
219 |
public function action_http_api_debug( $response, $action, $class, $args, $url ) {
|
220 |
|
239 |
|
240 |
}
|
241 |
|
242 |
+
/**
|
243 |
+
* @return void
|
244 |
+
*/
|
245 |
public function action_curl_before_request() {
|
246 |
$this->transport = 'curl';
|
247 |
}
|
248 |
|
249 |
+
/**
|
250 |
+
* @param mixed $headers
|
251 |
+
* @param mixed[] $info
|
252 |
+
* @return void
|
253 |
+
*/
|
254 |
public function action_curl_after_request( $headers, array $info = null ) {
|
255 |
$this->info = $info;
|
256 |
}
|
257 |
|
258 |
+
/**
|
259 |
+
* @return void
|
260 |
+
*/
|
261 |
public function action_fsockopen_before_request() {
|
262 |
$this->transport = 'fsockopen';
|
263 |
}
|
264 |
|
265 |
+
/**
|
266 |
+
* @param mixed $headers
|
267 |
+
* @param mixed[] $info
|
268 |
+
* @return void
|
269 |
+
*/
|
270 |
public function action_fsockopen_after_request( $headers, array $info = null ) {
|
271 |
$this->info = $info;
|
272 |
}
|
274 |
/**
|
275 |
* Log an HTTP response.
|
276 |
*
|
277 |
+
* @param mixed[]|WP_Error $response The HTTP response.
|
278 |
+
* @param array<string, mixed> $args HTTP request arguments.
|
279 |
+
* @param string $url The request URL.
|
280 |
+
* @return void
|
281 |
*/
|
282 |
public function log_http_response( $response, array $args, $url ) {
|
283 |
+
$this->data['http'][ $args['_qm_key'] ]['end'] = microtime( true );
|
284 |
$this->data['http'][ $args['_qm_key'] ]['response'] = $response;
|
285 |
+
$this->data['http'][ $args['_qm_key'] ]['args'] = $args;
|
286 |
if ( isset( $args['_qm_original_key'] ) ) {
|
287 |
+
$this->data['http'][ $args['_qm_original_key'] ]['end'] = $this->data['http'][ $args['_qm_original_key'] ]['start'];
|
288 |
$this->data['http'][ $args['_qm_original_key'] ]['response'] = new WP_Error( 'http_request_not_executed', sprintf(
|
289 |
/* translators: %s: Hook name */
|
290 |
__( 'Request not executed due to a filter on %s', 'query-monitor' ),
|
292 |
) );
|
293 |
}
|
294 |
|
295 |
+
$this->data['http'][ $args['_qm_key'] ]['info'] = $this->info;
|
296 |
$this->data['http'][ $args['_qm_key'] ]['transport'] = $this->transport;
|
297 |
+
$this->info = null;
|
298 |
$this->transport = null;
|
299 |
}
|
300 |
|
301 |
+
/**
|
302 |
+
* @return void
|
303 |
+
*/
|
304 |
public function process() {
|
305 |
$this->data['ltime'] = 0;
|
306 |
|
327 |
if ( ! isset( $http['response'] ) ) {
|
328 |
// Timed out
|
329 |
$http['response'] = new WP_Error( 'http_request_timed_out', __( 'Request timed out', 'query-monitor' ) );
|
330 |
+
$http['end'] = floatval( $http['start'] + $http['args']['timeout'] );
|
331 |
}
|
332 |
|
333 |
if ( is_wp_error( $http['response'] ) ) {
|
346 |
|
347 |
$http['ltime'] = ( $http['end'] - $http['start'] );
|
348 |
|
349 |
+
if ( isset( $http['info'] ) && ! empty( $http['info']['url'] ) ) {
|
350 |
+
// Ignore query variables when detecting a redirect.
|
351 |
+
$from = untrailingslashit( preg_replace( '#\?[^$]+$#', '', $http['url'] ) );
|
352 |
+
$to = untrailingslashit( preg_replace( '#\?[^$]+$#', '', $http['info']['url'] ) );
|
353 |
+
if ( $from !== $to ) {
|
354 |
+
$http['redirected_to'] = $http['info']['url'];
|
355 |
}
|
356 |
}
|
357 |
|
358 |
$this->data['ltime'] += $http['ltime'];
|
359 |
|
|
|
|
|
360 |
$host = (string) parse_url( $http['url'], PHP_URL_HOST );
|
361 |
|
362 |
$http['local'] = ( $host === $home_host );
|
collectors/languages.php
CHANGED
@@ -5,21 +5,39 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Languages extends QM_Collector {
|
11 |
|
12 |
public $id = 'languages';
|
13 |
|
14 |
-
|
|
|
|
|
|
|
15 |
|
16 |
-
parent::
|
17 |
|
18 |
add_filter( 'override_load_textdomain', array( $this, 'log_file_load' ), 9999, 3 );
|
19 |
add_filter( 'load_script_translation_file', array( $this, 'log_script_file_load' ), 9999, 3 );
|
20 |
|
21 |
}
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
public function get_concerned_actions() {
|
24 |
return array(
|
25 |
'load_textdomain',
|
@@ -27,6 +45,9 @@ class QM_Collector_Languages extends QM_Collector {
|
|
27 |
);
|
28 |
}
|
29 |
|
|
|
|
|
|
|
30 |
public function get_concerned_filters() {
|
31 |
return array(
|
32 |
'determine_locale',
|
@@ -48,20 +69,33 @@ class QM_Collector_Languages extends QM_Collector {
|
|
48 |
);
|
49 |
}
|
50 |
|
|
|
|
|
|
|
51 |
public function get_concerned_options() {
|
52 |
return array(
|
53 |
'WPLANG',
|
54 |
);
|
55 |
}
|
56 |
|
|
|
|
|
|
|
57 |
public function get_concerned_constants() {
|
58 |
return array(
|
59 |
'WPLANG',
|
60 |
);
|
61 |
}
|
62 |
|
|
|
|
|
|
|
63 |
public function process() {
|
64 |
-
$this->data['
|
|
|
|
|
|
|
|
|
65 |
$this->data['user_locale'] = function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
|
66 |
ksort( $this->data['languages'] );
|
67 |
|
@@ -81,55 +115,33 @@ class QM_Collector_Languages extends QM_Collector {
|
|
81 |
* @return bool
|
82 |
*/
|
83 |
public function log_file_load( $override, $domain, $mofile ) {
|
84 |
-
|
85 |
if ( 'query-monitor' === $domain && self::hide_qm() ) {
|
86 |
return $override;
|
87 |
}
|
88 |
|
89 |
-
$trace
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
'
|
97 |
-
'
|
98 |
-
'
|
99 |
-
'
|
100 |
-
|
101 |
-
|
102 |
-
$caller = $item;
|
103 |
-
$display = $i + 1;
|
104 |
-
if ( isset( $filtered[ $display ] ) ) {
|
105 |
-
$caller['display'] = $filtered[ $display ]['display'];
|
106 |
-
}
|
107 |
-
break;
|
108 |
-
}
|
109 |
-
}
|
110 |
-
|
111 |
-
if ( empty( $caller ) ) {
|
112 |
-
if ( isset( $filtered[1] ) ) {
|
113 |
-
$caller = $filtered[1];
|
114 |
-
} else {
|
115 |
-
$caller = $filtered[0];
|
116 |
-
}
|
117 |
-
}
|
118 |
-
|
119 |
-
if ( ! isset( $caller['file'] ) && isset( $filtered[0]['file'] ) && isset( $filtered[0]['line'] ) ) {
|
120 |
-
$caller['file'] = $filtered[0]['file'];
|
121 |
-
$caller['line'] = $filtered[0]['line'];
|
122 |
-
}
|
123 |
|
124 |
$found = file_exists( $mofile ) ? filesize( $mofile ) : false;
|
125 |
|
126 |
$this->data['languages'][ $domain ][] = array(
|
127 |
-
'caller' => $
|
128 |
'domain' => $domain,
|
129 |
-
'file'
|
130 |
-
'found'
|
131 |
'handle' => null,
|
132 |
-
'type'
|
133 |
);
|
134 |
|
135 |
return $override;
|
@@ -146,19 +158,21 @@ class QM_Collector_Languages extends QM_Collector {
|
|
146 |
* @return string|false Path to the translation file to load. False if there isn't one.
|
147 |
*/
|
148 |
public function log_script_file_load( $file, $handle, $domain ) {
|
149 |
-
$trace
|
150 |
-
|
151 |
-
|
|
|
|
|
152 |
|
153 |
$found = ( $file && file_exists( $file ) ) ? filesize( $file ) : false;
|
154 |
|
155 |
$this->data['languages'][ $domain ][] = array(
|
156 |
-
'caller' => $
|
157 |
'domain' => $domain,
|
158 |
-
'file'
|
159 |
-
'found'
|
160 |
'handle' => $handle,
|
161 |
-
'type'
|
162 |
);
|
163 |
|
164 |
return $file;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Languages extends QM_Collector {
|
13 |
|
14 |
public $id = 'languages';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
+
public function set_up() {
|
20 |
|
21 |
+
parent::set_up();
|
22 |
|
23 |
add_filter( 'override_load_textdomain', array( $this, 'log_file_load' ), 9999, 3 );
|
24 |
add_filter( 'load_script_translation_file', array( $this, 'log_script_file_load' ), 9999, 3 );
|
25 |
|
26 |
}
|
27 |
|
28 |
+
/**
|
29 |
+
* @return void
|
30 |
+
*/
|
31 |
+
public function tear_down() {
|
32 |
+
remove_filter( 'override_load_textdomain', array( $this, 'log_file_load' ), 9999 );
|
33 |
+
remove_filter( 'load_script_translation_file', array( $this, 'log_script_file_load' ), 9999 );
|
34 |
+
|
35 |
+
parent::tear_down();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* @return array<int, string>
|
40 |
+
*/
|
41 |
public function get_concerned_actions() {
|
42 |
return array(
|
43 |
'load_textdomain',
|
45 |
);
|
46 |
}
|
47 |
|
48 |
+
/**
|
49 |
+
* @return array<int, string>
|
50 |
+
*/
|
51 |
public function get_concerned_filters() {
|
52 |
return array(
|
53 |
'determine_locale',
|
69 |
);
|
70 |
}
|
71 |
|
72 |
+
/**
|
73 |
+
* @return array<int, string>
|
74 |
+
*/
|
75 |
public function get_concerned_options() {
|
76 |
return array(
|
77 |
'WPLANG',
|
78 |
);
|
79 |
}
|
80 |
|
81 |
+
/**
|
82 |
+
* @return array<int, string>
|
83 |
+
*/
|
84 |
public function get_concerned_constants() {
|
85 |
return array(
|
86 |
'WPLANG',
|
87 |
);
|
88 |
}
|
89 |
|
90 |
+
/**
|
91 |
+
* @return void
|
92 |
+
*/
|
93 |
public function process() {
|
94 |
+
if ( empty( $this->data['languages'] ) ) {
|
95 |
+
return;
|
96 |
+
}
|
97 |
+
|
98 |
+
$this->data['locale'] = get_locale();
|
99 |
$this->data['user_locale'] = function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
|
100 |
ksort( $this->data['languages'] );
|
101 |
|
115 |
* @return bool
|
116 |
*/
|
117 |
public function log_file_load( $override, $domain, $mofile ) {
|
|
|
118 |
if ( 'query-monitor' === $domain && self::hide_qm() ) {
|
119 |
return $override;
|
120 |
}
|
121 |
|
122 |
+
$trace = new QM_Backtrace( array(
|
123 |
+
'ignore_hook' => array(
|
124 |
+
current_filter() => true,
|
125 |
+
),
|
126 |
+
'ignore_func' => array(
|
127 |
+
'load_textdomain' => ( 'default' !== $domain ),
|
128 |
+
'load_muplugin_textdomain' => true,
|
129 |
+
'load_plugin_textdomain' => true,
|
130 |
+
'load_theme_textdomain' => true,
|
131 |
+
'load_child_theme_textdomain' => true,
|
132 |
+
'load_default_textdomain' => true,
|
133 |
+
),
|
134 |
+
) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
|
136 |
$found = file_exists( $mofile ) ? filesize( $mofile ) : false;
|
137 |
|
138 |
$this->data['languages'][ $domain ][] = array(
|
139 |
+
'caller' => $trace->get_caller(),
|
140 |
'domain' => $domain,
|
141 |
+
'file' => $mofile,
|
142 |
+
'found' => $found,
|
143 |
'handle' => null,
|
144 |
+
'type' => 'gettext',
|
145 |
);
|
146 |
|
147 |
return $override;
|
158 |
* @return string|false Path to the translation file to load. False if there isn't one.
|
159 |
*/
|
160 |
public function log_script_file_load( $file, $handle, $domain ) {
|
161 |
+
$trace = new QM_Backtrace( array(
|
162 |
+
'ignore_hook' => array(
|
163 |
+
current_filter() => true,
|
164 |
+
),
|
165 |
+
) );
|
166 |
|
167 |
$found = ( $file && file_exists( $file ) ) ? filesize( $file ) : false;
|
168 |
|
169 |
$this->data['languages'][ $domain ][] = array(
|
170 |
+
'caller' => $trace->get_caller(),
|
171 |
'domain' => $domain,
|
172 |
+
'file' => $file,
|
173 |
+
'found' => $found,
|
174 |
'handle' => $handle,
|
175 |
+
'type' => 'jed',
|
176 |
);
|
177 |
|
178 |
return $file;
|
collectors/logger.php
CHANGED
@@ -5,23 +5,31 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Logger extends QM_Collector {
|
11 |
|
12 |
public $id = 'logger';
|
13 |
|
14 |
const EMERGENCY = 'emergency';
|
15 |
-
const ALERT
|
16 |
-
const CRITICAL
|
17 |
-
const ERROR
|
18 |
-
const WARNING
|
19 |
-
const NOTICE
|
20 |
-
const INFO
|
21 |
-
const DEBUG
|
22 |
-
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
foreach ( $this->get_levels() as $level ) {
|
26 |
add_action( "qm/{$level}", array( $this, $level ), 10, 2 );
|
27 |
}
|
@@ -29,38 +37,98 @@ class QM_Collector_Logger extends QM_Collector {
|
|
29 |
add_action( 'qm/log', array( $this, 'log' ), 10, 3 );
|
30 |
}
|
31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
public function emergency( $message, array $context = array() ) {
|
33 |
$this->store( self::EMERGENCY, $message, $context );
|
34 |
}
|
35 |
|
|
|
|
|
|
|
|
|
|
|
36 |
public function alert( $message, array $context = array() ) {
|
37 |
$this->store( self::ALERT, $message, $context );
|
38 |
}
|
39 |
|
|
|
|
|
|
|
|
|
|
|
40 |
public function critical( $message, array $context = array() ) {
|
41 |
$this->store( self::CRITICAL, $message, $context );
|
42 |
}
|
43 |
|
|
|
|
|
|
|
|
|
|
|
44 |
public function error( $message, array $context = array() ) {
|
45 |
$this->store( self::ERROR, $message, $context );
|
46 |
}
|
47 |
|
|
|
|
|
|
|
|
|
|
|
48 |
public function warning( $message, array $context = array() ) {
|
49 |
$this->store( self::WARNING, $message, $context );
|
50 |
}
|
51 |
|
|
|
|
|
|
|
|
|
|
|
52 |
public function notice( $message, array $context = array() ) {
|
53 |
$this->store( self::NOTICE, $message, $context );
|
54 |
}
|
55 |
|
|
|
|
|
|
|
|
|
|
|
56 |
public function info( $message, array $context = array() ) {
|
57 |
$this->store( self::INFO, $message, $context );
|
58 |
}
|
59 |
|
|
|
|
|
|
|
|
|
|
|
60 |
public function debug( $message, array $context = array() ) {
|
61 |
$this->store( self::DEBUG, $message, $context );
|
62 |
}
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
public function log( $level, $message, array $context = array() ) {
|
65 |
if ( ! in_array( $level, $this->get_levels(), true ) ) {
|
66 |
throw new InvalidArgumentException( __( 'Unsupported log level', 'query-monitor' ) );
|
@@ -69,14 +137,21 @@ class QM_Collector_Logger extends QM_Collector {
|
|
69 |
$this->store( $level, $message, $context );
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
protected function store( $level, $message, array $context = array() ) {
|
73 |
-
$type = 'string';
|
74 |
$trace = new QM_Backtrace( array(
|
75 |
-
'
|
|
|
|
|
76 |
) );
|
77 |
|
78 |
if ( is_wp_error( $message ) ) {
|
79 |
-
$type = 'wp_error';
|
80 |
$message = sprintf(
|
81 |
'WP_Error: %s (%s)',
|
82 |
$message->get_error_message(),
|
@@ -85,7 +160,6 @@ class QM_Collector_Logger extends QM_Collector {
|
|
85 |
}
|
86 |
|
87 |
if ( ( $message instanceof Exception ) || ( $message instanceof Throwable ) ) {
|
88 |
-
$type = 'throwable';
|
89 |
$message = get_class( $message ) . ': ' . $message->getMessage();
|
90 |
}
|
91 |
|
@@ -98,21 +172,25 @@ class QM_Collector_Logger extends QM_Collector {
|
|
98 |
$message = 'true';
|
99 |
}
|
100 |
|
101 |
-
$type = 'dump';
|
102 |
$message = print_r( $message, true );
|
103 |
} elseif ( '' === trim( $message ) ) {
|
104 |
$message = '(Empty string)';
|
105 |
}
|
106 |
|
|
|
107 |
$this->data['logs'][] = array(
|
108 |
'message' => self::interpolate( $message, $context ),
|
109 |
-
'
|
110 |
-
'
|
111 |
-
'level'
|
112 |
-
'type' => $type,
|
113 |
);
|
114 |
}
|
115 |
|
|
|
|
|
|
|
|
|
|
|
116 |
protected static function interpolate( $message, array $context = array() ) {
|
117 |
// build a replacement array with braces around the context keys
|
118 |
$replace = array();
|
@@ -130,6 +208,9 @@ class QM_Collector_Logger extends QM_Collector {
|
|
130 |
return strtr( $message, $replace );
|
131 |
}
|
132 |
|
|
|
|
|
|
|
133 |
public function process() {
|
134 |
if ( empty( $this->data['logs'] ) ) {
|
135 |
return;
|
@@ -138,13 +219,17 @@ class QM_Collector_Logger extends QM_Collector {
|
|
138 |
$components = array();
|
139 |
|
140 |
foreach ( $this->data['logs'] as $row ) {
|
141 |
-
$component
|
142 |
$components[ $component->name ] = $component->name;
|
143 |
}
|
144 |
|
145 |
$this->data['components'] = $components;
|
146 |
}
|
147 |
|
|
|
|
|
|
|
|
|
148 |
public function get_levels() {
|
149 |
return array(
|
150 |
self::EMERGENCY,
|
@@ -158,6 +243,10 @@ class QM_Collector_Logger extends QM_Collector {
|
|
158 |
);
|
159 |
}
|
160 |
|
|
|
|
|
|
|
|
|
161 |
public function get_warning_levels() {
|
162 |
return array(
|
163 |
self::EMERGENCY,
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Logger extends QM_Collector {
|
13 |
|
14 |
public $id = 'logger';
|
15 |
|
16 |
const EMERGENCY = 'emergency';
|
17 |
+
const ALERT = 'alert';
|
18 |
+
const CRITICAL = 'critical';
|
19 |
+
const ERROR = 'error';
|
20 |
+
const WARNING = 'warning';
|
21 |
+
const NOTICE = 'notice';
|
22 |
+
const INFO = 'info';
|
23 |
+
const DEBUG = 'debug';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* @return void
|
27 |
+
*/
|
28 |
+
public function set_up() {
|
29 |
+
parent::set_up();
|
30 |
+
|
31 |
+
$this->data['counts'] = array_fill_keys( $this->get_levels(), 0 );
|
32 |
+
|
33 |
foreach ( $this->get_levels() as $level ) {
|
34 |
add_action( "qm/{$level}", array( $this, $level ), 10, 2 );
|
35 |
}
|
37 |
add_action( 'qm/log', array( $this, 'log' ), 10, 3 );
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* @return void
|
42 |
+
*/
|
43 |
+
public function tear_down() {
|
44 |
+
foreach ( $this->get_levels() as $level ) {
|
45 |
+
remove_action( "qm/{$level}", array( $this, $level ), 10 );
|
46 |
+
}
|
47 |
+
|
48 |
+
remove_action( 'qm/log', array( $this, 'log' ), 10 );
|
49 |
+
|
50 |
+
parent::tear_down();
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* @param mixed $message
|
55 |
+
* @param array<string, mixed> $context
|
56 |
+
* @return void
|
57 |
+
*/
|
58 |
public function emergency( $message, array $context = array() ) {
|
59 |
$this->store( self::EMERGENCY, $message, $context );
|
60 |
}
|
61 |
|
62 |
+
/**
|
63 |
+
* @param mixed $message
|
64 |
+
* @param array<string, mixed> $context
|
65 |
+
* @return void
|
66 |
+
*/
|
67 |
public function alert( $message, array $context = array() ) {
|
68 |
$this->store( self::ALERT, $message, $context );
|
69 |
}
|
70 |
|
71 |
+
/**
|
72 |
+
* @param mixed $message
|
73 |
+
* @param array<string, mixed> $context
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
public function critical( $message, array $context = array() ) {
|
77 |
$this->store( self::CRITICAL, $message, $context );
|
78 |
}
|
79 |
|
80 |
+
/**
|
81 |
+
* @param mixed $message
|
82 |
+
* @param array<string, mixed> $context
|
83 |
+
* @return void
|
84 |
+
*/
|
85 |
public function error( $message, array $context = array() ) {
|
86 |
$this->store( self::ERROR, $message, $context );
|
87 |
}
|
88 |
|
89 |
+
/**
|
90 |
+
* @param mixed $message
|
91 |
+
* @param array<string, mixed> $context
|
92 |
+
* @return void
|
93 |
+
*/
|
94 |
public function warning( $message, array $context = array() ) {
|
95 |
$this->store( self::WARNING, $message, $context );
|
96 |
}
|
97 |
|
98 |
+
/**
|
99 |
+
* @param mixed $message
|
100 |
+
* @param array<string, mixed> $context
|
101 |
+
* @return void
|
102 |
+
*/
|
103 |
public function notice( $message, array $context = array() ) {
|
104 |
$this->store( self::NOTICE, $message, $context );
|
105 |
}
|
106 |
|
107 |
+
/**
|
108 |
+
* @param mixed $message
|
109 |
+
* @param array<string, mixed> $context
|
110 |
+
* @return void
|
111 |
+
*/
|
112 |
public function info( $message, array $context = array() ) {
|
113 |
$this->store( self::INFO, $message, $context );
|
114 |
}
|
115 |
|
116 |
+
/**
|
117 |
+
* @param mixed $message
|
118 |
+
* @param array<string, mixed> $context
|
119 |
+
* @return void
|
120 |
+
*/
|
121 |
public function debug( $message, array $context = array() ) {
|
122 |
$this->store( self::DEBUG, $message, $context );
|
123 |
}
|
124 |
|
125 |
+
/**
|
126 |
+
* @param string $level
|
127 |
+
* @param mixed $message
|
128 |
+
* @param array<string, mixed> $context
|
129 |
+
* @phpstan-param self::* $level
|
130 |
+
* @return void
|
131 |
+
*/
|
132 |
public function log( $level, $message, array $context = array() ) {
|
133 |
if ( ! in_array( $level, $this->get_levels(), true ) ) {
|
134 |
throw new InvalidArgumentException( __( 'Unsupported log level', 'query-monitor' ) );
|
137 |
$this->store( $level, $message, $context );
|
138 |
}
|
139 |
|
140 |
+
/**
|
141 |
+
* @param string $level
|
142 |
+
* @param mixed $message
|
143 |
+
* @param array<string, mixed> $context
|
144 |
+
* @phpstan-param self::* $level
|
145 |
+
* @return void
|
146 |
+
*/
|
147 |
protected function store( $level, $message, array $context = array() ) {
|
|
|
148 |
$trace = new QM_Backtrace( array(
|
149 |
+
'ignore_hook' => array(
|
150 |
+
current_filter() => true,
|
151 |
+
),
|
152 |
) );
|
153 |
|
154 |
if ( is_wp_error( $message ) ) {
|
|
|
155 |
$message = sprintf(
|
156 |
'WP_Error: %s (%s)',
|
157 |
$message->get_error_message(),
|
160 |
}
|
161 |
|
162 |
if ( ( $message instanceof Exception ) || ( $message instanceof Throwable ) ) {
|
|
|
163 |
$message = get_class( $message ) . ': ' . $message->getMessage();
|
164 |
}
|
165 |
|
172 |
$message = 'true';
|
173 |
}
|
174 |
|
|
|
175 |
$message = print_r( $message, true );
|
176 |
} elseif ( '' === trim( $message ) ) {
|
177 |
$message = '(Empty string)';
|
178 |
}
|
179 |
|
180 |
+
$this->data['counts'][ $level ]++;
|
181 |
$this->data['logs'][] = array(
|
182 |
'message' => self::interpolate( $message, $context ),
|
183 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
184 |
+
'component' => $trace->get_component(),
|
185 |
+
'level' => $level,
|
|
|
186 |
);
|
187 |
}
|
188 |
|
189 |
+
/**
|
190 |
+
* @param string $message
|
191 |
+
* @param array<string, mixed> $context
|
192 |
+
* @return string
|
193 |
+
*/
|
194 |
protected static function interpolate( $message, array $context = array() ) {
|
195 |
// build a replacement array with braces around the context keys
|
196 |
$replace = array();
|
208 |
return strtr( $message, $replace );
|
209 |
}
|
210 |
|
211 |
+
/**
|
212 |
+
* @return void
|
213 |
+
*/
|
214 |
public function process() {
|
215 |
if ( empty( $this->data['logs'] ) ) {
|
216 |
return;
|
219 |
$components = array();
|
220 |
|
221 |
foreach ( $this->data['logs'] as $row ) {
|
222 |
+
$component = $row['component'];
|
223 |
$components[ $component->name ] = $component->name;
|
224 |
}
|
225 |
|
226 |
$this->data['components'] = $components;
|
227 |
}
|
228 |
|
229 |
+
/**
|
230 |
+
* @return array<int, string>
|
231 |
+
* @phpstan-return array<int, self::*>
|
232 |
+
*/
|
233 |
public function get_levels() {
|
234 |
return array(
|
235 |
self::EMERGENCY,
|
243 |
);
|
244 |
}
|
245 |
|
246 |
+
/**
|
247 |
+
* @return array<int, string>
|
248 |
+
* @phpstan-return array<int, self::*>
|
249 |
+
*/
|
250 |
public function get_warning_levels() {
|
251 |
return array(
|
252 |
self::EMERGENCY,
|
collectors/overview.php
CHANGED
@@ -5,24 +5,37 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Overview extends QM_Collector {
|
11 |
|
12 |
public $id = 'overview';
|
13 |
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
15 |
add_action( 'shutdown', array( $this, 'process_timing' ), 0 );
|
16 |
}
|
17 |
|
|
|
|
|
|
|
18 |
public function tear_down() {
|
19 |
remove_action( 'shutdown', array( $this, 'process_timing' ), 0 );
|
|
|
20 |
parent::tear_down();
|
21 |
}
|
22 |
|
23 |
/**
|
24 |
* Processes the timing and memory related stats as early as possible, so the
|
25 |
* data isn't skewed by collectors that are processed before this one.
|
|
|
|
|
26 |
*/
|
27 |
public function process_timing() {
|
28 |
$this->data['time_taken'] = self::timer_stop_float();
|
@@ -36,8 +49,11 @@ class QM_Collector_Overview extends QM_Collector {
|
|
36 |
}
|
37 |
}
|
38 |
|
|
|
|
|
|
|
39 |
public function process() {
|
40 |
-
if ( ! isset( $data['time_taken'] ) ) {
|
41 |
$this->process_timing();
|
42 |
}
|
43 |
|
@@ -78,7 +94,7 @@ class QM_Collector_Overview extends QM_Collector {
|
|
78 |
$this->data['wp_memory_usage'] = 0;
|
79 |
}
|
80 |
|
81 |
-
$this->data['display_time_usage_warning']
|
82 |
$this->data['display_memory_usage_warning'] = ( $this->data['memory_usage'] >= 75 );
|
83 |
|
84 |
$this->data['is_admin'] = is_admin();
|
@@ -86,6 +102,11 @@ class QM_Collector_Overview extends QM_Collector {
|
|
86 |
|
87 |
}
|
88 |
|
|
|
|
|
|
|
|
|
|
|
89 |
function register_qm_collector_overview( array $collectors, QueryMonitor $qm ) {
|
90 |
$collectors['overview'] = new QM_Collector_Overview();
|
91 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Overview extends QM_Collector {
|
13 |
|
14 |
public $id = 'overview';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
+
public function set_up() {
|
20 |
+
parent::set_up();
|
21 |
+
|
22 |
add_action( 'shutdown', array( $this, 'process_timing' ), 0 );
|
23 |
}
|
24 |
|
25 |
+
/**
|
26 |
+
* @return void
|
27 |
+
*/
|
28 |
public function tear_down() {
|
29 |
remove_action( 'shutdown', array( $this, 'process_timing' ), 0 );
|
30 |
+
|
31 |
parent::tear_down();
|
32 |
}
|
33 |
|
34 |
/**
|
35 |
* Processes the timing and memory related stats as early as possible, so the
|
36 |
* data isn't skewed by collectors that are processed before this one.
|
37 |
+
*
|
38 |
+
* @return void
|
39 |
*/
|
40 |
public function process_timing() {
|
41 |
$this->data['time_taken'] = self::timer_stop_float();
|
49 |
}
|
50 |
}
|
51 |
|
52 |
+
/**
|
53 |
+
* @return void
|
54 |
+
*/
|
55 |
public function process() {
|
56 |
+
if ( ! isset( $this->data['time_taken'] ) ) {
|
57 |
$this->process_timing();
|
58 |
}
|
59 |
|
94 |
$this->data['wp_memory_usage'] = 0;
|
95 |
}
|
96 |
|
97 |
+
$this->data['display_time_usage_warning'] = ( $this->data['time_usage'] >= 75 );
|
98 |
$this->data['display_memory_usage_warning'] = ( $this->data['memory_usage'] >= 75 );
|
99 |
|
100 |
$this->data['is_admin'] = is_admin();
|
102 |
|
103 |
}
|
104 |
|
105 |
+
/**
|
106 |
+
* @param array<string, QM_Collector> $collectors
|
107 |
+
* @param QueryMonitor $qm
|
108 |
+
* @return array<string, QM_Collector>
|
109 |
+
*/
|
110 |
function register_qm_collector_overview( array $collectors, QueryMonitor $qm ) {
|
111 |
$collectors['overview'] = new QM_Collector_Overview();
|
112 |
return $collectors;
|
collectors/php_errors.php
CHANGED
@@ -5,31 +5,69 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
define( 'QM_ERROR_FATALS', E_ERROR | E_PARSE | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR );
|
11 |
|
12 |
class QM_Collector_PHP_Errors extends QM_Collector {
|
13 |
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
private $error_reporting = null;
|
17 |
-
private $display_errors = null;
|
18 |
-
private $exception_handler = null;
|
19 |
-
private static $unexpected_error;
|
20 |
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
if ( defined( 'QM_DISABLE_ERROR_HANDLER' ) && QM_DISABLE_ERROR_HANDLER ) {
|
23 |
return;
|
24 |
}
|
25 |
|
26 |
-
parent::
|
27 |
|
28 |
// Capture the last error that occurred before QM loaded:
|
29 |
$prior_error = error_get_last();
|
30 |
|
31 |
// Non-fatal error handler for all PHP versions:
|
32 |
-
set_error_handler( array( $this, 'error_handler' ), ( E_ALL ^ QM_ERROR_FATALS ) );
|
33 |
|
34 |
if ( ! interface_exists( 'Throwable' ) ) {
|
35 |
// Fatal error handler for PHP < 7:
|
@@ -37,11 +75,11 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
37 |
}
|
38 |
|
39 |
// Fatal error handler for PHP >= 7, and uncaught exception handler for all PHP versions:
|
40 |
-
$this->
|
41 |
|
42 |
$this->error_reporting = error_reporting();
|
43 |
-
$this->display_errors
|
44 |
-
ini_set( 'display_errors', 0 );
|
45 |
|
46 |
if ( $prior_error ) {
|
47 |
$this->error_handler(
|
@@ -55,6 +93,33 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
55 |
}
|
56 |
}
|
57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
/**
|
59 |
* Uncaught exception handler.
|
60 |
*
|
@@ -62,6 +127,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
62 |
* In PHP < 7 it will receive an Exception object.
|
63 |
*
|
64 |
* @param Throwable|Exception $e The error or exception.
|
|
|
65 |
*/
|
66 |
public function exception_handler( $e ) {
|
67 |
if ( is_a( $e, 'Exception' ) ) {
|
@@ -76,15 +142,15 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
76 |
$error,
|
77 |
$e->getMessage()
|
78 |
),
|
79 |
-
'file'
|
80 |
-
'line'
|
81 |
-
'trace'
|
82 |
) );
|
83 |
|
84 |
// The exception must be re-thrown or passed to the previously registered exception handler so that the error
|
85 |
// is logged appropriately instead of discarded silently.
|
86 |
-
if ( $this->
|
87 |
-
call_user_func( $this->
|
88 |
} else {
|
89 |
throw $e;
|
90 |
}
|
@@ -92,18 +158,28 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
92 |
exit( 1 );
|
93 |
}
|
94 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
public function error_handler( $errno, $message, $file = null, $line = null, $context = null, $do_trace = true ) {
|
|
|
96 |
|
97 |
/**
|
98 |
* Fires before logging the PHP error in Query Monitor.
|
99 |
*
|
100 |
* @since 2.7.0
|
101 |
*
|
102 |
-
* @param int
|
103 |
-
* @param string
|
104 |
-
* @param string
|
105 |
-
* @param
|
106 |
-
* @param
|
107 |
*/
|
108 |
do_action( 'qm/collect/new_php_error', $errno, $message, $file, $line, $context );
|
109 |
|
@@ -128,10 +204,10 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
128 |
$type = 'deprecated';
|
129 |
break;
|
130 |
|
131 |
-
|
132 |
-
return false;
|
133 |
-
break;
|
134 |
|
|
|
|
|
135 |
}
|
136 |
|
137 |
if ( ! class_exists( 'QM_Backtrace' ) ) {
|
@@ -163,24 +239,23 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
163 |
return false;
|
164 |
}
|
165 |
|
166 |
-
$trace
|
167 |
-
'ignore_current_filter' => false,
|
168 |
-
) );
|
169 |
$caller = $trace->get_caller();
|
170 |
-
$key
|
171 |
|
172 |
if ( isset( $this->data[ $error_group ][ $type ][ $key ] ) ) {
|
173 |
$this->data[ $error_group ][ $type ][ $key ]['calls']++;
|
174 |
} else {
|
175 |
$this->data[ $error_group ][ $type ][ $key ] = array(
|
176 |
-
'errno'
|
177 |
-
'type'
|
178 |
-
'message'
|
179 |
-
'file'
|
180 |
'filename' => QM_Util::standard_dir( $file, '' ),
|
181 |
-
'line'
|
182 |
-
'
|
183 |
-
'
|
|
|
184 |
);
|
185 |
}
|
186 |
|
@@ -198,6 +273,8 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
198 |
|
199 |
/**
|
200 |
* Displays fatal error output for sites running PHP < 7.
|
|
|
|
|
201 |
*/
|
202 |
public function shutdown_handler() {
|
203 |
|
@@ -216,6 +293,18 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
216 |
$this->output_fatal( $error, $e );
|
217 |
}
|
218 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
protected function output_fatal( $error, array $e ) {
|
220 |
$dispatcher = QM_Dispatchers::get( 'html' );
|
221 |
|
@@ -256,7 +345,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
256 |
'<div id="qm-fatal" data-qm-message="%1$s" data-qm-file="%2$s" data-qm-line="%3$d">',
|
257 |
esc_attr( $e['message'] ),
|
258 |
esc_attr( QM_Util::standard_dir( $e['file'], '' ) ),
|
259 |
-
|
260 |
);
|
261 |
|
262 |
echo '<div class="qm-fatal-wrap">';
|
@@ -297,41 +386,37 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
297 |
echo '</div>';
|
298 |
}
|
299 |
|
300 |
-
public function post_process() {
|
301 |
-
ini_set( 'display_errors', $this->display_errors );
|
302 |
-
restore_error_handler();
|
303 |
-
restore_exception_handler();
|
304 |
-
}
|
305 |
-
|
306 |
/**
|
307 |
* Runs post-processing on the collected errors and updates the
|
308 |
* errors collected in the data->errors property.
|
309 |
*
|
310 |
* Any unreportable errors are placed in the data->filtered_errors
|
311 |
* property.
|
|
|
|
|
312 |
*/
|
313 |
public function process() {
|
314 |
$this->types = array(
|
315 |
-
'errors'
|
316 |
-
'warning'
|
317 |
-
'notice'
|
318 |
-
'strict'
|
319 |
'deprecated' => _x( 'Deprecated', 'PHP error level', 'query-monitor' ),
|
320 |
),
|
321 |
'suppressed' => array(
|
322 |
-
'warning'
|
323 |
-
'notice'
|
324 |
-
'strict'
|
325 |
'deprecated' => _x( 'Deprecated (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
|
326 |
),
|
327 |
-
'silenced'
|
328 |
-
'warning'
|
329 |
-
'notice'
|
330 |
-
'strict'
|
331 |
'deprecated' => _x( 'Deprecated (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
|
332 |
),
|
333 |
);
|
334 |
-
$components
|
335 |
|
336 |
if ( ! empty( $this->data ) && ! empty( $this->data['errors'] ) ) {
|
337 |
/**
|
@@ -370,7 +455,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
370 |
*
|
371 |
* @since 2.7.0
|
372 |
*
|
373 |
-
* @param int
|
374 |
*/
|
375 |
$levels = apply_filters( 'qm/collect/php_error_levels', array() );
|
376 |
|
@@ -393,8 +478,8 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
393 |
foreach ( $error_types as $type => $title ) {
|
394 |
if ( isset( $this->data[ $error_group ][ $type ] ) ) {
|
395 |
foreach ( $this->data[ $error_group ][ $type ] as $error ) {
|
396 |
-
if ( $error['
|
397 |
-
$component
|
398 |
$components[ $component->name ] = $component->name;
|
399 |
}
|
400 |
}
|
@@ -412,6 +497,7 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
412 |
*
|
413 |
* @param int[] $components The error levels keyed by component name.
|
414 |
* @param string $component_type The component type, for example 'plugin' or 'theme'.
|
|
|
415 |
*/
|
416 |
public function filter_reportable_errors( array $components, $component_type ) {
|
417 |
$all_errors = $this->data['errors'];
|
@@ -423,11 +509,11 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
423 |
continue;
|
424 |
}
|
425 |
|
426 |
-
if ( ! $error['
|
427 |
continue;
|
428 |
}
|
429 |
|
430 |
-
if ( ! $this->is_affected_component( $error['
|
431 |
continue;
|
432 |
}
|
433 |
|
@@ -455,9 +541,6 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
455 |
* @return bool
|
456 |
*/
|
457 |
public function is_affected_component( $component, $component_type, $component_context ) {
|
458 |
-
if ( empty( $component ) ) {
|
459 |
-
return false;
|
460 |
-
}
|
461 |
return ( $component->type === $component_type && $component->context === $component_context );
|
462 |
}
|
463 |
|
@@ -465,37 +548,38 @@ class QM_Collector_PHP_Errors extends QM_Collector {
|
|
465 |
* Checks if the error number specified is viewable based on the
|
466 |
* flags specified.
|
467 |
*
|
468 |
-
* @param int $error_no The errno from PHP
|
469 |
-
* @param int $flags The config flags specified by users
|
470 |
-
* @return int Truthy int value if reportable else 0.
|
471 |
-
*
|
472 |
* Eg:- If a plugin had the config flags,
|
473 |
*
|
474 |
-
*
|
475 |
*
|
476 |
* then,
|
477 |
*
|
478 |
-
*
|
479 |
-
*
|
480 |
*
|
481 |
-
* If the
|
482 |
* reportable by default.
|
|
|
|
|
|
|
|
|
483 |
*/
|
484 |
public function is_reportable_error( $error_no, $flags ) {
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
$result =
|
489 |
}
|
490 |
|
491 |
-
return
|
492 |
}
|
493 |
|
494 |
/**
|
495 |
* For testing purposes only. Sets the errors property manually.
|
496 |
* Needed to test the filter since the data property is protected.
|
497 |
*
|
498 |
-
* @param array $errors The list of errors
|
|
|
499 |
*/
|
500 |
public function set_php_errors( $errors ) {
|
501 |
$this->data['errors'] = $errors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
define( 'QM_ERROR_FATALS', E_ERROR | E_PARSE | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR );
|
13 |
|
14 |
class QM_Collector_PHP_Errors extends QM_Collector {
|
15 |
|
16 |
+
/**
|
17 |
+
* @var string
|
18 |
+
*/
|
19 |
+
public $id = 'php_errors';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @var array<string, array<string, string>>
|
23 |
+
*/
|
24 |
+
public $types = array();
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var int|null
|
28 |
+
*/
|
29 |
private $error_reporting = null;
|
|
|
|
|
|
|
30 |
|
31 |
+
/**
|
32 |
+
* @var string|false|null
|
33 |
+
*/
|
34 |
+
private $display_errors = null;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @var callable|null
|
38 |
+
*/
|
39 |
+
private $previous_error_handler = null;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* @var callable|null
|
43 |
+
*/
|
44 |
+
private $previous_exception_handler = null;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* @var string|null
|
48 |
+
*/
|
49 |
+
private static $unexpected_error = null;
|
50 |
+
|
51 |
+
/**
|
52 |
+
* @var bool
|
53 |
+
*/
|
54 |
+
protected $hide_silenced_php_errors = false;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @return void
|
58 |
+
*/
|
59 |
+
public function set_up() {
|
60 |
if ( defined( 'QM_DISABLE_ERROR_HANDLER' ) && QM_DISABLE_ERROR_HANDLER ) {
|
61 |
return;
|
62 |
}
|
63 |
|
64 |
+
parent::set_up();
|
65 |
|
66 |
// Capture the last error that occurred before QM loaded:
|
67 |
$prior_error = error_get_last();
|
68 |
|
69 |
// Non-fatal error handler for all PHP versions:
|
70 |
+
$this->previous_error_handler = set_error_handler( array( $this, 'error_handler' ), ( E_ALL ^ QM_ERROR_FATALS ) );
|
71 |
|
72 |
if ( ! interface_exists( 'Throwable' ) ) {
|
73 |
// Fatal error handler for PHP < 7:
|
75 |
}
|
76 |
|
77 |
// Fatal error handler for PHP >= 7, and uncaught exception handler for all PHP versions:
|
78 |
+
$this->previous_exception_handler = set_exception_handler( array( $this, 'exception_handler' ) );
|
79 |
|
80 |
$this->error_reporting = error_reporting();
|
81 |
+
$this->display_errors = ini_get( 'display_errors' );
|
82 |
+
ini_set( 'display_errors', '0' );
|
83 |
|
84 |
if ( $prior_error ) {
|
85 |
$this->error_handler(
|
93 |
}
|
94 |
}
|
95 |
|
96 |
+
/**
|
97 |
+
* @return void
|
98 |
+
*/
|
99 |
+
public function tear_down() {
|
100 |
+
if ( defined( 'QM_DISABLE_ERROR_HANDLER' ) && QM_DISABLE_ERROR_HANDLER ) {
|
101 |
+
return;
|
102 |
+
}
|
103 |
+
|
104 |
+
if ( null !== $this->previous_error_handler ) {
|
105 |
+
restore_error_handler();
|
106 |
+
}
|
107 |
+
|
108 |
+
if ( null !== $this->previous_exception_handler ) {
|
109 |
+
restore_exception_handler();
|
110 |
+
}
|
111 |
+
|
112 |
+
if ( null !== $this->error_reporting ) {
|
113 |
+
error_reporting( $this->error_reporting );
|
114 |
+
}
|
115 |
+
|
116 |
+
if ( false !== $this->display_errors ) {
|
117 |
+
ini_set( 'display_errors', $this->display_errors );
|
118 |
+
}
|
119 |
+
|
120 |
+
parent::tear_down();
|
121 |
+
}
|
122 |
+
|
123 |
/**
|
124 |
* Uncaught exception handler.
|
125 |
*
|
127 |
* In PHP < 7 it will receive an Exception object.
|
128 |
*
|
129 |
* @param Throwable|Exception $e The error or exception.
|
130 |
+
* @return void
|
131 |
*/
|
132 |
public function exception_handler( $e ) {
|
133 |
if ( is_a( $e, 'Exception' ) ) {
|
142 |
$error,
|
143 |
$e->getMessage()
|
144 |
),
|
145 |
+
'file' => $e->getFile(),
|
146 |
+
'line' => $e->getLine(),
|
147 |
+
'trace' => $e->getTrace(),
|
148 |
) );
|
149 |
|
150 |
// The exception must be re-thrown or passed to the previously registered exception handler so that the error
|
151 |
// is logged appropriately instead of discarded silently.
|
152 |
+
if ( $this->previous_exception_handler ) {
|
153 |
+
call_user_func( $this->previous_exception_handler, $e );
|
154 |
} else {
|
155 |
throw $e;
|
156 |
}
|
158 |
exit( 1 );
|
159 |
}
|
160 |
|
161 |
+
/**
|
162 |
+
* @param int $errno The error number.
|
163 |
+
* @param string $message The error message.
|
164 |
+
* @param string $file The file location.
|
165 |
+
* @param int $line The line number.
|
166 |
+
* @param mixed[] $context The context being passed.
|
167 |
+
* @param bool $do_trace Whether a stack trace should be included in the logged error data.
|
168 |
+
* @return bool
|
169 |
+
*/
|
170 |
public function error_handler( $errno, $message, $file = null, $line = null, $context = null, $do_trace = true ) {
|
171 |
+
$type = null;
|
172 |
|
173 |
/**
|
174 |
* Fires before logging the PHP error in Query Monitor.
|
175 |
*
|
176 |
* @since 2.7.0
|
177 |
*
|
178 |
+
* @param int $errno The error number.
|
179 |
+
* @param string $message The error message.
|
180 |
+
* @param string|null $file The file location.
|
181 |
+
* @param int|null $line The line number.
|
182 |
+
* @param mixed[]|null $context The context being passed.
|
183 |
*/
|
184 |
do_action( 'qm/collect/new_php_error', $errno, $message, $file, $line, $context );
|
185 |
|
204 |
$type = 'deprecated';
|
205 |
break;
|
206 |
|
207 |
+
}
|
|
|
|
|
208 |
|
209 |
+
if ( null === $type ) {
|
210 |
+
return false;
|
211 |
}
|
212 |
|
213 |
if ( ! class_exists( 'QM_Backtrace' ) ) {
|
239 |
return false;
|
240 |
}
|
241 |
|
242 |
+
$trace = new QM_Backtrace();
|
|
|
|
|
243 |
$caller = $trace->get_caller();
|
244 |
+
$key = md5( $message . $file . $line . $caller['id'] );
|
245 |
|
246 |
if ( isset( $this->data[ $error_group ][ $type ][ $key ] ) ) {
|
247 |
$this->data[ $error_group ][ $type ][ $key ]['calls']++;
|
248 |
} else {
|
249 |
$this->data[ $error_group ][ $type ][ $key ] = array(
|
250 |
+
'errno' => $errno,
|
251 |
+
'type' => $type,
|
252 |
+
'message' => wp_strip_all_tags( $message ),
|
253 |
+
'file' => $file,
|
254 |
'filename' => QM_Util::standard_dir( $file, '' ),
|
255 |
+
'line' => $line,
|
256 |
+
'filtered_trace' => ( $do_trace ? $trace->get_filtered_trace() : null ),
|
257 |
+
'component' => $trace->get_component(),
|
258 |
+
'calls' => 1,
|
259 |
);
|
260 |
}
|
261 |
|
273 |
|
274 |
/**
|
275 |
* Displays fatal error output for sites running PHP < 7.
|
276 |
+
*
|
277 |
+
* @return void
|
278 |
*/
|
279 |
public function shutdown_handler() {
|
280 |
|
293 |
$this->output_fatal( $error, $e );
|
294 |
}
|
295 |
|
296 |
+
/**
|
297 |
+
* @param string $error
|
298 |
+
* @param mixed[] $e
|
299 |
+
* @phpstan-param array{
|
300 |
+
* message: string,
|
301 |
+
* file: string,
|
302 |
+
* line: int,
|
303 |
+
* type?: int,
|
304 |
+
* trace?: mixed|null,
|
305 |
+
* } $e
|
306 |
+
* @return void
|
307 |
+
*/
|
308 |
protected function output_fatal( $error, array $e ) {
|
309 |
$dispatcher = QM_Dispatchers::get( 'html' );
|
310 |
|
345 |
'<div id="qm-fatal" data-qm-message="%1$s" data-qm-file="%2$s" data-qm-line="%3$d">',
|
346 |
esc_attr( $e['message'] ),
|
347 |
esc_attr( QM_Util::standard_dir( $e['file'], '' ) ),
|
348 |
+
intval( $e['line'] )
|
349 |
);
|
350 |
|
351 |
echo '<div class="qm-fatal-wrap">';
|
386 |
echo '</div>';
|
387 |
}
|
388 |
|
|
|
|
|
|
|
|
|
|
|
|
|
389 |
/**
|
390 |
* Runs post-processing on the collected errors and updates the
|
391 |
* errors collected in the data->errors property.
|
392 |
*
|
393 |
* Any unreportable errors are placed in the data->filtered_errors
|
394 |
* property.
|
395 |
+
*
|
396 |
+
* @return void
|
397 |
*/
|
398 |
public function process() {
|
399 |
$this->types = array(
|
400 |
+
'errors' => array(
|
401 |
+
'warning' => _x( 'Warning', 'PHP error level', 'query-monitor' ),
|
402 |
+
'notice' => _x( 'Notice', 'PHP error level', 'query-monitor' ),
|
403 |
+
'strict' => _x( 'Strict', 'PHP error level', 'query-monitor' ),
|
404 |
'deprecated' => _x( 'Deprecated', 'PHP error level', 'query-monitor' ),
|
405 |
),
|
406 |
'suppressed' => array(
|
407 |
+
'warning' => _x( 'Warning (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
|
408 |
+
'notice' => _x( 'Notice (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
|
409 |
+
'strict' => _x( 'Strict (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
|
410 |
'deprecated' => _x( 'Deprecated (Suppressed)', 'Suppressed PHP error level', 'query-monitor' ),
|
411 |
),
|
412 |
+
'silenced' => array(
|
413 |
+
'warning' => _x( 'Warning (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
|
414 |
+
'notice' => _x( 'Notice (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
|
415 |
+
'strict' => _x( 'Strict (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
|
416 |
'deprecated' => _x( 'Deprecated (Silenced)', 'Silenced PHP error level', 'query-monitor' ),
|
417 |
),
|
418 |
);
|
419 |
+
$components = array();
|
420 |
|
421 |
if ( ! empty( $this->data ) && ! empty( $this->data['errors'] ) ) {
|
422 |
/**
|
455 |
*
|
456 |
* @since 2.7.0
|
457 |
*
|
458 |
+
* @param array<string,array<string,int>> $levels The error levels used for each component.
|
459 |
*/
|
460 |
$levels = apply_filters( 'qm/collect/php_error_levels', array() );
|
461 |
|
478 |
foreach ( $error_types as $type => $title ) {
|
479 |
if ( isset( $this->data[ $error_group ][ $type ] ) ) {
|
480 |
foreach ( $this->data[ $error_group ][ $type ] as $error ) {
|
481 |
+
if ( $error['component'] ) {
|
482 |
+
$component = $error['component'];
|
483 |
$components[ $component->name ] = $component->name;
|
484 |
}
|
485 |
}
|
497 |
*
|
498 |
* @param int[] $components The error levels keyed by component name.
|
499 |
* @param string $component_type The component type, for example 'plugin' or 'theme'.
|
500 |
+
* @return void
|
501 |
*/
|
502 |
public function filter_reportable_errors( array $components, $component_type ) {
|
503 |
$all_errors = $this->data['errors'];
|
509 |
continue;
|
510 |
}
|
511 |
|
512 |
+
if ( ! $error['component'] ) {
|
513 |
continue;
|
514 |
}
|
515 |
|
516 |
+
if ( ! $this->is_affected_component( $error['component'], $component_type, $component_context ) ) {
|
517 |
continue;
|
518 |
}
|
519 |
|
541 |
* @return bool
|
542 |
*/
|
543 |
public function is_affected_component( $component, $component_type, $component_context ) {
|
|
|
|
|
|
|
544 |
return ( $component->type === $component_type && $component->context === $component_context );
|
545 |
}
|
546 |
|
548 |
* Checks if the error number specified is viewable based on the
|
549 |
* flags specified.
|
550 |
*
|
|
|
|
|
|
|
|
|
551 |
* Eg:- If a plugin had the config flags,
|
552 |
*
|
553 |
+
* E_ALL & ~E_NOTICE
|
554 |
*
|
555 |
* then,
|
556 |
*
|
557 |
+
* is_reportable_error( E_NOTICE, E_ALL & ~E_NOTICE ) is false
|
558 |
+
* is_reportable_error( E_WARNING, E_ALL & ~E_NOTICE ) is true
|
559 |
*
|
560 |
+
* If the `$flag` is null, all errors are assumed to be
|
561 |
* reportable by default.
|
562 |
+
*
|
563 |
+
* @param int $error_no The errno from PHP
|
564 |
+
* @param int|null $flags The config flags specified by users
|
565 |
+
* @return bool Whether the error is reportable.
|
566 |
*/
|
567 |
public function is_reportable_error( $error_no, $flags ) {
|
568 |
+
$result = true;
|
569 |
+
|
570 |
+
if ( null !== $flags ) {
|
571 |
+
$result = (bool) ( $error_no & $flags );
|
572 |
}
|
573 |
|
574 |
+
return $result;
|
575 |
}
|
576 |
|
577 |
/**
|
578 |
* For testing purposes only. Sets the errors property manually.
|
579 |
* Needed to test the filter since the data property is protected.
|
580 |
*
|
581 |
+
* @param array<string, mixed> $errors The list of errors
|
582 |
+
* @return void
|
583 |
*/
|
584 |
public function set_php_errors( $errors ) {
|
585 |
$this->data['errors'] = $errors;
|
collectors/raw_request.php
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
defined( 'ABSPATH' )
|
|
|
|
|
4 |
|
5 |
class QM_Collector_Raw_Request extends QM_Collector {
|
6 |
|
@@ -11,8 +13,8 @@ class QM_Collector_Raw_Request extends QM_Collector {
|
|
11 |
*
|
12 |
* From WP_REST_Server::get_headers()
|
13 |
*
|
14 |
-
* @param array $server Associative array similar to `$_SERVER`.
|
15 |
-
* @return array Headers extracted from the input.
|
16 |
*/
|
17 |
protected function get_headers( array $server ) {
|
18 |
$headers = array();
|
@@ -20,8 +22,8 @@ class QM_Collector_Raw_Request extends QM_Collector {
|
|
20 |
// CONTENT_* headers are not prefixed with HTTP_.
|
21 |
$additional = array(
|
22 |
'CONTENT_LENGTH' => true,
|
23 |
-
'CONTENT_MD5'
|
24 |
-
'CONTENT_TYPE'
|
25 |
);
|
26 |
|
27 |
foreach ( $server as $key => $value ) {
|
@@ -37,15 +39,17 @@ class QM_Collector_Raw_Request extends QM_Collector {
|
|
37 |
|
38 |
/**
|
39 |
* Process request and response data.
|
|
|
|
|
40 |
*/
|
41 |
public function process() {
|
42 |
$request = array(
|
43 |
-
'ip'
|
44 |
-
'method'
|
45 |
-
'scheme'
|
46 |
-
'host'
|
47 |
-
'path'
|
48 |
-
'query'
|
49 |
'headers' => $this->get_headers( wp_unslash( $_SERVER ) ),
|
50 |
);
|
51 |
|
@@ -65,15 +69,18 @@ class QM_Collector_Raw_Request extends QM_Collector {
|
|
65 |
ksort( $headers );
|
66 |
|
67 |
$response = array(
|
68 |
-
'status'
|
69 |
'headers' => $headers,
|
70 |
);
|
71 |
|
72 |
$this->data['response'] = $response;
|
73 |
}
|
74 |
|
|
|
|
|
|
|
75 |
public static function http_response_code() {
|
76 |
-
if (
|
77 |
// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.http_response_codeFound
|
78 |
return http_response_code();
|
79 |
}
|
@@ -82,6 +89,11 @@ class QM_Collector_Raw_Request extends QM_Collector {
|
|
82 |
}
|
83 |
}
|
84 |
|
|
|
|
|
|
|
|
|
|
|
85 |
function register_qm_collector_raw_request( array $collectors, QueryMonitor $qm ) {
|
86 |
$collectors['raw_request'] = new QM_Collector_Raw_Request();
|
87 |
return $collectors;
|
1 |
<?php
|
2 |
|
3 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
+
exit;
|
5 |
+
}
|
6 |
|
7 |
class QM_Collector_Raw_Request extends QM_Collector {
|
8 |
|
13 |
*
|
14 |
* From WP_REST_Server::get_headers()
|
15 |
*
|
16 |
+
* @param array<string, string> $server Associative array similar to `$_SERVER`.
|
17 |
+
* @return array<string, string> Headers extracted from the input.
|
18 |
*/
|
19 |
protected function get_headers( array $server ) {
|
20 |
$headers = array();
|
22 |
// CONTENT_* headers are not prefixed with HTTP_.
|
23 |
$additional = array(
|
24 |
'CONTENT_LENGTH' => true,
|
25 |
+
'CONTENT_MD5' => true,
|
26 |
+
'CONTENT_TYPE' => true,
|
27 |
);
|
28 |
|
29 |
foreach ( $server as $key => $value ) {
|
39 |
|
40 |
/**
|
41 |
* Process request and response data.
|
42 |
+
*
|
43 |
+
* @return void
|
44 |
*/
|
45 |
public function process() {
|
46 |
$request = array(
|
47 |
+
'ip' => $_SERVER['REMOTE_ADDR'],
|
48 |
+
'method' => strtoupper( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ),
|
49 |
+
'scheme' => is_ssl() ? 'https' : 'http',
|
50 |
+
'host' => wp_unslash( $_SERVER['HTTP_HOST'] ),
|
51 |
+
'path' => isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '/',
|
52 |
+
'query' => isset( $_SERVER['QUERY_STRING'] ) ? wp_unslash( $_SERVER['QUERY_STRING'] ) : '',
|
53 |
'headers' => $this->get_headers( wp_unslash( $_SERVER ) ),
|
54 |
);
|
55 |
|
69 |
ksort( $headers );
|
70 |
|
71 |
$response = array(
|
72 |
+
'status' => self::http_response_code(),
|
73 |
'headers' => $headers,
|
74 |
);
|
75 |
|
76 |
$this->data['response'] = $response;
|
77 |
}
|
78 |
|
79 |
+
/**
|
80 |
+
* @return int|bool|null
|
81 |
+
*/
|
82 |
public static function http_response_code() {
|
83 |
+
if ( function_exists( 'http_response_code' ) ) {
|
84 |
// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.http_response_codeFound
|
85 |
return http_response_code();
|
86 |
}
|
89 |
}
|
90 |
}
|
91 |
|
92 |
+
/**
|
93 |
+
* @param array<string, QM_Collector> $collectors
|
94 |
+
* @param QueryMonitor $qm
|
95 |
+
* @return array<string, QM_Collector>
|
96 |
+
*/
|
97 |
function register_qm_collector_raw_request( array $collectors, QueryMonitor $qm ) {
|
98 |
$collectors['raw_request'] = new QM_Collector_Raw_Request();
|
99 |
return $collectors;
|
collectors/redirects.php
CHANGED
@@ -5,28 +5,54 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Redirects extends QM_Collector {
|
11 |
|
12 |
public $id = 'redirects';
|
13 |
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
16 |
add_filter( 'wp_redirect', array( $this, 'filter_wp_redirect' ), 9999, 2 );
|
17 |
}
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
public function filter_wp_redirect( $location, $status ) {
|
20 |
|
21 |
if ( ! $location ) {
|
22 |
return $location;
|
23 |
}
|
24 |
|
25 |
-
$trace = new QM_Backtrace(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
-
$this->data['trace']
|
28 |
$this->data['location'] = $location;
|
29 |
-
$this->data['status']
|
30 |
|
31 |
return $location;
|
32 |
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Redirects extends QM_Collector {
|
13 |
|
14 |
public $id = 'redirects';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
+
public function set_up() {
|
20 |
+
parent::set_up();
|
21 |
add_filter( 'wp_redirect', array( $this, 'filter_wp_redirect' ), 9999, 2 );
|
22 |
}
|
23 |
|
24 |
+
/**
|
25 |
+
* @return void
|
26 |
+
*/
|
27 |
+
public function tear_down() {
|
28 |
+
remove_filter( 'wp_redirect', array( $this, 'filter_wp_redirect' ), 9999 );
|
29 |
+
|
30 |
+
parent::tear_down();
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @param string $location
|
35 |
+
* @param int $status
|
36 |
+
* @return string
|
37 |
+
*/
|
38 |
public function filter_wp_redirect( $location, $status ) {
|
39 |
|
40 |
if ( ! $location ) {
|
41 |
return $location;
|
42 |
}
|
43 |
|
44 |
+
$trace = new QM_Backtrace( array(
|
45 |
+
'ignore_hook' => array(
|
46 |
+
current_filter() => true,
|
47 |
+
),
|
48 |
+
'ignore_func' => array(
|
49 |
+
'wp_redirect' => true,
|
50 |
+
),
|
51 |
+
) );
|
52 |
|
53 |
+
$this->data['trace'] = $trace;
|
54 |
$this->data['location'] = $location;
|
55 |
+
$this->data['status'] = $status;
|
56 |
|
57 |
return $location;
|
58 |
|
collectors/request.php
CHANGED
@@ -5,12 +5,17 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Request extends QM_Collector {
|
11 |
|
12 |
public $id = 'request';
|
13 |
|
|
|
|
|
|
|
14 |
public function get_concerned_actions() {
|
15 |
return array(
|
16 |
# Rewrites
|
@@ -27,6 +32,9 @@ class QM_Collector_Request extends QM_Collector {
|
|
27 |
);
|
28 |
}
|
29 |
|
|
|
|
|
|
|
30 |
public function get_concerned_filters() {
|
31 |
global $wp_rewrite;
|
32 |
|
@@ -97,6 +105,9 @@ class QM_Collector_Request extends QM_Collector {
|
|
97 |
return $filters;
|
98 |
}
|
99 |
|
|
|
|
|
|
|
100 |
public function get_concerned_options() {
|
101 |
return array(
|
102 |
'home',
|
@@ -106,6 +117,9 @@ class QM_Collector_Request extends QM_Collector {
|
|
106 |
);
|
107 |
}
|
108 |
|
|
|
|
|
|
|
109 |
public function get_concerned_constants() {
|
110 |
return array(
|
111 |
'WP_HOME',
|
@@ -113,11 +127,14 @@ class QM_Collector_Request extends QM_Collector {
|
|
113 |
);
|
114 |
}
|
115 |
|
|
|
|
|
|
|
116 |
public function process() {
|
117 |
|
118 |
global $wp, $wp_query, $current_blog, $current_site, $wp_rewrite;
|
119 |
|
120 |
-
$qo
|
121 |
$user = wp_get_current_user();
|
122 |
|
123 |
if ( $user->exists() ) {
|
@@ -133,7 +150,7 @@ class QM_Collector_Request extends QM_Collector {
|
|
133 |
|
134 |
$this->data['user'] = array(
|
135 |
'title' => $user_title,
|
136 |
-
'data'
|
137 |
);
|
138 |
|
139 |
if ( is_multisite() ) {
|
@@ -143,7 +160,7 @@ class QM_Collector_Request extends QM_Collector {
|
|
143 |
__( 'Current Site: #%d', 'query-monitor' ),
|
144 |
$current_blog->blog_id
|
145 |
),
|
146 |
-
'data'
|
147 |
);
|
148 |
}
|
149 |
|
@@ -154,14 +171,14 @@ class QM_Collector_Request extends QM_Collector {
|
|
154 |
__( 'Current Network: #%d', 'query-monitor' ),
|
155 |
$current_site->id
|
156 |
),
|
157 |
-
'data'
|
158 |
);
|
159 |
}
|
160 |
|
161 |
if ( is_admin() ) {
|
162 |
if ( isset( $_SERVER['REQUEST_URI'] ) ) {
|
163 |
$home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' );
|
164 |
-
$request
|
165 |
|
166 |
$this->data['request']['request'] = str_replace( "/{$home_path}/", '', $request );
|
167 |
} else {
|
@@ -178,8 +195,8 @@ class QM_Collector_Request extends QM_Collector {
|
|
178 |
|
179 |
/** This filter is documented in wp-includes/class-wp.php */
|
180 |
$plugin_qvars = array_flip( apply_filters( 'query_vars', array() ) );
|
181 |
-
$qvars
|
182 |
-
$query_vars
|
183 |
|
184 |
foreach ( $qvars as $k => $v ) {
|
185 |
if ( isset( $plugin_qvars[ $k ] ) ) {
|
@@ -198,7 +215,7 @@ class QM_Collector_Request extends QM_Collector {
|
|
198 |
# First add plugin vars to $this->data['qvars']:
|
199 |
foreach ( $query_vars as $k => $v ) {
|
200 |
if ( isset( $plugin_qvars[ $k ] ) ) {
|
201 |
-
$this->data['qvars'][ $k ]
|
202 |
$this->data['plugin_qvars'][ $k ] = $v;
|
203 |
}
|
204 |
}
|
@@ -289,6 +306,11 @@ class QM_Collector_Request extends QM_Collector {
|
|
289 |
|
290 |
}
|
291 |
|
|
|
|
|
|
|
|
|
|
|
292 |
function register_qm_collector_request( array $collectors, QueryMonitor $qm ) {
|
293 |
$collectors['request'] = new QM_Collector_Request();
|
294 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Request extends QM_Collector {
|
13 |
|
14 |
public $id = 'request';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return array<int, string>
|
18 |
+
*/
|
19 |
public function get_concerned_actions() {
|
20 |
return array(
|
21 |
# Rewrites
|
32 |
);
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* @return array<int, string>
|
37 |
+
*/
|
38 |
public function get_concerned_filters() {
|
39 |
global $wp_rewrite;
|
40 |
|
105 |
return $filters;
|
106 |
}
|
107 |
|
108 |
+
/**
|
109 |
+
* @return array<int, string>
|
110 |
+
*/
|
111 |
public function get_concerned_options() {
|
112 |
return array(
|
113 |
'home',
|
117 |
);
|
118 |
}
|
119 |
|
120 |
+
/**
|
121 |
+
* @return array<int, string>
|
122 |
+
*/
|
123 |
public function get_concerned_constants() {
|
124 |
return array(
|
125 |
'WP_HOME',
|
127 |
);
|
128 |
}
|
129 |
|
130 |
+
/**
|
131 |
+
* @return void
|
132 |
+
*/
|
133 |
public function process() {
|
134 |
|
135 |
global $wp, $wp_query, $current_blog, $current_site, $wp_rewrite;
|
136 |
|
137 |
+
$qo = get_queried_object();
|
138 |
$user = wp_get_current_user();
|
139 |
|
140 |
if ( $user->exists() ) {
|
150 |
|
151 |
$this->data['user'] = array(
|
152 |
'title' => $user_title,
|
153 |
+
'data' => ( $user->exists() ? $user : false ),
|
154 |
);
|
155 |
|
156 |
if ( is_multisite() ) {
|
160 |
__( 'Current Site: #%d', 'query-monitor' ),
|
161 |
$current_blog->blog_id
|
162 |
),
|
163 |
+
'data' => $current_blog,
|
164 |
);
|
165 |
}
|
166 |
|
171 |
__( 'Current Network: #%d', 'query-monitor' ),
|
172 |
$current_site->id
|
173 |
),
|
174 |
+
'data' => $current_site,
|
175 |
);
|
176 |
}
|
177 |
|
178 |
if ( is_admin() ) {
|
179 |
if ( isset( $_SERVER['REQUEST_URI'] ) ) {
|
180 |
$home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' );
|
181 |
+
$request = wp_unslash( $_SERVER['REQUEST_URI'] ); // phpcs:ignore
|
182 |
|
183 |
$this->data['request']['request'] = str_replace( "/{$home_path}/", '', $request );
|
184 |
} else {
|
195 |
|
196 |
/** This filter is documented in wp-includes/class-wp.php */
|
197 |
$plugin_qvars = array_flip( apply_filters( 'query_vars', array() ) );
|
198 |
+
$qvars = $wp_query->query_vars;
|
199 |
+
$query_vars = array();
|
200 |
|
201 |
foreach ( $qvars as $k => $v ) {
|
202 |
if ( isset( $plugin_qvars[ $k ] ) ) {
|
215 |
# First add plugin vars to $this->data['qvars']:
|
216 |
foreach ( $query_vars as $k => $v ) {
|
217 |
if ( isset( $plugin_qvars[ $k ] ) ) {
|
218 |
+
$this->data['qvars'][ $k ] = $v;
|
219 |
$this->data['plugin_qvars'][ $k ] = $v;
|
220 |
}
|
221 |
}
|
306 |
|
307 |
}
|
308 |
|
309 |
+
/**
|
310 |
+
* @param array<string, QM_Collector> $collectors
|
311 |
+
* @param QueryMonitor $qm
|
312 |
+
* @return array<string, QM_Collector>
|
313 |
+
*/
|
314 |
function register_qm_collector_request( array $collectors, QueryMonitor $qm ) {
|
315 |
$collectors['request'] = new QM_Collector_Request();
|
316 |
return $collectors;
|
collectors/theme.php
CHANGED
@@ -5,28 +5,64 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Theme extends QM_Collector {
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
protected $got_theme_compat = false;
|
14 |
-
protected $query_templates = array();
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
|
|
|
|
|
|
|
|
20 |
add_action( 'template_redirect', array( $this, 'action_template_redirect' ) );
|
21 |
add_action( 'get_template_part', array( $this, 'action_get_template_part' ), 10, 3 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function get_concerned_actions() {
|
25 |
return array(
|
26 |
'template_redirect',
|
27 |
);
|
28 |
}
|
29 |
|
|
|
|
|
|
|
30 |
public function get_concerned_filters() {
|
31 |
$filters = array(
|
32 |
'stylesheet',
|
@@ -36,16 +72,17 @@ class QM_Collector_Theme extends QM_Collector {
|
|
36 |
'template_include',
|
37 |
);
|
38 |
|
39 |
-
foreach ( self::
|
40 |
-
|
41 |
-
$
|
42 |
-
$filters[] = "{$filter}_template_hierarchy";
|
43 |
-
$filters[] = "{$filter}_template";
|
44 |
}
|
45 |
|
46 |
return $filters;
|
47 |
}
|
48 |
|
|
|
|
|
|
|
49 |
public function get_concerned_options() {
|
50 |
return array(
|
51 |
'stylesheet',
|
@@ -53,41 +90,76 @@ class QM_Collector_Theme extends QM_Collector {
|
|
53 |
);
|
54 |
}
|
55 |
|
|
|
|
|
|
|
56 |
public static function get_query_template_names() {
|
57 |
$names = array();
|
58 |
|
59 |
-
$names['embed']
|
60 |
-
$names['404']
|
61 |
-
$names['search']
|
62 |
-
$names['front_page']
|
63 |
-
$names['home']
|
64 |
|
65 |
if ( function_exists( 'is_privacy_policy' ) ) {
|
66 |
$names['privacy_policy'] = 'is_privacy_policy';
|
67 |
}
|
68 |
|
69 |
$names['post_type_archive'] = 'is_post_type_archive';
|
70 |
-
$names['taxonomy']
|
71 |
-
$names['attachment']
|
72 |
-
$names['single']
|
73 |
-
$names['page']
|
74 |
-
$names['singular']
|
75 |
-
$names['category']
|
76 |
-
$names['tag']
|
77 |
-
$names['author']
|
78 |
-
$names['date']
|
79 |
-
$names['archive']
|
80 |
-
$names['index']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
return $names;
|
83 |
}
|
84 |
|
85 |
-
|
|
|
|
|
86 |
public function action_template_redirect() {
|
87 |
add_filter( 'template_include', array( $this, 'filter_template_include' ), PHP_INT_MAX );
|
88 |
|
89 |
foreach ( self::get_query_template_names() as $template => $conditional ) {
|
90 |
-
|
91 |
// If a matching theme-compat file is found, further conditional checks won't occur in template-loader.php
|
92 |
if ( $this->got_theme_compat ) {
|
93 |
break;
|
@@ -98,17 +170,10 @@ class QM_Collector_Theme extends QM_Collector {
|
|
98 |
if ( function_exists( $conditional ) && function_exists( $get_template ) && call_user_func( $conditional ) ) {
|
99 |
$filter = str_replace( '_', '', $template );
|
100 |
add_filter( "{$filter}_template_hierarchy", array( $this, 'filter_template_hierarchy' ), PHP_INT_MAX );
|
101 |
-
|
102 |
-
$default_template = locate_template( $this->query_templates );
|
103 |
-
|
104 |
-
if ( $default_template !== $loaded_template ) {
|
105 |
-
$this->data['template_altered'] = true;
|
106 |
-
}
|
107 |
-
|
108 |
remove_filter( "{$filter}_template_hierarchy", array( $this, 'filter_template_hierarchy' ), PHP_INT_MAX );
|
109 |
}
|
110 |
}
|
111 |
-
|
112 |
}
|
113 |
|
114 |
/**
|
@@ -117,20 +182,78 @@ class QM_Collector_Theme extends QM_Collector {
|
|
117 |
* @param string $slug The slug name for the generic template.
|
118 |
* @param string $name The name of the specialized template.
|
119 |
* @param string[] $templates Array of template files to search for, in order.
|
|
|
120 |
*/
|
121 |
public function action_get_template_part( $slug, $name, $templates ) {
|
122 |
$data = compact( 'slug', 'name', 'templates' );
|
123 |
|
124 |
-
$
|
125 |
-
'
|
|
|
|
|
126 |
) );
|
127 |
|
|
|
|
|
128 |
$this->data['requested_template_parts'][] = $data;
|
129 |
}
|
130 |
|
131 |
-
|
132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
if ( ! isset( $this->data['template_hierarchy'] ) ) {
|
135 |
$this->data['template_hierarchy'] = array();
|
136 |
}
|
@@ -147,16 +270,30 @@ class QM_Collector_Theme extends QM_Collector {
|
|
147 |
return $templates;
|
148 |
}
|
149 |
|
|
|
|
|
|
|
|
|
150 |
public function filter_body_class( array $class ) {
|
151 |
$this->data['body_class'] = $class;
|
152 |
return $class;
|
153 |
}
|
154 |
|
|
|
|
|
|
|
|
|
155 |
public function filter_template_include( $template_path ) {
|
156 |
$this->data['template_path'] = $template_path;
|
157 |
return $template_path;
|
158 |
}
|
159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
public function filter_timber_output( $output, $data = null, $file = null ) {
|
161 |
if ( $file ) {
|
162 |
$this->data['timber_files'][] = $file;
|
@@ -165,11 +302,14 @@ class QM_Collector_Theme extends QM_Collector {
|
|
165 |
return $output;
|
166 |
}
|
167 |
|
|
|
|
|
|
|
168 |
public function process() {
|
169 |
|
170 |
$stylesheet_directory = QM_Util::standard_dir( get_stylesheet_directory() );
|
171 |
-
$template_directory
|
172 |
-
$theme_directory
|
173 |
|
174 |
if ( isset( $this->data['template_hierarchy'] ) ) {
|
175 |
$this->data['template_hierarchy'] = array_unique( $this->data['template_hierarchy'] );
|
@@ -180,16 +320,13 @@ class QM_Collector_Theme extends QM_Collector {
|
|
180 |
if ( $this->data['has_template_part_action'] ) {
|
181 |
// Since WP 5.2, the `get_template_part` action populates this data nicely:
|
182 |
if ( ! empty( $this->data['requested_template_parts'] ) ) {
|
183 |
-
$this->data['template_parts']
|
184 |
$this->data['theme_template_parts'] = array();
|
185 |
$this->data['count_template_parts'] = array();
|
186 |
|
187 |
foreach ( $this->data['requested_template_parts'] as $part ) {
|
188 |
$file = locate_template( $part['templates'] );
|
189 |
|
190 |
-
$part['caller'] = $part['trace']->get_caller();
|
191 |
-
unset( $part['trace'] );
|
192 |
-
|
193 |
if ( ! $file ) {
|
194 |
$this->data['unsuccessful_template_parts'][] = $part;
|
195 |
continue;
|
@@ -209,11 +346,10 @@ class QM_Collector_Theme extends QM_Collector {
|
|
209 |
$template_directory,
|
210 |
), '', $file );
|
211 |
|
212 |
-
$
|
213 |
-
$display = trim( $filename, '/' );
|
214 |
$theme_display = trim( str_replace( $theme_directory, '', $file ), '/' );
|
215 |
|
216 |
-
$this->data['template_parts'][ $file ]
|
217 |
$this->data['theme_template_parts'][ $file ] = $theme_display;
|
218 |
}
|
219 |
}
|
@@ -227,19 +363,19 @@ class QM_Collector_Theme extends QM_Collector {
|
|
227 |
$template_directory,
|
228 |
), '', $file );
|
229 |
if ( $filename !== $file ) {
|
230 |
-
$slug
|
231 |
-
$display
|
232 |
$theme_display = trim( str_replace( $theme_directory, '', $file ), '/' );
|
233 |
-
$count
|
234 |
if ( $count ) {
|
235 |
-
$this->data['template_parts'][ $file ]
|
236 |
$this->data['theme_template_parts'][ $file ] = $theme_display;
|
237 |
$this->data['count_template_parts'][ $file ] = $count;
|
238 |
} else {
|
239 |
-
$slug
|
240 |
$count = did_action( "get_template_part_{$slug}" );
|
241 |
if ( $count ) {
|
242 |
-
$this->data['template_parts'][ $file ]
|
243 |
$this->data['theme_template_parts'][ $file ] = $theme_display;
|
244 |
$this->data['count_template_parts'][ $file ] = $count;
|
245 |
}
|
@@ -248,20 +384,71 @@ class QM_Collector_Theme extends QM_Collector {
|
|
248 |
}
|
249 |
}
|
250 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
if ( ! empty( $this->data['template_path'] ) ) {
|
252 |
-
$template_path
|
253 |
-
$template_file
|
254 |
-
$template_file
|
255 |
$theme_template_file = str_replace( array( $theme_directory, ABSPATH ), '', $template_path );
|
256 |
$theme_template_file = ltrim( $theme_template_file, '/' );
|
257 |
|
258 |
-
$this->data['template_path']
|
259 |
-
$this->data['template_file']
|
260 |
$this->data['theme_template_file'] = $theme_template_file;
|
261 |
}
|
262 |
|
263 |
-
$this->data['stylesheet']
|
264 |
-
$this->data['template']
|
265 |
$this->data['is_child_theme'] = ( $this->data['stylesheet'] !== $this->data['template'] );
|
266 |
|
267 |
if ( isset( $this->data['body_class'] ) ) {
|
@@ -272,6 +459,11 @@ class QM_Collector_Theme extends QM_Collector {
|
|
272 |
|
273 |
}
|
274 |
|
|
|
|
|
|
|
|
|
|
|
275 |
function register_qm_collector_theme( array $collectors, QueryMonitor $qm ) {
|
276 |
$collectors['response'] = new QM_Collector_Theme();
|
277 |
return $collectors;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Theme extends QM_Collector {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
public $id = 'response';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var bool
|
21 |
+
*/
|
22 |
protected $got_theme_compat = false;
|
|
|
23 |
|
24 |
+
/**
|
25 |
+
* @return void
|
26 |
+
*/
|
27 |
+
public function set_up() {
|
28 |
+
parent::set_up();
|
29 |
+
|
30 |
+
add_filter( 'body_class', array( $this, 'filter_body_class' ), 9999 );
|
31 |
+
add_filter( 'timber/output', array( $this, 'filter_timber_output' ), 9999, 3 );
|
32 |
add_action( 'template_redirect', array( $this, 'action_template_redirect' ) );
|
33 |
add_action( 'get_template_part', array( $this, 'action_get_template_part' ), 10, 3 );
|
34 |
+
add_action( 'render_block_core_template_part_post', array( $this, 'action_render_block_core_template_part_post' ), 10, 3 );
|
35 |
+
add_action( 'render_block_core_template_part_file', array( $this, 'action_render_block_core_template_part_file' ), 10, 3 );
|
36 |
+
add_action( 'render_block_core_template_part_none', array( $this, 'action_render_block_core_template_part_none' ), 10, 3 );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
+
public function tear_down() {
|
43 |
+
remove_filter( 'body_class', array( $this, 'filter_body_class' ), 9999 );
|
44 |
+
remove_filter( 'timber/output', array( $this, 'filter_timber_output' ), 9999 );
|
45 |
+
remove_action( 'template_redirect', array( $this, 'action_template_redirect' ) );
|
46 |
+
remove_action( 'get_template_part', array( $this, 'action_get_template_part' ), 10 );
|
47 |
+
remove_action( 'render_block_core_template_part_post', array( $this, 'action_render_block_core_template_part_post' ), 10 );
|
48 |
+
remove_action( 'render_block_core_template_part_file', array( $this, 'action_render_block_core_template_part_file' ), 10 );
|
49 |
+
remove_action( 'render_block_core_template_part_none', array( $this, 'action_render_block_core_template_part_none' ), 10 );
|
50 |
+
|
51 |
+
parent::tear_down();
|
52 |
}
|
53 |
|
54 |
+
/**
|
55 |
+
* @return array<int, string>
|
56 |
+
*/
|
57 |
public function get_concerned_actions() {
|
58 |
return array(
|
59 |
'template_redirect',
|
60 |
);
|
61 |
}
|
62 |
|
63 |
+
/**
|
64 |
+
* @return array<int, string>
|
65 |
+
*/
|
66 |
public function get_concerned_filters() {
|
67 |
$filters = array(
|
68 |
'stylesheet',
|
72 |
'template_include',
|
73 |
);
|
74 |
|
75 |
+
foreach ( self::get_query_filter_names() as $filter ) {
|
76 |
+
$filters[] = $filter;
|
77 |
+
$filters[] = "{$filter}_hierarchy";
|
|
|
|
|
78 |
}
|
79 |
|
80 |
return $filters;
|
81 |
}
|
82 |
|
83 |
+
/**
|
84 |
+
* @return array<int, string>
|
85 |
+
*/
|
86 |
public function get_concerned_options() {
|
87 |
return array(
|
88 |
'stylesheet',
|
90 |
);
|
91 |
}
|
92 |
|
93 |
+
/**
|
94 |
+
* @return string[]
|
95 |
+
*/
|
96 |
public static function get_query_template_names() {
|
97 |
$names = array();
|
98 |
|
99 |
+
$names['embed'] = 'is_embed';
|
100 |
+
$names['404'] = 'is_404';
|
101 |
+
$names['search'] = 'is_search';
|
102 |
+
$names['front_page'] = 'is_front_page';
|
103 |
+
$names['home'] = 'is_home';
|
104 |
|
105 |
if ( function_exists( 'is_privacy_policy' ) ) {
|
106 |
$names['privacy_policy'] = 'is_privacy_policy';
|
107 |
}
|
108 |
|
109 |
$names['post_type_archive'] = 'is_post_type_archive';
|
110 |
+
$names['taxonomy'] = 'is_tax';
|
111 |
+
$names['attachment'] = 'is_attachment';
|
112 |
+
$names['single'] = 'is_single';
|
113 |
+
$names['page'] = 'is_page';
|
114 |
+
$names['singular'] = 'is_singular';
|
115 |
+
$names['category'] = 'is_category';
|
116 |
+
$names['tag'] = 'is_tag';
|
117 |
+
$names['author'] = 'is_author';
|
118 |
+
$names['date'] = 'is_date';
|
119 |
+
$names['archive'] = 'is_archive';
|
120 |
+
$names['index'] = '__return_true';
|
121 |
+
|
122 |
+
return $names;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* @return string[]
|
127 |
+
*/
|
128 |
+
public static function get_query_filter_names() {
|
129 |
+
$names = array();
|
130 |
+
|
131 |
+
$names['embed'] = 'embed_template';
|
132 |
+
$names['404'] = '404_template';
|
133 |
+
$names['search'] = 'search_template';
|
134 |
+
$names['front_page'] = 'frontpage_template';
|
135 |
+
$names['home'] = 'home_template';
|
136 |
+
|
137 |
+
if ( function_exists( 'is_privacy_policy' ) ) {
|
138 |
+
$names['privacy_policy'] = 'privacypolicy_template';
|
139 |
+
}
|
140 |
+
|
141 |
+
$names['taxonomy'] = 'taxonomy_template';
|
142 |
+
$names['attachment'] = 'attachment_template';
|
143 |
+
$names['single'] = 'single_template';
|
144 |
+
$names['page'] = 'page_template';
|
145 |
+
$names['singular'] = 'singular_template';
|
146 |
+
$names['category'] = 'category_template';
|
147 |
+
$names['tag'] = 'tag_template';
|
148 |
+
$names['author'] = 'author_template';
|
149 |
+
$names['date'] = 'date_template';
|
150 |
+
$names['archive'] = 'archive_template';
|
151 |
+
$names['index'] = 'index_template';
|
152 |
|
153 |
return $names;
|
154 |
}
|
155 |
|
156 |
+
/**
|
157 |
+
* @return void
|
158 |
+
*/
|
159 |
public function action_template_redirect() {
|
160 |
add_filter( 'template_include', array( $this, 'filter_template_include' ), PHP_INT_MAX );
|
161 |
|
162 |
foreach ( self::get_query_template_names() as $template => $conditional ) {
|
|
|
163 |
// If a matching theme-compat file is found, further conditional checks won't occur in template-loader.php
|
164 |
if ( $this->got_theme_compat ) {
|
165 |
break;
|
170 |
if ( function_exists( $conditional ) && function_exists( $get_template ) && call_user_func( $conditional ) ) {
|
171 |
$filter = str_replace( '_', '', $template );
|
172 |
add_filter( "{$filter}_template_hierarchy", array( $this, 'filter_template_hierarchy' ), PHP_INT_MAX );
|
173 |
+
call_user_func( $get_template );
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
remove_filter( "{$filter}_template_hierarchy", array( $this, 'filter_template_hierarchy' ), PHP_INT_MAX );
|
175 |
}
|
176 |
}
|
|
|
177 |
}
|
178 |
|
179 |
/**
|
182 |
* @param string $slug The slug name for the generic template.
|
183 |
* @param string $name The name of the specialized template.
|
184 |
* @param string[] $templates Array of template files to search for, in order.
|
185 |
+
* @return void
|
186 |
*/
|
187 |
public function action_get_template_part( $slug, $name, $templates ) {
|
188 |
$data = compact( 'slug', 'name', 'templates' );
|
189 |
|
190 |
+
$trace = new QM_Backtrace( array(
|
191 |
+
'ignore_hook' => array(
|
192 |
+
current_filter() => true,
|
193 |
+
),
|
194 |
) );
|
195 |
|
196 |
+
$data['caller'] = $trace->get_caller();
|
197 |
+
|
198 |
$this->data['requested_template_parts'][] = $data;
|
199 |
}
|
200 |
|
201 |
+
/**
|
202 |
+
* Fires when a post is loaded for a template part block.
|
203 |
+
*
|
204 |
+
* @param string $template_part_id
|
205 |
+
* @param mixed[] $attributes
|
206 |
+
* @param WP_Post $post
|
207 |
+
* @return void
|
208 |
+
*/
|
209 |
+
public function action_render_block_core_template_part_post( $template_part_id, $attributes, WP_Post $post ) {
|
210 |
+
$data = array(
|
211 |
+
'id' => $template_part_id,
|
212 |
+
'attributes' => $attributes,
|
213 |
+
'post' => $post->ID,
|
214 |
+
);
|
215 |
+
$this->data['requested_template_part_posts'][] = $data;
|
216 |
+
}
|
217 |
|
218 |
+
/**
|
219 |
+
* Fires when a file is loaded for a template part block.
|
220 |
+
*
|
221 |
+
* @param string $template_part_id
|
222 |
+
* @param mixed[] $attributes
|
223 |
+
* @param string $template_part_file_path
|
224 |
+
* @return void
|
225 |
+
*/
|
226 |
+
public function action_render_block_core_template_part_file( $template_part_id, $attributes, $template_part_file_path ) {
|
227 |
+
$data = array(
|
228 |
+
'id' => $template_part_id,
|
229 |
+
'attributes' => $attributes,
|
230 |
+
'path' => $template_part_file_path,
|
231 |
+
);
|
232 |
+
$this->data['requested_template_part_files'][] = $data;
|
233 |
+
}
|
234 |
+
|
235 |
+
/**
|
236 |
+
* Fires when neither a post nor file is found for a template part block.
|
237 |
+
*
|
238 |
+
* @param string $template_part_id
|
239 |
+
* @param mixed[] $attributes
|
240 |
+
* @param string $template_part_file_path
|
241 |
+
* @return void
|
242 |
+
*/
|
243 |
+
public function action_render_block_core_template_part_none( $template_part_id, $attributes, $template_part_file_path ) {
|
244 |
+
$data = array(
|
245 |
+
'id' => $template_part_id,
|
246 |
+
'attributes' => $attributes,
|
247 |
+
'path' => $template_part_file_path,
|
248 |
+
);
|
249 |
+
$this->data['requested_template_part_nopes'][] = $data;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* @param array<int, string> $templates
|
254 |
+
* @return array<int, string>
|
255 |
+
*/
|
256 |
+
public function filter_template_hierarchy( array $templates ) {
|
257 |
if ( ! isset( $this->data['template_hierarchy'] ) ) {
|
258 |
$this->data['template_hierarchy'] = array();
|
259 |
}
|
270 |
return $templates;
|
271 |
}
|
272 |
|
273 |
+
/**
|
274 |
+
* @param array<int, string> $class
|
275 |
+
* @return array<int, string>
|
276 |
+
*/
|
277 |
public function filter_body_class( array $class ) {
|
278 |
$this->data['body_class'] = $class;
|
279 |
return $class;
|
280 |
}
|
281 |
|
282 |
+
/**
|
283 |
+
* @param array<int, string> $template_path
|
284 |
+
* @return array<int, string>
|
285 |
+
*/
|
286 |
public function filter_template_include( $template_path ) {
|
287 |
$this->data['template_path'] = $template_path;
|
288 |
return $template_path;
|
289 |
}
|
290 |
|
291 |
+
/**
|
292 |
+
* @param mixed[] $output
|
293 |
+
* @param mixed $data
|
294 |
+
* @param string $file
|
295 |
+
* @return mixed[]
|
296 |
+
*/
|
297 |
public function filter_timber_output( $output, $data = null, $file = null ) {
|
298 |
if ( $file ) {
|
299 |
$this->data['timber_files'][] = $file;
|
302 |
return $output;
|
303 |
}
|
304 |
|
305 |
+
/**
|
306 |
+
* @return void
|
307 |
+
*/
|
308 |
public function process() {
|
309 |
|
310 |
$stylesheet_directory = QM_Util::standard_dir( get_stylesheet_directory() );
|
311 |
+
$template_directory = QM_Util::standard_dir( get_template_directory() );
|
312 |
+
$theme_directory = QM_Util::standard_dir( get_theme_root() );
|
313 |
|
314 |
if ( isset( $this->data['template_hierarchy'] ) ) {
|
315 |
$this->data['template_hierarchy'] = array_unique( $this->data['template_hierarchy'] );
|
320 |
if ( $this->data['has_template_part_action'] ) {
|
321 |
// Since WP 5.2, the `get_template_part` action populates this data nicely:
|
322 |
if ( ! empty( $this->data['requested_template_parts'] ) ) {
|
323 |
+
$this->data['template_parts'] = array();
|
324 |
$this->data['theme_template_parts'] = array();
|
325 |
$this->data['count_template_parts'] = array();
|
326 |
|
327 |
foreach ( $this->data['requested_template_parts'] as $part ) {
|
328 |
$file = locate_template( $part['templates'] );
|
329 |
|
|
|
|
|
|
|
330 |
if ( ! $file ) {
|
331 |
$this->data['unsuccessful_template_parts'][] = $part;
|
332 |
continue;
|
346 |
$template_directory,
|
347 |
), '', $file );
|
348 |
|
349 |
+
$display = trim( $filename, '/' );
|
|
|
350 |
$theme_display = trim( str_replace( $theme_directory, '', $file ), '/' );
|
351 |
|
352 |
+
$this->data['template_parts'][ $file ] = $display;
|
353 |
$this->data['theme_template_parts'][ $file ] = $theme_display;
|
354 |
}
|
355 |
}
|
363 |
$template_directory,
|
364 |
), '', $file );
|
365 |
if ( $filename !== $file ) {
|
366 |
+
$slug = trim( str_replace( '.php', '', $filename ), '/' );
|
367 |
+
$display = trim( $filename, '/' );
|
368 |
$theme_display = trim( str_replace( $theme_directory, '', $file ), '/' );
|
369 |
+
$count = did_action( "get_template_part_{$slug}" );
|
370 |
if ( $count ) {
|
371 |
+
$this->data['template_parts'][ $file ] = $display;
|
372 |
$this->data['theme_template_parts'][ $file ] = $theme_display;
|
373 |
$this->data['count_template_parts'][ $file ] = $count;
|
374 |
} else {
|
375 |
+
$slug = trim( preg_replace( '|\-[^\-]+$|', '', $slug ), '/' );
|
376 |
$count = did_action( "get_template_part_{$slug}" );
|
377 |
if ( $count ) {
|
378 |
+
$this->data['template_parts'][ $file ] = $display;
|
379 |
$this->data['theme_template_parts'][ $file ] = $theme_display;
|
380 |
$this->data['count_template_parts'][ $file ] = $count;
|
381 |
}
|
384 |
}
|
385 |
}
|
386 |
|
387 |
+
if (
|
388 |
+
! empty( $this->data['requested_template_part_posts'] ) ||
|
389 |
+
! empty( $this->data['requested_template_part_files'] ) ||
|
390 |
+
! empty( $this->data['requested_template_part_nopes'] )
|
391 |
+
) {
|
392 |
+
$this->data['template_parts'] = array();
|
393 |
+
$this->data['theme_template_parts'] = array();
|
394 |
+
$this->data['count_template_parts'] = array();
|
395 |
+
|
396 |
+
$posts = ! empty( $this->data['requested_template_part_posts'] ) ? $this->data['requested_template_part_posts'] : array();
|
397 |
+
$files = ! empty( $this->data['requested_template_part_files'] ) ? $this->data['requested_template_part_files'] : array();
|
398 |
+
$nopes = ! empty( $this->data['requested_template_part_nopes'] ) ? $this->data['requested_template_part_nopes'] : array();
|
399 |
+
|
400 |
+
$this->data['has_template_part_action'] = true;
|
401 |
+
|
402 |
+
$all = array_merge( $posts, $files, $nopes );
|
403 |
+
|
404 |
+
foreach ( $all as $part ) {
|
405 |
+
$file = isset( $part['path'] ) ? $part['path'] : $part['post'];
|
406 |
+
|
407 |
+
if ( isset( $this->data['count_template_parts'][ $file ] ) ) {
|
408 |
+
$this->data['count_template_parts'][ $file ]++;
|
409 |
+
continue;
|
410 |
+
}
|
411 |
+
|
412 |
+
$this->data['count_template_parts'][ $file ] = 1;
|
413 |
+
|
414 |
+
if ( isset( $part['post'] ) ) {
|
415 |
+
$display = sprintf(
|
416 |
+
'%1$s (post ID %2$d)',
|
417 |
+
$part['id'],
|
418 |
+
$part['post']
|
419 |
+
);
|
420 |
+
$theme_display = $display;
|
421 |
+
} else {
|
422 |
+
$file = QM_Util::standard_dir( $file );
|
423 |
+
|
424 |
+
$filename = str_replace( array(
|
425 |
+
$stylesheet_directory,
|
426 |
+
$template_directory,
|
427 |
+
), '', $file );
|
428 |
+
|
429 |
+
$display = trim( $filename, '/' );
|
430 |
+
$theme_display = trim( str_replace( $theme_directory, '', $file ), '/' );
|
431 |
+
}
|
432 |
+
|
433 |
+
$this->data['template_parts'][ $file ] = $display;
|
434 |
+
$this->data['theme_template_parts'][ $file ] = $theme_display;
|
435 |
+
}
|
436 |
+
}
|
437 |
+
|
438 |
if ( ! empty( $this->data['template_path'] ) ) {
|
439 |
+
$template_path = QM_Util::standard_dir( $this->data['template_path'] );
|
440 |
+
$template_file = str_replace( array( $stylesheet_directory, $template_directory, ABSPATH ), '', $template_path );
|
441 |
+
$template_file = ltrim( $template_file, '/' );
|
442 |
$theme_template_file = str_replace( array( $theme_directory, ABSPATH ), '', $template_path );
|
443 |
$theme_template_file = ltrim( $theme_template_file, '/' );
|
444 |
|
445 |
+
$this->data['template_path'] = $template_path;
|
446 |
+
$this->data['template_file'] = $template_file;
|
447 |
$this->data['theme_template_file'] = $theme_template_file;
|
448 |
}
|
449 |
|
450 |
+
$this->data['stylesheet'] = get_stylesheet();
|
451 |
+
$this->data['template'] = get_template();
|
452 |
$this->data['is_child_theme'] = ( $this->data['stylesheet'] !== $this->data['template'] );
|
453 |
|
454 |
if ( isset( $this->data['body_class'] ) ) {
|
459 |
|
460 |
}
|
461 |
|
462 |
+
/**
|
463 |
+
* @param array<string, QM_Collector> $collectors
|
464 |
+
* @param QueryMonitor $qm
|
465 |
+
* @return array<string, QM_Collector>
|
466 |
+
*/
|
467 |
function register_qm_collector_theme( array $collectors, QueryMonitor $qm ) {
|
468 |
$collectors['response'] = new QM_Collector_Theme();
|
469 |
return $collectors;
|
collectors/timing.php
CHANGED
@@ -5,34 +5,75 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Timing extends QM_Collector {
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
private $track_timer = array();
|
14 |
-
private $start = array();
|
15 |
-
private $stop = array();
|
16 |
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
add_action( 'qm/start', array( $this, 'action_function_time_start' ), 10, 1 );
|
20 |
-
add_action( 'qm/stop',
|
21 |
-
add_action( 'qm/lap',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
}
|
23 |
|
|
|
|
|
|
|
|
|
24 |
public function action_function_time_start( $function ) {
|
25 |
$this->track_timer[ $function ] = new QM_Timer();
|
26 |
-
$this->start[ $function ]
|
27 |
}
|
28 |
|
|
|
|
|
|
|
|
|
29 |
public function action_function_time_stop( $function ) {
|
30 |
if ( ! isset( $this->track_timer[ $function ] ) ) {
|
31 |
-
$trace
|
32 |
$this->data['warning'][] = array(
|
33 |
'function' => $function,
|
34 |
-
'message'
|
35 |
-
'
|
|
|
36 |
);
|
37 |
return;
|
38 |
}
|
@@ -40,46 +81,61 @@ class QM_Collector_Timing extends QM_Collector {
|
|
40 |
$this->calculate_time( $function );
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
|
|
43 |
public function action_function_time_lap( $function, $name = null ) {
|
44 |
if ( ! isset( $this->track_timer[ $function ] ) ) {
|
45 |
-
$trace
|
46 |
$this->data['warning'][] = array(
|
47 |
'function' => $function,
|
48 |
-
'message'
|
49 |
-
'
|
|
|
50 |
);
|
51 |
return;
|
52 |
}
|
53 |
$this->track_timer[ $function ]->lap( array(), $name );
|
54 |
}
|
55 |
|
|
|
|
|
|
|
|
|
56 |
public function calculate_time( $function ) {
|
57 |
-
$trace
|
58 |
-
$function_time
|
59 |
$function_memory = $this->track_timer[ $function ]->get_memory();
|
60 |
-
$function_laps
|
61 |
-
$start_time
|
62 |
-
$end_time
|
63 |
|
64 |
$this->data['timing'][] = array(
|
65 |
-
'function'
|
66 |
-
'function_time'
|
67 |
'function_memory' => $function_memory,
|
68 |
-
'laps'
|
69 |
-
'
|
70 |
-
'
|
71 |
-
'
|
|
|
72 |
);
|
73 |
}
|
74 |
|
|
|
|
|
|
|
75 |
public function process() {
|
76 |
foreach ( $this->start as $function => $value ) {
|
77 |
if ( ! isset( $this->stop[ $function ] ) ) {
|
78 |
-
$trace
|
79 |
$this->data['warning'][] = array(
|
80 |
'function' => $function,
|
81 |
-
'message'
|
82 |
-
'
|
|
|
83 |
);
|
84 |
}
|
85 |
}
|
@@ -89,6 +145,12 @@ class QM_Collector_Timing extends QM_Collector {
|
|
89 |
}
|
90 |
}
|
91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
public function sort_by_start_time( array $a, array $b ) {
|
93 |
if ( $a['start_time'] === $b['start_time'] ) {
|
94 |
return 0;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Timing extends QM_Collector {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
public $id = 'timing';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var array<string, QM_Timer>
|
21 |
+
*/
|
22 |
private $track_timer = array();
|
|
|
|
|
23 |
|
24 |
+
/**
|
25 |
+
* @var array<string, QM_Timer>
|
26 |
+
*/
|
27 |
+
private $start = array();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @var array<string, QM_Timer>
|
31 |
+
*/
|
32 |
+
private $stop = array();
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
+
public function set_up() {
|
38 |
+
parent::set_up();
|
39 |
+
|
40 |
add_action( 'qm/start', array( $this, 'action_function_time_start' ), 10, 1 );
|
41 |
+
add_action( 'qm/stop', array( $this, 'action_function_time_stop' ), 10, 1 );
|
42 |
+
add_action( 'qm/lap', array( $this, 'action_function_time_lap' ), 10, 2 );
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @return void
|
47 |
+
*/
|
48 |
+
public function tear_down() {
|
49 |
+
remove_action( 'qm/start', array( $this, 'action_function_time_start' ), 10 );
|
50 |
+
remove_action( 'qm/stop', array( $this, 'action_function_time_stop' ), 10 );
|
51 |
+
remove_action( 'qm/lap', array( $this, 'action_function_time_lap' ), 10 );
|
52 |
+
|
53 |
+
parent::tear_down();
|
54 |
}
|
55 |
|
56 |
+
/**
|
57 |
+
* @param string $function
|
58 |
+
* @return void
|
59 |
+
*/
|
60 |
public function action_function_time_start( $function ) {
|
61 |
$this->track_timer[ $function ] = new QM_Timer();
|
62 |
+
$this->start[ $function ] = $this->track_timer[ $function ]->start();
|
63 |
}
|
64 |
|
65 |
+
/**
|
66 |
+
* @param string $function
|
67 |
+
* @return void
|
68 |
+
*/
|
69 |
public function action_function_time_stop( $function ) {
|
70 |
if ( ! isset( $this->track_timer[ $function ] ) ) {
|
71 |
+
$trace = new QM_Backtrace();
|
72 |
$this->data['warning'][] = array(
|
73 |
'function' => $function,
|
74 |
+
'message' => __( 'Timer not started', 'query-monitor' ),
|
75 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
76 |
+
'component' => $trace->get_component(),
|
77 |
);
|
78 |
return;
|
79 |
}
|
81 |
$this->calculate_time( $function );
|
82 |
}
|
83 |
|
84 |
+
/**
|
85 |
+
* @param string $function
|
86 |
+
* @param string $name
|
87 |
+
* @return void
|
88 |
+
*/
|
89 |
public function action_function_time_lap( $function, $name = null ) {
|
90 |
if ( ! isset( $this->track_timer[ $function ] ) ) {
|
91 |
+
$trace = new QM_Backtrace();
|
92 |
$this->data['warning'][] = array(
|
93 |
'function' => $function,
|
94 |
+
'message' => __( 'Timer not started', 'query-monitor' ),
|
95 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
96 |
+
'component' => $trace->get_component(),
|
97 |
);
|
98 |
return;
|
99 |
}
|
100 |
$this->track_timer[ $function ]->lap( array(), $name );
|
101 |
}
|
102 |
|
103 |
+
/**
|
104 |
+
* @param string $function
|
105 |
+
* @return void
|
106 |
+
*/
|
107 |
public function calculate_time( $function ) {
|
108 |
+
$trace = $this->track_timer[ $function ]->get_trace();
|
109 |
+
$function_time = $this->track_timer[ $function ]->get_time();
|
110 |
$function_memory = $this->track_timer[ $function ]->get_memory();
|
111 |
+
$function_laps = $this->track_timer[ $function ]->get_laps();
|
112 |
+
$start_time = $this->track_timer[ $function ]->get_start_time();
|
113 |
+
$end_time = $this->track_timer[ $function ]->get_end_time();
|
114 |
|
115 |
$this->data['timing'][] = array(
|
116 |
+
'function' => $function,
|
117 |
+
'function_time' => $function_time,
|
118 |
'function_memory' => $function_memory,
|
119 |
+
'laps' => $function_laps,
|
120 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
121 |
+
'component' => $trace->get_component(),
|
122 |
+
'start_time' => ( $start_time - $GLOBALS['timestart'] ),
|
123 |
+
'end_time' => ( $end_time - $GLOBALS['timestart'] ),
|
124 |
);
|
125 |
}
|
126 |
|
127 |
+
/**
|
128 |
+
* @return void
|
129 |
+
*/
|
130 |
public function process() {
|
131 |
foreach ( $this->start as $function => $value ) {
|
132 |
if ( ! isset( $this->stop[ $function ] ) ) {
|
133 |
+
$trace = $this->track_timer[ $function ]->get_trace();
|
134 |
$this->data['warning'][] = array(
|
135 |
'function' => $function,
|
136 |
+
'message' => __( 'Timer not stopped', 'query-monitor' ),
|
137 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
138 |
+
'component' => $trace->get_component(),
|
139 |
);
|
140 |
}
|
141 |
}
|
145 |
}
|
146 |
}
|
147 |
|
148 |
+
/**
|
149 |
+
* @param mixed[] $a
|
150 |
+
* @param mixed[] $b
|
151 |
+
* @return int
|
152 |
+
* @phpstan-return -1|0|1
|
153 |
+
*/
|
154 |
public function sort_by_start_time( array $a, array $b ) {
|
155 |
if ( $a['start_time'] === $b['start_time'] ) {
|
156 |
return 0;
|
collectors/transients.php
CHANGED
@@ -5,35 +5,70 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Collector_Transients extends QM_Collector {
|
11 |
|
12 |
public $id = 'transients';
|
13 |
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
16 |
add_action( 'setted_site_transient', array( $this, 'action_setted_site_transient' ), 10, 3 );
|
17 |
-
add_action( 'setted_transient',
|
18 |
}
|
19 |
|
|
|
|
|
|
|
20 |
public function tear_down() {
|
21 |
remove_action( 'setted_site_transient', array( $this, 'action_setted_site_transient' ), 10 );
|
22 |
-
remove_action( 'setted_transient',
|
23 |
parent::tear_down();
|
24 |
}
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
public function action_setted_site_transient( $transient, $value, $expiration ) {
|
27 |
$this->setted_transient( $transient, 'site', $value, $expiration );
|
28 |
}
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
public function action_setted_blog_transient( $transient, $value, $expiration ) {
|
31 |
$this->setted_transient( $transient, 'blog', $value, $expiration );
|
32 |
}
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
public function setted_transient( $transient, $type, $value, $expiration ) {
|
35 |
$trace = new QM_Backtrace( array(
|
36 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
) );
|
38 |
|
39 |
$name = str_replace( array(
|
@@ -44,37 +79,23 @@ class QM_Collector_Transients extends QM_Collector {
|
|
44 |
$size = strlen( maybe_serialize( $value ) );
|
45 |
|
46 |
$this->data['trans'][] = array(
|
47 |
-
'name'
|
48 |
-
'
|
49 |
-
'
|
50 |
-
'
|
|
|
51 |
'expiration' => $expiration,
|
52 |
-
'exp_diff'
|
53 |
-
'size'
|
54 |
'size_formatted' => size_format( $size ),
|
55 |
);
|
56 |
}
|
57 |
|
|
|
|
|
|
|
58 |
public function process() {
|
59 |
$this->data['has_type'] = is_multisite();
|
60 |
-
|
61 |
-
if ( empty( $this->data['trans'] ) ) {
|
62 |
-
return;
|
63 |
-
}
|
64 |
-
|
65 |
-
foreach ( $this->data['trans'] as $i => $transient ) {
|
66 |
-
$filtered_trace = $transient['trace']->get_display_trace();
|
67 |
-
|
68 |
-
array_shift( $filtered_trace ); // remove do_action('setted_(site_)?transient')
|
69 |
-
array_shift( $filtered_trace ); // remove set_(site_)?transient()
|
70 |
-
|
71 |
-
$component = $transient['trace']->get_component();
|
72 |
-
|
73 |
-
$this->data['trans'][ $i ]['filtered_trace'] = $filtered_trace;
|
74 |
-
$this->data['trans'][ $i ]['component'] = $component;
|
75 |
-
|
76 |
-
unset( $this->data['trans'][ $i ]['trace'] );
|
77 |
-
}
|
78 |
}
|
79 |
|
80 |
}
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Collector_Transients extends QM_Collector {
|
13 |
|
14 |
public $id = 'transients';
|
15 |
|
16 |
+
/**
|
17 |
+
* @return void
|
18 |
+
*/
|
19 |
+
public function set_up() {
|
20 |
+
parent::set_up();
|
21 |
+
|
22 |
add_action( 'setted_site_transient', array( $this, 'action_setted_site_transient' ), 10, 3 );
|
23 |
+
add_action( 'setted_transient', array( $this, 'action_setted_blog_transient' ), 10, 3 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return void
|
28 |
+
*/
|
29 |
public function tear_down() {
|
30 |
remove_action( 'setted_site_transient', array( $this, 'action_setted_site_transient' ), 10 );
|
31 |
+
remove_action( 'setted_transient', array( $this, 'action_setted_blog_transient' ), 10 );
|
32 |
parent::tear_down();
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* @param string $transient
|
37 |
+
* @param mixed $value
|
38 |
+
* @param int $expiration
|
39 |
+
* @return void
|
40 |
+
*/
|
41 |
public function action_setted_site_transient( $transient, $value, $expiration ) {
|
42 |
$this->setted_transient( $transient, 'site', $value, $expiration );
|
43 |
}
|
44 |
|
45 |
+
/**
|
46 |
+
* @param string $transient
|
47 |
+
* @param mixed $value
|
48 |
+
* @param int $expiration
|
49 |
+
* @return void
|
50 |
+
*/
|
51 |
public function action_setted_blog_transient( $transient, $value, $expiration ) {
|
52 |
$this->setted_transient( $transient, 'blog', $value, $expiration );
|
53 |
}
|
54 |
|
55 |
+
/**
|
56 |
+
* @param string $transient
|
57 |
+
* @param string $type
|
58 |
+
* @param mixed $value
|
59 |
+
* @param int $expiration
|
60 |
+
* @phpstan-param 'site'|'blog' $value
|
61 |
+
* @return void
|
62 |
+
*/
|
63 |
public function setted_transient( $transient, $type, $value, $expiration ) {
|
64 |
$trace = new QM_Backtrace( array(
|
65 |
+
'ignore_hook' => array(
|
66 |
+
current_filter() => true,
|
67 |
+
),
|
68 |
+
'ignore_func' => array(
|
69 |
+
'set_transient' => true,
|
70 |
+
'set_site_transient' => true,
|
71 |
+
),
|
72 |
) );
|
73 |
|
74 |
$name = str_replace( array(
|
79 |
$size = strlen( maybe_serialize( $value ) );
|
80 |
|
81 |
$this->data['trans'][] = array(
|
82 |
+
'name' => $name,
|
83 |
+
'filtered_trace' => $trace->get_filtered_trace(),
|
84 |
+
'component' => $trace->get_component(),
|
85 |
+
'type' => $type,
|
86 |
+
'value' => $value,
|
87 |
'expiration' => $expiration,
|
88 |
+
'exp_diff' => ( $expiration ? human_time_diff( 0, $expiration ) : '' ),
|
89 |
+
'size' => $size,
|
90 |
'size_formatted' => size_format( $size ),
|
91 |
);
|
92 |
}
|
93 |
|
94 |
+
/**
|
95 |
+
* @return void
|
96 |
+
*/
|
97 |
public function process() {
|
98 |
$this->data['has_type'] = is_multisite();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
}
|
100 |
|
101 |
}
|
composer.json
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "johnbillion/query-monitor",
|
3 |
+
"type": "wordpress-plugin",
|
4 |
+
"description": "The Developer Tools panel for WordPress.",
|
5 |
+
"homepage": "https://github.com/johnbillion/query-monitor/",
|
6 |
+
"license": "GPL-2.0-or-later",
|
7 |
+
"authors": [
|
8 |
+
{
|
9 |
+
"name": "John Blackbourn",
|
10 |
+
"homepage": "https://johnblackbourn.com/"
|
11 |
+
}
|
12 |
+
],
|
13 |
+
"require": {
|
14 |
+
"php": ">=5.3.6",
|
15 |
+
"composer/installers": "~1.0"
|
16 |
+
},
|
17 |
+
"require-dev": {
|
18 |
+
"dealerdirect/phpcodesniffer-composer-installer": "0.7.0",
|
19 |
+
"johnbillion/falsey-assertequals-detector": "^1 || ^3",
|
20 |
+
"phpcompatibility/phpcompatibility-wp": "2.1.0",
|
21 |
+
"phpstan/phpstan": "^1.0",
|
22 |
+
"phpstan/phpstan-phpunit": "^1.0",
|
23 |
+
"phpunit/phpunit": "^5 || ^7",
|
24 |
+
"roots/wordpress": "*",
|
25 |
+
"squizlabs/php_codesniffer": "3.5.8",
|
26 |
+
"szepeviktor/phpstan-wordpress": "^1.0",
|
27 |
+
"vlucas/phpdotenv": "^3",
|
28 |
+
"wp-cli/db-command": "^2",
|
29 |
+
"wp-coding-standards/wpcs": "2.3.0",
|
30 |
+
"wp-phpunit/wp-phpunit": "*",
|
31 |
+
"yoast/phpunit-polyfills": "^1.0"
|
32 |
+
},
|
33 |
+
"config": {
|
34 |
+
"preferred-install": "dist",
|
35 |
+
"sort-packages": true,
|
36 |
+
"allow-plugins": {
|
37 |
+
"composer/installers": true,
|
38 |
+
"dealerdirect/phpcodesniffer-composer-installer": true,
|
39 |
+
"roots/wordpress-core-installer": true
|
40 |
+
}
|
41 |
+
},
|
42 |
+
"extra": {
|
43 |
+
"wordpress-install-dir": "tests/wordpress"
|
44 |
+
},
|
45 |
+
"scripts": {
|
46 |
+
"post-update-cmd": [
|
47 |
+
"@php -r \"! file_exists( 'tests/.env' ) && copy( 'tests/.env.dist', 'tests/.env' );\""
|
48 |
+
],
|
49 |
+
"test": [
|
50 |
+
"@test:cs",
|
51 |
+
"@test:phpstan",
|
52 |
+
"@test:ut"
|
53 |
+
],
|
54 |
+
"test:cs": [
|
55 |
+
"phpcs -nps --colors --report-code --report-width=80 --cache=tests/cache/phpcs --basepath='./' ."
|
56 |
+
],
|
57 |
+
"test:phpstan": [
|
58 |
+
"phpstan analyze"
|
59 |
+
],
|
60 |
+
"test:ut": [
|
61 |
+
"wp db reset --yes --path=tests/wordpress #",
|
62 |
+
"export WP_MULTISITE=0 && phpunit --verbose --colors=always --exclude-group=ms-required",
|
63 |
+
"export WP_MULTISITE=1 && phpunit --verbose --colors=always --exclude-group=ms-excluded"
|
64 |
+
]
|
65 |
+
},
|
66 |
+
"support": {
|
67 |
+
"issues": "https://github.com/johnbillion/query-monitor/issues",
|
68 |
+
"forum": "https://wordpress.org/support/plugin/query-monitor",
|
69 |
+
"source": "https://github.com/johnbillion/query-monitor"
|
70 |
+
},
|
71 |
+
"funding": [
|
72 |
+
{
|
73 |
+
"type": "github",
|
74 |
+
"url": "https://github.com/sponsors/johnbillion"
|
75 |
+
}
|
76 |
+
]
|
77 |
+
}
|
dispatchers/AJAX.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Dispatcher_AJAX extends QM_Dispatcher {
|
11 |
|
@@ -20,6 +22,9 @@ class QM_Dispatcher_AJAX extends QM_Dispatcher {
|
|
20 |
add_action( 'shutdown', array( $this, 'dispatch' ), 0 );
|
21 |
}
|
22 |
|
|
|
|
|
|
|
23 |
public function init() {
|
24 |
|
25 |
if ( ! self::user_can_view() ) {
|
@@ -34,6 +39,9 @@ class QM_Dispatcher_AJAX extends QM_Dispatcher {
|
|
34 |
parent::init();
|
35 |
}
|
36 |
|
|
|
|
|
|
|
37 |
public function dispatch() {
|
38 |
|
39 |
if ( ! $this->should_dispatch() ) {
|
@@ -50,6 +58,9 @@ class QM_Dispatcher_AJAX extends QM_Dispatcher {
|
|
50 |
|
51 |
}
|
52 |
|
|
|
|
|
|
|
53 |
protected function before_output() {
|
54 |
|
55 |
require_once $this->qm->plugin_path( 'output/Headers.php' );
|
@@ -59,6 +70,9 @@ class QM_Dispatcher_AJAX extends QM_Dispatcher {
|
|
59 |
}
|
60 |
}
|
61 |
|
|
|
|
|
|
|
62 |
protected function after_output() {
|
63 |
|
64 |
# flush once, because we're nice
|
@@ -68,6 +82,9 @@ class QM_Dispatcher_AJAX extends QM_Dispatcher {
|
|
68 |
|
69 |
}
|
70 |
|
|
|
|
|
|
|
71 |
public function is_active() {
|
72 |
|
73 |
if ( ! QM_Util::is_ajax() ) {
|
@@ -100,6 +117,11 @@ class QM_Dispatcher_AJAX extends QM_Dispatcher {
|
|
100 |
|
101 |
}
|
102 |
|
|
|
|
|
|
|
|
|
|
|
103 |
function register_qm_dispatcher_ajax( array $dispatchers, QM_Plugin $qm ) {
|
104 |
$dispatchers['ajax'] = new QM_Dispatcher_AJAX( $qm );
|
105 |
return $dispatchers;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Dispatcher_AJAX extends QM_Dispatcher {
|
13 |
|
22 |
add_action( 'shutdown', array( $this, 'dispatch' ), 0 );
|
23 |
}
|
24 |
|
25 |
+
/**
|
26 |
+
* @return void
|
27 |
+
*/
|
28 |
public function init() {
|
29 |
|
30 |
if ( ! self::user_can_view() ) {
|
39 |
parent::init();
|
40 |
}
|
41 |
|
42 |
+
/**
|
43 |
+
* @return void
|
44 |
+
*/
|
45 |
public function dispatch() {
|
46 |
|
47 |
if ( ! $this->should_dispatch() ) {
|
58 |
|
59 |
}
|
60 |
|
61 |
+
/**
|
62 |
+
* @return void
|
63 |
+
*/
|
64 |
protected function before_output() {
|
65 |
|
66 |
require_once $this->qm->plugin_path( 'output/Headers.php' );
|
70 |
}
|
71 |
}
|
72 |
|
73 |
+
/**
|
74 |
+
* @return void
|
75 |
+
*/
|
76 |
protected function after_output() {
|
77 |
|
78 |
# flush once, because we're nice
|
82 |
|
83 |
}
|
84 |
|
85 |
+
/**
|
86 |
+
* @return bool
|
87 |
+
*/
|
88 |
public function is_active() {
|
89 |
|
90 |
if ( ! QM_Util::is_ajax() ) {
|
117 |
|
118 |
}
|
119 |
|
120 |
+
/**
|
121 |
+
* @param array<string, QM_Dispatcher> $dispatchers
|
122 |
+
* @param QM_Plugin $qm
|
123 |
+
* @return array<string, QM_Dispatcher>
|
124 |
+
*/
|
125 |
function register_qm_dispatcher_ajax( array $dispatchers, QM_Plugin $qm ) {
|
126 |
$dispatchers['ajax'] = new QM_Dispatcher_AJAX( $qm );
|
127 |
return $dispatchers;
|
dispatchers/Html.php
CHANGED
@@ -5,42 +5,61 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Dispatcher_Html extends QM_Dispatcher {
|
11 |
|
12 |
/**
|
13 |
* Outputter instances.
|
14 |
*
|
15 |
-
* @var QM_Output_Html
|
16 |
*/
|
17 |
protected $outputters = array();
|
18 |
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
public $did_footer = false;
|
21 |
|
|
|
|
|
|
|
22 |
protected $admin_bar_menu = array();
|
23 |
-
|
|
|
|
|
|
|
|
|
24 |
|
25 |
public function __construct( QM_Plugin $qm ) {
|
26 |
|
27 |
-
add_action( 'admin_bar_menu',
|
28 |
-
add_action( 'wp_ajax_qm_auth_on',
|
29 |
-
add_action( 'wp_ajax_qm_auth_off',
|
30 |
-
add_action( 'wp_ajax_qm_editor_set',
|
31 |
add_action( 'wp_ajax_nopriv_qm_auth_off', array( $this, 'ajax_off' ) );
|
32 |
|
33 |
-
add_action( 'shutdown',
|
34 |
|
35 |
-
add_action( 'wp_footer',
|
36 |
-
add_action( 'admin_footer',
|
37 |
-
add_action( 'login_footer',
|
38 |
-
add_action( 'gp_footer',
|
39 |
|
40 |
parent::__construct( $qm );
|
41 |
|
42 |
}
|
43 |
|
|
|
|
|
|
|
44 |
public function action_footer() {
|
45 |
$this->did_footer = true;
|
46 |
}
|
@@ -54,6 +73,9 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
54 |
return ( is_ssl() && ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) ) );
|
55 |
}
|
56 |
|
|
|
|
|
|
|
57 |
public function ajax_on() {
|
58 |
|
59 |
if ( ! current_user_can( 'view_query_monitor' ) || ! check_ajax_referer( 'qm-auth-on', 'nonce', false ) ) {
|
@@ -61,8 +83,8 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
61 |
}
|
62 |
|
63 |
$expiration = time() + ( 2 * DAY_IN_SECONDS );
|
64 |
-
$secure
|
65 |
-
$cookie
|
66 |
|
67 |
setcookie( QM_COOKIE, $cookie, $expiration, COOKIEPATH, COOKIE_DOMAIN, $secure, false );
|
68 |
|
@@ -70,6 +92,9 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
70 |
|
71 |
}
|
72 |
|
|
|
|
|
|
|
73 |
public function ajax_off() {
|
74 |
|
75 |
if ( ! self::user_verified() || ! check_ajax_referer( 'qm-auth-off', 'nonce', false ) ) {
|
@@ -84,6 +109,9 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
84 |
|
85 |
}
|
86 |
|
|
|
|
|
|
|
87 |
public function ajax_editor_set() {
|
88 |
|
89 |
if ( ! current_user_can( 'view_query_monitor' ) || ! check_ajax_referer( 'qm-editor-set', 'nonce', false ) ) {
|
@@ -91,8 +119,8 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
91 |
}
|
92 |
|
93 |
$expiration = time() + ( 2 * YEAR_IN_SECONDS );
|
94 |
-
$secure
|
95 |
-
$editor
|
96 |
|
97 |
setcookie( QM_EDITOR_COOKIE, $editor, $expiration, COOKIEPATH, COOKIE_DOMAIN, $secure, false );
|
98 |
|
@@ -100,6 +128,10 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
100 |
|
101 |
}
|
102 |
|
|
|
|
|
|
|
|
|
103 |
public function action_admin_bar_menu( WP_Admin_Bar $wp_admin_bar ) {
|
104 |
|
105 |
if ( ! self::user_can_view() ) {
|
@@ -109,40 +141,50 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
109 |
$title = __( 'Query Monitor', 'query-monitor' );
|
110 |
|
111 |
$wp_admin_bar->add_node( array(
|
112 |
-
'id'
|
113 |
'title' => esc_html( $title ),
|
114 |
-
'href'
|
115 |
) );
|
116 |
|
117 |
$wp_admin_bar->add_node( array(
|
118 |
'parent' => 'query-monitor',
|
119 |
-
'id'
|
120 |
-
'title'
|
121 |
-
'href'
|
122 |
) );
|
123 |
|
124 |
}
|
125 |
|
|
|
|
|
|
|
126 |
public function init() {
|
127 |
|
128 |
if ( ! self::user_can_view() ) {
|
129 |
return;
|
130 |
}
|
131 |
|
|
|
|
|
|
|
|
|
132 |
if ( ! file_exists( $this->qm->plugin_path( 'assets/query-monitor.css' ) ) ) {
|
133 |
add_action( 'admin_notices', array( $this, 'build_warning' ) );
|
134 |
}
|
135 |
|
136 |
-
add_action( 'wp_enqueue_scripts',
|
137 |
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), -9999 );
|
138 |
add_action( 'login_enqueue_scripts', array( $this, 'enqueue_assets' ), -9999 );
|
139 |
add_action( 'enqueue_embed_scripts', array( $this, 'enqueue_assets' ), -9999 );
|
140 |
|
141 |
-
add_action( 'gp_head',
|
142 |
|
143 |
parent::init();
|
144 |
}
|
145 |
|
|
|
|
|
|
|
146 |
public function manually_print_assets() {
|
147 |
wp_print_scripts( array(
|
148 |
'query-monitor',
|
@@ -152,6 +194,9 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
152 |
) );
|
153 |
}
|
154 |
|
|
|
|
|
|
|
155 |
public function build_warning() {
|
156 |
printf(
|
157 |
'<div id="qm-built-nope" class="notice notice-error"><p>%s</p></div>',
|
@@ -167,8 +212,11 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
167 |
);
|
168 |
}
|
169 |
|
|
|
|
|
|
|
170 |
public function enqueue_assets() {
|
171 |
-
global $wp_locale
|
172 |
|
173 |
$deps = array(
|
174 |
'jquery',
|
@@ -207,10 +255,10 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
207 |
'qm_l10n',
|
208 |
array(
|
209 |
'ajax_error' => __( 'PHP Errors in Ajax Response', 'query-monitor' ),
|
210 |
-
'ajaxurl'
|
211 |
'auth_nonce' => array(
|
212 |
-
'on'
|
213 |
-
'off'
|
214 |
'editor-set' => wp_create_nonce( 'qm-editor-set' ),
|
215 |
),
|
216 |
'fatal_error' => __( 'PHP Fatal Error', 'query-monitor' ),
|
@@ -227,13 +275,42 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
227 |
do_action( 'qm/output/enqueued-assets', $this );
|
228 |
}
|
229 |
|
|
|
|
|
|
|
230 |
public function dispatch() {
|
231 |
-
|
232 |
if ( ! $this->should_dispatch() ) {
|
233 |
return;
|
234 |
}
|
235 |
|
236 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
|
238 |
$this->before_output();
|
239 |
|
@@ -257,11 +334,14 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
257 |
$this->after_output();
|
258 |
|
259 |
if ( $switched_locale ) {
|
260 |
-
restore_previous_locale();
|
261 |
}
|
262 |
|
263 |
}
|
264 |
|
|
|
|
|
|
|
265 |
protected function before_output() {
|
266 |
|
267 |
require_once $this->qm->plugin_path( 'output/Html.php' );
|
@@ -270,7 +350,10 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
270 |
require_once $file;
|
271 |
}
|
272 |
|
273 |
-
|
|
|
|
|
|
|
274 |
|
275 |
/**
|
276 |
* Filters the menu items shown in Query Monitor's admin toolbar menu.
|
@@ -294,9 +377,14 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
294 |
$collector = $output->get_collector();
|
295 |
|
296 |
if ( ( ! empty( $collector->concerned_filters ) || ! empty( $collector->concerned_actions ) ) && isset( $this->panel_menu[ 'qm-' . $output_id ] ) ) {
|
|
|
297 |
$this->panel_menu[ 'qm-' . $output_id ]['children'][ 'qm-' . $output_id . '-concerned_hooks' ] = array(
|
298 |
-
'href'
|
299 |
-
'title' =>
|
|
|
|
|
|
|
|
|
300 |
);
|
301 |
}
|
302 |
}
|
@@ -315,7 +403,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
315 |
}
|
316 |
|
317 |
$json = array(
|
318 |
-
'menu'
|
319 |
'ajax_errors' => array(), # @TODO move this into the php_errors collector
|
320 |
);
|
321 |
|
@@ -390,6 +478,11 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
390 |
|
391 |
}
|
392 |
|
|
|
|
|
|
|
|
|
|
|
393 |
protected function do_panel_menu_item( $id, array $menu ) {
|
394 |
printf(
|
395 |
'<li role="presentation"><button role="tab" data-qm-href="%1$s">%2$s</button>',
|
@@ -408,12 +501,15 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
408 |
echo '</li>';
|
409 |
}
|
410 |
|
|
|
|
|
|
|
411 |
protected function after_output() {
|
412 |
|
413 |
$state = self::user_verified() ? 'on' : 'off';
|
414 |
$editor = self::editor_cookie();
|
415 |
-
$text
|
416 |
-
'on'
|
417 |
'off' => __( 'Set authentication cookie', 'query-monitor' ),
|
418 |
);
|
419 |
|
@@ -444,12 +540,12 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
444 |
echo '<select id="qm-editor-select" name="qm-editor-select" class="qm-filter">';
|
445 |
|
446 |
$editors = array(
|
447 |
-
'Default/Xdebug'
|
448 |
-
'Atom'
|
449 |
-
'Netbeans'
|
450 |
-
'PhpStorm'
|
451 |
-
'Sublime Text'
|
452 |
-
'TextMate'
|
453 |
'Visual Studio Code' => 'vscode',
|
454 |
);
|
455 |
|
@@ -467,42 +563,46 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
467 |
|
468 |
echo '<div class="qm-boxed">';
|
469 |
$constants = array(
|
470 |
-
'QM_DARK_MODE'
|
471 |
-
'label'
|
472 |
'default' => false,
|
473 |
),
|
474 |
-
'QM_DB_EXPENSIVE'
|
475 |
-
'label'
|
476 |
'default' => 0.05,
|
477 |
),
|
478 |
-
'QM_DISABLED'
|
479 |
-
'label'
|
480 |
'default' => false,
|
481 |
),
|
482 |
'QM_DISABLE_ERROR_HANDLER' => array(
|
483 |
-
'label'
|
484 |
'default' => false,
|
485 |
),
|
486 |
-
'QM_ENABLE_CAPS_PANEL'
|
487 |
-
'label'
|
488 |
'default' => false,
|
489 |
),
|
490 |
-
'QM_HIDE_CORE_ACTIONS'
|
491 |
-
'label'
|
492 |
'default' => false,
|
493 |
),
|
494 |
-
'QM_HIDE_SELF'
|
495 |
-
'label'
|
496 |
'default' => true,
|
497 |
),
|
498 |
-
'QM_NO_JQUERY'
|
499 |
-
'label'
|
500 |
'default' => false,
|
501 |
),
|
502 |
-
'QM_SHOW_ALL_HOOKS'
|
503 |
-
'label'
|
504 |
'default' => false,
|
505 |
),
|
|
|
|
|
|
|
|
|
506 |
);
|
507 |
|
508 |
echo '<section>';
|
@@ -520,10 +620,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
520 |
foreach ( $constants as $name => $constant ) {
|
521 |
echo '<dt><code>' . esc_html( $name ) . '</code></dt>';
|
522 |
echo '<dd>';
|
523 |
-
|
524 |
-
esc_html( $constant['label'] ),
|
525 |
-
'<code>' . esc_html( $constant['default'] ) . '</code>'
|
526 |
-
);
|
527 |
|
528 |
$default_value = $constant['default'];
|
529 |
if ( is_bool( $default_value ) ) {
|
@@ -534,18 +631,16 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
534 |
printf(
|
535 |
/* translators: %s: Default value for a PHP constant */
|
536 |
esc_html__( 'Default value: %s', 'query-monitor' ),
|
537 |
-
'<code>' . esc_html( $default_value ) . '</code>'
|
538 |
);
|
539 |
echo '</span>';
|
540 |
|
541 |
-
if ( defined( $name ) ) {
|
542 |
$current_value = constant( $name );
|
543 |
if ( is_bool( $current_value ) ) {
|
544 |
$current_value = QM_Collector::format_bool_constant( $name );
|
545 |
}
|
546 |
-
}
|
547 |
|
548 |
-
if ( defined( $name ) && ( constant( $name ) !== $constant['default'] ) ) {
|
549 |
echo '<br><span class="qm-info">';
|
550 |
printf(
|
551 |
/* translators: %s: Current value for a PHP constant */
|
@@ -622,6 +717,10 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
622 |
|
623 |
}
|
624 |
|
|
|
|
|
|
|
|
|
625 |
public static function size( $var ) {
|
626 |
$start_memory = memory_get_usage();
|
627 |
|
@@ -634,6 +733,9 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
634 |
return memory_get_usage() - $start_memory - ( PHP_INT_SIZE * 8 );
|
635 |
}
|
636 |
|
|
|
|
|
|
|
637 |
public function js_admin_bar_menu() {
|
638 |
|
639 |
/**
|
@@ -656,7 +758,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
656 |
*
|
657 |
* @param array $output_title List of titles.
|
658 |
*/
|
659 |
-
$title = implode( '  
|
660 |
|
661 |
if ( empty( $title ) ) {
|
662 |
$title = esc_html__( 'Query Monitor', 'query-monitor' );
|
@@ -664,7 +766,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
664 |
|
665 |
$admin_bar_menu = array(
|
666 |
'top' => array(
|
667 |
-
'title'
|
668 |
'<span class="ab-icon">QM</span><span class="ab-label">%s</span>',
|
669 |
$title
|
670 |
),
|
@@ -681,6 +783,26 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
681 |
|
682 |
}
|
683 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
684 |
public function is_active() {
|
685 |
|
686 |
if ( ! self::user_can_view() ) {
|
@@ -691,8 +813,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
691 |
return false;
|
692 |
}
|
693 |
|
694 |
-
|
695 |
-
if ( QM_Util::is_async() && ( ! function_exists( 'is_customize_preview' ) || ! is_customize_preview() ) ) {
|
696 |
return false;
|
697 |
}
|
698 |
|
@@ -707,11 +828,6 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
707 |
}
|
708 |
}
|
709 |
|
710 |
-
// Don't dispatch during an iframed request, eg the plugin info modal or an upgrader action:
|
711 |
-
if ( defined( 'IFRAME_REQUEST' ) && IFRAME_REQUEST ) {
|
712 |
-
return false;
|
713 |
-
}
|
714 |
-
|
715 |
/** Back-compat filter. Please use `qm/dispatch/html` instead */
|
716 |
if ( ! apply_filters( 'qm/process', true, is_admin_bar_showing() ) ) {
|
717 |
return false;
|
@@ -721,8 +837,21 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
|
|
721 |
|
722 |
}
|
723 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
724 |
}
|
725 |
|
|
|
|
|
|
|
|
|
|
|
726 |
function register_qm_dispatcher_html( array $dispatchers, QM_Plugin $qm ) {
|
727 |
$dispatchers['html'] = new QM_Dispatcher_Html( $qm );
|
728 |
return $dispatchers;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Dispatcher_Html extends QM_Dispatcher {
|
13 |
|
14 |
/**
|
15 |
* Outputter instances.
|
16 |
*
|
17 |
+
* @var array<string, QM_Output_Html> Array of outputters.
|
18 |
*/
|
19 |
protected $outputters = array();
|
20 |
|
21 |
+
/**
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
public $id = 'html';
|
25 |
+
|
26 |
+
/**
|
27 |
+
* @var bool
|
28 |
+
*/
|
29 |
public $did_footer = false;
|
30 |
|
31 |
+
/**
|
32 |
+
* @var array<string, mixed[]>
|
33 |
+
*/
|
34 |
protected $admin_bar_menu = array();
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @var array<string, mixed[]>
|
38 |
+
*/
|
39 |
+
protected $panel_menu = array();
|
40 |
|
41 |
public function __construct( QM_Plugin $qm ) {
|
42 |
|
43 |
+
add_action( 'admin_bar_menu', array( $this, 'action_admin_bar_menu' ), 999 );
|
44 |
+
add_action( 'wp_ajax_qm_auth_on', array( $this, 'ajax_on' ) );
|
45 |
+
add_action( 'wp_ajax_qm_auth_off', array( $this, 'ajax_off' ) );
|
46 |
+
add_action( 'wp_ajax_qm_editor_set', array( $this, 'ajax_editor_set' ) );
|
47 |
add_action( 'wp_ajax_nopriv_qm_auth_off', array( $this, 'ajax_off' ) );
|
48 |
|
49 |
+
add_action( 'shutdown', array( $this, 'dispatch' ), 0 );
|
50 |
|
51 |
+
add_action( 'wp_footer', array( $this, 'action_footer' ) );
|
52 |
+
add_action( 'admin_footer', array( $this, 'action_footer' ) );
|
53 |
+
add_action( 'login_footer', array( $this, 'action_footer' ) );
|
54 |
+
add_action( 'gp_footer', array( $this, 'action_footer' ) );
|
55 |
|
56 |
parent::__construct( $qm );
|
57 |
|
58 |
}
|
59 |
|
60 |
+
/**
|
61 |
+
* @return void
|
62 |
+
*/
|
63 |
public function action_footer() {
|
64 |
$this->did_footer = true;
|
65 |
}
|
73 |
return ( is_ssl() && ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) ) );
|
74 |
}
|
75 |
|
76 |
+
/**
|
77 |
+
* @return void
|
78 |
+
*/
|
79 |
public function ajax_on() {
|
80 |
|
81 |
if ( ! current_user_can( 'view_query_monitor' ) || ! check_ajax_referer( 'qm-auth-on', 'nonce', false ) ) {
|
83 |
}
|
84 |
|
85 |
$expiration = time() + ( 2 * DAY_IN_SECONDS );
|
86 |
+
$secure = self::secure_cookie();
|
87 |
+
$cookie = wp_generate_auth_cookie( get_current_user_id(), $expiration, 'logged_in' );
|
88 |
|
89 |
setcookie( QM_COOKIE, $cookie, $expiration, COOKIEPATH, COOKIE_DOMAIN, $secure, false );
|
90 |
|
92 |
|
93 |
}
|
94 |
|
95 |
+
/**
|
96 |
+
* @return void
|
97 |
+
*/
|
98 |
public function ajax_off() {
|
99 |
|
100 |
if ( ! self::user_verified() || ! check_ajax_referer( 'qm-auth-off', 'nonce', false ) ) {
|
109 |
|
110 |
}
|
111 |
|
112 |
+
/**
|
113 |
+
* @return void
|
114 |
+
*/
|
115 |
public function ajax_editor_set() {
|
116 |
|
117 |
if ( ! current_user_can( 'view_query_monitor' ) || ! check_ajax_referer( 'qm-editor-set', 'nonce', false ) ) {
|
119 |
}
|
120 |
|
121 |
$expiration = time() + ( 2 * YEAR_IN_SECONDS );
|
122 |
+
$secure = self::secure_cookie();
|
123 |
+
$editor = wp_unslash( $_POST['editor'] );
|
124 |
|
125 |
setcookie( QM_EDITOR_COOKIE, $editor, $expiration, COOKIEPATH, COOKIE_DOMAIN, $secure, false );
|
126 |
|
128 |
|
129 |
}
|
130 |
|
131 |
+
/**
|
132 |
+
* @param WP_Admin_Bar $wp_admin_bar
|
133 |
+
* @return void
|
134 |
+
*/
|
135 |
public function action_admin_bar_menu( WP_Admin_Bar $wp_admin_bar ) {
|
136 |
|
137 |
if ( ! self::user_can_view() ) {
|
141 |
$title = __( 'Query Monitor', 'query-monitor' );
|
142 |
|
143 |
$wp_admin_bar->add_node( array(
|
144 |
+
'id' => 'query-monitor',
|
145 |
'title' => esc_html( $title ),
|
146 |
+
'href' => '#qm-overview',
|
147 |
) );
|
148 |
|
149 |
$wp_admin_bar->add_node( array(
|
150 |
'parent' => 'query-monitor',
|
151 |
+
'id' => 'query-monitor-placeholder',
|
152 |
+
'title' => esc_html( $title ),
|
153 |
+
'href' => '#qm-overview',
|
154 |
) );
|
155 |
|
156 |
}
|
157 |
|
158 |
+
/**
|
159 |
+
* @return void
|
160 |
+
*/
|
161 |
public function init() {
|
162 |
|
163 |
if ( ! self::user_can_view() ) {
|
164 |
return;
|
165 |
}
|
166 |
|
167 |
+
if ( ! self::request_supported() ) {
|
168 |
+
return;
|
169 |
+
}
|
170 |
+
|
171 |
if ( ! file_exists( $this->qm->plugin_path( 'assets/query-monitor.css' ) ) ) {
|
172 |
add_action( 'admin_notices', array( $this, 'build_warning' ) );
|
173 |
}
|
174 |
|
175 |
+
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ), -9999 );
|
176 |
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), -9999 );
|
177 |
add_action( 'login_enqueue_scripts', array( $this, 'enqueue_assets' ), -9999 );
|
178 |
add_action( 'enqueue_embed_scripts', array( $this, 'enqueue_assets' ), -9999 );
|
179 |
|
180 |
+
add_action( 'gp_head', array( $this, 'manually_print_assets' ), 11 );
|
181 |
|
182 |
parent::init();
|
183 |
}
|
184 |
|
185 |
+
/**
|
186 |
+
* @return void
|
187 |
+
*/
|
188 |
public function manually_print_assets() {
|
189 |
wp_print_scripts( array(
|
190 |
'query-monitor',
|
194 |
) );
|
195 |
}
|
196 |
|
197 |
+
/**
|
198 |
+
* @return void
|
199 |
+
*/
|
200 |
public function build_warning() {
|
201 |
printf(
|
202 |
'<div id="qm-built-nope" class="notice notice-error"><p>%s</p></div>',
|
212 |
);
|
213 |
}
|
214 |
|
215 |
+
/**
|
216 |
+
* @return void
|
217 |
+
*/
|
218 |
public function enqueue_assets() {
|
219 |
+
global $wp_locale;
|
220 |
|
221 |
$deps = array(
|
222 |
'jquery',
|
255 |
'qm_l10n',
|
256 |
array(
|
257 |
'ajax_error' => __( 'PHP Errors in Ajax Response', 'query-monitor' ),
|
258 |
+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
259 |
'auth_nonce' => array(
|
260 |
+
'on' => wp_create_nonce( 'qm-auth-on' ),
|
261 |
+
'off' => wp_create_nonce( 'qm-auth-off' ),
|
262 |
'editor-set' => wp_create_nonce( 'qm-editor-set' ),
|
263 |
),
|
264 |
'fatal_error' => __( 'PHP Fatal Error', 'query-monitor' ),
|
275 |
do_action( 'qm/output/enqueued-assets', $this );
|
276 |
}
|
277 |
|
278 |
+
/**
|
279 |
+
* @return void
|
280 |
+
*/
|
281 |
public function dispatch() {
|
|
|
282 |
if ( ! $this->should_dispatch() ) {
|
283 |
return;
|
284 |
}
|
285 |
|
286 |
+
if ( $this->ceased ) {
|
287 |
+
$admin_bar_menu = array(
|
288 |
+
'top' => array(
|
289 |
+
'title' => 'Query Monitor',
|
290 |
+
),
|
291 |
+
'sub' => array(
|
292 |
+
'ceased' => array(
|
293 |
+
'title' => esc_html__( 'Data collection ceased', 'query-monitor' ),
|
294 |
+
'id' => 'query-monitor-ceased',
|
295 |
+
'href' => '#',
|
296 |
+
),
|
297 |
+
),
|
298 |
+
);
|
299 |
+
|
300 |
+
$json = array(
|
301 |
+
'menu' => $admin_bar_menu,
|
302 |
+
);
|
303 |
+
|
304 |
+
echo '<!-- Begin Query Monitor output -->' . "\n\n";
|
305 |
+
echo '<script type="text/javascript">' . "\n\n";
|
306 |
+
echo 'var qm = ' . json_encode( $json ) . ';' . "\n\n";
|
307 |
+
echo '</script>' . "\n\n";
|
308 |
+
echo '<div id="query-monitor-ceased"></div>';
|
309 |
+
echo '<!-- End Query Monitor output -->' . "\n\n";
|
310 |
+
return;
|
311 |
+
}
|
312 |
+
|
313 |
+
$switched_locale = self::switch_to_locale( get_user_locale() );
|
314 |
|
315 |
$this->before_output();
|
316 |
|
334 |
$this->after_output();
|
335 |
|
336 |
if ( $switched_locale ) {
|
337 |
+
self::restore_previous_locale();
|
338 |
}
|
339 |
|
340 |
}
|
341 |
|
342 |
+
/**
|
343 |
+
* @return void
|
344 |
+
*/
|
345 |
protected function before_output() {
|
346 |
|
347 |
require_once $this->qm->plugin_path( 'output/Html.php' );
|
350 |
require_once $file;
|
351 |
}
|
352 |
|
353 |
+
/** @var QM_Output_Html[] */
|
354 |
+
$outputters = $this->get_outputters( 'html' );
|
355 |
+
|
356 |
+
$this->outputters = $outputters;
|
357 |
|
358 |
/**
|
359 |
* Filters the menu items shown in Query Monitor's admin toolbar menu.
|
377 |
$collector = $output->get_collector();
|
378 |
|
379 |
if ( ( ! empty( $collector->concerned_filters ) || ! empty( $collector->concerned_actions ) ) && isset( $this->panel_menu[ 'qm-' . $output_id ] ) ) {
|
380 |
+
$count = count( $collector->concerned_filters ) + count( $collector->concerned_actions );
|
381 |
$this->panel_menu[ 'qm-' . $output_id ]['children'][ 'qm-' . $output_id . '-concerned_hooks' ] = array(
|
382 |
+
'href' => esc_attr( '#' . $collector->id() . '-concerned_hooks' ),
|
383 |
+
'title' => sprintf(
|
384 |
+
/* translators: %s: Number of hooks */
|
385 |
+
__( 'Hooks in Use (%s)', 'query-monitor' ),
|
386 |
+
number_format_i18n( $count )
|
387 |
+
),
|
388 |
);
|
389 |
}
|
390 |
}
|
403 |
}
|
404 |
|
405 |
$json = array(
|
406 |
+
'menu' => $this->js_admin_bar_menu(),
|
407 |
'ajax_errors' => array(), # @TODO move this into the php_errors collector
|
408 |
);
|
409 |
|
478 |
|
479 |
}
|
480 |
|
481 |
+
/**
|
482 |
+
* @param string $id
|
483 |
+
* @param mixed[] $menu
|
484 |
+
* @return void
|
485 |
+
*/
|
486 |
protected function do_panel_menu_item( $id, array $menu ) {
|
487 |
printf(
|
488 |
'<li role="presentation"><button role="tab" data-qm-href="%1$s">%2$s</button>',
|
501 |
echo '</li>';
|
502 |
}
|
503 |
|
504 |
+
/**
|
505 |
+
* @return void
|
506 |
+
*/
|
507 |
protected function after_output() {
|
508 |
|
509 |
$state = self::user_verified() ? 'on' : 'off';
|
510 |
$editor = self::editor_cookie();
|
511 |
+
$text = array(
|
512 |
+
'on' => __( 'Clear authentication cookie', 'query-monitor' ),
|
513 |
'off' => __( 'Set authentication cookie', 'query-monitor' ),
|
514 |
);
|
515 |
|
540 |
echo '<select id="qm-editor-select" name="qm-editor-select" class="qm-filter">';
|
541 |
|
542 |
$editors = array(
|
543 |
+
'Default/Xdebug' => '',
|
544 |
+
'Atom' => 'atom',
|
545 |
+
'Netbeans' => 'netbeans',
|
546 |
+
'PhpStorm' => 'phpstorm',
|
547 |
+
'Sublime Text' => 'sublime',
|
548 |
+
'TextMate' => 'textmate',
|
549 |
'Visual Studio Code' => 'vscode',
|
550 |
);
|
551 |
|
563 |
|
564 |
echo '<div class="qm-boxed">';
|
565 |
$constants = array(
|
566 |
+
'QM_DARK_MODE' => array(
|
567 |
+
'label' => __( 'Enable dark mode for Query Monitor\'s interface.', 'query-monitor' ),
|
568 |
'default' => false,
|
569 |
),
|
570 |
+
'QM_DB_EXPENSIVE' => array(
|
571 |
+
'label' => __( 'If an individual database query takes longer than this time to execute, it\'s considered "slow" and triggers a warning.', 'query-monitor' ),
|
572 |
'default' => 0.05,
|
573 |
),
|
574 |
+
'QM_DISABLED' => array(
|
575 |
+
'label' => __( 'Disable Query Monitor entirely.', 'query-monitor' ),
|
576 |
'default' => false,
|
577 |
),
|
578 |
'QM_DISABLE_ERROR_HANDLER' => array(
|
579 |
+
'label' => __( 'Disable the handling of PHP errors.', 'query-monitor' ),
|
580 |
'default' => false,
|
581 |
),
|
582 |
+
'QM_ENABLE_CAPS_PANEL' => array(
|
583 |
+
'label' => __( 'Enable the Capability Checks panel.', 'query-monitor' ),
|
584 |
'default' => false,
|
585 |
),
|
586 |
+
'QM_HIDE_CORE_ACTIONS' => array(
|
587 |
+
'label' => __( 'Hide WordPress core on the Hooks & Actions panel.', 'query-monitor' ),
|
588 |
'default' => false,
|
589 |
),
|
590 |
+
'QM_HIDE_SELF' => array(
|
591 |
+
'label' => __( 'Hide Query Monitor itself from various panels. Set to false if you want to see how Query Monitor hooks into WordPress.', 'query-monitor' ),
|
592 |
'default' => true,
|
593 |
),
|
594 |
+
'QM_NO_JQUERY' => array(
|
595 |
+
'label' => __( 'Don\'t specify jQuery as a dependency of Query Monitor. If jQuery isn\'t enqueued then Query Monitor will still operate, but with some reduced functionality.', 'query-monitor' ),
|
596 |
'default' => false,
|
597 |
),
|
598 |
+
'QM_SHOW_ALL_HOOKS' => array(
|
599 |
+
'label' => __( 'In the Hooks & Actions panel, show every hook that has an action or filter attached (instead of every action hook that fired during the request).', 'query-monitor' ),
|
600 |
'default' => false,
|
601 |
),
|
602 |
+
'QM_DB_SYMLINK' => array(
|
603 |
+
'label' => __( 'Allow the wp-content/db.php file symlink to be put into place during activation. Set to false to prevent the symlink creation.', 'query-monitor' ),
|
604 |
+
'default' => true,
|
605 |
+
),
|
606 |
);
|
607 |
|
608 |
echo '<section>';
|
620 |
foreach ( $constants as $name => $constant ) {
|
621 |
echo '<dt><code>' . esc_html( $name ) . '</code></dt>';
|
622 |
echo '<dd>';
|
623 |
+
echo esc_html( $constant['label'] );
|
|
|
|
|
|
|
624 |
|
625 |
$default_value = $constant['default'];
|
626 |
if ( is_bool( $default_value ) ) {
|
631 |
printf(
|
632 |
/* translators: %s: Default value for a PHP constant */
|
633 |
esc_html__( 'Default value: %s', 'query-monitor' ),
|
634 |
+
'<code>' . esc_html( (string) $default_value ) . '</code>'
|
635 |
);
|
636 |
echo '</span>';
|
637 |
|
638 |
+
if ( defined( $name ) && ( constant( $name ) !== $constant['default'] ) ) {
|
639 |
$current_value = constant( $name );
|
640 |
if ( is_bool( $current_value ) ) {
|
641 |
$current_value = QM_Collector::format_bool_constant( $name );
|
642 |
}
|
|
|
643 |
|
|
|
644 |
echo '<br><span class="qm-info">';
|
645 |
printf(
|
646 |
/* translators: %s: Current value for a PHP constant */
|
717 |
|
718 |
}
|
719 |
|
720 |
+
/**
|
721 |
+
* @param mixed $var
|
722 |
+
* @return int|Exception
|
723 |
+
*/
|
724 |
public static function size( $var ) {
|
725 |
$start_memory = memory_get_usage();
|
726 |
|
733 |
return memory_get_usage() - $start_memory - ( PHP_INT_SIZE * 8 );
|
734 |
}
|
735 |
|
736 |
+
/**
|
737 |
+
* @return array<string, mixed>
|
738 |
+
*/
|
739 |
public function js_admin_bar_menu() {
|
740 |
|
741 |
/**
|
758 |
*
|
759 |
* @param array $output_title List of titles.
|
760 |
*/
|
761 |
+
$title = implode( ' ', apply_filters( 'qm/output/title', array() ) );
|
762 |
|
763 |
if ( empty( $title ) ) {
|
764 |
$title = esc_html__( 'Query Monitor', 'query-monitor' );
|
766 |
|
767 |
$admin_bar_menu = array(
|
768 |
'top' => array(
|
769 |
+
'title' => sprintf(
|
770 |
'<span class="ab-icon">QM</span><span class="ab-label">%s</span>',
|
771 |
$title
|
772 |
),
|
783 |
|
784 |
}
|
785 |
|
786 |
+
/**
|
787 |
+
* @return bool
|
788 |
+
*/
|
789 |
+
public static function request_supported() {
|
790 |
+
// Don't dispatch if this is an async request and not a customizer preview:
|
791 |
+
if ( QM_Util::is_async() && ( ! function_exists( 'is_customize_preview' ) || ! is_customize_preview() ) ) {
|
792 |
+
return false;
|
793 |
+
}
|
794 |
+
|
795 |
+
// Don't dispatch during an iframed request, eg the plugin info modal, an upgrader action, or the Customizer:
|
796 |
+
if ( defined( 'IFRAME_REQUEST' ) && IFRAME_REQUEST ) {
|
797 |
+
return false;
|
798 |
+
}
|
799 |
+
|
800 |
+
return true;
|
801 |
+
}
|
802 |
+
|
803 |
+
/**
|
804 |
+
* @return bool
|
805 |
+
*/
|
806 |
public function is_active() {
|
807 |
|
808 |
if ( ! self::user_can_view() ) {
|
813 |
return false;
|
814 |
}
|
815 |
|
816 |
+
if ( ! self::request_supported() ) {
|
|
|
817 |
return false;
|
818 |
}
|
819 |
|
828 |
}
|
829 |
}
|
830 |
|
|
|
|
|
|
|
|
|
|
|
831 |
/** Back-compat filter. Please use `qm/dispatch/html` instead */
|
832 |
if ( ! apply_filters( 'qm/process', true, is_admin_bar_showing() ) ) {
|
833 |
return false;
|
837 |
|
838 |
}
|
839 |
|
840 |
+
/**
|
841 |
+
* Cease without deactivating the dispatcher.
|
842 |
+
*
|
843 |
+
* @return void
|
844 |
+
*/
|
845 |
+
public function cease() {
|
846 |
+
$this->ceased = true;
|
847 |
+
}
|
848 |
}
|
849 |
|
850 |
+
/**
|
851 |
+
* @param array<string, QM_Dispatcher> $dispatchers
|
852 |
+
* @param QM_Plugin $qm
|
853 |
+
* @return array<string, QM_Dispatcher>
|
854 |
+
*/
|
855 |
function register_qm_dispatcher_html( array $dispatchers, QM_Plugin $qm ) {
|
856 |
$dispatchers['html'] = new QM_Dispatcher_Html( $qm );
|
857 |
return $dispatchers;
|
dispatchers/REST.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Dispatcher_REST extends QM_Dispatcher {
|
11 |
|
@@ -45,6 +47,9 @@ class QM_Dispatcher_REST extends QM_Dispatcher {
|
|
45 |
|
46 |
}
|
47 |
|
|
|
|
|
|
|
48 |
protected function before_output() {
|
49 |
|
50 |
require_once $this->qm->plugin_path( 'output/Headers.php' );
|
@@ -54,6 +59,9 @@ class QM_Dispatcher_REST extends QM_Dispatcher {
|
|
54 |
}
|
55 |
}
|
56 |
|
|
|
|
|
|
|
57 |
public function is_active() {
|
58 |
|
59 |
# If the headers have already been sent then we can't do anything about it
|
@@ -75,6 +83,11 @@ class QM_Dispatcher_REST extends QM_Dispatcher {
|
|
75 |
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
|
|
78 |
function register_qm_dispatcher_rest( array $dispatchers, QM_Plugin $qm ) {
|
79 |
$dispatchers['rest'] = new QM_Dispatcher_REST( $qm );
|
80 |
return $dispatchers;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Dispatcher_REST extends QM_Dispatcher {
|
13 |
|
47 |
|
48 |
}
|
49 |
|
50 |
+
/**
|
51 |
+
* @return void
|
52 |
+
*/
|
53 |
protected function before_output() {
|
54 |
|
55 |
require_once $this->qm->plugin_path( 'output/Headers.php' );
|
59 |
}
|
60 |
}
|
61 |
|
62 |
+
/**
|
63 |
+
* @return bool
|
64 |
+
*/
|
65 |
public function is_active() {
|
66 |
|
67 |
# If the headers have already been sent then we can't do anything about it
|
83 |
|
84 |
}
|
85 |
|
86 |
+
/**
|
87 |
+
* @param array<string, QM_Dispatcher> $dispatchers
|
88 |
+
* @param QM_Plugin $qm
|
89 |
+
* @return array<string, QM_Dispatcher>
|
90 |
+
*/
|
91 |
function register_qm_dispatcher_rest( array $dispatchers, QM_Plugin $qm ) {
|
92 |
$dispatchers['rest'] = new QM_Dispatcher_REST( $qm );
|
93 |
return $dispatchers;
|
dispatchers/REST_Envelope.php
CHANGED
@@ -18,9 +18,9 @@ class QM_Dispatcher_REST_Envelope extends QM_Dispatcher {
|
|
18 |
/**
|
19 |
* Filters the enveloped form of a REST API response to add QM's data.
|
20 |
*
|
21 |
-
* @param array
|
22 |
-
* @param WP_REST_Response
|
23 |
-
* @return array Envelope data.
|
24 |
*/
|
25 |
public function filter_rest_envelope_response( array $envelope, WP_REST_Response $response ) {
|
26 |
if ( ! $this->should_dispatch() ) {
|
@@ -33,7 +33,7 @@ class QM_Dispatcher_REST_Envelope extends QM_Dispatcher {
|
|
33 |
|
34 |
/* @var QM_Output_Raw[] */
|
35 |
foreach ( $this->get_outputters( 'raw' ) as $id => $output ) {
|
36 |
-
$data[ $id ] = $output->
|
37 |
}
|
38 |
|
39 |
$this->after_output();
|
@@ -43,6 +43,9 @@ class QM_Dispatcher_REST_Envelope extends QM_Dispatcher {
|
|
43 |
return $envelope;
|
44 |
}
|
45 |
|
|
|
|
|
|
|
46 |
protected function before_output() {
|
47 |
require_once $this->qm->plugin_path( 'output/Raw.php' );
|
48 |
|
@@ -51,6 +54,9 @@ class QM_Dispatcher_REST_Envelope extends QM_Dispatcher {
|
|
51 |
}
|
52 |
}
|
53 |
|
|
|
|
|
|
|
54 |
public function is_active() {
|
55 |
if ( ! self::user_can_view() ) {
|
56 |
return false;
|
@@ -61,6 +67,11 @@ class QM_Dispatcher_REST_Envelope extends QM_Dispatcher {
|
|
61 |
|
62 |
}
|
63 |
|
|
|
|
|
|
|
|
|
|
|
64 |
function register_qm_dispatcher_rest_envelope( array $dispatchers, QM_Plugin $qm ) {
|
65 |
$dispatchers['rest_envelope'] = new QM_Dispatcher_REST_Envelope( $qm );
|
66 |
return $dispatchers;
|
18 |
/**
|
19 |
* Filters the enveloped form of a REST API response to add QM's data.
|
20 |
*
|
21 |
+
* @param array<string, mixed> $envelope Envelope data.
|
22 |
+
* @param WP_REST_Response $response Original response data.
|
23 |
+
* @return array<string, mixed> Envelope data.
|
24 |
*/
|
25 |
public function filter_rest_envelope_response( array $envelope, WP_REST_Response $response ) {
|
26 |
if ( ! $this->should_dispatch() ) {
|
33 |
|
34 |
/* @var QM_Output_Raw[] */
|
35 |
foreach ( $this->get_outputters( 'raw' ) as $id => $output ) {
|
36 |
+
$data[ $id ] = $output->get_output();
|
37 |
}
|
38 |
|
39 |
$this->after_output();
|
43 |
return $envelope;
|
44 |
}
|
45 |
|
46 |
+
/**
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
protected function before_output() {
|
50 |
require_once $this->qm->plugin_path( 'output/Raw.php' );
|
51 |
|
54 |
}
|
55 |
}
|
56 |
|
57 |
+
/**
|
58 |
+
* @return bool
|
59 |
+
*/
|
60 |
public function is_active() {
|
61 |
if ( ! self::user_can_view() ) {
|
62 |
return false;
|
67 |
|
68 |
}
|
69 |
|
70 |
+
/**
|
71 |
+
* @param array<string, QM_Dispatcher> $dispatchers
|
72 |
+
* @param QM_Plugin $qm
|
73 |
+
* @return array<string, QM_Dispatcher>
|
74 |
+
*/
|
75 |
function register_qm_dispatcher_rest_envelope( array $dispatchers, QM_Plugin $qm ) {
|
76 |
$dispatchers['rest_envelope'] = new QM_Dispatcher_REST_Envelope( $qm );
|
77 |
return $dispatchers;
|
dispatchers/Redirect.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Dispatcher_Redirect extends QM_Dispatcher {
|
11 |
|
@@ -23,6 +25,7 @@ class QM_Dispatcher_Redirect extends QM_Dispatcher {
|
|
23 |
*
|
24 |
* @param string $location The path to redirect to.
|
25 |
* @param int $status Status code to use.
|
|
|
26 |
*/
|
27 |
public function filter_wp_redirect( $location, $status ) {
|
28 |
|
@@ -43,6 +46,9 @@ class QM_Dispatcher_Redirect extends QM_Dispatcher {
|
|
43 |
|
44 |
}
|
45 |
|
|
|
|
|
|
|
46 |
protected function before_output() {
|
47 |
|
48 |
require_once $this->qm->plugin_path( 'output/Headers.php' );
|
@@ -52,6 +58,9 @@ class QM_Dispatcher_Redirect extends QM_Dispatcher {
|
|
52 |
}
|
53 |
}
|
54 |
|
|
|
|
|
|
|
55 |
public function is_active() {
|
56 |
|
57 |
if ( ! self::user_can_view() ) {
|
@@ -80,6 +89,11 @@ class QM_Dispatcher_Redirect extends QM_Dispatcher {
|
|
80 |
|
81 |
}
|
82 |
|
|
|
|
|
|
|
|
|
|
|
83 |
function register_qm_dispatcher_redirect( array $dispatchers, QM_Plugin $qm ) {
|
84 |
$dispatchers['redirect'] = new QM_Dispatcher_Redirect( $qm );
|
85 |
return $dispatchers;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Dispatcher_Redirect extends QM_Dispatcher {
|
13 |
|
25 |
*
|
26 |
* @param string $location The path to redirect to.
|
27 |
* @param int $status Status code to use.
|
28 |
+
* @return string
|
29 |
*/
|
30 |
public function filter_wp_redirect( $location, $status ) {
|
31 |
|
46 |
|
47 |
}
|
48 |
|
49 |
+
/**
|
50 |
+
* @return void
|
51 |
+
*/
|
52 |
protected function before_output() {
|
53 |
|
54 |
require_once $this->qm->plugin_path( 'output/Headers.php' );
|
58 |
}
|
59 |
}
|
60 |
|
61 |
+
/**
|
62 |
+
* @return bool
|
63 |
+
*/
|
64 |
public function is_active() {
|
65 |
|
66 |
if ( ! self::user_can_view() ) {
|
89 |
|
90 |
}
|
91 |
|
92 |
+
/**
|
93 |
+
* @param array<string, QM_Dispatcher> $dispatchers
|
94 |
+
* @param QM_Plugin $qm
|
95 |
+
* @return array<string, QM_Dispatcher>
|
96 |
+
*/
|
97 |
function register_qm_dispatcher_redirect( array $dispatchers, QM_Plugin $qm ) {
|
98 |
$dispatchers['redirect'] = new QM_Dispatcher_Redirect( $qm );
|
99 |
return $dispatchers;
|
dispatchers/WP_Die.php
CHANGED
@@ -5,14 +5,21 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Dispatcher_WP_Die extends QM_Dispatcher {
|
11 |
|
12 |
-
|
13 |
-
|
|
|
|
|
14 |
|
15 |
-
|
|
|
|
|
|
|
16 |
|
17 |
public function __construct( QM_Plugin $qm ) {
|
18 |
add_action( 'shutdown', array( $this, 'dispatch' ), 0 );
|
@@ -22,14 +29,23 @@ class QM_Dispatcher_WP_Die extends QM_Dispatcher {
|
|
22 |
parent::__construct( $qm );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
|
|
25 |
public function filter_wp_die_handler( $handler ) {
|
26 |
$this->trace = new QM_Backtrace( array(
|
27 |
-
'
|
|
|
|
|
28 |
) );
|
29 |
|
30 |
return $handler;
|
31 |
}
|
32 |
|
|
|
|
|
|
|
33 |
public function dispatch() {
|
34 |
if ( ! $this->should_dispatch() ) {
|
35 |
return;
|
@@ -37,25 +53,15 @@ class QM_Dispatcher_WP_Die extends QM_Dispatcher {
|
|
37 |
|
38 |
require_once $this->qm->plugin_path( 'output/Html.php' );
|
39 |
|
40 |
-
$switched_locale =
|
41 |
-
$stack
|
42 |
-
$filtered_trace
|
43 |
-
|
44 |
-
// Ignore the `apply_filters('wp_die_handler')` stack frame:
|
45 |
-
array_shift( $filtered_trace );
|
46 |
|
47 |
foreach ( $filtered_trace as $i => $item ) {
|
48 |
$stack[] = QM_Output_Html::output_filename( $item['display'], $item['file'], $item['line'] );
|
49 |
}
|
50 |
|
51 |
-
if ( isset( $filtered_trace[ $i - 1 ] ) ) {
|
52 |
-
$culprit = $filtered_trace[ $i - 1 ];
|
53 |
-
} else {
|
54 |
-
$culprit = $filtered_trace[ $i ];
|
55 |
-
}
|
56 |
-
|
57 |
-
$component = QM_Backtrace::get_frame_component( $culprit );
|
58 |
-
|
59 |
printf(
|
60 |
// phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
|
61 |
'<link rel="stylesheet" href="%s" media="all" />',
|
@@ -117,7 +123,7 @@ class QM_Dispatcher_WP_Die extends QM_Dispatcher {
|
|
117 |
echo '<p>';
|
118 |
echo '<span class="dashicons dashicons-info" aria-hidden="true"></span>';
|
119 |
|
120 |
-
if ( $component ) {
|
121 |
$name = ( 'plugin' === $component->type ) ? $component->context : $component->name;
|
122 |
printf(
|
123 |
/* translators: %s: Plugin or theme name */
|
@@ -138,10 +144,13 @@ class QM_Dispatcher_WP_Die extends QM_Dispatcher {
|
|
138 |
echo '</div>';
|
139 |
|
140 |
if ( $switched_locale ) {
|
141 |
-
restore_previous_locale();
|
142 |
}
|
143 |
}
|
144 |
|
|
|
|
|
|
|
145 |
public function is_active() {
|
146 |
if ( ! $this->trace ) {
|
147 |
return false;
|
@@ -156,6 +165,11 @@ class QM_Dispatcher_WP_Die extends QM_Dispatcher {
|
|
156 |
|
157 |
}
|
158 |
|
|
|
|
|
|
|
|
|
|
|
159 |
function register_qm_dispatcher_wp_die( array $dispatchers, QM_Plugin $qm ) {
|
160 |
$dispatchers['wp_die'] = new QM_Dispatcher_WP_Die( $qm );
|
161 |
return $dispatchers;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Dispatcher_WP_Die extends QM_Dispatcher {
|
13 |
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
public $id = 'wp_die';
|
18 |
|
19 |
+
/**
|
20 |
+
* @var QM_Backtrace|null
|
21 |
+
*/
|
22 |
+
public $trace = null;
|
23 |
|
24 |
public function __construct( QM_Plugin $qm ) {
|
25 |
add_action( 'shutdown', array( $this, 'dispatch' ), 0 );
|
29 |
parent::__construct( $qm );
|
30 |
}
|
31 |
|
32 |
+
/**
|
33 |
+
* @param callable $handler
|
34 |
+
* @return callable
|
35 |
+
*/
|
36 |
public function filter_wp_die_handler( $handler ) {
|
37 |
$this->trace = new QM_Backtrace( array(
|
38 |
+
'ignore_hook' => array(
|
39 |
+
current_filter() => true,
|
40 |
+
),
|
41 |
) );
|
42 |
|
43 |
return $handler;
|
44 |
}
|
45 |
|
46 |
+
/**
|
47 |
+
* @return void
|
48 |
+
*/
|
49 |
public function dispatch() {
|
50 |
if ( ! $this->should_dispatch() ) {
|
51 |
return;
|
53 |
|
54 |
require_once $this->qm->plugin_path( 'output/Html.php' );
|
55 |
|
56 |
+
$switched_locale = self::switch_to_locale( get_user_locale() );
|
57 |
+
$stack = array();
|
58 |
+
$filtered_trace = $this->trace->get_filtered_trace();
|
59 |
+
$component = $this->trace->get_component();
|
|
|
|
|
60 |
|
61 |
foreach ( $filtered_trace as $i => $item ) {
|
62 |
$stack[] = QM_Output_Html::output_filename( $item['display'], $item['file'], $item['line'] );
|
63 |
}
|
64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
printf(
|
66 |
// phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
|
67 |
'<link rel="stylesheet" href="%s" media="all" />',
|
123 |
echo '<p>';
|
124 |
echo '<span class="dashicons dashicons-info" aria-hidden="true"></span>';
|
125 |
|
126 |
+
if ( 'unknown' !== $component->type ) {
|
127 |
$name = ( 'plugin' === $component->type ) ? $component->context : $component->name;
|
128 |
printf(
|
129 |
/* translators: %s: Plugin or theme name */
|
144 |
echo '</div>';
|
145 |
|
146 |
if ( $switched_locale ) {
|
147 |
+
self::restore_previous_locale();
|
148 |
}
|
149 |
}
|
150 |
|
151 |
+
/**
|
152 |
+
* @return bool
|
153 |
+
*/
|
154 |
public function is_active() {
|
155 |
if ( ! $this->trace ) {
|
156 |
return false;
|
165 |
|
166 |
}
|
167 |
|
168 |
+
/**
|
169 |
+
* @param array<string, QM_Dispatcher> $dispatchers
|
170 |
+
* @param QM_Plugin $qm
|
171 |
+
* @return array<string, QM_Dispatcher>
|
172 |
+
*/
|
173 |
function register_qm_dispatcher_wp_die( array $dispatchers, QM_Plugin $qm ) {
|
174 |
$dispatchers['wp_die'] = new QM_Dispatcher_WP_Die( $qm );
|
175 |
return $dispatchers;
|
output/Headers.php
CHANGED
@@ -6,7 +6,14 @@
|
|
6 |
*/
|
7 |
|
8 |
abstract class QM_Output_Headers extends QM_Output {
|
|
|
|
|
|
|
|
|
9 |
|
|
|
|
|
|
|
10 |
public function output() {
|
11 |
|
12 |
$id = $this->collector->id;
|
6 |
*/
|
7 |
|
8 |
abstract class QM_Output_Headers extends QM_Output {
|
9 |
+
/**
|
10 |
+
* @return array<string, mixed>
|
11 |
+
*/
|
12 |
+
abstract public function get_output();
|
13 |
|
14 |
+
/**
|
15 |
+
* @return void
|
16 |
+
*/
|
17 |
public function output() {
|
18 |
|
19 |
$id = $this->collector->id;
|
output/Html.php
CHANGED
@@ -7,21 +7,32 @@
|
|
7 |
|
8 |
abstract class QM_Output_Html extends QM_Output {
|
9 |
|
|
|
|
|
|
|
10 |
protected static $file_link_format = null;
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
protected $current_name = null;
|
14 |
|
|
|
|
|
|
|
15 |
public function name() {
|
16 |
-
|
17 |
-
esc_html( get_class( $this->collector ) . '::name()' ),
|
18 |
-
'3.5',
|
19 |
-
esc_html( get_class( $this ) . '::name()' )
|
20 |
-
);
|
21 |
-
|
22 |
-
return $this->collector->name();
|
23 |
}
|
24 |
|
|
|
|
|
|
|
|
|
25 |
public function admin_menu( array $menu ) {
|
26 |
|
27 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
@@ -31,6 +42,9 @@ abstract class QM_Output_Html extends QM_Output {
|
|
31 |
|
32 |
}
|
33 |
|
|
|
|
|
|
|
34 |
public function get_output() {
|
35 |
ob_start();
|
36 |
// compat until I convert all the existing outputters to use `get_output()`
|
@@ -39,6 +53,11 @@ abstract class QM_Output_Html extends QM_Output {
|
|
39 |
return $out;
|
40 |
}
|
41 |
|
|
|
|
|
|
|
|
|
|
|
42 |
protected function before_tabular_output( $id = null, $name = null ) {
|
43 |
if ( null === $id ) {
|
44 |
$id = $this->collector->id();
|
@@ -47,7 +66,7 @@ abstract class QM_Output_Html extends QM_Output {
|
|
47 |
$name = $this->name();
|
48 |
}
|
49 |
|
50 |
-
$this->current_id
|
51 |
$this->current_name = $name;
|
52 |
|
53 |
printf(
|
@@ -64,6 +83,9 @@ abstract class QM_Output_Html extends QM_Output {
|
|
64 |
);
|
65 |
}
|
66 |
|
|
|
|
|
|
|
67 |
protected function after_tabular_output() {
|
68 |
echo '</table>';
|
69 |
echo '</div>';
|
@@ -71,6 +93,11 @@ abstract class QM_Output_Html extends QM_Output {
|
|
71 |
$this->output_concerns();
|
72 |
}
|
73 |
|
|
|
|
|
|
|
|
|
|
|
74 |
protected function before_non_tabular_output( $id = null, $name = null ) {
|
75 |
if ( null === $id ) {
|
76 |
$id = $this->collector->id();
|
@@ -79,7 +106,7 @@ abstract class QM_Output_Html extends QM_Output {
|
|
79 |
$name = $this->name();
|
80 |
}
|
81 |
|
82 |
-
$this->current_id
|
83 |
$this->current_name = $name;
|
84 |
|
85 |
printf(
|
@@ -96,6 +123,9 @@ abstract class QM_Output_Html extends QM_Output {
|
|
96 |
);
|
97 |
}
|
98 |
|
|
|
|
|
|
|
99 |
protected function after_non_tabular_output() {
|
100 |
echo '</div>';
|
101 |
echo '</div>';
|
@@ -103,6 +133,9 @@ abstract class QM_Output_Html extends QM_Output {
|
|
103 |
$this->output_concerns();
|
104 |
}
|
105 |
|
|
|
|
|
|
|
106 |
protected function output_concerns() {
|
107 |
$concerns = array(
|
108 |
'concerned_actions' => array(
|
@@ -161,6 +194,11 @@ abstract class QM_Output_Html extends QM_Output {
|
|
161 |
echo '</div>';
|
162 |
}
|
163 |
|
|
|
|
|
|
|
|
|
|
|
164 |
protected function before_debug_bar_output( $id = null, $name = null ) {
|
165 |
if ( null === $id ) {
|
166 |
$id = $this->collector->id();
|
@@ -181,10 +219,17 @@ abstract class QM_Output_Html extends QM_Output {
|
|
181 |
);
|
182 |
}
|
183 |
|
|
|
|
|
|
|
184 |
protected function after_debug_bar_output() {
|
185 |
echo '</div>';
|
186 |
}
|
187 |
|
|
|
|
|
|
|
|
|
188 |
protected function build_notice( $notice ) {
|
189 |
$return = '<section>';
|
190 |
$return .= '<div class="qm-notice">';
|
@@ -197,6 +242,10 @@ abstract class QM_Output_Html extends QM_Output {
|
|
197 |
return $return;
|
198 |
}
|
199 |
|
|
|
|
|
|
|
|
|
200 |
public static function output_inner( $vars ) {
|
201 |
|
202 |
echo '<table>';
|
@@ -237,15 +286,20 @@ abstract class QM_Output_Html extends QM_Output {
|
|
237 |
* @param string[] $values Option values for this control.
|
238 |
* @param string $label Label text for the filter control.
|
239 |
* @param array $args {
|
240 |
-
* @type string
|
241 |
-
* @type
|
242 |
-
* @type
|
243 |
* }
|
|
|
|
|
|
|
|
|
|
|
244 |
* @return string Markup for the table filter controls.
|
245 |
*/
|
246 |
-
protected function build_filter( $name,
|
247 |
|
248 |
-
if ( empty( $values ) ) {
|
249 |
return esc_html( $label ); // Return label text, without being marked up as a label element.
|
250 |
}
|
251 |
|
@@ -257,16 +311,17 @@ abstract class QM_Output_Html extends QM_Output {
|
|
257 |
|
258 |
$args = array_merge( array(
|
259 |
'highlight' => '',
|
260 |
-
'prepend'
|
261 |
-
'append'
|
|
|
262 |
), $args );
|
263 |
|
264 |
-
$core_val = __( 'Core', 'query-monitor' );
|
265 |
$core_key = array_search( $core_val, $values, true );
|
266 |
|
267 |
if ( 'component' === $name && count( $values ) > 1 && false !== $core_key ) {
|
268 |
$args['append'][ $core_val ] = $core_val;
|
269 |
-
$args['append']['non-core']
|
270 |
unset( $values[ $core_key ] );
|
271 |
}
|
272 |
|
@@ -275,7 +330,7 @@ abstract class QM_Output_Html extends QM_Output {
|
|
275 |
$out = '<div class="qm-filter-container">';
|
276 |
$out .= '<label for="' . esc_attr( $filter_id ) . '">' . esc_html( $label ) . '</label>';
|
277 |
$out .= '<select id="' . esc_attr( $filter_id ) . '" class="qm-filter" data-filter="' . esc_attr( $name ) . '" data-highlight="' . esc_attr( $args['highlight'] ) . '">';
|
278 |
-
$out .= '<option value="">' .
|
279 |
|
280 |
if ( ! empty( $args['prepend'] ) ) {
|
281 |
foreach ( $args['prepend'] as $value => $label ) {
|
@@ -339,10 +394,14 @@ abstract class QM_Output_Html extends QM_Output {
|
|
339 |
return $out;
|
340 |
}
|
341 |
|
|
|
|
|
|
|
|
|
342 |
protected function menu( array $args ) {
|
343 |
|
344 |
return array_merge( array(
|
345 |
-
'id'
|
346 |
'href' => esc_attr( '#' . $this->collector->id() ),
|
347 |
), $args );
|
348 |
|
@@ -361,10 +420,10 @@ abstract class QM_Output_Html extends QM_Output {
|
|
361 |
$sql = trim( $sql );
|
362 |
|
363 |
$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';
|
364 |
-
$sql
|
365 |
|
366 |
-
$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';
|
367 |
-
$sql
|
368 |
|
369 |
return '<code>' . $sql . '</code>';
|
370 |
|
@@ -468,6 +527,9 @@ abstract class QM_Output_Html extends QM_Output {
|
|
468 |
}
|
469 |
}
|
470 |
|
|
|
|
|
|
|
471 |
public static function get_file_link_format() {
|
472 |
if ( ! isset( self::$file_link_format ) ) {
|
473 |
$format = ini_get( 'xdebug.file_link_format' );
|
@@ -485,7 +547,7 @@ abstract class QM_Output_Html extends QM_Output {
|
|
485 |
* @link https://querymonitor.com/blog/2019/02/clickable-stack-traces-and-function-names-in-query-monitor/
|
486 |
* @since 3.0.0
|
487 |
*
|
488 |
-
* @param string $format The format of the clickable file link.
|
489 |
*/
|
490 |
$format = apply_filters( 'qm/output/file_link_format', $format );
|
491 |
if ( empty( $format ) ) {
|
@@ -498,6 +560,9 @@ abstract class QM_Output_Html extends QM_Output {
|
|
498 |
return self::$file_link_format;
|
499 |
}
|
500 |
|
|
|
|
|
|
|
501 |
public static function get_file_path_map() {
|
502 |
/**
|
503 |
* Filters the file path mapping for clickable file links.
|
@@ -510,6 +575,9 @@ abstract class QM_Output_Html extends QM_Output {
|
|
510 |
return apply_filters( 'qm/output/file_path_map', array() );
|
511 |
}
|
512 |
|
|
|
|
|
|
|
513 |
public static function has_clickable_links() {
|
514 |
return ( false !== self::get_file_link_format() );
|
515 |
}
|
7 |
|
8 |
abstract class QM_Output_Html extends QM_Output {
|
9 |
|
10 |
+
/**
|
11 |
+
* @var string|false|null
|
12 |
+
*/
|
13 |
protected static $file_link_format = null;
|
14 |
|
15 |
+
/**
|
16 |
+
* @var string|null
|
17 |
+
*/
|
18 |
+
protected $current_id = null;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var string|null
|
22 |
+
*/
|
23 |
protected $current_name = null;
|
24 |
|
25 |
+
/**
|
26 |
+
* @return string
|
27 |
+
*/
|
28 |
public function name() {
|
29 |
+
return $this->collector->id;
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
}
|
31 |
|
32 |
+
/**
|
33 |
+
* @param array<string, mixed[]> $menu
|
34 |
+
* @return array<string, mixed[]>
|
35 |
+
*/
|
36 |
public function admin_menu( array $menu ) {
|
37 |
|
38 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
42 |
|
43 |
}
|
44 |
|
45 |
+
/**
|
46 |
+
* @return string
|
47 |
+
*/
|
48 |
public function get_output() {
|
49 |
ob_start();
|
50 |
// compat until I convert all the existing outputters to use `get_output()`
|
53 |
return $out;
|
54 |
}
|
55 |
|
56 |
+
/**
|
57 |
+
* @param string $id
|
58 |
+
* @param string $name
|
59 |
+
* @return void
|
60 |
+
*/
|
61 |
protected function before_tabular_output( $id = null, $name = null ) {
|
62 |
if ( null === $id ) {
|
63 |
$id = $this->collector->id();
|
66 |
$name = $this->name();
|
67 |
}
|
68 |
|
69 |
+
$this->current_id = $id;
|
70 |
$this->current_name = $name;
|
71 |
|
72 |
printf(
|
83 |
);
|
84 |
}
|
85 |
|
86 |
+
/**
|
87 |
+
* @return void
|
88 |
+
*/
|
89 |
protected function after_tabular_output() {
|
90 |
echo '</table>';
|
91 |
echo '</div>';
|
93 |
$this->output_concerns();
|
94 |
}
|
95 |
|
96 |
+
/**
|
97 |
+
* @param string $id
|
98 |
+
* @param string $name
|
99 |
+
* @return void
|
100 |
+
*/
|
101 |
protected function before_non_tabular_output( $id = null, $name = null ) {
|
102 |
if ( null === $id ) {
|
103 |
$id = $this->collector->id();
|
106 |
$name = $this->name();
|
107 |
}
|
108 |
|
109 |
+
$this->current_id = $id;
|
110 |
$this->current_name = $name;
|
111 |
|
112 |
printf(
|
123 |
);
|
124 |
}
|
125 |
|
126 |
+
/**
|
127 |
+
* @return void
|
128 |
+
*/
|
129 |
protected function after_non_tabular_output() {
|
130 |
echo '</div>';
|
131 |
echo '</div>';
|
133 |
$this->output_concerns();
|
134 |
}
|
135 |
|
136 |
+
/**
|
137 |
+
* @return void
|
138 |
+
*/
|
139 |
protected function output_concerns() {
|
140 |
$concerns = array(
|
141 |
'concerned_actions' => array(
|
194 |
echo '</div>';
|
195 |
}
|
196 |
|
197 |
+
/**
|
198 |
+
* @param string $id
|
199 |
+
* @param string $name
|
200 |
+
* @return void
|
201 |
+
*/
|
202 |
protected function before_debug_bar_output( $id = null, $name = null ) {
|
203 |
if ( null === $id ) {
|
204 |
$id = $this->collector->id();
|
219 |
);
|
220 |
}
|
221 |
|
222 |
+
/**
|
223 |
+
* @return void
|
224 |
+
*/
|
225 |
protected function after_debug_bar_output() {
|
226 |
echo '</div>';
|
227 |
}
|
228 |
|
229 |
+
/**
|
230 |
+
* @param string $notice
|
231 |
+
* @return string
|
232 |
+
*/
|
233 |
protected function build_notice( $notice ) {
|
234 |
$return = '<section>';
|
235 |
$return .= '<div class="qm-notice">';
|
242 |
return $return;
|
243 |
}
|
244 |
|
245 |
+
/**
|
246 |
+
* @param array<string, mixed> $vars
|
247 |
+
* @return void
|
248 |
+
*/
|
249 |
public static function output_inner( $vars ) {
|
250 |
|
251 |
echo '<table>';
|
286 |
* @param string[] $values Option values for this control.
|
287 |
* @param string $label Label text for the filter control.
|
288 |
* @param array $args {
|
289 |
+
* @type string $highlight The name for the `data-` attributes that get highlighted by this control.
|
290 |
+
* @type string[] $prepend Associative array of options to prepend to the list of values.
|
291 |
+
* @type string[] $append Associative array of options to append to the list of values.
|
292 |
* }
|
293 |
+
* @phpstan-param array{
|
294 |
+
* highlight?: string,
|
295 |
+
* prepend?: array<string, string>,
|
296 |
+
* append?: array<string, string>,
|
297 |
+
* } $args
|
298 |
* @return string Markup for the table filter controls.
|
299 |
*/
|
300 |
+
protected function build_filter( $name, $values, $label, $args = array() ) {
|
301 |
|
302 |
+
if ( empty( $values ) || ! is_array( $values ) ) {
|
303 |
return esc_html( $label ); // Return label text, without being marked up as a label element.
|
304 |
}
|
305 |
|
311 |
|
312 |
$args = array_merge( array(
|
313 |
'highlight' => '',
|
314 |
+
'prepend' => array(),
|
315 |
+
'append' => array(),
|
316 |
+
'all' => _x( 'All', '"All" option for filters', 'query-monitor' ),
|
317 |
), $args );
|
318 |
|
319 |
+
$core_val = __( 'WordPress Core', 'query-monitor' );
|
320 |
$core_key = array_search( $core_val, $values, true );
|
321 |
|
322 |
if ( 'component' === $name && count( $values ) > 1 && false !== $core_key ) {
|
323 |
$args['append'][ $core_val ] = $core_val;
|
324 |
+
$args['append']['non-core'] = __( 'Non-WordPress Core', 'query-monitor' );
|
325 |
unset( $values[ $core_key ] );
|
326 |
}
|
327 |
|
330 |
$out = '<div class="qm-filter-container">';
|
331 |
$out .= '<label for="' . esc_attr( $filter_id ) . '">' . esc_html( $label ) . '</label>';
|
332 |
$out .= '<select id="' . esc_attr( $filter_id ) . '" class="qm-filter" data-filter="' . esc_attr( $name ) . '" data-highlight="' . esc_attr( $args['highlight'] ) . '">';
|
333 |
+
$out .= '<option value="">' . esc_html( $args['all'] ) . '</option>';
|
334 |
|
335 |
if ( ! empty( $args['prepend'] ) ) {
|
336 |
foreach ( $args['prepend'] as $value => $label ) {
|
394 |
return $out;
|
395 |
}
|
396 |
|
397 |
+
/**
|
398 |
+
* @param array<string, mixed> $args
|
399 |
+
* @return array<string, mixed>
|
400 |
+
*/
|
401 |
protected function menu( array $args ) {
|
402 |
|
403 |
return array_merge( array(
|
404 |
+
'id' => esc_attr( "query-monitor-{$this->collector->id}" ),
|
405 |
'href' => esc_attr( '#' . $this->collector->id() ),
|
406 |
), $args );
|
407 |
|
420 |
$sql = trim( $sql );
|
421 |
|
422 |
$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';
|
423 |
+
$sql = preg_replace( '# (' . $regex . ') #', '<br> $1 ', $sql );
|
424 |
|
425 |
+
$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|FORCE|FOREIGN|FORCE|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';
|
426 |
+
$sql = preg_replace( '#' . $keywords . '#', '<b>$0</b>', $sql );
|
427 |
|
428 |
return '<code>' . $sql . '</code>';
|
429 |
|
527 |
}
|
528 |
}
|
529 |
|
530 |
+
/**
|
531 |
+
* @return string|false
|
532 |
+
*/
|
533 |
public static function get_file_link_format() {
|
534 |
if ( ! isset( self::$file_link_format ) ) {
|
535 |
$format = ini_get( 'xdebug.file_link_format' );
|
547 |
* @link https://querymonitor.com/blog/2019/02/clickable-stack-traces-and-function-names-in-query-monitor/
|
548 |
* @since 3.0.0
|
549 |
*
|
550 |
+
* @param string|false $format The format of the clickable file link, or false if there is none.
|
551 |
*/
|
552 |
$format = apply_filters( 'qm/output/file_link_format', $format );
|
553 |
if ( empty( $format ) ) {
|
560 |
return self::$file_link_format;
|
561 |
}
|
562 |
|
563 |
+
/**
|
564 |
+
* @return array<string, string>
|
565 |
+
*/
|
566 |
public static function get_file_path_map() {
|
567 |
/**
|
568 |
* Filters the file path mapping for clickable file links.
|
575 |
return apply_filters( 'qm/output/file_path_map', array() );
|
576 |
}
|
577 |
|
578 |
+
/**
|
579 |
+
* @return bool
|
580 |
+
*/
|
581 |
public static function has_clickable_links() {
|
582 |
return ( false !== self::get_file_link_format() );
|
583 |
}
|
output/Raw.php
CHANGED
@@ -6,9 +6,8 @@
|
|
6 |
*/
|
7 |
|
8 |
abstract class QM_Output_Raw extends QM_Output {
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
}
|
6 |
*/
|
7 |
|
8 |
abstract class QM_Output_Raw extends QM_Output {
|
9 |
+
/**
|
10 |
+
* @return array<string, mixed>
|
11 |
+
*/
|
12 |
+
abstract public function get_output();
|
|
|
13 |
}
|
output/headers/overview.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Headers_Overview extends QM_Output_Headers {
|
11 |
|
@@ -16,9 +18,12 @@ class QM_Output_Headers_Overview extends QM_Output_Headers {
|
|
16 |
*/
|
17 |
protected $collector;
|
18 |
|
|
|
|
|
|
|
19 |
public function get_output() {
|
20 |
|
21 |
-
$data
|
22 |
$headers = array();
|
23 |
|
24 |
$headers['time_taken'] = number_format_i18n( $data['time_taken'], 4 );
|
@@ -49,6 +54,11 @@ class QM_Output_Headers_Overview extends QM_Output_Headers {
|
|
49 |
|
50 |
}
|
51 |
|
|
|
|
|
|
|
|
|
|
|
52 |
function register_qm_output_headers_overview( array $output, QM_Collectors $collectors ) {
|
53 |
$collector = QM_Collectors::get( 'overview' );
|
54 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Headers_Overview extends QM_Output_Headers {
|
13 |
|
18 |
*/
|
19 |
protected $collector;
|
20 |
|
21 |
+
/**
|
22 |
+
* @return array<string, mixed>
|
23 |
+
*/
|
24 |
public function get_output() {
|
25 |
|
26 |
+
$data = $this->collector->get_data();
|
27 |
$headers = array();
|
28 |
|
29 |
$headers['time_taken'] = number_format_i18n( $data['time_taken'], 4 );
|
54 |
|
55 |
}
|
56 |
|
57 |
+
/**
|
58 |
+
* @param array<string, QM_Output> $output
|
59 |
+
* @param QM_Collectors $collectors
|
60 |
+
* @return array<string, QM_Output>
|
61 |
+
*/
|
62 |
function register_qm_output_headers_overview( array $output, QM_Collectors $collectors ) {
|
63 |
$collector = QM_Collectors::get( 'overview' );
|
64 |
if ( $collector ) {
|
output/headers/php_errors.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
|
11 |
|
@@ -16,9 +18,12 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
|
|
16 |
*/
|
17 |
protected $collector;
|
18 |
|
|
|
|
|
|
|
19 |
public function get_output() {
|
20 |
|
21 |
-
$data
|
22 |
$headers = array();
|
23 |
|
24 |
if ( empty( $data['errors'] ) ) {
|
@@ -37,23 +42,23 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
|
|
37 |
# separately in each output.
|
38 |
if ( $error['trace'] ) {
|
39 |
$component = $error['trace']->get_component()->name;
|
40 |
-
$stack
|
41 |
} else {
|
42 |
$component = __( 'Unknown', 'query-monitor' );
|
43 |
-
$stack
|
44 |
}
|
45 |
|
46 |
$output_error = array(
|
47 |
-
'key'
|
48 |
-
'type'
|
49 |
-
'message'
|
50 |
-
'file'
|
51 |
-
'line'
|
52 |
-
'stack'
|
53 |
'component' => $component,
|
54 |
);
|
55 |
|
56 |
-
$key
|
57 |
$headers[ $key ] = json_encode( $output_error );
|
58 |
|
59 |
}
|
@@ -69,6 +74,11 @@ class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
|
|
69 |
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
72 |
function register_qm_output_headers_php_errors( array $output, QM_Collectors $collectors ) {
|
73 |
$collector = QM_Collectors::get( 'php_errors' );
|
74 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Headers_PHP_Errors extends QM_Output_Headers {
|
13 |
|
18 |
*/
|
19 |
protected $collector;
|
20 |
|
21 |
+
/**
|
22 |
+
* @return array<string, mixed>
|
23 |
+
*/
|
24 |
public function get_output() {
|
25 |
|
26 |
+
$data = $this->collector->get_data();
|
27 |
$headers = array();
|
28 |
|
29 |
if ( empty( $data['errors'] ) ) {
|
42 |
# separately in each output.
|
43 |
if ( $error['trace'] ) {
|
44 |
$component = $error['trace']->get_component()->name;
|
45 |
+
$stack = $error['trace']->get_stack();
|
46 |
} else {
|
47 |
$component = __( 'Unknown', 'query-monitor' );
|
48 |
+
$stack = array();
|
49 |
}
|
50 |
|
51 |
$output_error = array(
|
52 |
+
'key' => $error_key,
|
53 |
+
'type' => $error['type'],
|
54 |
+
'message' => $error['message'],
|
55 |
+
'file' => QM_Util::standard_dir( $error['file'], '' ),
|
56 |
+
'line' => $error['line'],
|
57 |
+
'stack' => $stack,
|
58 |
'component' => $component,
|
59 |
);
|
60 |
|
61 |
+
$key = sprintf( 'error-%d', $count );
|
62 |
$headers[ $key ] = json_encode( $output_error );
|
63 |
|
64 |
}
|
74 |
|
75 |
}
|
76 |
|
77 |
+
/**
|
78 |
+
* @param array<string, QM_Output> $output
|
79 |
+
* @param QM_Collectors $collectors
|
80 |
+
* @return array<string, QM_Output>
|
81 |
+
*/
|
82 |
function register_qm_output_headers_php_errors( array $output, QM_Collectors $collectors ) {
|
83 |
$collector = QM_Collectors::get( 'php_errors' );
|
84 |
if ( $collector ) {
|
output/headers/redirects.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Headers_Redirects extends QM_Output_Headers {
|
11 |
|
@@ -16,9 +18,12 @@ class QM_Output_Headers_Redirects extends QM_Output_Headers {
|
|
16 |
*/
|
17 |
protected $collector;
|
18 |
|
|
|
|
|
|
|
19 |
public function get_output() {
|
20 |
|
21 |
-
$data
|
22 |
$headers = array();
|
23 |
|
24 |
if ( empty( $data['trace'] ) ) {
|
@@ -32,6 +37,11 @@ class QM_Output_Headers_Redirects extends QM_Output_Headers {
|
|
32 |
|
33 |
}
|
34 |
|
|
|
|
|
|
|
|
|
|
|
35 |
function register_qm_output_headers_redirects( array $output, QM_Collectors $collectors ) {
|
36 |
$collector = QM_Collectors::get( 'redirects' );
|
37 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Headers_Redirects extends QM_Output_Headers {
|
13 |
|
18 |
*/
|
19 |
protected $collector;
|
20 |
|
21 |
+
/**
|
22 |
+
* @return array<string, mixed>
|
23 |
+
*/
|
24 |
public function get_output() {
|
25 |
|
26 |
+
$data = $this->collector->get_data();
|
27 |
$headers = array();
|
28 |
|
29 |
if ( empty( $data['trace'] ) ) {
|
37 |
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* @param array<string, QM_Output> $output
|
42 |
+
* @param QM_Collectors $collectors
|
43 |
+
* @return array<string, QM_Output>
|
44 |
+
*/
|
45 |
function register_qm_output_headers_redirects( array $output, QM_Collectors $collectors ) {
|
46 |
$collector = QM_Collectors::get( 'redirects' );
|
47 |
if ( $collector ) {
|
output/html/admin.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Admin extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Admin extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 60 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Admin Screen', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -111,6 +119,11 @@ class QM_Output_Html_Admin extends QM_Output_Html {
|
|
111 |
|
112 |
}
|
113 |
|
|
|
|
|
|
|
|
|
|
|
114 |
function register_qm_output_html_admin( array $output, QM_Collectors $collectors ) {
|
115 |
if ( ! is_admin() ) {
|
116 |
return $output;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Admin extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 60 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Admin Screen', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
119 |
|
120 |
}
|
121 |
|
122 |
+
/**
|
123 |
+
* @param array<string, QM_Output> $output
|
124 |
+
* @param QM_Collectors $collectors
|
125 |
+
* @return array<string, QM_Output>
|
126 |
+
*/
|
127 |
function register_qm_output_html_admin( array $output, QM_Collectors $collectors ) {
|
128 |
if ( ! is_admin() ) {
|
129 |
return $output;
|
output/html/assets.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
11 |
|
@@ -18,30 +20,40 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
18 |
|
19 |
public function __construct( QM_Collector $collector ) {
|
20 |
parent::__construct( $collector );
|
21 |
-
add_filter( 'qm/output/menus',
|
22 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
25 |
abstract public function get_type_labels();
|
26 |
|
|
|
|
|
|
|
27 |
public function output() {
|
28 |
|
29 |
$data = $this->collector->get_data();
|
|
|
30 |
|
31 |
if ( empty( $data['assets'] ) ) {
|
|
|
|
|
|
|
|
|
32 |
return;
|
33 |
}
|
34 |
|
35 |
$position_labels = array(
|
36 |
// @TODO translator comments or context:
|
37 |
'missing' => __( 'Missing', 'query-monitor' ),
|
38 |
-
'broken'
|
39 |
-
'header'
|
40 |
-
'footer'
|
41 |
);
|
42 |
|
43 |
-
$
|
44 |
-
$this->type = $this->collector->get_dependency_type();
|
45 |
|
46 |
$hosts = array(
|
47 |
__( 'Other', 'query-monitor' ),
|
@@ -59,14 +71,14 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
59 |
'local' => $data['host'],
|
60 |
),
|
61 |
);
|
62 |
-
echo $this->build_filter( $
|
63 |
echo '</th>';
|
64 |
echo '<th scope="col">' . esc_html__( 'Source', 'query-monitor' ) . '</th>';
|
65 |
echo '<th scope="col" class="qm-filterable-column">';
|
66 |
-
echo $this->build_filter( $
|
67 |
echo '</th>';
|
68 |
echo '<th scope="col" class="qm-filterable-column">';
|
69 |
-
echo $this->build_filter( $
|
70 |
echo '</th>';
|
71 |
echo '<th scope="col">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
|
72 |
echo '</tr>';
|
@@ -100,14 +112,20 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
100 |
$this->after_tabular_output();
|
101 |
}
|
102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
protected function dependency_row( $handle, array $asset, $label ) {
|
104 |
$data = $this->collector->get_data();
|
105 |
|
106 |
-
$highlight_deps
|
107 |
$highlight_dependents = array_map( array( $this, '_prefix_type' ), $asset['dependents'] );
|
108 |
|
109 |
$dependencies_list = implode( ' ', $asset['dependencies'] );
|
110 |
-
$dependents_list
|
111 |
|
112 |
$dependency_output = array();
|
113 |
|
@@ -134,7 +152,9 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
134 |
$class = 'qm-warn';
|
135 |
}
|
136 |
|
137 |
-
|
|
|
|
|
138 |
echo '<td class="qm-nowrap">';
|
139 |
|
140 |
if ( $asset['warning'] ) {
|
@@ -144,7 +164,7 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
144 |
echo esc_html( $label );
|
145 |
echo '</td>';
|
146 |
|
147 |
-
$host
|
148 |
$parts = explode( '.', $host );
|
149 |
|
150 |
foreach ( $parts as $k => $part ) {
|
@@ -155,6 +175,10 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
155 |
|
156 |
$host = implode( '.', $parts );
|
157 |
|
|
|
|
|
|
|
|
|
158 |
echo '<td class="qm-nowrap qm-ltr">' . esc_html( $handle ) . '</td>';
|
159 |
echo '<td class="qm-nowrap qm-ltr">' . esc_html( $host ) . '</td>';
|
160 |
echo '<td class="qm-ltr">';
|
@@ -192,10 +216,18 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
192 |
echo '</tr>';
|
193 |
}
|
194 |
|
|
|
|
|
|
|
|
|
195 |
public function _prefix_type( $val ) {
|
196 |
-
return $this->
|
197 |
}
|
198 |
|
|
|
|
|
|
|
|
|
199 |
public function admin_class( array $class ) {
|
200 |
|
201 |
$data = $this->collector->get_data();
|
@@ -208,6 +240,10 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
208 |
|
209 |
}
|
210 |
|
|
|
|
|
|
|
|
|
211 |
public function admin_menu( array $menu ) {
|
212 |
|
213 |
$data = $this->collector->get_data();
|
@@ -224,15 +260,15 @@ abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
|
224 |
|
225 |
$args = array(
|
226 |
'title' => esc_html( $label ),
|
227 |
-
'id'
|
228 |
-
'href'
|
229 |
);
|
230 |
|
231 |
if ( ! empty( $data['broken'] ) || ! empty( $data['missing'] ) ) {
|
232 |
$args['meta']['classname'] = 'qm-error';
|
233 |
}
|
234 |
|
235 |
-
$id
|
236 |
$menu[ $id ] = $this->menu( $args );
|
237 |
|
238 |
return $menu;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
abstract class QM_Output_Html_Assets extends QM_Output_Html {
|
13 |
|
20 |
|
21 |
public function __construct( QM_Collector $collector ) {
|
22 |
parent::__construct( $collector );
|
23 |
+
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 70 );
|
24 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
+
* @return array<string, string>
|
29 |
+
*/
|
30 |
abstract public function get_type_labels();
|
31 |
|
32 |
+
/**
|
33 |
+
* @return void
|
34 |
+
*/
|
35 |
public function output() {
|
36 |
|
37 |
$data = $this->collector->get_data();
|
38 |
+
$type_label = $this->get_type_labels();
|
39 |
|
40 |
if ( empty( $data['assets'] ) ) {
|
41 |
+
$this->before_non_tabular_output();
|
42 |
+
$notice = esc_html( $type_label['none'] );
|
43 |
+
echo $this->build_notice( $notice ); // WPCS: XSS ok.
|
44 |
+
$this->after_non_tabular_output();
|
45 |
return;
|
46 |
}
|
47 |
|
48 |
$position_labels = array(
|
49 |
// @TODO translator comments or context:
|
50 |
'missing' => __( 'Missing', 'query-monitor' ),
|
51 |
+
'broken' => __( 'Missing Dependencies', 'query-monitor' ),
|
52 |
+
'header' => __( 'Header', 'query-monitor' ),
|
53 |
+
'footer' => __( 'Footer', 'query-monitor' ),
|
54 |
);
|
55 |
|
56 |
+
$type = $this->collector->get_dependency_type();
|
|
|
57 |
|
58 |
$hosts = array(
|
59 |
__( 'Other', 'query-monitor' ),
|
71 |
'local' => $data['host'],
|
72 |
),
|
73 |
);
|
74 |
+
echo $this->build_filter( $type . '-host', $hosts, __( 'Host', 'query-monitor' ), $args ); // WPCS: XSS ok.
|
75 |
echo '</th>';
|
76 |
echo '<th scope="col">' . esc_html__( 'Source', 'query-monitor' ) . '</th>';
|
77 |
echo '<th scope="col" class="qm-filterable-column">';
|
78 |
+
echo $this->build_filter( $type . '-dependencies', $data['dependencies'], __( 'Dependencies', 'query-monitor' ) ); // WPCS: XSS ok.
|
79 |
echo '</th>';
|
80 |
echo '<th scope="col" class="qm-filterable-column">';
|
81 |
+
echo $this->build_filter( $type . '-dependents', $data['dependents'], __( 'Dependents', 'query-monitor' ) ); // WPCS: XSS ok.
|
82 |
echo '</th>';
|
83 |
echo '<th scope="col">' . esc_html__( 'Version', 'query-monitor' ) . '</th>';
|
84 |
echo '</tr>';
|
112 |
$this->after_tabular_output();
|
113 |
}
|
114 |
|
115 |
+
/**
|
116 |
+
* @param string $handle
|
117 |
+
* @param array<string, mixed> $asset
|
118 |
+
* @param string $label
|
119 |
+
* @return void
|
120 |
+
*/
|
121 |
protected function dependency_row( $handle, array $asset, $label ) {
|
122 |
$data = $this->collector->get_data();
|
123 |
|
124 |
+
$highlight_deps = array_map( array( $this, '_prefix_type' ), $asset['dependencies'] );
|
125 |
$highlight_dependents = array_map( array( $this, '_prefix_type' ), $asset['dependents'] );
|
126 |
|
127 |
$dependencies_list = implode( ' ', $asset['dependencies'] );
|
128 |
+
$dependents_list = implode( ' ', $asset['dependents'] );
|
129 |
|
130 |
$dependency_output = array();
|
131 |
|
152 |
$class = 'qm-warn';
|
153 |
}
|
154 |
|
155 |
+
$type = $this->collector->get_dependency_type();
|
156 |
+
|
157 |
+
echo '<tr data-qm-subject="' . esc_attr( $type . '-' . $handle ) . '" data-qm-' . esc_attr( $type ) . '-host="' . esc_attr( $qm_host ) . '" data-qm-' . esc_attr( $type ) . '-dependents="' . esc_attr( $dependents_list ) . '" data-qm-' . esc_attr( $type ) . '-dependencies="' . esc_attr( $dependencies_list ) . '" class="' . esc_attr( $class ) . '">';
|
158 |
echo '<td class="qm-nowrap">';
|
159 |
|
160 |
if ( $asset['warning'] ) {
|
164 |
echo esc_html( $label );
|
165 |
echo '</td>';
|
166 |
|
167 |
+
$host = $asset['host'];
|
168 |
$parts = explode( '.', $host );
|
169 |
|
170 |
foreach ( $parts as $k => $part ) {
|
175 |
|
176 |
$host = implode( '.', $parts );
|
177 |
|
178 |
+
if ( ! empty( $asset['port'] ) ) {
|
179 |
+
$host = "{$host}:{$asset['port']}";
|
180 |
+
}
|
181 |
+
|
182 |
echo '<td class="qm-nowrap qm-ltr">' . esc_html( $handle ) . '</td>';
|
183 |
echo '<td class="qm-nowrap qm-ltr">' . esc_html( $host ) . '</td>';
|
184 |
echo '<td class="qm-ltr">';
|
216 |
echo '</tr>';
|
217 |
}
|
218 |
|
219 |
+
/**
|
220 |
+
* @param string $val
|
221 |
+
* @return string
|
222 |
+
*/
|
223 |
public function _prefix_type( $val ) {
|
224 |
+
return $this->collector->get_dependency_type() . '-' . $val;
|
225 |
}
|
226 |
|
227 |
+
/**
|
228 |
+
* @param array<int, string> $class
|
229 |
+
* @return array<int, string>
|
230 |
+
*/
|
231 |
public function admin_class( array $class ) {
|
232 |
|
233 |
$data = $this->collector->get_data();
|
240 |
|
241 |
}
|
242 |
|
243 |
+
/**
|
244 |
+
* @param array<string, mixed[]> $menu
|
245 |
+
* @return array<string, mixed[]>
|
246 |
+
*/
|
247 |
public function admin_menu( array $menu ) {
|
248 |
|
249 |
$data = $this->collector->get_data();
|
260 |
|
261 |
$args = array(
|
262 |
'title' => esc_html( $label ),
|
263 |
+
'id' => esc_attr( "query-monitor-{$this->collector->id}" ),
|
264 |
+
'href' => esc_attr( '#' . $this->collector->id() ),
|
265 |
);
|
266 |
|
267 |
if ( ! empty( $data['broken'] ) || ! empty( $data['missing'] ) ) {
|
268 |
$args['meta']['classname'] = 'qm-error';
|
269 |
}
|
270 |
|
271 |
+
$id = $this->collector->id();
|
272 |
$menu[ $id ] = $this->menu( $args );
|
273 |
|
274 |
return $menu;
|
output/html/assets_scripts.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Assets_Scripts extends QM_Output_Html_Assets {
|
11 |
|
@@ -16,22 +18,34 @@ class QM_Output_Html_Assets_Scripts extends QM_Output_Html_Assets {
|
|
16 |
*/
|
17 |
protected $collector;
|
18 |
|
|
|
|
|
|
|
19 |
public function name() {
|
20 |
return __( 'Scripts', 'query-monitor' );
|
21 |
}
|
22 |
|
|
|
|
|
|
|
23 |
public function get_type_labels() {
|
24 |
return array(
|
25 |
/* translators: %s: Total number of enqueued scripts */
|
26 |
-
'total'
|
27 |
'plural' => __( 'Scripts', 'query-monitor' ),
|
28 |
/* translators: %s: Total number of enqueued scripts */
|
29 |
-
'count'
|
|
|
30 |
);
|
31 |
}
|
32 |
|
33 |
}
|
34 |
|
|
|
|
|
|
|
|
|
|
|
35 |
function register_qm_output_html_assets_scripts( array $output, QM_Collectors $collectors ) {
|
36 |
$collector = QM_Collectors::get( 'assets_scripts' );
|
37 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Assets_Scripts extends QM_Output_Html_Assets {
|
13 |
|
18 |
*/
|
19 |
protected $collector;
|
20 |
|
21 |
+
/**
|
22 |
+
* @return string
|
23 |
+
*/
|
24 |
public function name() {
|
25 |
return __( 'Scripts', 'query-monitor' );
|
26 |
}
|
27 |
|
28 |
+
/**
|
29 |
+
* @return array<string, string>
|
30 |
+
*/
|
31 |
public function get_type_labels() {
|
32 |
return array(
|
33 |
/* translators: %s: Total number of enqueued scripts */
|
34 |
+
'total' => _x( 'Total: %s', 'Enqueued scripts', 'query-monitor' ),
|
35 |
'plural' => __( 'Scripts', 'query-monitor' ),
|
36 |
/* translators: %s: Total number of enqueued scripts */
|
37 |
+
'count' => _x( 'Scripts (%s)', 'Enqueued scripts', 'query-monitor' ),
|
38 |
+
'none' => __( 'No JavaScript files were enqueued.', 'query-monitor' ),
|
39 |
);
|
40 |
}
|
41 |
|
42 |
}
|
43 |
|
44 |
+
/**
|
45 |
+
* @param array<string, QM_Output> $output
|
46 |
+
* @param QM_Collectors $collectors
|
47 |
+
* @return array<string, QM_Output>
|
48 |
+
*/
|
49 |
function register_qm_output_html_assets_scripts( array $output, QM_Collectors $collectors ) {
|
50 |
$collector = QM_Collectors::get( 'assets_scripts' );
|
51 |
if ( $collector ) {
|
output/html/assets_styles.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Assets_Styles extends QM_Output_Html_Assets {
|
11 |
|
@@ -16,22 +18,34 @@ class QM_Output_Html_Assets_Styles extends QM_Output_Html_Assets {
|
|
16 |
*/
|
17 |
protected $collector;
|
18 |
|
|
|
|
|
|
|
19 |
public function name() {
|
20 |
return __( 'Styles', 'query-monitor' );
|
21 |
}
|
22 |
|
|
|
|
|
|
|
23 |
public function get_type_labels() {
|
24 |
return array(
|
25 |
/* translators: %s: Total number of enqueued styles */
|
26 |
-
'total'
|
27 |
'plural' => __( 'Styles', 'query-monitor' ),
|
28 |
/* translators: %s: Total number of enqueued styles */
|
29 |
-
'count'
|
|
|
30 |
);
|
31 |
}
|
32 |
|
33 |
}
|
34 |
|
|
|
|
|
|
|
|
|
|
|
35 |
function register_qm_output_html_assets_styles( array $output, QM_Collectors $collectors ) {
|
36 |
$collector = QM_Collectors::get( 'assets_styles' );
|
37 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Assets_Styles extends QM_Output_Html_Assets {
|
13 |
|
18 |
*/
|
19 |
protected $collector;
|
20 |
|
21 |
+
/**
|
22 |
+
* @return string
|
23 |
+
*/
|
24 |
public function name() {
|
25 |
return __( 'Styles', 'query-monitor' );
|
26 |
}
|
27 |
|
28 |
+
/**
|
29 |
+
* @return array<string, string>
|
30 |
+
*/
|
31 |
public function get_type_labels() {
|
32 |
return array(
|
33 |
/* translators: %s: Total number of enqueued styles */
|
34 |
+
'total' => _x( 'Total: %s', 'Enqueued styles', 'query-monitor' ),
|
35 |
'plural' => __( 'Styles', 'query-monitor' ),
|
36 |
/* translators: %s: Total number of enqueued styles */
|
37 |
+
'count' => _x( 'Styles (%s)', 'Enqueued styles', 'query-monitor' ),
|
38 |
+
'none' => __( 'No CSS files were enqueued.', 'query-monitor' ),
|
39 |
);
|
40 |
}
|
41 |
|
42 |
}
|
43 |
|
44 |
+
/**
|
45 |
+
* @param array<string, QM_Output> $output
|
46 |
+
* @param QM_Collectors $collectors
|
47 |
+
* @return array<string, QM_Output>
|
48 |
+
*/
|
49 |
function register_qm_output_html_assets_styles( array $output, QM_Collectors $collectors ) {
|
50 |
$collector = QM_Collectors::get( 'assets_styles' );
|
51 |
if ( $collector ) {
|
output/html/block_editor.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Block_Editor extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Block_Editor extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 55 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Blocks', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
$data = $this->collector->get_data();
|
30 |
|
@@ -101,25 +109,31 @@ class QM_Output_Html_Block_Editor extends QM_Output_Html {
|
|
101 |
$this->after_tabular_output();
|
102 |
}
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
protected static function render_block( $i, array $block, array $data ) {
|
105 |
-
$block_error
|
106 |
-
$row_class
|
107 |
$referenced_post = null;
|
108 |
$referenced_type = null;
|
109 |
-
$referenced_pto
|
110 |
-
$error_message
|
111 |
|
112 |
if ( 'core/block' === $block['blockName'] && ! empty( $block['attrs']['ref'] ) ) {
|
113 |
$referenced_post = get_post( $block['attrs']['ref'] );
|
114 |
|
115 |
if ( ! $referenced_post ) {
|
116 |
-
$block_error
|
117 |
$error_message = esc_html__( 'Referenced block does not exist.', 'query-monitor' );
|
118 |
} else {
|
119 |
$referenced_type = $referenced_post->post_type;
|
120 |
-
$referenced_pto
|
121 |
if ( 'wp_block' !== $referenced_type ) {
|
122 |
-
$block_error
|
123 |
$error_message = sprintf(
|
124 |
/* translators: %1$s: Erroneous post type name, %2$s: WordPress block post type name */
|
125 |
esc_html__( 'Referenced post is of type %1$s instead of %2$s.', 'query-monitor' ),
|
@@ -131,26 +145,26 @@ class QM_Output_Html_Block_Editor extends QM_Output_Html {
|
|
131 |
}
|
132 |
|
133 |
$media_blocks = array(
|
134 |
-
'core/audio'
|
135 |
-
'core/cover'
|
136 |
'core/cover-image' => 'id',
|
137 |
-
'core/file'
|
138 |
-
'core/image'
|
139 |
-
'core/media-text'
|
140 |
-
'core/video'
|
141 |
);
|
142 |
|
143 |
if ( isset( $media_blocks[ $block['blockName'] ] ) && is_array( $block['attrs'] ) && ! empty( $block['attrs'][ $media_blocks[ $block['blockName'] ] ] ) ) {
|
144 |
$referenced_post = get_post( $block['attrs'][ $media_blocks[ $block['blockName'] ] ] );
|
145 |
|
146 |
if ( ! $referenced_post ) {
|
147 |
-
$block_error
|
148 |
$error_message = esc_html__( 'Referenced media does not exist.', 'query-monitor' );
|
149 |
} else {
|
150 |
$referenced_type = $referenced_post->post_type;
|
151 |
-
$referenced_pto
|
152 |
if ( 'attachment' !== $referenced_type ) {
|
153 |
-
$block_error
|
154 |
$error_message = sprintf(
|
155 |
/* translators: %1$s: Erroneous post type name, %2$s: WordPress attachment post type name */
|
156 |
esc_html__( 'Referenced media is of type %1$s instead of %2$s.', 'query-monitor' ),
|
@@ -284,6 +298,10 @@ class QM_Output_Html_Block_Editor extends QM_Output_Html {
|
|
284 |
}
|
285 |
}
|
286 |
|
|
|
|
|
|
|
|
|
287 |
public function admin_menu( array $menu ) {
|
288 |
$data = $this->collector->get_data();
|
289 |
|
@@ -300,6 +318,11 @@ class QM_Output_Html_Block_Editor extends QM_Output_Html {
|
|
300 |
|
301 |
}
|
302 |
|
|
|
|
|
|
|
|
|
|
|
303 |
function register_qm_output_html_block_editor( array $output, QM_Collectors $collectors ) {
|
304 |
$collector = QM_Collectors::get( 'block_editor' );
|
305 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Block_Editor extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 55 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Blocks', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
$data = $this->collector->get_data();
|
38 |
|
109 |
$this->after_tabular_output();
|
110 |
}
|
111 |
|
112 |
+
/**
|
113 |
+
* @param int|string $i
|
114 |
+
* @param array<string, mixed> $block
|
115 |
+
* @param array<string, mixed> $data
|
116 |
+
* @return void
|
117 |
+
*/
|
118 |
protected static function render_block( $i, array $block, array $data ) {
|
119 |
+
$block_error = false;
|
120 |
+
$row_class = '';
|
121 |
$referenced_post = null;
|
122 |
$referenced_type = null;
|
123 |
+
$referenced_pto = null;
|
124 |
+
$error_message = null;
|
125 |
|
126 |
if ( 'core/block' === $block['blockName'] && ! empty( $block['attrs']['ref'] ) ) {
|
127 |
$referenced_post = get_post( $block['attrs']['ref'] );
|
128 |
|
129 |
if ( ! $referenced_post ) {
|
130 |
+
$block_error = true;
|
131 |
$error_message = esc_html__( 'Referenced block does not exist.', 'query-monitor' );
|
132 |
} else {
|
133 |
$referenced_type = $referenced_post->post_type;
|
134 |
+
$referenced_pto = get_post_type_object( $referenced_type );
|
135 |
if ( 'wp_block' !== $referenced_type ) {
|
136 |
+
$block_error = true;
|
137 |
$error_message = sprintf(
|
138 |
/* translators: %1$s: Erroneous post type name, %2$s: WordPress block post type name */
|
139 |
esc_html__( 'Referenced post is of type %1$s instead of %2$s.', 'query-monitor' ),
|
145 |
}
|
146 |
|
147 |
$media_blocks = array(
|
148 |
+
'core/audio' => 'id',
|
149 |
+
'core/cover' => 'id',
|
150 |
'core/cover-image' => 'id',
|
151 |
+
'core/file' => 'id',
|
152 |
+
'core/image' => 'id',
|
153 |
+
'core/media-text' => 'mediaId', // (╯°□°)╯︵ ┻━┻
|
154 |
+
'core/video' => 'id',
|
155 |
);
|
156 |
|
157 |
if ( isset( $media_blocks[ $block['blockName'] ] ) && is_array( $block['attrs'] ) && ! empty( $block['attrs'][ $media_blocks[ $block['blockName'] ] ] ) ) {
|
158 |
$referenced_post = get_post( $block['attrs'][ $media_blocks[ $block['blockName'] ] ] );
|
159 |
|
160 |
if ( ! $referenced_post ) {
|
161 |
+
$block_error = true;
|
162 |
$error_message = esc_html__( 'Referenced media does not exist.', 'query-monitor' );
|
163 |
} else {
|
164 |
$referenced_type = $referenced_post->post_type;
|
165 |
+
$referenced_pto = get_post_type_object( $referenced_type );
|
166 |
if ( 'attachment' !== $referenced_type ) {
|
167 |
+
$block_error = true;
|
168 |
$error_message = sprintf(
|
169 |
/* translators: %1$s: Erroneous post type name, %2$s: WordPress attachment post type name */
|
170 |
esc_html__( 'Referenced media is of type %1$s instead of %2$s.', 'query-monitor' ),
|
298 |
}
|
299 |
}
|
300 |
|
301 |
+
/**
|
302 |
+
* @param array<string, mixed[]> $menu
|
303 |
+
* @return array<string, mixed[]>
|
304 |
+
*/
|
305 |
public function admin_menu( array $menu ) {
|
306 |
$data = $this->collector->get_data();
|
307 |
|
318 |
|
319 |
}
|
320 |
|
321 |
+
/**
|
322 |
+
* @param array<string, QM_Output> $output
|
323 |
+
* @param QM_Collectors $collectors
|
324 |
+
* @return array<string, QM_Output>
|
325 |
+
*/
|
326 |
function register_qm_output_html_block_editor( array $output, QM_Collectors $collectors ) {
|
327 |
$collector = QM_Collectors::get( 'block_editor' );
|
328 |
if ( $collector ) {
|
output/html/caps.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Caps extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Caps extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 105 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Capability Checks', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
$collector = $this->collector;
|
30 |
|
@@ -54,12 +62,12 @@ class QM_Output_Html_Caps extends QM_Output_Html {
|
|
54 |
if ( ! empty( $data['caps'] ) ) {
|
55 |
$this->before_tabular_output();
|
56 |
|
57 |
-
$results
|
58 |
'true',
|
59 |
'false',
|
60 |
);
|
61 |
-
$show_user
|
62 |
-
$parts
|
63 |
$components = $data['components'];
|
64 |
|
65 |
usort( $parts, 'strcasecmp' );
|
@@ -94,11 +102,11 @@ class QM_Output_Html_Caps extends QM_Output_Html {
|
|
94 |
foreach ( $data['caps'] as $row ) {
|
95 |
$component = $row['component'];
|
96 |
|
97 |
-
$row_attr
|
98 |
-
$row_attr['data-qm-name']
|
99 |
-
$row_attr['data-qm-user']
|
100 |
$row_attr['data-qm-component'] = $component->name;
|
101 |
-
$row_attr['data-qm-result']
|
102 |
|
103 |
if ( 'core' !== $component->context ) {
|
104 |
$row_attr['data-qm-component'] .= ' non-core';
|
@@ -145,8 +153,8 @@ class QM_Output_Html_Caps extends QM_Output_Html {
|
|
145 |
|
146 |
$stack = array();
|
147 |
|
148 |
-
foreach ( $row['filtered_trace'] as $
|
149 |
-
$stack[] = self::output_filename( $
|
150 |
}
|
151 |
|
152 |
$caller = array_shift( $stack );
|
@@ -204,6 +212,10 @@ class QM_Output_Html_Caps extends QM_Output_Html {
|
|
204 |
}
|
205 |
}
|
206 |
|
|
|
|
|
|
|
|
|
207 |
public function admin_menu( array $menu ) {
|
208 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
209 |
'title' => $this->name(),
|
@@ -214,6 +226,11 @@ class QM_Output_Html_Caps extends QM_Output_Html {
|
|
214 |
|
215 |
}
|
216 |
|
|
|
|
|
|
|
|
|
|
|
217 |
function register_qm_output_html_caps( array $output, QM_Collectors $collectors ) {
|
218 |
$collector = QM_Collectors::get( 'caps' );
|
219 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Caps extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 105 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Capability Checks', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
$collector = $this->collector;
|
38 |
|
62 |
if ( ! empty( $data['caps'] ) ) {
|
63 |
$this->before_tabular_output();
|
64 |
|
65 |
+
$results = array(
|
66 |
'true',
|
67 |
'false',
|
68 |
);
|
69 |
+
$show_user = ( count( $data['users'] ) > 1 );
|
70 |
+
$parts = $data['parts'];
|
71 |
$components = $data['components'];
|
72 |
|
73 |
usort( $parts, 'strcasecmp' );
|
102 |
foreach ( $data['caps'] as $row ) {
|
103 |
$component = $row['component'];
|
104 |
|
105 |
+
$row_attr = array();
|
106 |
+
$row_attr['data-qm-name'] = implode( ' ', $row['parts'] );
|
107 |
+
$row_attr['data-qm-user'] = $row['user'];
|
108 |
$row_attr['data-qm-component'] = $component->name;
|
109 |
+
$row_attr['data-qm-result'] = ( $row['result'] ) ? 'true' : 'false';
|
110 |
|
111 |
if ( 'core' !== $component->context ) {
|
112 |
$row_attr['data-qm-component'] .= ' non-core';
|
153 |
|
154 |
$stack = array();
|
155 |
|
156 |
+
foreach ( $row['filtered_trace'] as $frame ) {
|
157 |
+
$stack[] = self::output_filename( $frame['display'], $frame['calling_file'], $frame['calling_line'] );
|
158 |
}
|
159 |
|
160 |
$caller = array_shift( $stack );
|
212 |
}
|
213 |
}
|
214 |
|
215 |
+
/**
|
216 |
+
* @param array<string, mixed[]> $menu
|
217 |
+
* @return array<string, mixed[]>
|
218 |
+
*/
|
219 |
public function admin_menu( array $menu ) {
|
220 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
221 |
'title' => $this->name(),
|
226 |
|
227 |
}
|
228 |
|
229 |
+
/**
|
230 |
+
* @param array<string, QM_Output> $output
|
231 |
+
* @param QM_Collectors $collectors
|
232 |
+
* @return array<string, QM_Output>
|
233 |
+
*/
|
234 |
function register_qm_output_html_caps( array $output, QM_Collectors $collectors ) {
|
235 |
$collector = QM_Collectors::get( 'caps' );
|
236 |
if ( $collector ) {
|
output/html/conditionals.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Conditionals extends QM_Output_Html {
|
11 |
|
@@ -22,10 +24,16 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
|
|
22 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 1000 );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
25 |
public function name() {
|
26 |
return __( 'Conditionals', 'query-monitor' );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
29 |
public function output() {
|
30 |
$data = $this->collector->get_data();
|
31 |
|
@@ -58,16 +66,20 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
|
|
58 |
$this->after_non_tabular_output();
|
59 |
}
|
60 |
|
|
|
|
|
|
|
|
|
61 |
public function admin_menu( array $menu ) {
|
62 |
|
63 |
$data = $this->collector->get_data();
|
64 |
|
65 |
foreach ( $data['conds']['true'] as $cond ) {
|
66 |
-
$id
|
67 |
$menu[ $id ] = $this->menu( array(
|
68 |
'title' => esc_html( $cond . '()' ),
|
69 |
-
'id'
|
70 |
-
'meta'
|
71 |
'classname' => 'qm-true qm-ltr',
|
72 |
),
|
73 |
) );
|
@@ -77,6 +89,10 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
|
|
77 |
|
78 |
}
|
79 |
|
|
|
|
|
|
|
|
|
80 |
public function panel_menu( array $menu ) {
|
81 |
|
82 |
$data = $this->collector->get_data();
|
@@ -88,7 +104,7 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
|
|
88 |
|
89 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
90 |
'title' => esc_html__( 'Conditionals', 'query-monitor' ),
|
91 |
-
'id'
|
92 |
) );
|
93 |
|
94 |
return $menu;
|
@@ -98,6 +114,11 @@ class QM_Output_Html_Conditionals extends QM_Output_Html {
|
|
98 |
|
99 |
}
|
100 |
|
|
|
|
|
|
|
|
|
|
|
101 |
function register_qm_output_html_conditionals( array $output, QM_Collectors $collectors ) {
|
102 |
$collector = QM_Collectors::get( 'conditionals' );
|
103 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Conditionals extends QM_Output_Html {
|
13 |
|
24 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 1000 );
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
public function name() {
|
31 |
return __( 'Conditionals', 'query-monitor' );
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
public function output() {
|
38 |
$data = $this->collector->get_data();
|
39 |
|
66 |
$this->after_non_tabular_output();
|
67 |
}
|
68 |
|
69 |
+
/**
|
70 |
+
* @param array<string, mixed[]> $menu
|
71 |
+
* @return array<string, mixed[]>
|
72 |
+
*/
|
73 |
public function admin_menu( array $menu ) {
|
74 |
|
75 |
$data = $this->collector->get_data();
|
76 |
|
77 |
foreach ( $data['conds']['true'] as $cond ) {
|
78 |
+
$id = $this->collector->id() . '-' . $cond;
|
79 |
$menu[ $id ] = $this->menu( array(
|
80 |
'title' => esc_html( $cond . '()' ),
|
81 |
+
'id' => 'query-monitor-conditionals-' . esc_attr( $cond ),
|
82 |
+
'meta' => array(
|
83 |
'classname' => 'qm-true qm-ltr',
|
84 |
),
|
85 |
) );
|
89 |
|
90 |
}
|
91 |
|
92 |
+
/**
|
93 |
+
* @param array<string, mixed[]> $menu
|
94 |
+
* @return array<string, mixed[]>
|
95 |
+
*/
|
96 |
public function panel_menu( array $menu ) {
|
97 |
|
98 |
$data = $this->collector->get_data();
|
104 |
|
105 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
106 |
'title' => esc_html__( 'Conditionals', 'query-monitor' ),
|
107 |
+
'id' => 'query-monitor-conditionals',
|
108 |
) );
|
109 |
|
110 |
return $menu;
|
114 |
|
115 |
}
|
116 |
|
117 |
+
/**
|
118 |
+
* @param array<string, QM_Output> $output
|
119 |
+
* @param QM_Collectors $collectors
|
120 |
+
* @return array<string, QM_Output>
|
121 |
+
*/
|
122 |
function register_qm_output_html_conditionals( array $output, QM_Collectors $collectors ) {
|
123 |
$collector = QM_Collectors::get( 'conditionals' );
|
124 |
if ( $collector ) {
|
output/html/db_callers.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_DB_Callers extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 30 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Queries by Caller', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -58,7 +66,7 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
|
|
58 |
|
59 |
foreach ( $data['times'] as $row ) {
|
60 |
$total_time += $row['ltime'];
|
61 |
-
$stime
|
62 |
|
63 |
echo '<tr>';
|
64 |
echo '<td class="qm-ltr"><button 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></button></td>';
|
@@ -105,6 +113,10 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
|
|
105 |
}
|
106 |
}
|
107 |
|
|
|
|
|
|
|
|
|
108 |
public function panel_menu( array $menu ) {
|
109 |
$dbq = QM_Collectors::get( 'db_queries' );
|
110 |
|
@@ -122,6 +134,11 @@ class QM_Output_Html_DB_Callers extends QM_Output_Html {
|
|
122 |
|
123 |
}
|
124 |
|
|
|
|
|
|
|
|
|
|
|
125 |
function register_qm_output_html_db_callers( array $output, QM_Collectors $collectors ) {
|
126 |
$collector = QM_Collectors::get( 'db_callers' );
|
127 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_DB_Callers extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 30 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Queries by Caller', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
66 |
|
67 |
foreach ( $data['times'] as $row ) {
|
68 |
$total_time += $row['ltime'];
|
69 |
+
$stime = number_format_i18n( $row['ltime'], 4 );
|
70 |
|
71 |
echo '<tr>';
|
72 |
echo '<td class="qm-ltr"><button 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></button></td>';
|
113 |
}
|
114 |
}
|
115 |
|
116 |
+
/**
|
117 |
+
* @param array<string, mixed[]> $menu
|
118 |
+
* @return array<string, mixed[]>
|
119 |
+
*/
|
120 |
public function panel_menu( array $menu ) {
|
121 |
$dbq = QM_Collectors::get( 'db_queries' );
|
122 |
|
134 |
|
135 |
}
|
136 |
|
137 |
+
/**
|
138 |
+
* @param array<string, QM_Output> $output
|
139 |
+
* @param QM_Collectors $collectors
|
140 |
+
* @return array<string, QM_Output>
|
141 |
+
*/
|
142 |
function register_qm_output_html_db_callers( array $output, QM_Collectors $collectors ) {
|
143 |
$collector = QM_Collectors::get( 'db_callers' );
|
144 |
if ( $collector ) {
|
output/html/db_components.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_DB_Components extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 40 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Queries by Component', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -34,7 +42,7 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
|
|
34 |
}
|
35 |
|
36 |
$total_time = 0;
|
37 |
-
$span
|
38 |
|
39 |
$this->before_tabular_output();
|
40 |
|
@@ -96,6 +104,10 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
|
|
96 |
$this->after_tabular_output();
|
97 |
}
|
98 |
|
|
|
|
|
|
|
|
|
99 |
public function panel_menu( array $menu ) {
|
100 |
$data = $this->collector->get_data();
|
101 |
|
@@ -119,6 +131,11 @@ class QM_Output_Html_DB_Components extends QM_Output_Html {
|
|
119 |
|
120 |
}
|
121 |
|
|
|
|
|
|
|
|
|
|
|
122 |
function register_qm_output_html_db_components( array $output, QM_Collectors $collectors ) {
|
123 |
$collector = QM_Collectors::get( 'db_components' );
|
124 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_DB_Components extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 40 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Queries by Component', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
42 |
}
|
43 |
|
44 |
$total_time = 0;
|
45 |
+
$span = count( $data['types'] ) + 2;
|
46 |
|
47 |
$this->before_tabular_output();
|
48 |
|
104 |
$this->after_tabular_output();
|
105 |
}
|
106 |
|
107 |
+
/**
|
108 |
+
* @param array<string, mixed[]> $menu
|
109 |
+
* @return array<string, mixed[]>
|
110 |
+
*/
|
111 |
public function panel_menu( array $menu ) {
|
112 |
$data = $this->collector->get_data();
|
113 |
|
131 |
|
132 |
}
|
133 |
|
134 |
+
/**
|
135 |
+
* @param array<string, QM_Output> $output
|
136 |
+
* @param QM_Collectors $collectors
|
137 |
+
* @return array<string, QM_Output>
|
138 |
+
*/
|
139 |
function register_qm_output_html_db_components( array $output, QM_Collectors $collectors ) {
|
140 |
$collector = QM_Collectors::get( 'db_components' );
|
141 |
if ( $collector ) {
|
output/html/db_dupes.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_DB_Dupes extends QM_Output_Html {
|
11 |
|
@@ -22,10 +24,16 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
|
|
22 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 25 );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
25 |
public function name() {
|
26 |
return __( 'Duplicate Queries', 'query-monitor' );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
29 |
public function output() {
|
30 |
|
31 |
$data = $this->collector->get_data();
|
@@ -58,7 +66,7 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
|
|
58 |
foreach ( $data['dupes'] as $sql => $queries ) {
|
59 |
|
60 |
// This should probably happen in the collector's processor
|
61 |
-
$type
|
62 |
$sql_out = self::format_sql( $sql );
|
63 |
|
64 |
if ( 'SELECT' !== $type ) {
|
@@ -118,6 +126,10 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
|
|
118 |
$this->after_tabular_output();
|
119 |
}
|
120 |
|
|
|
|
|
|
|
|
|
121 |
public function admin_menu( array $menu ) {
|
122 |
$dbq = QM_Collectors::get( 'db_dupes' );
|
123 |
|
@@ -138,6 +150,10 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
|
|
138 |
|
139 |
}
|
140 |
|
|
|
|
|
|
|
|
|
141 |
public function panel_menu( array $menu ) {
|
142 |
$id = $this->collector->id();
|
143 |
if ( isset( $menu[ $id ] ) ) {
|
@@ -152,6 +168,11 @@ class QM_Output_Html_DB_Dupes extends QM_Output_Html {
|
|
152 |
|
153 |
}
|
154 |
|
|
|
|
|
|
|
|
|
|
|
155 |
function register_qm_output_html_db_dupes( array $output, QM_Collectors $collectors ) {
|
156 |
$collector = QM_Collectors::get( 'db_dupes' );
|
157 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_DB_Dupes extends QM_Output_Html {
|
13 |
|
24 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 25 );
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
public function name() {
|
31 |
return __( 'Duplicate Queries', 'query-monitor' );
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
public function output() {
|
38 |
|
39 |
$data = $this->collector->get_data();
|
66 |
foreach ( $data['dupes'] as $sql => $queries ) {
|
67 |
|
68 |
// This should probably happen in the collector's processor
|
69 |
+
$type = QM_Util::get_query_type( $sql );
|
70 |
$sql_out = self::format_sql( $sql );
|
71 |
|
72 |
if ( 'SELECT' !== $type ) {
|
126 |
$this->after_tabular_output();
|
127 |
}
|
128 |
|
129 |
+
/**
|
130 |
+
* @param array<string, mixed[]> $menu
|
131 |
+
* @return array<string, mixed[]>
|
132 |
+
*/
|
133 |
public function admin_menu( array $menu ) {
|
134 |
$dbq = QM_Collectors::get( 'db_dupes' );
|
135 |
|
150 |
|
151 |
}
|
152 |
|
153 |
+
/**
|
154 |
+
* @param array<string, mixed[]> $menu
|
155 |
+
* @return array<string, mixed[]>
|
156 |
+
*/
|
157 |
public function panel_menu( array $menu ) {
|
158 |
$id = $this->collector->id();
|
159 |
if ( isset( $menu[ $id ] ) ) {
|
168 |
|
169 |
}
|
170 |
|
171 |
+
/**
|
172 |
+
* @param array<string, QM_Output> $output
|
173 |
+
* @param QM_Collectors $collectors
|
174 |
+
* @return array<string, QM_Output>
|
175 |
+
*/
|
176 |
function register_qm_output_html_db_dupes( array $output, QM_Collectors $collectors ) {
|
177 |
$collector = QM_Collectors::get( 'db_dupes' );
|
178 |
if ( $collector ) {
|
output/html/db_queries.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
11 |
|
@@ -16,6 +18,9 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
16 |
*/
|
17 |
protected $collector;
|
18 |
|
|
|
|
|
|
|
19 |
public $query_row = 0;
|
20 |
|
21 |
public function __construct( QM_Collector $collector ) {
|
@@ -26,10 +31,16 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
26 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
29 |
public function name() {
|
30 |
return __( 'Database Queries', 'query-monitor' );
|
31 |
}
|
32 |
|
|
|
|
|
|
|
33 |
public function output() {
|
34 |
|
35 |
$data = $this->collector->get_data();
|
@@ -53,6 +64,9 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
53 |
|
54 |
}
|
55 |
|
|
|
|
|
|
|
56 |
protected function output_empty_queries() {
|
57 |
$id = sprintf(
|
58 |
'%s-wpdb',
|
@@ -75,6 +89,10 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
75 |
$this->after_non_tabular_output();
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
78 |
protected function output_error_queries( array $errors ) {
|
79 |
$this->before_tabular_output( 'qm-query-errors', __( 'Database Errors', 'query-monitor' ) );
|
80 |
|
@@ -98,6 +116,10 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
98 |
$this->after_tabular_output();
|
99 |
}
|
100 |
|
|
|
|
|
|
|
|
|
101 |
protected function output_expensive_queries( array $expensive ) {
|
102 |
$dp = strlen( substr( strrchr( (string) QM_DB_EXPENSIVE, '.' ), 1 ) );
|
103 |
|
@@ -135,6 +157,12 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
135 |
$this->after_tabular_output();
|
136 |
}
|
137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
protected function output_queries( $name, stdClass $db, array $data ) {
|
139 |
$this->query_row = 0;
|
140 |
$span = 4;
|
@@ -199,9 +227,9 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
199 |
echo '</tr>';
|
200 |
}
|
201 |
|
202 |
-
$types
|
203 |
-
$prepend
|
204 |
-
$callers
|
205 |
|
206 |
sort( $types );
|
207 |
usort( $callers, 'strcasecmp' );
|
@@ -296,6 +324,11 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
296 |
}
|
297 |
}
|
298 |
|
|
|
|
|
|
|
|
|
|
|
299 |
protected function output_query_row( array $row, array $cols ) {
|
300 |
|
301 |
$cols = array_flip( $cols );
|
@@ -317,14 +350,14 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
317 |
|
318 |
if ( isset( $row['trace'] ) ) {
|
319 |
|
320 |
-
$caller
|
321 |
-
$caller_name
|
322 |
-
$stack
|
323 |
-
$filtered_trace = $row['trace']->
|
324 |
array_shift( $filtered_trace );
|
325 |
|
326 |
-
foreach ( $filtered_trace as $
|
327 |
-
$stack[] = self::output_filename( $
|
328 |
}
|
329 |
} else {
|
330 |
|
@@ -334,11 +367,10 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
334 |
$caller_name = '<code>' . esc_html__( 'Unknown', 'query-monitor' ) . '</code>';
|
335 |
}
|
336 |
|
337 |
-
$stack
|
338 |
-
$stack = array_reverse( $stack );
|
339 |
array_shift( $stack );
|
340 |
-
$stack
|
341 |
-
return '<code>' . esc_html( $
|
342 |
}, $stack );
|
343 |
|
344 |
}
|
@@ -446,7 +478,7 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
446 |
|
447 |
if ( isset( $cols['time'] ) ) {
|
448 |
$expensive = $this->collector->is_expensive( $row );
|
449 |
-
$td_class
|
450 |
|
451 |
echo '<td class="qm-num qm-row-time' . esc_attr( $td_class ) . '" data-qm-sort-weight="' . esc_attr( $row['ltime'] ) . '">';
|
452 |
|
@@ -462,14 +494,18 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
462 |
|
463 |
}
|
464 |
|
|
|
|
|
|
|
|
|
465 |
public function admin_title( array $existing ) {
|
466 |
-
|
467 |
$data = $this->collector->get_data();
|
468 |
|
469 |
if ( isset( $data['dbs'] ) ) {
|
470 |
foreach ( $data['dbs'] as $key => $db ) {
|
471 |
-
/* translators: %s:
|
472 |
-
$text =
|
473 |
|
474 |
// Avoid a potentially blank translation for the plural form.
|
475 |
// @see https://meta.trac.wordpress.org/ticket/5377
|
@@ -479,12 +515,12 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
479 |
|
480 |
$title[] = sprintf(
|
481 |
esc_html( '%s' . $text ),
|
482 |
-
( count( $data['dbs'] ) > 1 ? '•  
|
483 |
-
number_format_i18n( $db->total_time,
|
484 |
);
|
485 |
|
486 |
-
/* translators: %s: Number of database queries */
|
487 |
-
$text =
|
488 |
|
489 |
// Avoid a potentially blank translation for the plural form.
|
490 |
// @see https://meta.trac.wordpress.org/ticket/5377
|
@@ -498,8 +534,8 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
498 |
);
|
499 |
}
|
500 |
} elseif ( isset( $data['total_qs'] ) ) {
|
501 |
-
/* translators: %s: Number of database queries */
|
502 |
-
$text =
|
503 |
|
504 |
// Avoid a potentially blank translation for the plural form.
|
505 |
// @see https://meta.trac.wordpress.org/ticket/5377
|
@@ -508,7 +544,6 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
508 |
}
|
509 |
|
510 |
$title[] = sprintf(
|
511 |
-
/* translators: %s: Number of database queries */
|
512 |
esc_html( $text ),
|
513 |
number_format_i18n( $data['total_qs'] )
|
514 |
);
|
@@ -523,6 +558,10 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
523 |
return $title;
|
524 |
}
|
525 |
|
|
|
|
|
|
|
|
|
526 |
public function admin_class( array $class ) {
|
527 |
|
528 |
if ( $this->collector->get_errors() ) {
|
@@ -535,40 +574,44 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
535 |
|
536 |
}
|
537 |
|
|
|
|
|
|
|
|
|
538 |
public function admin_menu( array $menu ) {
|
539 |
|
540 |
-
$data
|
541 |
-
$errors
|
542 |
$expensive = $this->collector->get_expensive();
|
543 |
|
544 |
if ( isset( $data['dbs'] ) && count( $data['dbs'] ) > 1 ) {
|
545 |
foreach ( $data['dbs'] as $name => $db ) {
|
546 |
-
$name_attr
|
547 |
-
$id
|
548 |
$menu[ $id ] = $this->menu( array(
|
549 |
-
'id'
|
550 |
'title' => esc_html( sprintf(
|
551 |
/* translators: %s: Name of database controller */
|
552 |
__( 'Queries: %s', 'query-monitor' ),
|
553 |
$name
|
554 |
) ),
|
555 |
-
'href'
|
556 |
) );
|
557 |
}
|
558 |
} else {
|
559 |
-
$id
|
560 |
$menu[ $id ] = $this->menu( array(
|
561 |
'title' => esc_html__( 'Queries', 'query-monitor' ),
|
562 |
-
'href'
|
563 |
) );
|
564 |
}
|
565 |
|
566 |
if ( $errors ) {
|
567 |
-
$id
|
568 |
-
$count
|
569 |
$menu[ $id ] = $this->menu( array(
|
570 |
-
'id'
|
571 |
-
'href'
|
572 |
'title' => esc_html( sprintf(
|
573 |
/* translators: %s: Number of database errors */
|
574 |
__( 'Database Errors (%s)', 'query-monitor' ),
|
@@ -578,11 +621,11 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
578 |
}
|
579 |
|
580 |
if ( $expensive ) {
|
581 |
-
$id
|
582 |
-
$count
|
583 |
$menu[ $id ] = $this->menu( array(
|
584 |
-
'id'
|
585 |
-
'href'
|
586 |
'title' => esc_html( sprintf(
|
587 |
/* translators: %s: Number of slow database queries */
|
588 |
__( 'Slow Queries (%s)', 'query-monitor' ),
|
@@ -595,6 +638,10 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
595 |
|
596 |
}
|
597 |
|
|
|
|
|
|
|
|
|
598 |
public function panel_menu( array $menu ) {
|
599 |
foreach ( array( 'errors', 'expensive' ) as $sub ) {
|
600 |
$id = $this->collector->id() . '-' . $sub;
|
@@ -611,6 +658,11 @@ class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
|
611 |
|
612 |
}
|
613 |
|
|
|
|
|
|
|
|
|
|
|
614 |
function register_qm_output_html_db_queries( array $output, QM_Collectors $collectors ) {
|
615 |
$collector = QM_Collectors::get( 'db_queries' );
|
616 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_DB_Queries extends QM_Output_Html {
|
13 |
|
18 |
*/
|
19 |
protected $collector;
|
20 |
|
21 |
+
/**
|
22 |
+
* @var int
|
23 |
+
*/
|
24 |
public $query_row = 0;
|
25 |
|
26 |
public function __construct( QM_Collector $collector ) {
|
31 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @return string
|
36 |
+
*/
|
37 |
public function name() {
|
38 |
return __( 'Database Queries', 'query-monitor' );
|
39 |
}
|
40 |
|
41 |
+
/**
|
42 |
+
* @return void
|
43 |
+
*/
|
44 |
public function output() {
|
45 |
|
46 |
$data = $this->collector->get_data();
|
64 |
|
65 |
}
|
66 |
|
67 |
+
/**
|
68 |
+
* @return void
|
69 |
+
*/
|
70 |
protected function output_empty_queries() {
|
71 |
$id = sprintf(
|
72 |
'%s-wpdb',
|
89 |
$this->after_non_tabular_output();
|
90 |
}
|
91 |
|
92 |
+
/**
|
93 |
+
* @param array<int, mixed> $errors
|
94 |
+
* @return void
|
95 |
+
*/
|
96 |
protected function output_error_queries( array $errors ) {
|
97 |
$this->before_tabular_output( 'qm-query-errors', __( 'Database Errors', 'query-monitor' ) );
|
98 |
|
116 |
$this->after_tabular_output();
|
117 |
}
|
118 |
|
119 |
+
/**
|
120 |
+
* @param array<int, mixed> $expensive
|
121 |
+
* @return void
|
122 |
+
*/
|
123 |
protected function output_expensive_queries( array $expensive ) {
|
124 |
$dp = strlen( substr( strrchr( (string) QM_DB_EXPENSIVE, '.' ), 1 ) );
|
125 |
|
157 |
$this->after_tabular_output();
|
158 |
}
|
159 |
|
160 |
+
/**
|
161 |
+
* @param string $name
|
162 |
+
* @param stdClass $db
|
163 |
+
* @param array<string, mixed> $data
|
164 |
+
* @return void
|
165 |
+
*/
|
166 |
protected function output_queries( $name, stdClass $db, array $data ) {
|
167 |
$this->query_row = 0;
|
168 |
$span = 4;
|
227 |
echo '</tr>';
|
228 |
}
|
229 |
|
230 |
+
$types = array_keys( $db->types );
|
231 |
+
$prepend = array();
|
232 |
+
$callers = wp_list_pluck( $data['times'], 'caller' );
|
233 |
|
234 |
sort( $types );
|
235 |
usort( $callers, 'strcasecmp' );
|
324 |
}
|
325 |
}
|
326 |
|
327 |
+
/**
|
328 |
+
* @param array<string, mixed> $row
|
329 |
+
* @param array<int, string> $cols
|
330 |
+
* @return void
|
331 |
+
*/
|
332 |
protected function output_query_row( array $row, array $cols ) {
|
333 |
|
334 |
$cols = array_flip( $cols );
|
350 |
|
351 |
if ( isset( $row['trace'] ) ) {
|
352 |
|
353 |
+
$caller = $row['trace']->get_caller();
|
354 |
+
$caller_name = self::output_filename( $row['caller'], $caller['calling_file'], $caller['calling_line'] );
|
355 |
+
$stack = array();
|
356 |
+
$filtered_trace = $row['trace']->get_filtered_trace();
|
357 |
array_shift( $filtered_trace );
|
358 |
|
359 |
+
foreach ( $filtered_trace as $frame ) {
|
360 |
+
$stack[] = self::output_filename( $frame['display'], $frame['calling_file'], $frame['calling_line'] );
|
361 |
}
|
362 |
} else {
|
363 |
|
367 |
$caller_name = '<code>' . esc_html__( 'Unknown', 'query-monitor' ) . '</code>';
|
368 |
}
|
369 |
|
370 |
+
$stack = $row['stack'];
|
|
|
371 |
array_shift( $stack );
|
372 |
+
$stack = array_map( function( $frame ) {
|
373 |
+
return '<code>' . esc_html( $frame ) . '</code>';
|
374 |
}, $stack );
|
375 |
|
376 |
}
|
478 |
|
479 |
if ( isset( $cols['time'] ) ) {
|
480 |
$expensive = $this->collector->is_expensive( $row );
|
481 |
+
$td_class = ( $expensive ) ? ' qm-warn' : '';
|
482 |
|
483 |
echo '<td class="qm-num qm-row-time' . esc_attr( $td_class ) . '" data-qm-sort-weight="' . esc_attr( $row['ltime'] ) . '">';
|
484 |
|
494 |
|
495 |
}
|
496 |
|
497 |
+
/**
|
498 |
+
* @param array<int, string> $existing
|
499 |
+
* @return array<int, string>
|
500 |
+
*/
|
501 |
public function admin_title( array $existing ) {
|
502 |
+
$title = array();
|
503 |
$data = $this->collector->get_data();
|
504 |
|
505 |
if ( isset( $data['dbs'] ) ) {
|
506 |
foreach ( $data['dbs'] as $key => $db ) {
|
507 |
+
/* translators: %s: Time in seconds. Note the space between value and unit. */
|
508 |
+
$text = _n( '%s S', '%s S', $db->total_time, 'query-monitor' );
|
509 |
|
510 |
// Avoid a potentially blank translation for the plural form.
|
511 |
// @see https://meta.trac.wordpress.org/ticket/5377
|
515 |
|
516 |
$title[] = sprintf(
|
517 |
esc_html( '%s' . $text ),
|
518 |
+
( count( $data['dbs'] ) > 1 ? '•  ' : '' ),
|
519 |
+
number_format_i18n( $db->total_time, 2 )
|
520 |
);
|
521 |
|
522 |
+
/* translators: %s: Number of database queries. Note the space between value and unit. */
|
523 |
+
$text = _n( '%s Q', '%s Q', $db->total_qs, 'query-monitor' );
|
524 |
|
525 |
// Avoid a potentially blank translation for the plural form.
|
526 |
// @see https://meta.trac.wordpress.org/ticket/5377
|
534 |
);
|
535 |
}
|
536 |
} elseif ( isset( $data['total_qs'] ) ) {
|
537 |
+
/* translators: %s: Number of database queries. Note the space between value and unit. */
|
538 |
+
$text = _n( '%s Q', '%s Q', $data['total_qs'], 'query-monitor' );
|
539 |
|
540 |
// Avoid a potentially blank translation for the plural form.
|
541 |
// @see https://meta.trac.wordpress.org/ticket/5377
|
544 |
}
|
545 |
|
546 |
$title[] = sprintf(
|
|
|
547 |
esc_html( $text ),
|
548 |
number_format_i18n( $data['total_qs'] )
|
549 |
);
|
558 |
return $title;
|
559 |
}
|
560 |
|
561 |
+
/**
|
562 |
+
* @param array<int, string> $class
|
563 |
+
* @return array<int, string>
|
564 |
+
*/
|
565 |
public function admin_class( array $class ) {
|
566 |
|
567 |
if ( $this->collector->get_errors() ) {
|
574 |
|
575 |
}
|
576 |
|
577 |
+
/**
|
578 |
+
* @param array<string, mixed[]> $menu
|
579 |
+
* @return array<string, mixed[]>
|
580 |
+
*/
|
581 |
public function admin_menu( array $menu ) {
|
582 |
|
583 |
+
$data = $this->collector->get_data();
|
584 |
+
$errors = $this->collector->get_errors();
|
585 |
$expensive = $this->collector->get_expensive();
|
586 |
|
587 |
if ( isset( $data['dbs'] ) && count( $data['dbs'] ) > 1 ) {
|
588 |
foreach ( $data['dbs'] as $name => $db ) {
|
589 |
+
$name_attr = sanitize_title_with_dashes( $name );
|
590 |
+
$id = $this->collector->id() . '-' . $name_attr;
|
591 |
$menu[ $id ] = $this->menu( array(
|
592 |
+
'id' => esc_attr( sprintf( 'query-monitor-%s-db-%s', $this->collector->id(), $name_attr ) ),
|
593 |
'title' => esc_html( sprintf(
|
594 |
/* translators: %s: Name of database controller */
|
595 |
__( 'Queries: %s', 'query-monitor' ),
|
596 |
$name
|
597 |
) ),
|
598 |
+
'href' => esc_attr( sprintf( '#%s-%s', $this->collector->id(), $name_attr ) ),
|
599 |
) );
|
600 |
}
|
601 |
} else {
|
602 |
+
$id = $this->collector->id() . '-$wpdb';
|
603 |
$menu[ $id ] = $this->menu( array(
|
604 |
'title' => esc_html__( 'Queries', 'query-monitor' ),
|
605 |
+
'href' => esc_attr( sprintf( '#%s-wpdb', $this->collector->id() ) ),
|
606 |
) );
|
607 |
}
|
608 |
|
609 |
if ( $errors ) {
|
610 |
+
$id = $this->collector->id() . '-errors';
|
611 |
+
$count = count( $errors );
|
612 |
$menu[ $id ] = $this->menu( array(
|
613 |
+
'id' => 'query-monitor-errors',
|
614 |
+
'href' => '#qm-query-errors',
|
615 |
'title' => esc_html( sprintf(
|
616 |
/* translators: %s: Number of database errors */
|
617 |
__( 'Database Errors (%s)', 'query-monitor' ),
|
621 |
}
|
622 |
|
623 |
if ( $expensive ) {
|
624 |
+
$id = $this->collector->id() . '-expensive';
|
625 |
+
$count = count( $expensive );
|
626 |
$menu[ $id ] = $this->menu( array(
|
627 |
+
'id' => 'query-monitor-expensive',
|
628 |
+
'href' => '#qm-query-expensive',
|
629 |
'title' => esc_html( sprintf(
|
630 |
/* translators: %s: Number of slow database queries */
|
631 |
__( 'Slow Queries (%s)', 'query-monitor' ),
|
638 |
|
639 |
}
|
640 |
|
641 |
+
/**
|
642 |
+
* @param array<string, mixed[]> $menu
|
643 |
+
* @return array<string, mixed[]>
|
644 |
+
*/
|
645 |
public function panel_menu( array $menu ) {
|
646 |
foreach ( array( 'errors', 'expensive' ) as $sub ) {
|
647 |
$id = $this->collector->id() . '-' . $sub;
|
658 |
|
659 |
}
|
660 |
|
661 |
+
/**
|
662 |
+
* @param array<string, QM_Output> $output
|
663 |
+
* @param QM_Collectors $collectors
|
664 |
+
* @return array<string, QM_Output>
|
665 |
+
*/
|
666 |
function register_qm_output_html_db_queries( array $output, QM_Collectors $collectors ) {
|
667 |
$collector = QM_Collectors::get( 'db_queries' );
|
668 |
if ( $collector ) {
|
output/html/debug_bar.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Debug_Bar extends QM_Output_Html {
|
11 |
|
@@ -21,6 +23,9 @@ class QM_Output_Html_Debug_Bar extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 200 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
$title = $this->collector->get_panel()->title();
|
26 |
|
@@ -31,6 +36,9 @@ class QM_Output_Html_Debug_Bar extends QM_Output_Html {
|
|
31 |
);
|
32 |
}
|
33 |
|
|
|
|
|
|
|
34 |
public function output() {
|
35 |
$target = sanitize_html_class( get_class( $this->collector->get_panel() ) );
|
36 |
|
@@ -71,6 +79,11 @@ class QM_Output_Html_Debug_Bar extends QM_Output_Html {
|
|
71 |
|
72 |
}
|
73 |
|
|
|
|
|
|
|
|
|
|
|
74 |
function register_qm_output_html_debug_bar( array $output, QM_Collectors $collectors ) {
|
75 |
global $debug_bar;
|
76 |
|
@@ -79,7 +92,8 @@ function register_qm_output_html_debug_bar( array $output, QM_Collectors $collec
|
|
79 |
}
|
80 |
|
81 |
foreach ( $debug_bar->panels as $panel ) {
|
82 |
-
$panel_id
|
|
|
83 |
$collector = QM_Collectors::get( "debug_bar_{$panel_id}" );
|
84 |
|
85 |
if ( $collector && $collector->is_visible() ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Debug_Bar extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 200 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
$title = $this->collector->get_panel()->title();
|
31 |
|
36 |
);
|
37 |
}
|
38 |
|
39 |
+
/**
|
40 |
+
* @return void
|
41 |
+
*/
|
42 |
public function output() {
|
43 |
$target = sanitize_html_class( get_class( $this->collector->get_panel() ) );
|
44 |
|
79 |
|
80 |
}
|
81 |
|
82 |
+
/**
|
83 |
+
* @param array<string, QM_Output> $output
|
84 |
+
* @param QM_Collectors $collectors
|
85 |
+
* @return array<string, QM_Output>
|
86 |
+
*/
|
87 |
function register_qm_output_html_debug_bar( array $output, QM_Collectors $collectors ) {
|
88 |
global $debug_bar;
|
89 |
|
92 |
}
|
93 |
|
94 |
foreach ( $debug_bar->panels as $panel ) {
|
95 |
+
$panel_id = strtolower( sanitize_html_class( get_class( $panel ) ) );
|
96 |
+
/** @var QM_Collector_Debug_Bar|null */
|
97 |
$collector = QM_Collectors::get( "debug_bar_{$panel_id}" );
|
98 |
|
99 |
if ( $collector && $collector->is_visible() ) {
|
output/html/environment.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Environment extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 110 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Environment', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -37,8 +45,8 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
37 |
echo '<table>';
|
38 |
echo '<tbody>';
|
39 |
|
40 |
-
$append
|
41 |
-
$class
|
42 |
$php_warning = $data['php']['old'];
|
43 |
|
44 |
if ( $php_warning ) {
|
@@ -47,7 +55,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
47 |
'https://wordpress.org/support/update-php/',
|
48 |
esc_html__( 'Help', 'query-monitor' )
|
49 |
);
|
50 |
-
$class
|
51 |
}
|
52 |
|
53 |
echo '<tr class="' . esc_attr( $class ) . '">';
|
@@ -78,7 +86,7 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
78 |
echo '</tr>';
|
79 |
|
80 |
foreach ( $data['php']['variables'] as $key => $val ) {
|
81 |
-
$class
|
82 |
$warners = array(
|
83 |
'max_execution_time',
|
84 |
'memory_limit',
|
@@ -182,11 +190,11 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
182 |
|
183 |
$info = array(
|
184 |
'server-version' => __( 'Server Version', 'query-monitor' ),
|
185 |
-
'extension'
|
186 |
'client-version' => __( 'Client Version', 'query-monitor' ),
|
187 |
-
'user'
|
188 |
-
'host'
|
189 |
-
'database'
|
190 |
);
|
191 |
|
192 |
foreach ( $info as $field => $label ) {
|
@@ -282,11 +290,13 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
282 |
echo '<h3>' . esc_html__( 'Server', 'query-monitor' ) . '</h3>';
|
283 |
|
284 |
$server = array(
|
285 |
-
'name'
|
286 |
'version' => __( 'Version', 'query-monitor' ),
|
287 |
-
'address' => __( 'Address', 'query-monitor' ),
|
288 |
-
'host'
|
289 |
-
|
|
|
|
|
290 |
);
|
291 |
|
292 |
echo '<table>';
|
@@ -312,6 +322,11 @@ class QM_Output_Html_Environment extends QM_Output_Html {
|
|
312 |
|
313 |
}
|
314 |
|
|
|
|
|
|
|
|
|
|
|
315 |
function register_qm_output_html_environment( array $output, QM_Collectors $collectors ) {
|
316 |
$collector = QM_Collectors::get( 'environment' );
|
317 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Environment extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 110 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Environment', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
45 |
echo '<table>';
|
46 |
echo '<tbody>';
|
47 |
|
48 |
+
$append = '';
|
49 |
+
$class = '';
|
50 |
$php_warning = $data['php']['old'];
|
51 |
|
52 |
if ( $php_warning ) {
|
55 |
'https://wordpress.org/support/update-php/',
|
56 |
esc_html__( 'Help', 'query-monitor' )
|
57 |
);
|
58 |
+
$class = 'qm-warn';
|
59 |
}
|
60 |
|
61 |
echo '<tr class="' . esc_attr( $class ) . '">';
|
86 |
echo '</tr>';
|
87 |
|
88 |
foreach ( $data['php']['variables'] as $key => $val ) {
|
89 |
+
$class = '';
|
90 |
$warners = array(
|
91 |
'max_execution_time',
|
92 |
'memory_limit',
|
190 |
|
191 |
$info = array(
|
192 |
'server-version' => __( 'Server Version', 'query-monitor' ),
|
193 |
+
'extension' => __( 'Extension', 'query-monitor' ),
|
194 |
'client-version' => __( 'Client Version', 'query-monitor' ),
|
195 |
+
'user' => __( 'User', 'query-monitor' ),
|
196 |
+
'host' => __( 'Host', 'query-monitor' ),
|
197 |
+
'database' => __( 'Database', 'query-monitor' ),
|
198 |
);
|
199 |
|
200 |
foreach ( $info as $field => $label ) {
|
290 |
echo '<h3>' . esc_html__( 'Server', 'query-monitor' ) . '</h3>';
|
291 |
|
292 |
$server = array(
|
293 |
+
'name' => __( 'Software', 'query-monitor' ),
|
294 |
'version' => __( 'Version', 'query-monitor' ),
|
295 |
+
'address' => __( 'IP Address', 'query-monitor' ),
|
296 |
+
'host' => __( 'Host', 'query-monitor' ),
|
297 |
+
/* translators: OS stands for Operating System */
|
298 |
+
'OS' => __( 'OS', 'query-monitor' ),
|
299 |
+
'arch' => __( 'Architecture', 'query-monitor' ),
|
300 |
);
|
301 |
|
302 |
echo '<table>';
|
322 |
|
323 |
}
|
324 |
|
325 |
+
/**
|
326 |
+
* @param array<string, QM_Output> $output
|
327 |
+
* @param QM_Collectors $collectors
|
328 |
+
* @return array<string, QM_Output>
|
329 |
+
*/
|
330 |
function register_qm_output_html_environment( array $output, QM_Collectors $collectors ) {
|
331 |
$collector = QM_Collectors::get( 'environment' );
|
332 |
if ( $collector ) {
|
output/html/headers.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Headers extends QM_Output_Html {
|
11 |
|
@@ -32,11 +34,17 @@ class QM_Output_Html_Headers extends QM_Output_Html {
|
|
32 |
return __( 'Request Data', 'query-monitor' );
|
33 |
}
|
34 |
|
|
|
|
|
|
|
35 |
public function output() {
|
36 |
$this->output_request();
|
37 |
$this->output_response();
|
38 |
}
|
39 |
|
|
|
|
|
|
|
40 |
public function output_request() {
|
41 |
$data = $this->collector->get_data();
|
42 |
|
@@ -47,9 +55,12 @@ class QM_Output_Html_Headers extends QM_Output_Html {
|
|
47 |
$this->after_tabular_output();
|
48 |
}
|
49 |
|
|
|
|
|
|
|
50 |
public function output_response() {
|
51 |
$data = $this->collector->get_data();
|
52 |
-
$id
|
53 |
|
54 |
$this->before_tabular_output( $id );
|
55 |
|
@@ -58,6 +69,11 @@ class QM_Output_Html_Headers extends QM_Output_Html {
|
|
58 |
$this->after_tabular_output();
|
59 |
}
|
60 |
|
|
|
|
|
|
|
|
|
|
|
61 |
protected function output_header_table( array $headers, $title ) {
|
62 |
echo '<thead>';
|
63 |
echo '<tr>';
|
@@ -87,19 +103,23 @@ class QM_Output_Html_Headers extends QM_Output_Html {
|
|
87 |
echo '</tfoot>';
|
88 |
}
|
89 |
|
|
|
|
|
|
|
|
|
90 |
public function panel_menu( array $menu ) {
|
91 |
if ( ! isset( $menu['qm-request'] ) ) {
|
92 |
return $menu;
|
93 |
}
|
94 |
|
95 |
$ids = array(
|
96 |
-
$this->collector->id()
|
97 |
$this->collector->id() . '-response' => __( 'Response Headers', 'query-monitor' ),
|
98 |
);
|
99 |
foreach ( $ids as $id => $title ) {
|
100 |
$menu['qm-request']['children'][] = array(
|
101 |
-
'id'
|
102 |
-
'href'
|
103 |
'title' => esc_html( $title ),
|
104 |
);
|
105 |
}
|
@@ -108,6 +128,11 @@ class QM_Output_Html_Headers extends QM_Output_Html {
|
|
108 |
}
|
109 |
}
|
110 |
|
|
|
|
|
|
|
|
|
|
|
111 |
function register_qm_output_html_headers( array $output, QM_Collectors $collectors ) {
|
112 |
$collector = QM_Collectors::get( 'raw_request' );
|
113 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Headers extends QM_Output_Html {
|
13 |
|
34 |
return __( 'Request Data', 'query-monitor' );
|
35 |
}
|
36 |
|
37 |
+
/**
|
38 |
+
* @return void
|
39 |
+
*/
|
40 |
public function output() {
|
41 |
$this->output_request();
|
42 |
$this->output_response();
|
43 |
}
|
44 |
|
45 |
+
/**
|
46 |
+
* @return void
|
47 |
+
*/
|
48 |
public function output_request() {
|
49 |
$data = $this->collector->get_data();
|
50 |
|
55 |
$this->after_tabular_output();
|
56 |
}
|
57 |
|
58 |
+
/**
|
59 |
+
* @return void
|
60 |
+
*/
|
61 |
public function output_response() {
|
62 |
$data = $this->collector->get_data();
|
63 |
+
$id = sprintf( 'qm-%s-response', $this->collector->id );
|
64 |
|
65 |
$this->before_tabular_output( $id );
|
66 |
|
69 |
$this->after_tabular_output();
|
70 |
}
|
71 |
|
72 |
+
/**
|
73 |
+
* @param array<string, string> $headers
|
74 |
+
* @param string $title
|
75 |
+
* @return void
|
76 |
+
*/
|
77 |
protected function output_header_table( array $headers, $title ) {
|
78 |
echo '<thead>';
|
79 |
echo '<tr>';
|
103 |
echo '</tfoot>';
|
104 |
}
|
105 |
|
106 |
+
/**
|
107 |
+
* @param array<string, mixed[]> $menu
|
108 |
+
* @return array<string, mixed[]>
|
109 |
+
*/
|
110 |
public function panel_menu( array $menu ) {
|
111 |
if ( ! isset( $menu['qm-request'] ) ) {
|
112 |
return $menu;
|
113 |
}
|
114 |
|
115 |
$ids = array(
|
116 |
+
$this->collector->id() => __( 'Request Headers', 'query-monitor' ),
|
117 |
$this->collector->id() . '-response' => __( 'Response Headers', 'query-monitor' ),
|
118 |
);
|
119 |
foreach ( $ids as $id => $title ) {
|
120 |
$menu['qm-request']['children'][] = array(
|
121 |
+
'id' => $id,
|
122 |
+
'href' => '#' . $id,
|
123 |
'title' => esc_html( $title ),
|
124 |
);
|
125 |
}
|
128 |
}
|
129 |
}
|
130 |
|
131 |
+
/**
|
132 |
+
* @param array<string, QM_Output> $output
|
133 |
+
* @param QM_Collectors $collectors
|
134 |
+
* @return array<string, QM_Output>
|
135 |
+
*/
|
136 |
function register_qm_output_html_headers( array $output, QM_Collectors $collectors ) {
|
137 |
$collector = QM_Collectors::get( 'raw_request' );
|
138 |
if ( $collector ) {
|
output/html/hooks.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Hooks extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 80 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Hooks & Actions', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -59,12 +67,16 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
|
|
59 |
$this->after_tabular_output();
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
62 |
public static function output_hook_table( array $hooks ) {
|
63 |
-
$core = __( 'Core', 'query-monitor' );
|
64 |
|
65 |
foreach ( $hooks as $hook ) {
|
66 |
-
$row_attr
|
67 |
-
$row_attr['data-qm-name']
|
68 |
$row_attr['data-qm-component'] = implode( ' ', $hook['components'] );
|
69 |
|
70 |
if ( ! empty( $row_attr['data-qm-component'] ) && $core !== $row_attr['data-qm-component'] ) {
|
@@ -89,11 +101,11 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
|
|
89 |
|
90 |
foreach ( $hook['actions'] as $action ) {
|
91 |
$component = '';
|
92 |
-
$subject
|
93 |
|
94 |
if ( isset( $action['callback']['component'] ) ) {
|
95 |
$component = $action['callback']['component']->name;
|
96 |
-
$subject
|
97 |
}
|
98 |
|
99 |
if ( $core !== $component ) {
|
@@ -196,6 +208,11 @@ class QM_Output_Html_Hooks extends QM_Output_Html {
|
|
196 |
|
197 |
}
|
198 |
|
|
|
|
|
|
|
|
|
|
|
199 |
function register_qm_output_html_hooks( array $output, QM_Collectors $collectors ) {
|
200 |
$collector = QM_Collectors::get( 'hooks' );
|
201 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Hooks extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 80 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Hooks & Actions', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
67 |
$this->after_tabular_output();
|
68 |
}
|
69 |
|
70 |
+
/**
|
71 |
+
* @param array<int, mixed[]> $hooks
|
72 |
+
* @return void
|
73 |
+
*/
|
74 |
public static function output_hook_table( array $hooks ) {
|
75 |
+
$core = __( 'WordPress Core', 'query-monitor' );
|
76 |
|
77 |
foreach ( $hooks as $hook ) {
|
78 |
+
$row_attr = array();
|
79 |
+
$row_attr['data-qm-name'] = implode( ' ', $hook['parts'] );
|
80 |
$row_attr['data-qm-component'] = implode( ' ', $hook['components'] );
|
81 |
|
82 |
if ( ! empty( $row_attr['data-qm-component'] ) && $core !== $row_attr['data-qm-component'] ) {
|
101 |
|
102 |
foreach ( $hook['actions'] as $action ) {
|
103 |
$component = '';
|
104 |
+
$subject = '';
|
105 |
|
106 |
if ( isset( $action['callback']['component'] ) ) {
|
107 |
$component = $action['callback']['component']->name;
|
108 |
+
$subject = $component;
|
109 |
}
|
110 |
|
111 |
if ( $core !== $component ) {
|
208 |
|
209 |
}
|
210 |
|
211 |
+
/**
|
212 |
+
* @param array<string, QM_Output> $output
|
213 |
+
* @param QM_Collectors $collectors
|
214 |
+
* @return array<string, QM_Output>
|
215 |
+
*/
|
216 |
function register_qm_output_html_hooks( array $output, QM_Collectors $collectors ) {
|
217 |
$collector = QM_Collectors::get( 'hooks' );
|
218 |
if ( $collector ) {
|
output/html/http.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_HTTP extends QM_Output_Html {
|
11 |
|
@@ -22,16 +24,22 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
22 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
25 |
public function name() {
|
26 |
return __( 'HTTP API Calls', 'query-monitor' );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
29 |
public function output() {
|
30 |
|
31 |
$data = $this->collector->get_data();
|
32 |
|
33 |
if ( ! empty( $data['http'] ) ) {
|
34 |
-
$statuses
|
35 |
$components = wp_list_pluck( $data['component_times'], 'component' );
|
36 |
|
37 |
usort( $statuses, 'strcasecmp' );
|
@@ -76,7 +84,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
76 |
$i++;
|
77 |
$is_error = false;
|
78 |
$row_attr = array();
|
79 |
-
$css
|
80 |
|
81 |
if ( is_wp_error( $row['response'] ) ) {
|
82 |
$response = $row['response']->get_error_message();
|
@@ -86,7 +94,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
86 |
$response = __( 'Non-blocking', 'query-monitor' );
|
87 |
} else {
|
88 |
$code = wp_remote_retrieve_response_code( $row['response'] );
|
89 |
-
$msg
|
90 |
|
91 |
if ( intval( $code ) >= 400 ) {
|
92 |
$is_error = true;
|
@@ -100,7 +108,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
100 |
$css = 'qm-warn';
|
101 |
}
|
102 |
|
103 |
-
$url
|
104 |
$info = '';
|
105 |
|
106 |
$url = preg_replace( '|^http:|', '<span class="qm-warn">http</span>:', $url );
|
@@ -120,45 +128,16 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
120 |
|
121 |
$component = $row['component'];
|
122 |
|
123 |
-
$stack
|
124 |
-
$filtered_trace = $row['
|
125 |
-
|
126 |
-
$filtered_trace = array_filter( $filtered_trace, function( $item ) {
|
127 |
-
// @TODO This should happen during collection.
|
128 |
-
if ( isset( $item['class'] ) ) {
|
129 |
-
return ! in_array( $item['class'], array(
|
130 |
-
'WP_Http',
|
131 |
-
), true );
|
132 |
-
}
|
133 |
-
|
134 |
-
if ( isset( $item['function'] ) ) {
|
135 |
-
return ! in_array( $item['function'], array(
|
136 |
-
'wp_safe_remote_request',
|
137 |
-
'wp_safe_remote_get',
|
138 |
-
'wp_safe_remote_post',
|
139 |
-
'wp_safe_remote_head',
|
140 |
-
'wp_remote_request',
|
141 |
-
'wp_remote_get',
|
142 |
-
'wp_remote_post',
|
143 |
-
'wp_remote_head',
|
144 |
-
'wp_remote_fopen',
|
145 |
-
'download_url',
|
146 |
-
'vip_safe_wp_remote_get',
|
147 |
-
'vip_safe_wp_remote_request',
|
148 |
-
'wpcom_vip_file_get_contents',
|
149 |
-
), true );
|
150 |
-
}
|
151 |
-
|
152 |
-
return true;
|
153 |
-
} );
|
154 |
|
155 |
-
foreach ( $filtered_trace as $
|
156 |
-
$stack[] = self::output_filename( $
|
157 |
}
|
158 |
|
159 |
$row_attr['data-qm-component'] = $component->name;
|
160 |
-
$row_attr['data-qm-type']
|
161 |
-
$row_attr['data-qm-time']
|
162 |
|
163 |
if ( 'core' !== $component->context ) {
|
164 |
$row_attr['data-qm-component'] .= ' non-core';
|
@@ -221,8 +200,8 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
221 |
|
222 |
if ( ! empty( $row['info'] ) ) {
|
223 |
$time_fields = array(
|
224 |
-
'namelookup_time'
|
225 |
-
'connect_time'
|
226 |
'starttransfer_time' => __( 'Transfer Start Time (TTFB)', 'query-monitor' ),
|
227 |
);
|
228 |
foreach ( $time_fields as $key => $value ) {
|
@@ -252,7 +231,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
252 |
|
253 |
$other_fields = array(
|
254 |
'content_type' => __( 'Response Content Type', 'query-monitor' ),
|
255 |
-
'primary_ip'
|
256 |
);
|
257 |
foreach ( $other_fields as $key => $value ) {
|
258 |
if ( ! isset( $row['info'][ $key ] ) ) {
|
@@ -316,7 +295,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
316 |
echo '<tfoot>';
|
317 |
|
318 |
$total_stime = number_format_i18n( $data['ltime'], 4 );
|
319 |
-
$count
|
320 |
|
321 |
echo '<tr>';
|
322 |
printf(
|
@@ -342,6 +321,10 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
342 |
}
|
343 |
}
|
344 |
|
|
|
|
|
|
|
|
|
345 |
public function admin_class( array $class ) {
|
346 |
|
347 |
$data = $this->collector->get_data();
|
@@ -357,6 +340,10 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
357 |
|
358 |
}
|
359 |
|
|
|
|
|
|
|
|
|
360 |
public function admin_menu( array $menu ) {
|
361 |
|
362 |
$data = $this->collector->get_data();
|
@@ -390,6 +377,11 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
|
|
390 |
|
391 |
}
|
392 |
|
|
|
|
|
|
|
|
|
|
|
393 |
function register_qm_output_html_http( array $output, QM_Collectors $collectors ) {
|
394 |
$collector = QM_Collectors::get( 'http' );
|
395 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_HTTP extends QM_Output_Html {
|
13 |
|
24 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
public function name() {
|
31 |
return __( 'HTTP API Calls', 'query-monitor' );
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
public function output() {
|
38 |
|
39 |
$data = $this->collector->get_data();
|
40 |
|
41 |
if ( ! empty( $data['http'] ) ) {
|
42 |
+
$statuses = array_keys( $data['types'] );
|
43 |
$components = wp_list_pluck( $data['component_times'], 'component' );
|
44 |
|
45 |
usort( $statuses, 'strcasecmp' );
|
84 |
$i++;
|
85 |
$is_error = false;
|
86 |
$row_attr = array();
|
87 |
+
$css = '';
|
88 |
|
89 |
if ( is_wp_error( $row['response'] ) ) {
|
90 |
$response = $row['response']->get_error_message();
|
94 |
$response = __( 'Non-blocking', 'query-monitor' );
|
95 |
} else {
|
96 |
$code = wp_remote_retrieve_response_code( $row['response'] );
|
97 |
+
$msg = wp_remote_retrieve_response_message( $row['response'] );
|
98 |
|
99 |
if ( intval( $code ) >= 400 ) {
|
100 |
$is_error = true;
|
108 |
$css = 'qm-warn';
|
109 |
}
|
110 |
|
111 |
+
$url = self::format_url( $row['url'] );
|
112 |
$info = '';
|
113 |
|
114 |
$url = preg_replace( '|^http:|', '<span class="qm-warn">http</span>:', $url );
|
128 |
|
129 |
$component = $row['component'];
|
130 |
|
131 |
+
$stack = array();
|
132 |
+
$filtered_trace = $row['filtered_trace'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
|
134 |
+
foreach ( $filtered_trace as $frame ) {
|
135 |
+
$stack[] = self::output_filename( $frame['display'], $frame['calling_file'], $frame['calling_line'] );
|
136 |
}
|
137 |
|
138 |
$row_attr['data-qm-component'] = $component->name;
|
139 |
+
$row_attr['data-qm-type'] = $row['type'];
|
140 |
+
$row_attr['data-qm-time'] = $row['ltime'];
|
141 |
|
142 |
if ( 'core' !== $component->context ) {
|
143 |
$row_attr['data-qm-component'] .= ' non-core';
|
200 |
|
201 |
if ( ! empty( $row['info'] ) ) {
|
202 |
$time_fields = array(
|
203 |
+
'namelookup_time' => __( 'DNS Resolution Time', 'query-monitor' ),
|
204 |
+
'connect_time' => __( 'Connection Time', 'query-monitor' ),
|
205 |
'starttransfer_time' => __( 'Transfer Start Time (TTFB)', 'query-monitor' ),
|
206 |
);
|
207 |
foreach ( $time_fields as $key => $value ) {
|
231 |
|
232 |
$other_fields = array(
|
233 |
'content_type' => __( 'Response Content Type', 'query-monitor' ),
|
234 |
+
'primary_ip' => __( 'IP Address', 'query-monitor' ),
|
235 |
);
|
236 |
foreach ( $other_fields as $key => $value ) {
|
237 |
if ( ! isset( $row['info'][ $key ] ) ) {
|
295 |
echo '<tfoot>';
|
296 |
|
297 |
$total_stime = number_format_i18n( $data['ltime'], 4 );
|
298 |
+
$count = count( $data['http'] );
|
299 |
|
300 |
echo '<tr>';
|
301 |
printf(
|
321 |
}
|
322 |
}
|
323 |
|
324 |
+
/**
|
325 |
+
* @param array<int, string> $class
|
326 |
+
* @return array<int, string>
|
327 |
+
*/
|
328 |
public function admin_class( array $class ) {
|
329 |
|
330 |
$data = $this->collector->get_data();
|
340 |
|
341 |
}
|
342 |
|
343 |
+
/**
|
344 |
+
* @param array<string, mixed[]> $menu
|
345 |
+
* @return array<string, mixed[]>
|
346 |
+
*/
|
347 |
public function admin_menu( array $menu ) {
|
348 |
|
349 |
$data = $this->collector->get_data();
|
377 |
|
378 |
}
|
379 |
|
380 |
+
/**
|
381 |
+
* @param array<string, QM_Output> $output
|
382 |
+
* @param QM_Collectors $collectors
|
383 |
+
* @return array<string, QM_Output>
|
384 |
+
*/
|
385 |
function register_qm_output_html_http( array $output, QM_Collectors $collectors ) {
|
386 |
$collector = QM_Collectors::get( 'http' );
|
387 |
if ( $collector ) {
|
output/html/languages.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Languages extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Languages extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 80 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Languages', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -75,7 +83,11 @@ class QM_Output_Html_Languages extends QM_Output_Html {
|
|
75 |
|
76 |
echo '<td class="qm-ltr">';
|
77 |
if ( $mofile['file'] ) {
|
78 |
-
|
|
|
|
|
|
|
|
|
79 |
} else {
|
80 |
echo '<em>' . esc_html__( 'None', 'query-monitor' ) . '</em>';
|
81 |
}
|
@@ -100,6 +112,10 @@ class QM_Output_Html_Languages extends QM_Output_Html {
|
|
100 |
$this->after_tabular_output();
|
101 |
}
|
102 |
|
|
|
|
|
|
|
|
|
103 |
public function admin_menu( array $menu ) {
|
104 |
|
105 |
$data = $this->collector->get_data();
|
@@ -115,6 +131,11 @@ class QM_Output_Html_Languages extends QM_Output_Html {
|
|
115 |
|
116 |
}
|
117 |
|
|
|
|
|
|
|
|
|
|
|
118 |
function register_qm_output_html_languages( array $output, QM_Collectors $collectors ) {
|
119 |
$collector = QM_Collectors::get( 'languages' );
|
120 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Languages extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 80 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Languages', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
83 |
|
84 |
echo '<td class="qm-ltr">';
|
85 |
if ( $mofile['file'] ) {
|
86 |
+
if ( $mofile['found'] && 'jed' === $mofile['type'] && self::has_clickable_links() ) {
|
87 |
+
echo self::output_filename( QM_Util::standard_dir( $mofile['file'], '' ), $mofile['file'], 1, true ); // WPCS: XSS ok.
|
88 |
+
} else {
|
89 |
+
echo esc_html( QM_Util::standard_dir( $mofile['file'], '' ) );
|
90 |
+
}
|
91 |
} else {
|
92 |
echo '<em>' . esc_html__( 'None', 'query-monitor' ) . '</em>';
|
93 |
}
|
112 |
$this->after_tabular_output();
|
113 |
}
|
114 |
|
115 |
+
/**
|
116 |
+
* @param array<string, mixed[]> $menu
|
117 |
+
* @return array<string, mixed[]>
|
118 |
+
*/
|
119 |
public function admin_menu( array $menu ) {
|
120 |
|
121 |
$data = $this->collector->get_data();
|
131 |
|
132 |
}
|
133 |
|
134 |
+
/**
|
135 |
+
* @param array<string, QM_Output> $output
|
136 |
+
* @param QM_Collectors $collectors
|
137 |
+
* @return array<string, QM_Output>
|
138 |
+
*/
|
139 |
function register_qm_output_html_languages( array $output, QM_Collectors $collectors ) {
|
140 |
$collector = QM_Collectors::get( 'languages' );
|
141 |
if ( $collector ) {
|
output/html/logger.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Logger extends QM_Output_Html {
|
11 |
|
@@ -22,10 +24,16 @@ class QM_Output_Html_Logger extends QM_Output_Html {
|
|
22 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
25 |
public function name() {
|
26 |
return __( 'Logger', 'query-monitor' );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
29 |
public function output() {
|
30 |
|
31 |
$data = $this->collector->get_data();
|
@@ -45,14 +53,34 @@ class QM_Output_Html_Logger extends QM_Output_Html {
|
|
45 |
return;
|
46 |
}
|
47 |
|
48 |
-
$levels =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
$this->before_tabular_output();
|
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
echo '<thead>';
|
53 |
echo '<tr>';
|
54 |
echo '<th scope="col" class="qm-filterable-column">';
|
55 |
-
echo $this->build_filter( 'type', $levels, __( 'Level', 'query-monitor' ) ); // WPCS: XSS ok.
|
56 |
echo '</th>';
|
57 |
echo '<th scope="col" class="qm-col-message">' . esc_html__( 'Message', 'query-monitor' ) . '</th>';
|
58 |
echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
|
@@ -65,11 +93,11 @@ class QM_Output_Html_Logger extends QM_Output_Html {
|
|
65 |
echo '<tbody>';
|
66 |
|
67 |
foreach ( $data['logs'] as $row ) {
|
68 |
-
$component = $row['
|
69 |
|
70 |
-
$row_attr
|
71 |
$row_attr['data-qm-component'] = $component->name;
|
72 |
-
$row_attr['data-qm-type']
|
73 |
|
74 |
$attr = '';
|
75 |
|
@@ -103,11 +131,11 @@ class QM_Output_Html_Logger extends QM_Output_Html {
|
|
103 |
esc_html( $row['message'] )
|
104 |
);
|
105 |
|
106 |
-
$stack
|
107 |
-
$filtered_trace = $row['
|
108 |
|
109 |
-
foreach ( $filtered_trace as $
|
110 |
-
$stack[] = self::output_filename( $
|
111 |
}
|
112 |
|
113 |
$caller = array_shift( $stack );
|
@@ -142,6 +170,10 @@ class QM_Output_Html_Logger extends QM_Output_Html {
|
|
142 |
$this->after_tabular_output();
|
143 |
}
|
144 |
|
|
|
|
|
|
|
|
|
145 |
public function admin_class( array $class ) {
|
146 |
$data = $this->collector->get_data();
|
147 |
|
@@ -159,9 +191,13 @@ class QM_Output_Html_Logger extends QM_Output_Html {
|
|
159 |
return $class;
|
160 |
}
|
161 |
|
|
|
|
|
|
|
|
|
162 |
public function admin_menu( array $menu ) {
|
163 |
-
$data
|
164 |
-
$key
|
165 |
$count = 0;
|
166 |
|
167 |
if ( ! empty( $data['logs'] ) ) {
|
@@ -181,7 +217,7 @@ class QM_Output_Html_Logger extends QM_Output_Html {
|
|
181 |
}
|
182 |
|
183 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
184 |
-
'id'
|
185 |
'title' => esc_html( sprintf(
|
186 |
$label,
|
187 |
number_format_i18n( $count )
|
@@ -193,6 +229,11 @@ class QM_Output_Html_Logger extends QM_Output_Html {
|
|
193 |
|
194 |
}
|
195 |
|
|
|
|
|
|
|
|
|
|
|
196 |
function register_qm_output_html_logger( array $output, QM_Collectors $collectors ) {
|
197 |
$collector = QM_Collectors::get( 'logger' );
|
198 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Logger extends QM_Output_Html {
|
13 |
|
24 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
public function name() {
|
31 |
return __( 'Logger', 'query-monitor' );
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
public function output() {
|
38 |
|
39 |
$data = $this->collector->get_data();
|
53 |
return;
|
54 |
}
|
55 |
|
56 |
+
$levels = array();
|
57 |
+
|
58 |
+
foreach ( $this->collector->get_levels() as $level ) {
|
59 |
+
if ( $data['counts'][ $level ] ) {
|
60 |
+
$levels[ $level ] = sprintf(
|
61 |
+
'%s (%d)',
|
62 |
+
ucfirst( $level ),
|
63 |
+
$data['counts'][ $level ]
|
64 |
+
);
|
65 |
+
} else {
|
66 |
+
$levels[ $level ] = ucfirst( $level );
|
67 |
+
}
|
68 |
+
}
|
69 |
|
70 |
$this->before_tabular_output();
|
71 |
|
72 |
+
$level_args = array(
|
73 |
+
'all' => sprintf(
|
74 |
+
/* translators: %s: Total number of items in a list */
|
75 |
+
__( 'All (%d)', 'query-monitor' ),
|
76 |
+
count( $data['logs'] )
|
77 |
+
),
|
78 |
+
);
|
79 |
+
|
80 |
echo '<thead>';
|
81 |
echo '<tr>';
|
82 |
echo '<th scope="col" class="qm-filterable-column">';
|
83 |
+
echo $this->build_filter( 'type', $levels, __( 'Level', 'query-monitor' ), $level_args ); // WPCS: XSS ok.
|
84 |
echo '</th>';
|
85 |
echo '<th scope="col" class="qm-col-message">' . esc_html__( 'Message', 'query-monitor' ) . '</th>';
|
86 |
echo '<th scope="col">' . esc_html__( 'Caller', 'query-monitor' ) . '</th>';
|
93 |
echo '<tbody>';
|
94 |
|
95 |
foreach ( $data['logs'] as $row ) {
|
96 |
+
$component = $row['component'];
|
97 |
|
98 |
+
$row_attr = array();
|
99 |
$row_attr['data-qm-component'] = $component->name;
|
100 |
+
$row_attr['data-qm-type'] = $row['level'];
|
101 |
|
102 |
$attr = '';
|
103 |
|
131 |
esc_html( $row['message'] )
|
132 |
);
|
133 |
|
134 |
+
$stack = array();
|
135 |
+
$filtered_trace = $row['filtered_trace'];
|
136 |
|
137 |
+
foreach ( $filtered_trace as $frame ) {
|
138 |
+
$stack[] = self::output_filename( $frame['display'], $frame['calling_file'], $frame['calling_line'] );
|
139 |
}
|
140 |
|
141 |
$caller = array_shift( $stack );
|
170 |
$this->after_tabular_output();
|
171 |
}
|
172 |
|
173 |
+
/**
|
174 |
+
* @param array<int, string> $class
|
175 |
+
* @return array<int, string>
|
176 |
+
*/
|
177 |
public function admin_class( array $class ) {
|
178 |
$data = $this->collector->get_data();
|
179 |
|
191 |
return $class;
|
192 |
}
|
193 |
|
194 |
+
/**
|
195 |
+
* @param array<string, mixed[]> $menu
|
196 |
+
* @return array<string, mixed[]>
|
197 |
+
*/
|
198 |
public function admin_menu( array $menu ) {
|
199 |
+
$data = $this->collector->get_data();
|
200 |
+
$key = 'log';
|
201 |
$count = 0;
|
202 |
|
203 |
if ( ! empty( $data['logs'] ) ) {
|
217 |
}
|
218 |
|
219 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
220 |
+
'id' => "query-monitor-logger-{$key}",
|
221 |
'title' => esc_html( sprintf(
|
222 |
$label,
|
223 |
number_format_i18n( $count )
|
229 |
|
230 |
}
|
231 |
|
232 |
+
/**
|
233 |
+
* @param array<string, QM_Output> $output
|
234 |
+
* @param QM_Collectors $collectors
|
235 |
+
* @return array<string, QM_Output>
|
236 |
+
*/
|
237 |
function register_qm_output_html_logger( array $output, QM_Collectors $collectors ) {
|
238 |
$collector = QM_Collectors::get( 'logger' );
|
239 |
if ( $collector ) {
|
output/html/overview.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Overview extends QM_Output_Html {
|
11 |
|
@@ -21,15 +23,21 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/title', array( $this, 'admin_title' ), 10 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Overview', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
$data = $this->collector->get_data();
|
30 |
|
31 |
-
$db_query_num
|
32 |
-
$db_queries
|
33 |
|
34 |
if ( $db_queries ) {
|
35 |
# @TODO: make this less derpy:
|
@@ -43,7 +51,7 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
43 |
$cache = QM_Collectors::get( 'cache' );
|
44 |
$http = QM_Collectors::get( 'http' );
|
45 |
|
46 |
-
$qm_broken
|
47 |
$ajax_errors = __( 'PHP errors were triggered during an Ajax request. See your browser developer console for details.', 'query-monitor' );
|
48 |
|
49 |
$this->before_non_tabular_output();
|
@@ -81,7 +89,13 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
81 |
echo '<section>';
|
82 |
echo '<h3>' . esc_html__( 'Page Generation Time', 'query-monitor' ) . '</h3>';
|
83 |
echo '<p>';
|
84 |
-
echo esc_html(
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
|
86 |
if ( $data['time_limit'] > 0 ) {
|
87 |
if ( $data['display_time_usage_warning'] ) {
|
@@ -117,9 +131,10 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
117 |
esc_html_e( 'Unknown', 'query-monitor' );
|
118 |
} else {
|
119 |
echo esc_html( sprintf(
|
120 |
-
/* translators:
|
121 |
-
__( '%s
|
122 |
-
number_format_i18n( $data['memory']
|
|
|
123 |
) );
|
124 |
|
125 |
if ( $data['memory_limit'] > 0 ) {
|
@@ -129,10 +144,10 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
129 |
echo '<br><span class="qm-info">';
|
130 |
}
|
131 |
echo esc_html( sprintf(
|
132 |
-
/* translators: 1: Percentage of memory limit used, 2: Memory limit in
|
133 |
-
__( '%1$s%% of %2$s
|
134 |
number_format_i18n( $data['memory_usage'], 1 ),
|
135 |
-
number_format_i18n( $data['memory_limit'] / 1024 )
|
136 |
) );
|
137 |
echo '</span>';
|
138 |
} else {
|
@@ -153,10 +168,10 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
153 |
echo '<br><span class="qm-info">';
|
154 |
}
|
155 |
echo esc_html( sprintf(
|
156 |
-
|
157 |
-
__( '%1$s%% of %2$s
|
158 |
number_format_i18n( $data['wp_memory_usage'], 1 ),
|
159 |
-
number_format_i18n( $data['wp_memory_limit'] / 1024 )
|
160 |
) );
|
161 |
echo '</span>';
|
162 |
}
|
@@ -169,11 +184,15 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
169 |
echo '<section>';
|
170 |
echo '<h3>' . esc_html__( 'Database Queries', 'query-monitor' ) . '</h3>';
|
171 |
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
|
|
|
|
|
|
|
|
177 |
|
178 |
echo '<p>';
|
179 |
|
@@ -205,10 +224,16 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
205 |
$http_data = $http->get_data();
|
206 |
|
207 |
if ( ! empty( $http_data['http'] ) ) {
|
208 |
-
|
209 |
-
|
210 |
-
|
|
|
|
|
|
|
|
|
211 |
);
|
|
|
|
|
212 |
printf(
|
213 |
'<button class="qm-filter-trigger" data-qm-target="http" data-qm-filter="type" data-qm-value="">%1$s: %2$s</button>',
|
214 |
esc_html( _x( 'Total', 'HTTP API calls', 'query-monitor' ) ),
|
@@ -224,10 +249,10 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
224 |
echo '</section>';
|
225 |
}
|
226 |
|
227 |
-
|
228 |
-
|
229 |
-
echo '<h3>' . esc_html__( 'Object Cache', 'query-monitor' ) . '</h3>';
|
230 |
|
|
|
231 |
$cache_data = $cache->get_data();
|
232 |
if ( isset( $cache_data['stats'] ) && isset( $cache_data['cache_hit_percentage'] ) ) {
|
233 |
$cache_hit_percentage = $cache_data['cache_hit_percentage'];
|
@@ -243,10 +268,6 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
243 |
number_format_i18n( $cache_data['stats']['cache_misses'], 0 )
|
244 |
) );
|
245 |
echo '</p>';
|
246 |
-
} else {
|
247 |
-
echo '<p>';
|
248 |
-
echo esc_html__( 'Object cache statistics are not available', 'query-monitor' );
|
249 |
-
echo '</p>';
|
250 |
}
|
251 |
|
252 |
if ( $cache_data['has_object_cache'] ) {
|
@@ -254,28 +275,59 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
254 |
printf(
|
255 |
'<a href="%s" class="qm-link">%s</a>',
|
256 |
esc_url( network_admin_url( 'plugins.php?plugin_status=dropins' ) ),
|
257 |
-
esc_html__( '
|
258 |
);
|
259 |
echo '</span></p>';
|
260 |
} else {
|
261 |
-
echo '<p>';
|
262 |
-
echo esc_html__( '
|
263 |
-
echo '</p>';
|
264 |
|
265 |
$potentials = array_filter( $cache_data['object_cache_extensions'] );
|
266 |
|
267 |
if ( ! empty( $potentials ) ) {
|
268 |
foreach ( $potentials as $name => $value ) {
|
|
|
|
|
|
|
|
|
269 |
echo '<p>';
|
270 |
-
echo
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
echo '</p>';
|
276 |
}
|
|
|
|
|
|
|
|
|
277 |
}
|
278 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
|
280 |
if ( $cache_data['has_opcode_cache'] ) {
|
281 |
foreach ( array_filter( $cache_data['opcode_cache_extensions'] ) as $opcache_name => $opcache_state ) {
|
@@ -287,7 +339,14 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
287 |
) );
|
288 |
echo '</p>';
|
289 |
}
|
290 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
|
292 |
echo '</section>';
|
293 |
}
|
@@ -295,6 +354,10 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
295 |
$this->after_non_tabular_output();
|
296 |
}
|
297 |
|
|
|
|
|
|
|
|
|
298 |
public function admin_title( array $existing ) {
|
299 |
|
300 |
$data = $this->collector->get_data();
|
@@ -302,17 +365,17 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
302 |
if ( empty( $data['memory'] ) ) {
|
303 |
$memory = '??';
|
304 |
} else {
|
305 |
-
$memory = number_format_i18n( ( $data['memory'] / 1024 ),
|
306 |
}
|
307 |
|
308 |
$title[] = sprintf(
|
309 |
-
/* translators: %s:
|
310 |
-
|
311 |
number_format_i18n( $data['time_taken'], 2 )
|
312 |
);
|
313 |
$title[] = sprintf(
|
314 |
-
/* translators: %s: Memory usage in
|
315 |
-
|
316 |
$memory
|
317 |
);
|
318 |
|
@@ -327,6 +390,11 @@ class QM_Output_Html_Overview extends QM_Output_Html {
|
|
327 |
|
328 |
}
|
329 |
|
|
|
|
|
|
|
|
|
|
|
330 |
function register_qm_output_html_overview( array $output, QM_Collectors $collectors ) {
|
331 |
$collector = QM_Collectors::get( 'overview' );
|
332 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Overview extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/title', array( $this, 'admin_title' ), 10 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Overview', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
$data = $this->collector->get_data();
|
38 |
|
39 |
+
$db_query_num = null;
|
40 |
+
$db_queries = QM_Collectors::get( 'db_queries' );
|
41 |
|
42 |
if ( $db_queries ) {
|
43 |
# @TODO: make this less derpy:
|
51 |
$cache = QM_Collectors::get( 'cache' );
|
52 |
$http = QM_Collectors::get( 'http' );
|
53 |
|
54 |
+
$qm_broken = __( 'A JavaScript problem on the page is preventing Query Monitor from working correctly. jQuery may have been blocked from loading.', 'query-monitor' );
|
55 |
$ajax_errors = __( 'PHP errors were triggered during an Ajax request. See your browser developer console for details.', 'query-monitor' );
|
56 |
|
57 |
$this->before_non_tabular_output();
|
89 |
echo '<section>';
|
90 |
echo '<h3>' . esc_html__( 'Page Generation Time', 'query-monitor' ) . '</h3>';
|
91 |
echo '<p>';
|
92 |
+
echo esc_html(
|
93 |
+
sprintf(
|
94 |
+
/* translators: %s: A time in seconds with a decimal fraction. No space between value and unit. */
|
95 |
+
_x( '%ss', 'Time in seconds', 'query-monitor' ),
|
96 |
+
number_format_i18n( $data['time_taken'], 4 )
|
97 |
+
)
|
98 |
+
);
|
99 |
|
100 |
if ( $data['time_limit'] > 0 ) {
|
101 |
if ( $data['display_time_usage_warning'] ) {
|
131 |
esc_html_e( 'Unknown', 'query-monitor' );
|
132 |
} else {
|
133 |
echo esc_html( sprintf(
|
134 |
+
/* translators: 1: Memory used in bytes, 2: Memory used in megabytes */
|
135 |
+
__( '%1$s bytes (%2$s MB)', 'query-monitor' ),
|
136 |
+
number_format_i18n( $data['memory'] ),
|
137 |
+
number_format_i18n( ( $data['memory'] / 1024 / 1024 ), 1 )
|
138 |
) );
|
139 |
|
140 |
if ( $data['memory_limit'] > 0 ) {
|
144 |
echo '<br><span class="qm-info">';
|
145 |
}
|
146 |
echo esc_html( sprintf(
|
147 |
+
/* translators: 1: Percentage of memory limit used, 2: Memory limit in megabytes */
|
148 |
+
__( '%1$s%% of %2$s MB server limit', 'query-monitor' ),
|
149 |
number_format_i18n( $data['memory_usage'], 1 ),
|
150 |
+
number_format_i18n( $data['memory_limit'] / 1024 / 1024 )
|
151 |
) );
|
152 |
echo '</span>';
|
153 |
} else {
|
168 |
echo '<br><span class="qm-info">';
|
169 |
}
|
170 |
echo esc_html( sprintf(
|
171 |
+
/* translators: 1: Percentage of memory limit used, 2: Memory limit in megabytes */
|
172 |
+
__( '%1$s%% of %2$s MB WordPress limit', 'query-monitor' ),
|
173 |
number_format_i18n( $data['wp_memory_usage'], 1 ),
|
174 |
+
number_format_i18n( $data['wp_memory_limit'] / 1024 / 1024 )
|
175 |
) );
|
176 |
echo '</span>';
|
177 |
}
|
184 |
echo '<section>';
|
185 |
echo '<h3>' . esc_html__( 'Database Queries', 'query-monitor' ) . '</h3>';
|
186 |
|
187 |
+
echo '<p>';
|
188 |
+
echo esc_html(
|
189 |
+
sprintf(
|
190 |
+
/* translators: %s: A time in seconds with a decimal fraction. No space between value and unit. */
|
191 |
+
_x( '%ss', 'Time in seconds', 'query-monitor' ),
|
192 |
+
number_format_i18n( $db_queries_data['total_time'], 4 )
|
193 |
+
)
|
194 |
+
);
|
195 |
+
echo '</p>';
|
196 |
|
197 |
echo '<p>';
|
198 |
|
224 |
$http_data = $http->get_data();
|
225 |
|
226 |
if ( ! empty( $http_data['http'] ) ) {
|
227 |
+
echo '<p>';
|
228 |
+
echo esc_html(
|
229 |
+
sprintf(
|
230 |
+
/* translators: %s: A time in seconds with a decimal fraction. No space between value and unit. */
|
231 |
+
_x( '%ss', 'Time in seconds', 'query-monitor' ),
|
232 |
+
number_format_i18n( $http_data['ltime'], 4 )
|
233 |
+
)
|
234 |
);
|
235 |
+
echo '</p>';
|
236 |
+
|
237 |
printf(
|
238 |
'<button class="qm-filter-trigger" data-qm-target="http" data-qm-filter="type" data-qm-value="">%1$s: %2$s</button>',
|
239 |
esc_html( _x( 'Total', 'HTTP API calls', 'query-monitor' ) ),
|
249 |
echo '</section>';
|
250 |
}
|
251 |
|
252 |
+
echo '<section>';
|
253 |
+
echo '<h3>' . esc_html__( 'Object Cache', 'query-monitor' ) . '</h3>';
|
|
|
254 |
|
255 |
+
if ( $cache ) {
|
256 |
$cache_data = $cache->get_data();
|
257 |
if ( isset( $cache_data['stats'] ) && isset( $cache_data['cache_hit_percentage'] ) ) {
|
258 |
$cache_hit_percentage = $cache_data['cache_hit_percentage'];
|
268 |
number_format_i18n( $cache_data['stats']['cache_misses'], 0 )
|
269 |
) );
|
270 |
echo '</p>';
|
|
|
|
|
|
|
|
|
271 |
}
|
272 |
|
273 |
if ( $cache_data['has_object_cache'] ) {
|
275 |
printf(
|
276 |
'<a href="%s" class="qm-link">%s</a>',
|
277 |
esc_url( network_admin_url( 'plugins.php?plugin_status=dropins' ) ),
|
278 |
+
esc_html__( 'Persistent object cache plugin in use', 'query-monitor' )
|
279 |
);
|
280 |
echo '</span></p>';
|
281 |
} else {
|
282 |
+
echo '<p><span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
|
283 |
+
echo esc_html__( 'Persistent object cache plugin not in use', 'query-monitor' );
|
284 |
+
echo '</span></p>';
|
285 |
|
286 |
$potentials = array_filter( $cache_data['object_cache_extensions'] );
|
287 |
|
288 |
if ( ! empty( $potentials ) ) {
|
289 |
foreach ( $potentials as $name => $value ) {
|
290 |
+
$url = sprintf(
|
291 |
+
'https://wordpress.org/plugins/search/%s/',
|
292 |
+
strtolower( $name )
|
293 |
+
);
|
294 |
echo '<p>';
|
295 |
+
echo wp_kses(
|
296 |
+
sprintf(
|
297 |
+
/* translators: 1: PHP extension name, 2: URL to plugin directory */
|
298 |
+
__( 'The %1$s object cache extension for PHP is installed but is not in use by WordPress. You should <a href="%2$s" target="_blank" class="qm-external-link">install a %1$s plugin</a>.', 'query-monitor' ),
|
299 |
+
esc_html( $name ),
|
300 |
+
esc_url( $url )
|
301 |
+
),
|
302 |
+
array(
|
303 |
+
'a' => array(
|
304 |
+
'href' => array(),
|
305 |
+
'target' => array(),
|
306 |
+
'class' => array(),
|
307 |
+
),
|
308 |
+
)
|
309 |
+
);
|
310 |
echo '</p>';
|
311 |
}
|
312 |
+
} else {
|
313 |
+
echo '<p>';
|
314 |
+
echo esc_html__( 'Speak to your web host about enabling an object cache extension such as Redis or Memcached.', 'query-monitor' );
|
315 |
+
echo '</p>';
|
316 |
}
|
317 |
}
|
318 |
+
} else {
|
319 |
+
echo '<p>';
|
320 |
+
echo esc_html__( 'Object cache statistics are not available', 'query-monitor' );
|
321 |
+
echo '</p>';
|
322 |
+
}
|
323 |
+
|
324 |
+
echo '</section>';
|
325 |
+
|
326 |
+
if ( $cache ) {
|
327 |
+
$cache_data = $cache->get_data();
|
328 |
+
|
329 |
+
echo '<section>';
|
330 |
+
echo '<h3>' . esc_html__( 'Opcode Cache', 'query-monitor' ) . '</h3>';
|
331 |
|
332 |
if ( $cache_data['has_opcode_cache'] ) {
|
333 |
foreach ( array_filter( $cache_data['opcode_cache_extensions'] ) as $opcache_name => $opcache_state ) {
|
339 |
) );
|
340 |
echo '</p>';
|
341 |
}
|
342 |
+
} else {
|
343 |
+
echo '<p><span class="qm-warn"><span class="dashicons dashicons-warning" aria-hidden="true"></span>';
|
344 |
+
echo esc_html__( 'Opcode cache not in use', 'query-monitor' );
|
345 |
+
echo '</span></p>';
|
346 |
+
echo '<p>';
|
347 |
+
echo esc_html__( 'Speak to your web host about enabling an opcode cache such as OPcache.', 'query-monitor' );
|
348 |
+
echo '</p>';
|
349 |
+
}
|
350 |
|
351 |
echo '</section>';
|
352 |
}
|
354 |
$this->after_non_tabular_output();
|
355 |
}
|
356 |
|
357 |
+
/**
|
358 |
+
* @param array<int, string> $existing
|
359 |
+
* @return array<int, string>
|
360 |
+
*/
|
361 |
public function admin_title( array $existing ) {
|
362 |
|
363 |
$data = $this->collector->get_data();
|
365 |
if ( empty( $data['memory'] ) ) {
|
366 |
$memory = '??';
|
367 |
} else {
|
368 |
+
$memory = number_format_i18n( ( $data['memory'] / 1024 / 1024 ), 1 );
|
369 |
}
|
370 |
|
371 |
$title[] = sprintf(
|
372 |
+
/* translators: %s: Time in seconds with a decimal fraction. Note the space between value and unit. */
|
373 |
+
esc_html__( '%s S', 'query-monitor' ),
|
374 |
number_format_i18n( $data['time_taken'], 2 )
|
375 |
);
|
376 |
$title[] = sprintf(
|
377 |
+
/* translators: %s: Memory usage in megabytes with a decimal fraction. Note the space between value and unit. */
|
378 |
+
esc_html__( '%s MB', 'query-monitor' ),
|
379 |
$memory
|
380 |
);
|
381 |
|
390 |
|
391 |
}
|
392 |
|
393 |
+
/**
|
394 |
+
* @param array<string, QM_Output> $output
|
395 |
+
* @param QM_Collectors $collectors
|
396 |
+
* @return array<string, QM_Output>
|
397 |
+
*/
|
398 |
function register_qm_output_html_overview( array $output, QM_Collectors $collectors ) {
|
399 |
$collector = QM_Collectors::get( 'overview' );
|
400 |
if ( $collector ) {
|
output/html/php_errors.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
11 |
|
@@ -23,10 +25,16 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
23 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
24 |
}
|
25 |
|
|
|
|
|
|
|
26 |
public function name() {
|
27 |
return __( 'PHP Errors', 'query-monitor' );
|
28 |
}
|
29 |
|
|
|
|
|
|
|
30 |
public function output() {
|
31 |
|
32 |
$data = $this->collector->get_data();
|
@@ -35,7 +43,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
35 |
return;
|
36 |
}
|
37 |
|
38 |
-
$levels
|
39 |
'Warning',
|
40 |
'Notice',
|
41 |
'Strict',
|
@@ -72,12 +80,12 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
72 |
|
73 |
foreach ( $data[ $error_group ][ $type ] as $error_key => $error ) {
|
74 |
|
75 |
-
$row_attr
|
76 |
-
$row_attr['data-qm-type']
|
77 |
-
$row_attr['data-qm-key']
|
78 |
|
79 |
-
if ( $error['
|
80 |
-
$component
|
81 |
$row_attr['data-qm-component'] = $component->name;
|
82 |
|
83 |
if ( 'core' !== $component->context ) {
|
@@ -114,10 +122,10 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
114 |
echo '<td class="qm-ltr">' . esc_html( $error['message'] ) . '</td>';
|
115 |
echo '<td class="qm-num">' . esc_html( number_format_i18n( $error['calls'] ) ) . '</td>';
|
116 |
|
117 |
-
$stack
|
118 |
|
119 |
-
if ( $error['
|
120 |
-
$filtered_trace = $error['
|
121 |
|
122 |
// debug_backtrace() (used within QM_Backtrace) doesn't like being used within an error handler so
|
123 |
// we need to handle its somewhat unreliable stack trace items.
|
@@ -167,6 +175,10 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
167 |
$this->after_tabular_output();
|
168 |
}
|
169 |
|
|
|
|
|
|
|
|
|
170 |
public function admin_class( array $class ) {
|
171 |
|
172 |
$data = $this->collector->get_data();
|
@@ -181,41 +193,45 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
181 |
|
182 |
}
|
183 |
|
|
|
|
|
|
|
|
|
184 |
public function admin_menu( array $menu ) {
|
185 |
|
186 |
-
$data
|
187 |
$menu_label = array();
|
188 |
|
189 |
$types = array(
|
190 |
/* translators: %s: Number of deprecated PHP errors */
|
191 |
'deprecated' => _nx_noop( '%s Deprecated', '%s Deprecated', 'PHP error level', 'query-monitor' ),
|
192 |
/* translators: %s: Number of strict PHP errors */
|
193 |
-
'strict'
|
194 |
/* translators: %s: Number of PHP notices */
|
195 |
-
'notice'
|
196 |
/* translators: %s: Number of PHP warnings */
|
197 |
-
'warning'
|
198 |
);
|
199 |
|
200 |
-
$key
|
201 |
$generic = false;
|
202 |
|
203 |
foreach ( $types as $type => $label ) {
|
204 |
|
205 |
-
$count
|
206 |
$has_errors = false;
|
207 |
|
208 |
if ( isset( $data['suppressed'][ $type ] ) ) {
|
209 |
$has_errors = true;
|
210 |
-
$generic
|
211 |
}
|
212 |
if ( isset( $data['silenced'][ $type ] ) ) {
|
213 |
$has_errors = true;
|
214 |
-
$generic
|
215 |
}
|
216 |
if ( isset( $data['errors'][ $type ] ) ) {
|
217 |
$has_errors = true;
|
218 |
-
$key
|
219 |
$count += array_sum( wp_list_pluck( $data['errors'][ $type ], 'calls' ) );
|
220 |
}
|
221 |
|
@@ -224,7 +240,7 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
224 |
}
|
225 |
|
226 |
if ( $count ) {
|
227 |
-
$label
|
228 |
translate_nooped_plural(
|
229 |
$label,
|
230 |
$count,
|
@@ -256,19 +272,23 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
256 |
}
|
257 |
|
258 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
259 |
-
'id'
|
260 |
'title' => $title,
|
261 |
) );
|
262 |
return $menu;
|
263 |
|
264 |
}
|
265 |
|
|
|
|
|
|
|
|
|
266 |
public function panel_menu( array $menu ) {
|
267 |
if ( ! isset( $menu[ $this->collector->id() ] ) ) {
|
268 |
return $menu;
|
269 |
}
|
270 |
|
271 |
-
$data
|
272 |
$count = 0;
|
273 |
$types = array(
|
274 |
'suppressed',
|
@@ -295,6 +315,11 @@ class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
|
295 |
|
296 |
}
|
297 |
|
|
|
|
|
|
|
|
|
|
|
298 |
function register_qm_output_html_php_errors( array $output, QM_Collectors $collectors ) {
|
299 |
$collector = QM_Collectors::get( 'php_errors' );
|
300 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_PHP_Errors extends QM_Output_Html {
|
13 |
|
25 |
add_filter( 'qm/output/menu_class', array( $this, 'admin_class' ) );
|
26 |
}
|
27 |
|
28 |
+
/**
|
29 |
+
* @return string
|
30 |
+
*/
|
31 |
public function name() {
|
32 |
return __( 'PHP Errors', 'query-monitor' );
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* @return void
|
37 |
+
*/
|
38 |
public function output() {
|
39 |
|
40 |
$data = $this->collector->get_data();
|
43 |
return;
|
44 |
}
|
45 |
|
46 |
+
$levels = array(
|
47 |
'Warning',
|
48 |
'Notice',
|
49 |
'Strict',
|
80 |
|
81 |
foreach ( $data[ $error_group ][ $type ] as $error_key => $error ) {
|
82 |
|
83 |
+
$row_attr = array();
|
84 |
+
$row_attr['data-qm-type'] = ucfirst( $type );
|
85 |
+
$row_attr['data-qm-key'] = $error_key;
|
86 |
|
87 |
+
if ( $error['component'] ) {
|
88 |
+
$component = $error['component'];
|
89 |
$row_attr['data-qm-component'] = $component->name;
|
90 |
|
91 |
if ( 'core' !== $component->context ) {
|
122 |
echo '<td class="qm-ltr">' . esc_html( $error['message'] ) . '</td>';
|
123 |
echo '<td class="qm-num">' . esc_html( number_format_i18n( $error['calls'] ) ) . '</td>';
|
124 |
|
125 |
+
$stack = array();
|
126 |
|
127 |
+
if ( $error['filtered_trace'] ) {
|
128 |
+
$filtered_trace = $error['filtered_trace'];
|
129 |
|
130 |
// debug_backtrace() (used within QM_Backtrace) doesn't like being used within an error handler so
|
131 |
// we need to handle its somewhat unreliable stack trace items.
|
175 |
$this->after_tabular_output();
|
176 |
}
|
177 |
|
178 |
+
/**
|
179 |
+
* @param array<int, string> $class
|
180 |
+
* @return array<int, string>
|
181 |
+
*/
|
182 |
public function admin_class( array $class ) {
|
183 |
|
184 |
$data = $this->collector->get_data();
|
193 |
|
194 |
}
|
195 |
|
196 |
+
/**
|
197 |
+
* @param array<string, mixed[]> $menu
|
198 |
+
* @return array<string, mixed[]>
|
199 |
+
*/
|
200 |
public function admin_menu( array $menu ) {
|
201 |
|
202 |
+
$data = $this->collector->get_data();
|
203 |
$menu_label = array();
|
204 |
|
205 |
$types = array(
|
206 |
/* translators: %s: Number of deprecated PHP errors */
|
207 |
'deprecated' => _nx_noop( '%s Deprecated', '%s Deprecated', 'PHP error level', 'query-monitor' ),
|
208 |
/* translators: %s: Number of strict PHP errors */
|
209 |
+
'strict' => _nx_noop( '%s Strict', '%s Stricts', 'PHP error level', 'query-monitor' ),
|
210 |
/* translators: %s: Number of PHP notices */
|
211 |
+
'notice' => _nx_noop( '%s Notice', '%s Notices', 'PHP error level', 'query-monitor' ),
|
212 |
/* translators: %s: Number of PHP warnings */
|
213 |
+
'warning' => _nx_noop( '%s Warning', '%s Warnings', 'PHP error level', 'query-monitor' ),
|
214 |
);
|
215 |
|
216 |
+
$key = 'quiet';
|
217 |
$generic = false;
|
218 |
|
219 |
foreach ( $types as $type => $label ) {
|
220 |
|
221 |
+
$count = 0;
|
222 |
$has_errors = false;
|
223 |
|
224 |
if ( isset( $data['suppressed'][ $type ] ) ) {
|
225 |
$has_errors = true;
|
226 |
+
$generic = true;
|
227 |
}
|
228 |
if ( isset( $data['silenced'][ $type ] ) ) {
|
229 |
$has_errors = true;
|
230 |
+
$generic = true;
|
231 |
}
|
232 |
if ( isset( $data['errors'][ $type ] ) ) {
|
233 |
$has_errors = true;
|
234 |
+
$key = $type;
|
235 |
$count += array_sum( wp_list_pluck( $data['errors'][ $type ], 'calls' ) );
|
236 |
}
|
237 |
|
240 |
}
|
241 |
|
242 |
if ( $count ) {
|
243 |
+
$label = sprintf(
|
244 |
translate_nooped_plural(
|
245 |
$label,
|
246 |
$count,
|
272 |
}
|
273 |
|
274 |
$menu[ $this->collector->id() ] = $this->menu( array(
|
275 |
+
'id' => "query-monitor-{$key}s",
|
276 |
'title' => $title,
|
277 |
) );
|
278 |
return $menu;
|
279 |
|
280 |
}
|
281 |
|
282 |
+
/**
|
283 |
+
* @param array<string, mixed[]> $menu
|
284 |
+
* @return array<string, mixed[]>
|
285 |
+
*/
|
286 |
public function panel_menu( array $menu ) {
|
287 |
if ( ! isset( $menu[ $this->collector->id() ] ) ) {
|
288 |
return $menu;
|
289 |
}
|
290 |
|
291 |
+
$data = $this->collector->get_data();
|
292 |
$count = 0;
|
293 |
$types = array(
|
294 |
'suppressed',
|
315 |
|
316 |
}
|
317 |
|
318 |
+
/**
|
319 |
+
* @param array<string, QM_Output> $output
|
320 |
+
* @param QM_Collectors $collectors
|
321 |
+
* @return array<string, QM_Output>
|
322 |
+
*/
|
323 |
function register_qm_output_html_php_errors( array $output, QM_Collectors $collectors ) {
|
324 |
$collector = QM_Collectors::get( 'php_errors' );
|
325 |
if ( $collector ) {
|
output/html/request.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Request extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Request extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 50 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Request', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -35,10 +43,10 @@ class QM_Output_Html_Request extends QM_Output_Html {
|
|
35 |
$this->before_non_tabular_output();
|
36 |
|
37 |
foreach ( array(
|
38 |
-
'request'
|
39 |
-
'matched_rule'
|
40 |
'matched_query' => __( 'Matched Query', 'query-monitor' ),
|
41 |
-
'query_string'
|
42 |
) as $item => $name ) {
|
43 |
if ( is_admin() && ! isset( $data['request'][ $item ] ) ) {
|
44 |
continue;
|
@@ -179,9 +187,9 @@ class QM_Output_Html_Request extends QM_Output_Html {
|
|
179 |
echo '<table>';
|
180 |
|
181 |
foreach ( array(
|
182 |
-
'ip'
|
183 |
'method' => __( 'HTTP method', 'query-monitor' ),
|
184 |
-
'url'
|
185 |
) as $item => $name ) {
|
186 |
echo '<tr>';
|
187 |
echo '<th scope="row">' . esc_html( $name ) . '</td>';
|
@@ -197,9 +205,13 @@ class QM_Output_Html_Request extends QM_Output_Html {
|
|
197 |
$this->after_non_tabular_output();
|
198 |
}
|
199 |
|
|
|
|
|
|
|
|
|
200 |
public function admin_menu( array $menu ) {
|
201 |
|
202 |
-
$data
|
203 |
$count = isset( $data['plugin_qvars'] ) ? count( $data['plugin_qvars'] ) : 0;
|
204 |
|
205 |
$title = ( empty( $count ) )
|
@@ -219,6 +231,11 @@ class QM_Output_Html_Request extends QM_Output_Html {
|
|
219 |
|
220 |
}
|
221 |
|
|
|
|
|
|
|
|
|
|
|
222 |
function register_qm_output_html_request( array $output, QM_Collectors $collectors ) {
|
223 |
$collector = QM_Collectors::get( 'request' );
|
224 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Request extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 50 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Request', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
43 |
$this->before_non_tabular_output();
|
44 |
|
45 |
foreach ( array(
|
46 |
+
'request' => __( 'Request', 'query-monitor' ),
|
47 |
+
'matched_rule' => __( 'Matched Rule', 'query-monitor' ),
|
48 |
'matched_query' => __( 'Matched Query', 'query-monitor' ),
|
49 |
+
'query_string' => __( 'Query String', 'query-monitor' ),
|
50 |
) as $item => $name ) {
|
51 |
if ( is_admin() && ! isset( $data['request'][ $item ] ) ) {
|
52 |
continue;
|
187 |
echo '<table>';
|
188 |
|
189 |
foreach ( array(
|
190 |
+
'ip' => __( 'Remote IP', 'query-monitor' ),
|
191 |
'method' => __( 'HTTP method', 'query-monitor' ),
|
192 |
+
'url' => __( 'Requested URL', 'query-monitor' ),
|
193 |
) as $item => $name ) {
|
194 |
echo '<tr>';
|
195 |
echo '<th scope="row">' . esc_html( $name ) . '</td>';
|
205 |
$this->after_non_tabular_output();
|
206 |
}
|
207 |
|
208 |
+
/**
|
209 |
+
* @param array<string, mixed[]> $menu
|
210 |
+
* @return array<string, mixed[]>
|
211 |
+
*/
|
212 |
public function admin_menu( array $menu ) {
|
213 |
|
214 |
+
$data = $this->collector->get_data();
|
215 |
$count = isset( $data['plugin_qvars'] ) ? count( $data['plugin_qvars'] ) : 0;
|
216 |
|
217 |
$title = ( empty( $count ) )
|
231 |
|
232 |
}
|
233 |
|
234 |
+
/**
|
235 |
+
* @param array<string, QM_Output> $output
|
236 |
+
* @param QM_Collectors $collectors
|
237 |
+
* @return array<string, QM_Output>
|
238 |
+
*/
|
239 |
function register_qm_output_html_request( array $output, QM_Collectors $collectors ) {
|
240 |
$collector = QM_Collectors::get( 'request' );
|
241 |
if ( $collector ) {
|
output/html/theme.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Theme extends QM_Output_Html {
|
11 |
|
@@ -22,10 +24,16 @@ class QM_Output_Html_Theme extends QM_Output_Html {
|
|
22 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 60 );
|
23 |
}
|
24 |
|
|
|
|
|
|
|
25 |
public function name() {
|
26 |
return __( 'Theme', 'query-monitor' );
|
27 |
}
|
28 |
|
|
|
|
|
|
|
29 |
public function output() {
|
30 |
$data = $this->collector->get_data();
|
31 |
|
@@ -65,13 +73,6 @@ class QM_Output_Html_Theme extends QM_Output_Html {
|
|
65 |
echo '<p><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></p>';
|
66 |
}
|
67 |
|
68 |
-
if ( ! empty( $data['template_altered'] ) ) {
|
69 |
-
printf(
|
70 |
-
'<p><button class="qm-filter-trigger qm-filter-info" data-qm-target="response-concerned_hooks">%s</button></p>',
|
71 |
-
esc_html__( 'Template Hooks in Use', 'query-monitor' )
|
72 |
-
);
|
73 |
-
}
|
74 |
-
|
75 |
if ( ! empty( $data['template_hierarchy'] ) ) {
|
76 |
echo '<h3>' . esc_html__( 'Template Hierarchy', 'query-monitor' ) . '</h3>';
|
77 |
echo '<ol class="qm-ltr"><li>' . implode( '</li><li>', array_map( 'esc_html', $data['template_hierarchy'] ) ) . '</li></ol>';
|
@@ -95,7 +96,13 @@ class QM_Output_Html_Theme extends QM_Output_Html {
|
|
95 |
foreach ( $parts as $filename => $display ) {
|
96 |
echo '<li>';
|
97 |
|
98 |
-
if (
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
echo self::output_filename( $display, $filename, 0, true ); // WPCS: XSS ok.
|
100 |
} else {
|
101 |
echo esc_html( $display );
|
@@ -139,7 +146,7 @@ class QM_Output_Html_Theme extends QM_Output_Html {
|
|
139 |
}
|
140 |
|
141 |
echo '</ul>';
|
142 |
-
}
|
143 |
echo '<p><em>' . esc_html__( 'None', 'query-monitor' ) . '</em></p>';
|
144 |
}
|
145 |
}
|
@@ -176,6 +183,10 @@ class QM_Output_Html_Theme extends QM_Output_Html {
|
|
176 |
$this->after_non_tabular_output();
|
177 |
}
|
178 |
|
|
|
|
|
|
|
|
|
179 |
public function admin_menu( array $menu ) {
|
180 |
|
181 |
$data = $this->collector->get_data();
|
@@ -198,6 +209,10 @@ class QM_Output_Html_Theme extends QM_Output_Html {
|
|
198 |
|
199 |
}
|
200 |
|
|
|
|
|
|
|
|
|
201 |
public function panel_menu( array $menu ) {
|
202 |
if ( isset( $menu[ $this->collector->id() ] ) ) {
|
203 |
$menu[ $this->collector->id() ]['title'] = __( 'Template', 'query-monitor' );
|
@@ -208,6 +223,11 @@ class QM_Output_Html_Theme extends QM_Output_Html {
|
|
208 |
|
209 |
}
|
210 |
|
|
|
|
|
|
|
|
|
|
|
211 |
function register_qm_output_html_theme( array $output, QM_Collectors $collectors ) {
|
212 |
if ( is_admin() ) {
|
213 |
return $output;
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Theme extends QM_Output_Html {
|
13 |
|
24 |
add_filter( 'qm/output/panel_menus', array( $this, 'panel_menu' ), 60 );
|
25 |
}
|
26 |
|
27 |
+
/**
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
public function name() {
|
31 |
return __( 'Theme', 'query-monitor' );
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @return void
|
36 |
+
*/
|
37 |
public function output() {
|
38 |
$data = $this->collector->get_data();
|
39 |
|
73 |
echo '<p><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></p>';
|
74 |
}
|
75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
if ( ! empty( $data['template_hierarchy'] ) ) {
|
77 |
echo '<h3>' . esc_html__( 'Template Hierarchy', 'query-monitor' ) . '</h3>';
|
78 |
echo '<ol class="qm-ltr"><li>' . implode( '</li><li>', array_map( 'esc_html', $data['template_hierarchy'] ) ) . '</li></ol>';
|
96 |
foreach ( $parts as $filename => $display ) {
|
97 |
echo '<li>';
|
98 |
|
99 |
+
if ( is_numeric( $filename ) ) {
|
100 |
+
printf(
|
101 |
+
'<a href="%1$s">%2$s</a>',
|
102 |
+
esc_url( get_edit_post_link( $filename ) ),
|
103 |
+
esc_html( $display )
|
104 |
+
);
|
105 |
+
} elseif ( self::has_clickable_links() ) {
|
106 |
echo self::output_filename( $display, $filename, 0, true ); // WPCS: XSS ok.
|
107 |
} else {
|
108 |
echo esc_html( $display );
|
146 |
}
|
147 |
|
148 |
echo '</ul>';
|
149 |
+
} else {
|
150 |
echo '<p><em>' . esc_html__( 'None', 'query-monitor' ) . '</em></p>';
|
151 |
}
|
152 |
}
|
183 |
$this->after_non_tabular_output();
|
184 |
}
|
185 |
|
186 |
+
/**
|
187 |
+
* @param array<string, mixed[]> $menu
|
188 |
+
* @return array<string, mixed[]>
|
189 |
+
*/
|
190 |
public function admin_menu( array $menu ) {
|
191 |
|
192 |
$data = $this->collector->get_data();
|
209 |
|
210 |
}
|
211 |
|
212 |
+
/**
|
213 |
+
* @param array<string, mixed[]> $menu
|
214 |
+
* @return array<string, mixed[]>
|
215 |
+
*/
|
216 |
public function panel_menu( array $menu ) {
|
217 |
if ( isset( $menu[ $this->collector->id() ] ) ) {
|
218 |
$menu[ $this->collector->id() ]['title'] = __( 'Template', 'query-monitor' );
|
223 |
|
224 |
}
|
225 |
|
226 |
+
/**
|
227 |
+
* @param array<string, QM_Output> $output
|
228 |
+
* @param QM_Collectors $collectors
|
229 |
+
* @return array<string, QM_Output>
|
230 |
+
*/
|
231 |
function register_qm_output_html_theme( array $output, QM_Collectors $collectors ) {
|
232 |
if ( is_admin() ) {
|
233 |
return $output;
|
output/html/timing.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Timing extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Timing extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 15 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Timing', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -50,9 +58,9 @@ class QM_Output_Html_Timing extends QM_Output_Html {
|
|
50 |
if ( ! empty( $data['timing'] ) ) {
|
51 |
foreach ( $data['timing'] as $row ) {
|
52 |
|
53 |
-
$component = $row['
|
54 |
-
$trace
|
55 |
-
$file
|
56 |
|
57 |
echo '<tr>';
|
58 |
|
@@ -135,9 +143,9 @@ class QM_Output_Html_Timing extends QM_Output_Html {
|
|
135 |
}
|
136 |
if ( ! empty( $data['warning'] ) ) {
|
137 |
foreach ( $data['warning'] as $row ) {
|
138 |
-
$component = $row['
|
139 |
-
$trace
|
140 |
-
$file
|
141 |
|
142 |
echo '<tr class="qm-warn">';
|
143 |
if ( self::has_clickable_links() ) {
|
@@ -171,6 +179,10 @@ class QM_Output_Html_Timing extends QM_Output_Html {
|
|
171 |
$this->after_tabular_output();
|
172 |
}
|
173 |
|
|
|
|
|
|
|
|
|
174 |
public function admin_menu( array $menu ) {
|
175 |
$data = $this->collector->get_data();
|
176 |
|
@@ -198,6 +210,11 @@ class QM_Output_Html_Timing extends QM_Output_Html {
|
|
198 |
|
199 |
}
|
200 |
|
|
|
|
|
|
|
|
|
|
|
201 |
function register_qm_output_html_timing( array $output, QM_Collectors $collectors ) {
|
202 |
$collector = QM_Collectors::get( 'timing' );
|
203 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Timing extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 15 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Timing', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
58 |
if ( ! empty( $data['timing'] ) ) {
|
59 |
foreach ( $data['timing'] as $row ) {
|
60 |
|
61 |
+
$component = $row['component'];
|
62 |
+
$trace = $row['filtered_trace'];
|
63 |
+
$file = self::output_filename( $row['function'], $trace[0]['file'], $trace[0]['line'] );
|
64 |
|
65 |
echo '<tr>';
|
66 |
|
143 |
}
|
144 |
if ( ! empty( $data['warning'] ) ) {
|
145 |
foreach ( $data['warning'] as $row ) {
|
146 |
+
$component = $row['component'];
|
147 |
+
$trace = $row['filtered_trace'];
|
148 |
+
$file = self::output_filename( $row['function'], $trace[0]['file'], $trace[0]['line'] );
|
149 |
|
150 |
echo '<tr class="qm-warn">';
|
151 |
if ( self::has_clickable_links() ) {
|
179 |
$this->after_tabular_output();
|
180 |
}
|
181 |
|
182 |
+
/**
|
183 |
+
* @param array<string, mixed[]> $menu
|
184 |
+
* @return array<string, mixed[]>
|
185 |
+
*/
|
186 |
public function admin_menu( array $menu ) {
|
187 |
$data = $this->collector->get_data();
|
188 |
|
210 |
|
211 |
}
|
212 |
|
213 |
+
/**
|
214 |
+
* @param array<string, QM_Output> $output
|
215 |
+
* @param QM_Collectors $collectors
|
216 |
+
* @return array<string, QM_Output>
|
217 |
+
*/
|
218 |
function register_qm_output_html_timing( array $output, QM_Collectors $collectors ) {
|
219 |
$collector = QM_Collectors::get( 'timing' );
|
220 |
if ( $collector ) {
|
output/html/transients.php
CHANGED
@@ -5,7 +5,9 @@
|
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
-
defined( 'ABSPATH' )
|
|
|
|
|
9 |
|
10 |
class QM_Output_Html_Transients extends QM_Output_Html {
|
11 |
|
@@ -21,10 +23,16 @@ class QM_Output_Html_Transients extends QM_Output_Html {
|
|
21 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 100 );
|
22 |
}
|
23 |
|
|
|
|
|
|
|
24 |
public function name() {
|
25 |
return __( 'Transients', 'query-monitor' );
|
26 |
}
|
27 |
|
|
|
|
|
|
|
28 |
public function output() {
|
29 |
|
30 |
$data = $this->collector->get_data();
|
@@ -83,8 +91,8 @@ class QM_Output_Html_Transients extends QM_Output_Html {
|
|
83 |
|
84 |
$stack = array();
|
85 |
|
86 |
-
foreach ( $row['filtered_trace'] as $
|
87 |
-
$stack[] = self::output_filename( $
|
88 |
}
|
89 |
|
90 |
$caller = array_shift( $stack );
|
@@ -125,9 +133,13 @@ class QM_Output_Html_Transients extends QM_Output_Html {
|
|
125 |
}
|
126 |
}
|
127 |
|
|
|
|
|
|
|
|
|
128 |
public function admin_menu( array $menu ) {
|
129 |
|
130 |
-
$data
|
131 |
$count = isset( $data['trans'] ) ? count( $data['trans'] ) : 0;
|
132 |
|
133 |
$title = ( empty( $count ) )
|
@@ -147,6 +159,11 @@ class QM_Output_Html_Transients extends QM_Output_Html {
|
|
147 |
|
148 |
}
|
149 |
|
|
|
|
|
|
|
|
|
|
|
150 |
function register_qm_output_html_transients( array $output, QM_Collectors $collectors ) {
|
151 |
$collector = QM_Collectors::get( 'transients' );
|
152 |
if ( $collector ) {
|
5 |
* @package query-monitor
|
6 |
*/
|
7 |
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
|
12 |
class QM_Output_Html_Transients extends QM_Output_Html {
|
13 |
|
23 |
add_filter( 'qm/output/menus', array( $this, 'admin_menu' ), 100 );
|
24 |
}
|
25 |
|
26 |
+
/**
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
public function name() {
|
30 |
return __( 'Transients', 'query-monitor' );
|
31 |
}
|
32 |
|
33 |
+
/**
|
34 |
+
* @return void
|
35 |
+
*/
|
36 |
public function output() {
|
37 |
|
38 |
$data = $this->collector->get_data();
|
91 |
|
92 |
$stack = array();
|
93 |
|
94 |
+
foreach ( $row['filtered_trace'] as $frame ) {
|
95 |
+
$stack[] = self::output_filename( $frame['display'], $frame['calling_file'], $frame['calling_line'] );
|
96 |
}
|
97 |
|
98 |
$caller = array_shift( $stack );
|
133 |
}
|
134 |
}
|
135 |
|
136 |
+
/**
|
137 |
+
* @param array<string, mixed[]> $menu
|
138 |
+
* @return array<string, mixed[]>
|
139 |
+
*/
|
140 |
public function admin_menu( array $menu ) {
|
141 |
|
142 |
+
$data = $this->collector->get_data();
|
143 |
$count = isset( $data['trans'] ) ? count( $data['trans'] ) : 0;
|
144 |
|
145 |
$title = ( empty( $count ) )
|
159 |
|
160 |
}
|
161 |
|
162 |
+
/**
|
163 |
+
* @param array<string, QM_Output> $output
|
164 |
+
* @param QM_Collectors $collectors
|
165 |
+
* @return array<string, QM_Output>
|
166 |
+
*/
|
167 |
function register_qm_output_html_transients( array $output, QM_Collectors $collectors ) {
|
168 |
$collector = QM_Collectors::get( 'transients' );
|
169 |
if ( $collector ) {
|
output/raw/cache.php
CHANGED
@@ -14,15 +14,21 @@ class QM_Output_Raw_Cache extends QM_Output_Raw {
|
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
|
|
|
|
|
|
17 |
public function name() {
|
18 |
return __( 'Object Cache', 'query-monitor' );
|
19 |
}
|
20 |
|
|
|
|
|
|
|
21 |
public function get_output() {
|
22 |
$output = array(
|
23 |
'hit_percentage' => null,
|
24 |
-
'hits'
|
25 |
-
'misses'
|
26 |
);
|
27 |
$data = $this->collector->get_data();
|
28 |
|
@@ -36,6 +42,11 @@ class QM_Output_Raw_Cache extends QM_Output_Raw {
|
|
36 |
}
|
37 |
}
|
38 |
|
|
|
|
|
|
|
|
|
|
|
39 |
function register_qm_output_raw_cache( array $output, QM_Collectors $collectors ) {
|
40 |
$collector = QM_Collectors::get( 'cache' );
|
41 |
if ( $collector ) {
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
17 |
+
/**
|
18 |
+
* @return string
|
19 |
+
*/
|
20 |
public function name() {
|
21 |
return __( 'Object Cache', 'query-monitor' );
|
22 |
}
|
23 |
|
24 |
+
/**
|
25 |
+
* @return array<string, mixed>
|
26 |
+
*/
|
27 |
public function get_output() {
|
28 |
$output = array(
|
29 |
'hit_percentage' => null,
|
30 |
+
'hits' => null,
|
31 |
+
'misses' => null,
|
32 |
);
|
33 |
$data = $this->collector->get_data();
|
34 |
|
42 |
}
|
43 |
}
|
44 |
|
45 |
+
/**
|
46 |
+
* @param array<string, QM_Output> $output
|
47 |
+
* @param QM_Collectors $collectors
|
48 |
+
* @return array<string, QM_Output>
|
49 |
+
*/
|
50 |
function register_qm_output_raw_cache( array $output, QM_Collectors $collectors ) {
|
51 |
$collector = QM_Collectors::get( 'cache' );
|
52 |
if ( $collector ) {
|
output/raw/conditionals.php
CHANGED
@@ -14,10 +14,16 @@ class QM_Output_Raw_Conditionals extends QM_Output_Raw {
|
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
|
|
|
|
|
|
17 |
public function name() {
|
18 |
return __( 'Conditionals', 'query-monitor' );
|
19 |
}
|
20 |
|
|
|
|
|
|
|
21 |
public function get_output() {
|
22 |
$data = $this->collector->get_data();
|
23 |
|
@@ -25,6 +31,11 @@ class QM_Output_Raw_Conditionals extends QM_Output_Raw {
|
|
25 |
}
|
26 |
}
|
27 |
|
|
|
|
|
|
|
|
|
|
|
28 |
function register_qm_output_raw_conditionals( array $output, QM_Collectors $collectors ) {
|
29 |
$collector = QM_Collectors::get( 'conditionals' );
|
30 |
if ( $collector ) {
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
17 |
+
/**
|
18 |
+
* @return string
|
19 |
+
*/
|
20 |
public function name() {
|
21 |
return __( 'Conditionals', 'query-monitor' );
|
22 |
}
|
23 |
|
24 |
+
/**
|
25 |
+
* @return mixed
|
26 |
+
*/
|
27 |
public function get_output() {
|
28 |
$data = $this->collector->get_data();
|
29 |
|
31 |
}
|
32 |
}
|
33 |
|
34 |
+
/**
|
35 |
+
* @param array<string, QM_Output> $output
|
36 |
+
* @param QM_Collectors $collectors
|
37 |
+
* @return array<string, QM_Output>
|
38 |
+
*/
|
39 |
function register_qm_output_raw_conditionals( array $output, QM_Collectors $collectors ) {
|
40 |
$collector = QM_Collectors::get( 'conditionals' );
|
41 |
if ( $collector ) {
|
output/raw/db_queries.php
CHANGED
@@ -14,15 +14,24 @@ class QM_Output_Raw_DB_Queries extends QM_Output_Raw {
|
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
|
|
|
|
|
|
17 |
public $query_row = 0;
|
18 |
|
|
|
|
|
|
|
19 |
public function name() {
|
20 |
return __( 'Database Queries', 'query-monitor' );
|
21 |
}
|
22 |
|
|
|
|
|
|
|
23 |
public function get_output() {
|
24 |
$output = array();
|
25 |
-
$data
|
26 |
|
27 |
if ( empty( $data['dbs'] ) ) {
|
28 |
return $output;
|
@@ -61,6 +70,17 @@ class QM_Output_Raw_DB_Queries extends QM_Output_Raw {
|
|
61 |
return $output;
|
62 |
}
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
protected function output_queries( $name, stdClass $db, array $data ) {
|
65 |
$this->query_row = 0;
|
66 |
|
@@ -75,38 +95,46 @@ class QM_Output_Raw_DB_Queries extends QM_Output_Raw {
|
|
75 |
}
|
76 |
|
77 |
return array(
|
78 |
-
'total'
|
79 |
-
'time'
|
80 |
'queries' => $output,
|
81 |
);
|
82 |
}
|
83 |
|
|
|
|
|
|
|
|
|
84 |
protected function output_query_row( array $row ) {
|
85 |
$output = array();
|
86 |
|
87 |
-
$output['i']
|
88 |
-
$output['sql']
|
89 |
-
$output['time'] = (
|
90 |
|
91 |
if ( isset( $row['trace'] ) ) {
|
92 |
$stack = array();
|
93 |
-
$filtered_trace = $row['trace']->
|
94 |
|
95 |
foreach ( $filtered_trace as $item ) {
|
96 |
$stack[] = $item['display'];
|
97 |
}
|
98 |
} else {
|
99 |
-
$stack =
|
100 |
-
$stack = array_reverse( $stack );
|
101 |
}
|
102 |
|
103 |
$output['stack'] = $stack;
|
104 |
-
$output['result']
|
105 |
|
106 |
return $output;
|
107 |
}
|
108 |
}
|
109 |
|
|
|
|
|
|
|
|
|
|
|
110 |
function register_qm_output_raw_db_queries( array $output, QM_Collectors $collectors ) {
|
111 |
$collector = QM_Collectors::get( 'db_queries' );
|
112 |
if ( $collector ) {
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
17 |
+
/**
|
18 |
+
* @var int
|
19 |
+
*/
|
20 |
public $query_row = 0;
|
21 |
|
22 |
+
/**
|
23 |
+
* @return string
|
24 |
+
*/
|
25 |
public function name() {
|
26 |
return __( 'Database Queries', 'query-monitor' );
|
27 |
}
|
28 |
|
29 |
+
/**
|
30 |
+
* @return array<string, mixed>
|
31 |
+
*/
|
32 |
public function get_output() {
|
33 |
$output = array();
|
34 |
+
$data = $this->collector->get_data();
|
35 |
|
36 |
if ( empty( $data['dbs'] ) ) {
|
37 |
return $output;
|
70 |
return $output;
|
71 |
}
|
72 |
|
73 |
+
/**
|
74 |
+
* @param string $name
|
75 |
+
* @param stdClass $db
|
76 |
+
* @param mixed[] $data
|
77 |
+
* @return array
|
78 |
+
* @phpstan-return array{
|
79 |
+
* total: int,
|
80 |
+
* time: float,
|
81 |
+
* queries: mixed[],
|
82 |
+
* }|array{}
|
83 |
+
*/
|
84 |
protected function output_queries( $name, stdClass $db, array $data ) {
|
85 |
$this->query_row = 0;
|
86 |
|
95 |
}
|
96 |
|
97 |
return array(
|
98 |
+
'total' => $db->total_qs,
|
99 |
+
'time' => round( $db->total_time, 4 ),
|
100 |
'queries' => $output,
|
101 |
);
|
102 |
}
|
103 |
|
104 |
+
/**
|
105 |
+
* @param array<string, mixed> $row
|
106 |
+
* @return array<string, mixed>
|
107 |
+
*/
|
108 |
protected function output_query_row( array $row ) {
|
109 |
$output = array();
|
110 |
|
111 |
+
$output['i'] = ++$this->query_row;
|
112 |
+
$output['sql'] = $row['sql'];
|
113 |
+
$output['time'] = round( $row['ltime'], 4 );
|
114 |
|
115 |
if ( isset( $row['trace'] ) ) {
|
116 |
$stack = array();
|
117 |
+
$filtered_trace = $row['trace']->get_filtered_trace();
|
118 |
|
119 |
foreach ( $filtered_trace as $item ) {
|
120 |
$stack[] = $item['display'];
|
121 |
}
|
122 |
} else {
|
123 |
+
$stack = $row['stack'];
|
|
|
124 |
}
|
125 |
|
126 |
$output['stack'] = $stack;
|
127 |
+
$output['result'] = $row['result'];
|
128 |
|
129 |
return $output;
|
130 |
}
|
131 |
}
|
132 |
|
133 |
+
/**
|
134 |
+
* @param array<string, QM_Output> $output
|
135 |
+
* @param QM_Collectors $collectors
|
136 |
+
* @return array<string, QM_Output>
|
137 |
+
*/
|
138 |
function register_qm_output_raw_db_queries( array $output, QM_Collectors $collectors ) {
|
139 |
$collector = QM_Collectors::get( 'db_queries' );
|
140 |
if ( $collector ) {
|
output/raw/http.php
CHANGED
@@ -14,13 +14,19 @@ class QM_Output_Raw_HTTP extends QM_Output_Raw {
|
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
|
|
|
|
|
|
17 |
public function name() {
|
18 |
return __( 'HTTP API Calls', 'query-monitor' );
|
19 |
}
|
20 |
|
|
|
|
|
|
|
21 |
public function get_output() {
|
22 |
$output = array();
|
23 |
-
$data
|
24 |
|
25 |
if ( empty( $data['http'] ) ) {
|
26 |
return $output;
|
@@ -32,7 +38,7 @@ class QM_Output_Raw_HTTP extends QM_Output_Raw {
|
|
32 |
$stack = array();
|
33 |
|
34 |
if ( isset( $http['trace'] ) ) {
|
35 |
-
$filtered_trace = $http['trace']->
|
36 |
|
37 |
foreach ( $filtered_trace as $item ) {
|
38 |
$stack[] = $item['display'];
|
@@ -42,7 +48,7 @@ class QM_Output_Raw_HTTP extends QM_Output_Raw {
|
|
42 |
$requests[] = array(
|
43 |
'url' => $http['url'],
|
44 |
'method' => $http['args']['method'],
|
45 |
-
'response' => $http['response']['response'],
|
46 |
'time' => (float) number_format_i18n( $http['end'] - $http['start'], 4 ),
|
47 |
'stack' => $stack,
|
48 |
);
|
@@ -56,6 +62,11 @@ class QM_Output_Raw_HTTP extends QM_Output_Raw {
|
|
56 |
}
|
57 |
}
|
58 |
|
|
|
|
|
|
|
|
|
|
|
59 |
function register_qm_output_raw_http( array $output, QM_Collectors $collectors ) {
|
60 |
$collector = QM_Collectors::get( 'http' );
|
61 |
if ( $collector ) {
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
17 |
+
/**
|
18 |
+
* @return string
|
19 |
+
*/
|
20 |
public function name() {
|
21 |
return __( 'HTTP API Calls', 'query-monitor' );
|
22 |
}
|
23 |
|
24 |
+
/**
|
25 |
+
* @return array<string, mixed>
|
26 |
+
*/
|
27 |
public function get_output() {
|
28 |
$output = array();
|
29 |
+
$data = $this->collector->get_data();
|
30 |
|
31 |
if ( empty( $data['http'] ) ) {
|
32 |
return $output;
|
38 |
$stack = array();
|
39 |
|
40 |
if ( isset( $http['trace'] ) ) {
|
41 |
+
$filtered_trace = $http['trace']->get_filtered_trace();
|
42 |
|
43 |
foreach ( $filtered_trace as $item ) {
|
44 |
$stack[] = $item['display'];
|
48 |
$requests[] = array(
|
49 |
'url' => $http['url'],
|
50 |
'method' => $http['args']['method'],
|
51 |
+
'response' => is_wp_error( $http['response'] ) ? $http['response']->get_error_message() : $http['response']['response'],
|
52 |
'time' => (float) number_format_i18n( $http['end'] - $http['start'], 4 ),
|
53 |
'stack' => $stack,
|
54 |
);
|
62 |
}
|
63 |
}
|
64 |
|
65 |
+
/**
|
66 |
+
* @param array<string, QM_Output> $output
|
67 |
+
* @param QM_Collectors $collectors
|
68 |
+
* @return array<string, QM_Output>
|
69 |
+
*/
|
70 |
function register_qm_output_raw_http( array $output, QM_Collectors $collectors ) {
|
71 |
$collector = QM_Collectors::get( 'http' );
|
72 |
if ( $collector ) {
|
output/raw/logger.php
CHANGED
@@ -14,13 +14,19 @@ class QM_Output_Raw_Logger extends QM_Output_Raw {
|
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
|
|
|
|
|
|
17 |
public function name() {
|
18 |
return __( 'Logs', 'query-monitor' );
|
19 |
}
|
20 |
|
|
|
|
|
|
|
21 |
public function get_output() {
|
22 |
$output = array();
|
23 |
-
$data
|
24 |
|
25 |
if ( empty( $data['logs'] ) ) {
|
26 |
return $output;
|
@@ -30,7 +36,7 @@ class QM_Output_Raw_Logger extends QM_Output_Raw {
|
|
30 |
$stack = array();
|
31 |
|
32 |
if ( isset( $log['trace'] ) ) {
|
33 |
-
$filtered_trace = $log['trace']->
|
34 |
|
35 |
foreach ( $filtered_trace as $item ) {
|
36 |
$stack[] = $item['display'];
|
@@ -47,6 +53,11 @@ class QM_Output_Raw_Logger extends QM_Output_Raw {
|
|
47 |
}
|
48 |
}
|
49 |
|
|
|
|
|
|
|
|
|
|
|
50 |
function register_qm_output_raw_logger( array $output, QM_Collectors $collectors ) {
|
51 |
$collector = QM_Collectors::get( 'logger' );
|
52 |
if ( $collector ) {
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
17 |
+
/**
|
18 |
+
* @return string
|
19 |
+
*/
|
20 |
public function name() {
|
21 |
return __( 'Logs', 'query-monitor' );
|
22 |
}
|
23 |
|
24 |
+
/**
|
25 |
+
* @return array<string, mixed>
|
26 |
+
*/
|
27 |
public function get_output() {
|
28 |
$output = array();
|
29 |
+
$data = $this->collector->get_data();
|
30 |
|
31 |
if ( empty( $data['logs'] ) ) {
|
32 |
return $output;
|
36 |
$stack = array();
|
37 |
|
38 |
if ( isset( $log['trace'] ) ) {
|
39 |
+
$filtered_trace = $log['trace']->get_filtered_trace();
|
40 |
|
41 |
foreach ( $filtered_trace as $item ) {
|
42 |
$stack[] = $item['display'];
|
53 |
}
|
54 |
}
|
55 |
|
56 |
+
/**
|
57 |
+
* @param array<string, QM_Output> $output
|
58 |
+
* @param QM_Collectors $collectors
|
59 |
+
* @return array<string, QM_Output>
|
60 |
+
*/
|
61 |
function register_qm_output_raw_logger( array $output, QM_Collectors $collectors ) {
|
62 |
$collector = QM_Collectors::get( 'logger' );
|
63 |
if ( $collector ) {
|
output/raw/transients.php
CHANGED
@@ -14,13 +14,19 @@ class QM_Output_Raw_Transients extends QM_Output_Raw {
|
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
|
|
|
|
|
|
17 |
public function name() {
|
18 |
return __( 'Transients', 'query-monitor' );
|
19 |
}
|
20 |
|
|
|
|
|
|
|
21 |
public function get_output() {
|
22 |
$output = array();
|
23 |
-
$data
|
24 |
|
25 |
if ( empty( $data['trans'] ) ) {
|
26 |
return $output;
|
@@ -55,6 +61,11 @@ class QM_Output_Raw_Transients extends QM_Output_Raw {
|
|
55 |
}
|
56 |
}
|
57 |
|
|
|
|
|
|
|
|
|
|
|
58 |
function register_qm_output_raw_transients( array $output, QM_Collectors $collectors ) {
|
59 |
$collector = QM_Collectors::get( 'transients' );
|
60 |
if ( $collector ) {
|
14 |
*/
|
15 |
protected $collector;
|
16 |
|
17 |
+
/**
|
18 |
+
* @return string
|
19 |
+
*/
|
20 |
public function name() {
|
21 |
return __( 'Transients', 'query-monitor' );
|
22 |
}
|
23 |
|
24 |
+
/**
|
25 |
+
* @return array<string, mixed>
|
26 |
+
*/
|
27 |
public function get_output() {
|
28 |
$output = array();
|
29 |
+
$data = $this->collector->get_data();
|
30 |
|
31 |
if ( empty( $data['trans'] ) ) {
|
32 |
return $output;
|
61 |
}
|
62 |
}
|
63 |
|
64 |
+
/**
|
65 |
+
* @param array<string, QM_Output> $output
|
66 |
+
* @param QM_Collectors $collectors
|
67 |
+
* @return array<string, QM_Output>
|
68 |
+
*/
|
69 |
function register_qm_output_raw_transients( array $output, QM_Collectors $collectors ) {
|
70 |
$collector = QM_Collectors::get( 'transients' );
|
71 |
if ( $collector ) {
|
query-monitor.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
*
|
11 |
* Plugin Name: Query Monitor
|
12 |
* Description: The Developer Tools Panel for WordPress.
|
13 |
-
* Version: 3.
|
14 |
* Plugin URI: https://querymonitor.com/
|
15 |
* Author: John Blackbourn
|
16 |
* Author URI: https://querymonitor.com/
|
@@ -29,7 +29,9 @@
|
|
29 |
* GNU General Public License for more details.
|
30 |
*/
|
31 |
|
32 |
-
defined( 'ABSPATH' )
|
|
|
|
|
33 |
|
34 |
$qm_dir = dirname( __FILE__ );
|
35 |
|
@@ -47,10 +49,6 @@ foreach ( array( 'Activation', 'Util', 'QM' ) as $qm_class ) {
|
|
47 |
|
48 |
QM_Activation::init( __FILE__ );
|
49 |
|
50 |
-
if ( ! QM_Plugin::php_version_met() ) {
|
51 |
-
return;
|
52 |
-
}
|
53 |
-
|
54 |
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
55 |
require_once "{$qm_dir}/classes/CLI.php";
|
56 |
QM_CLI::init( __FILE__ );
|
@@ -80,4 +78,4 @@ unset(
|
|
80 |
$qm_class
|
81 |
);
|
82 |
|
83 |
-
QueryMonitor::init( __FILE__ );
|
10 |
*
|
11 |
* Plugin Name: Query Monitor
|
12 |
* Description: The Developer Tools Panel for WordPress.
|
13 |
+
* Version: 3.8.0
|
14 |
* Plugin URI: https://querymonitor.com/
|
15 |
* Author: John Blackbourn
|
16 |
* Author URI: https://querymonitor.com/
|
29 |
* GNU General Public License for more details.
|
30 |
*/
|
31 |
|
32 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
33 |
+
exit;
|
34 |
+
}
|
35 |
|
36 |
$qm_dir = dirname( __FILE__ );
|
37 |
|
49 |
|
50 |
QM_Activation::init( __FILE__ );
|
51 |
|
|
|
|
|
|
|
|
|
52 |
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
53 |
require_once "{$qm_dir}/classes/CLI.php";
|
54 |
QM_CLI::init( __FILE__ );
|
78 |
$qm_class
|
79 |
);
|
80 |
|
81 |
+
QueryMonitor::init( __FILE__ )->set_up();
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: johnbillion
|
3 |
Tags: debug, debug-bar, debugging, development, developer, performance, profiler, queries, query monitor, rest-api
|
4 |
Requires at least: 3.7
|
5 |
-
Tested up to: 5.
|
6 |
-
Stable tag: 3.
|
7 |
License: GPLv2 or later
|
8 |
Requires PHP: 5.3
|
9 |
Donate link: https://johnblackbourn.com/donations/
|
@@ -88,6 +88,16 @@ Long answer: Query Monitor has a small impact on page generation time because it
|
|
88 |
|
89 |
Query Monitor's memory usage typically accounts for around 10% of the total memory used to generate the page.
|
90 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
### Are there any add-on plugins for Query Monitor?
|
92 |
|
93 |
[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)
|
@@ -131,6 +141,18 @@ In addition, if you like the plugin then I'd love for you to [leave a review](ht
|
|
131 |
|
132 |
## Changelog ##
|
133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
### 3.7.1 ###
|
135 |
|
136 |
* Add a fallback for timing processing during Ajax requests that are dispatched before the `shutdown` hook.
|
@@ -445,20 +467,3 @@ New features! Read about them here: https://querymonitor.com/blog/2019/02/new-fe
|
|
445 |
* Switch back to depending on `jquery` instead of `jquery-core`.
|
446 |
* Don't assume `php_uname()` is always callable. Add info about the host OS too.
|
447 |
* Reset inline height attribute when the panel is closed.
|
448 |
-
|
449 |
-
### 3.0.0 ###
|
450 |
-
|
451 |
-
* Brand new UI that resembles familiar web developer tools. Lots of related improvements and fixes.
|
452 |
-
* Introduce some basic timing functionality in a Timings panel. See #282 for usage.
|
453 |
-
* Introduce a `QM_NO_JQUERY` constant for running QM without jQuery as a dependency.
|
454 |
-
* Greater resilience to JavaScript errors.
|
455 |
-
* Allow the Scripts and Styles panel to be filtered by host name.
|
456 |
-
* Expose information about redirects that occurred in HTTP API requests.
|
457 |
-
* Expose more debugging information for HTTP API requests.
|
458 |
-
* Don't enable the Capability Checks panel by default as it's very memory intensive.
|
459 |
-
* Allow PHP errors to be silenced according to their component. See `qm/collect/php_error_levels` and `qm/collect/hide_silenced_php_errors` filters.
|
460 |
-
* Hide all file paths and stack traces behind toggles by default.
|
461 |
-
* Remove support for the AMP for WordPress plugin.
|
462 |
-
* Add associative keys to the array passed to the `qm/built-in-collectors` filter.
|
463 |
-
* Drop support for PHP 5.2.
|
464 |
-
* Generally improve performance and reduce memory usage.
|
2 |
Contributors: johnbillion
|
3 |
Tags: debug, debug-bar, debugging, development, developer, performance, profiler, queries, query monitor, rest-api
|
4 |
Requires at least: 3.7
|
5 |
+
Tested up to: 5.8
|
6 |
+
Stable tag: 3.8.0
|
7 |
License: GPLv2 or later
|
8 |
Requires PHP: 5.3
|
9 |
Donate link: https://johnblackbourn.com/donations/
|
88 |
|
89 |
Query Monitor's memory usage typically accounts for around 10% of the total memory used to generate the page.
|
90 |
|
91 |
+
### Can I prevent Query Monitor from collecting data during long-running requests?
|
92 |
+
|
93 |
+
Yes, if anything calls `do_action( 'qm/cease' )` then Query Monitor will cease operating for the remainder of the page generation. It detaches itself from further data collection, discards any data it's collected so far, and skips the output of its information.
|
94 |
+
|
95 |
+
This is useful for long-running operations that perform a very high number of database queries, consume a lot of memory, or otherwise are of no concern to Query Monitor, for example:
|
96 |
+
|
97 |
+
* Backuping up or restoring your site
|
98 |
+
* Exporting a large amount of data
|
99 |
+
* Running security scans
|
100 |
+
|
101 |
### Are there any add-on plugins for Query Monitor?
|
102 |
|
103 |
[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)
|
141 |
|
142 |
## Changelog ##
|
143 |
|
144 |
+
### 3.8.0 ###
|
145 |
+
|
146 |
+
* Introduces the ability for a third party to cease all further data collection and output at any point by calling `do_action( 'qm/cease' )`, for example to prevent memory exhaustion during long-running operations
|
147 |
+
* Reduces the width of the admin toolbar menu item by using lower decimal precision
|
148 |
+
* Improves the Template panel information when a block theme is in use (for Full Site Editing)
|
149 |
+
* Improves the performance and accuracy of stack traces and calling function information
|
150 |
+
* Corrects some formatting of numbers and error messages in the REST API output
|
151 |
+
* Adds more useful information when a persistent object cache or opcode cache isn't in use
|
152 |
+
* Improves clarity in the Scripts and Styles panels when any of the URLs include a port number
|
153 |
+
* Introduces the `qm/component_context/{$type}` filter to complement `qm/component_name/{$type}` and `qm/component_dirs`
|
154 |
+
* Improves internal code quality, internationalisation, and further reduces overall memory usage
|
155 |
+
|
156 |
### 3.7.1 ###
|
157 |
|
158 |
* Add a fallback for timing processing during Ajax requests that are dispatched before the `shutdown` hook.
|
467 |
* Switch back to depending on `jquery` instead of `jquery-core`.
|
468 |
* Don't assume `php_uname()` is always callable. Add info about the host OS too.
|
469 |
* Reset inline height attribute when the panel is closed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wp-content/db.php
CHANGED
@@ -12,7 +12,9 @@
|
|
12 |
* @package query-monitor
|
13 |
*/
|
14 |
|
15 |
-
defined( 'ABSPATH' )
|
|
|
|
|
16 |
|
17 |
if ( defined( 'QM_DISABLED' ) && QM_DISABLED ) {
|
18 |
return;
|
@@ -30,7 +32,7 @@ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
|
30 |
}
|
31 |
|
32 |
# No autoloaders for us. See https://github.com/johnbillion/query-monitor/issues/7
|
33 |
-
$qm_dir
|
34 |
$qm_plugin = "{$qm_dir}/classes/Plugin.php";
|
35 |
|
36 |
if ( ! is_readable( $qm_plugin ) ) {
|
@@ -54,13 +56,21 @@ if ( ! defined( 'SAVEQUERIES' ) ) {
|
|
54 |
|
55 |
class QM_DB extends wpdb {
|
56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
public $qm_php_vars = array(
|
58 |
-
'max_execution_time'
|
59 |
-
'memory_limit'
|
60 |
'upload_max_filesize' => null,
|
61 |
-
'post_max_size'
|
62 |
-
'display_errors'
|
63 |
-
'log_errors'
|
64 |
);
|
65 |
|
66 |
/**
|
@@ -86,28 +96,24 @@ class QM_DB extends wpdb {
|
|
86 |
* affected/selected for all other queries. Boolean false on error.
|
87 |
*/
|
88 |
public function query( $query ) {
|
89 |
-
if ( ! $this->ready ) {
|
90 |
-
if ( isset( $this->check_current_query ) ) {
|
91 |
-
// This property was introduced in WP 4.2
|
92 |
-
$this->check_current_query = true;
|
93 |
-
}
|
94 |
-
return false;
|
95 |
-
}
|
96 |
-
|
97 |
if ( $this->show_errors ) {
|
98 |
$this->hide_errors();
|
99 |
}
|
100 |
|
101 |
$result = parent::query( $query );
|
102 |
-
$i
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
if ( ! isset( $this->queries[ $i ] ) ) {
|
105 |
return $result;
|
106 |
}
|
107 |
|
108 |
-
$this->queries[ $i ]['trace'] = new QM_Backtrace(
|
109 |
-
'ignore_frames' => 1,
|
110 |
-
) );
|
111 |
|
112 |
if ( ! isset( $this->queries[ $i ][3] ) ) {
|
113 |
$this->queries[ $i ][3] = $this->time_start;
|
@@ -115,17 +121,17 @@ class QM_DB extends wpdb {
|
|
115 |
|
116 |
if ( $this->last_error ) {
|
117 |
$code = 'qmdb';
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
}
|
122 |
-
} else {
|
123 |
-
if ( is_resource( $this->dbh ) ) {
|
124 |
-
// Please do not report this code as a PHP 7 incompatibility. Observe the surrounding logic.
|
125 |
-
// phpcs:ignore
|
126 |
-
$code = mysql_errno( $this->dbh );
|
127 |
-
}
|
128 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
$this->queries[ $i ]['result'] = new WP_Error( $code, $this->last_error );
|
130 |
} else {
|
131 |
$this->queries[ $i ]['result'] = $result;
|
12 |
* @package query-monitor
|
13 |
*/
|
14 |
|
15 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
16 |
+
exit;
|
17 |
+
}
|
18 |
|
19 |
if ( defined( 'QM_DISABLED' ) && QM_DISABLED ) {
|
20 |
return;
|
32 |
}
|
33 |
|
34 |
# No autoloaders for us. See https://github.com/johnbillion/query-monitor/issues/7
|
35 |
+
$qm_dir = dirname( dirname( __FILE__ ) );
|
36 |
$qm_plugin = "{$qm_dir}/classes/Plugin.php";
|
37 |
|
38 |
if ( ! is_readable( $qm_plugin ) ) {
|
56 |
|
57 |
class QM_DB extends wpdb {
|
58 |
|
59 |
+
/**
|
60 |
+
* @var float
|
61 |
+
*/
|
62 |
+
public $time_start;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @var array<string, string|null>
|
66 |
+
*/
|
67 |
public $qm_php_vars = array(
|
68 |
+
'max_execution_time' => null,
|
69 |
+
'memory_limit' => null,
|
70 |
'upload_max_filesize' => null,
|
71 |
+
'post_max_size' => null,
|
72 |
+
'display_errors' => null,
|
73 |
+
'log_errors' => null,
|
74 |
);
|
75 |
|
76 |
/**
|
96 |
* affected/selected for all other queries. Boolean false on error.
|
97 |
*/
|
98 |
public function query( $query ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
if ( $this->show_errors ) {
|
100 |
$this->hide_errors();
|
101 |
}
|
102 |
|
103 |
$result = parent::query( $query );
|
104 |
+
$i = $this->num_queries - 1;
|
105 |
+
|
106 |
+
if ( did_action( 'qm/cease' ) ) {
|
107 |
+
// It's not possible to prevent the parent class from logging queries because it reads
|
108 |
+
// the `SAVEQUERIES` constant and I don't want to override more methods than necessary.
|
109 |
+
$this->queries = array();
|
110 |
+
}
|
111 |
|
112 |
if ( ! isset( $this->queries[ $i ] ) ) {
|
113 |
return $result;
|
114 |
}
|
115 |
|
116 |
+
$this->queries[ $i ]['trace'] = new QM_Backtrace();
|
|
|
|
|
117 |
|
118 |
if ( ! isset( $this->queries[ $i ][3] ) ) {
|
119 |
$this->queries[ $i ][3] = $this->time_start;
|
121 |
|
122 |
if ( $this->last_error ) {
|
123 |
$code = 'qmdb';
|
124 |
+
|
125 |
+
if ( $this->dbh instanceof mysqli ) {
|
126 |
+
$code = mysqli_errno( $this->dbh );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
}
|
128 |
+
|
129 |
+
if ( is_resource( $this->dbh ) ) {
|
130 |
+
// Please do not report this code as a PHP 7 incompatibility. Observe the surrounding logic.
|
131 |
+
// phpcs:ignore
|
132 |
+
$code = mysql_errno( $this->dbh );
|
133 |
+
}
|
134 |
+
|
135 |
$this->queries[ $i ]['result'] = new WP_Error( $code, $this->last_error );
|
136 |
} else {
|
137 |
$this->queries[ $i ]['result'] = $result;
|