Query Monitor - Version 3.0.1

Version Description

Download this release

Release Info

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

Code changes from version 3.0.0 to 3.0.1

assets/query-monitor.css CHANGED
@@ -184,9 +184,7 @@ body.admin-color-light #wp-admin-bar-query-monitor:not(.qm-all-clear):not(:hover
184
  }
185
 
186
  #query-monitor.qm-show,
187
- #query-monitor.qm-peek,
188
- .no-js #query-monitor,
189
- .nojs #query-monitor {
190
  height: 27px;
191
  display: flex;
192
  flex-direction: column;
184
  }
185
 
186
  #query-monitor.qm-show,
187
+ #query-monitor.qm-peek {
 
 
188
  height: 27px;
189
  display: flex;
190
  flex-direction: column;
assets/query-monitor.js CHANGED
@@ -395,7 +395,7 @@ if ( window.jQuery ) {
395
  });
396
 
397
  $('.qm-button-container-close').click(function(){
398
- $('#query-monitor').removeClass('qm-show');
399
  localStorage.removeItem( container_pinned_key );
400
  $('.qm-button-container-pin').removeClass( 'qm-button-active' );
401
  });
@@ -539,16 +539,25 @@ if ( window.jQuery ) {
539
 
540
  }
541
 
542
- if ( ( 'undefined' === typeof jQuery ) || ! jQuery ) {
543
- window.addEventListener('load', function() {
544
  /* Fallback for running without jQuery (`QM_NO_JQUERY`) */
545
  document.getElementById( 'query-monitor' ).className += ' qm-broken';
546
  console.error( document.getElementById( 'qm-broken' ).textContent );
 
 
 
 
 
 
 
 
 
547
  var menu_item = document.getElementById( 'wp-admin-bar-query-monitor' );
548
  if ( menu_item ) {
549
  menu_item.addEventListener( 'click', function() {
550
  document.getElementById( 'query-monitor' ).className += ' qm-show';
551
  } );
552
  }
553
- } );
554
- }
395
  });
396
 
397
  $('.qm-button-container-close').click(function(){
398
+ $('#query-monitor').removeClass('qm-show').height('');
399
  localStorage.removeItem( container_pinned_key );
400
  $('.qm-button-container-pin').removeClass( 'qm-button-active' );
401
  });
539
 
540
  }
541
 
542
+ window.addEventListener('load', function() {
543
+ if ( ( 'undefined' === typeof jQuery ) || ! window.jQuery ) {
544
  /* Fallback for running without jQuery (`QM_NO_JQUERY`) */
545
  document.getElementById( 'query-monitor' ).className += ' qm-broken';
546
  console.error( document.getElementById( 'qm-broken' ).textContent );
547
+
548
+ if ( 'undefined' === typeof jQuery ) {
549
+ console.error( 'QM error from JS: undefined jQuery' );
550
+ }
551
+
552
+ if ( ! window.jQuery ) {
553
+ console.error( 'QM error from JS: no jQuery' );
554
+ }
555
+
556
  var menu_item = document.getElementById( 'wp-admin-bar-query-monitor' );
557
  if ( menu_item ) {
558
  menu_item.addEventListener( 'click', function() {
559
  document.getElementById( 'query-monitor' ).className += ' qm-show';
560
  } );
561
  }
562
+ }
563
+ } );
classes/Util.php CHANGED
@@ -74,6 +74,11 @@ class QM_Util {
74
  self::$file_dirs['go-plugin'] = self::standard_dir( WPMU_PLUGIN_DIR . '/shared-plugins' );
75
  self::$file_dirs['mu-plugin'] = self::standard_dir( WPMU_PLUGIN_DIR );
76
  self::$file_dirs['vip-plugin'] = self::standard_dir( get_theme_root() . '/vip/plugins' );
 
 
 
 
 
77
  self::$file_dirs['theme'] = null;
78
  self::$file_dirs['stylesheet'] = self::standard_dir( get_stylesheet_directory() );
79
  self::$file_dirs['template'] = self::standard_dir( get_template_directory() );
@@ -126,6 +131,7 @@ class QM_Util {
126
  break;
127
  case 'go-plugin':
128
  case 'vip-plugin':
 
129
  $plug = str_replace( self::$file_dirs[ $type ], '', $file );
130
  $plug = trim( $plug, '/' );
131
  if ( strpos( $plug, '/' ) ) {
@@ -134,8 +140,13 @@ class QM_Util {
134
  } else {
135
  $plug = basename( $plug );
136
  }
137
- /* translators: %s: Plugin name */
138
- $name = sprintf( __( 'VIP Plugin: %s', 'query-monitor' ), $plug );
 
 
 
 
 
139
  $context = $plug;
140
  break;
141
  case 'stylesheet':
74
  self::$file_dirs['go-plugin'] = self::standard_dir( WPMU_PLUGIN_DIR . '/shared-plugins' );
75
  self::$file_dirs['mu-plugin'] = self::standard_dir( WPMU_PLUGIN_DIR );
76
  self::$file_dirs['vip-plugin'] = self::standard_dir( get_theme_root() . '/vip/plugins' );
77
+
78
+ if ( defined( 'WPCOM_VIP_CLIENT_MU_PLUGIN_DIR' ) ) {
79
+ self::$file_dirs['vip-client-mu-plugin'] = self::standard_dir( WPCOM_VIP_CLIENT_MU_PLUGIN_DIR );
80
+ }
81
+
82
  self::$file_dirs['theme'] = null;
83
  self::$file_dirs['stylesheet'] = self::standard_dir( get_stylesheet_directory() );
84
  self::$file_dirs['template'] = self::standard_dir( get_template_directory() );
131
  break;
132
  case 'go-plugin':
133
  case 'vip-plugin':
134
+ case 'vip-client-mu-plugin':
135
  $plug = str_replace( self::$file_dirs[ $type ], '', $file );
136
  $plug = trim( $plug, '/' );
137
  if ( strpos( $plug, '/' ) ) {
140
  } else {
141
  $plug = basename( $plug );
142
  }
143
+ if ( 'vip-client-mu-plugin' === $type ) {
144
+ /* translators: %s: Plugin name */
145
+ $name = sprintf( __( 'VIP Client MU Plugin: %s', 'query-monitor' ), $plug );
146
+ } else {
147
+ /* translators: %s: Plugin name */
148
+ $name = sprintf( __( 'VIP Plugin: %s', 'query-monitor' ), $plug );
149
+ }
150
  $context = $plug;
151
  break;
152
  case 'stylesheet':
collectors/caps.php CHANGED
@@ -114,6 +114,11 @@ class QM_Collector_Caps extends QM_Collector {
114
 
115
  foreach ( $this->data['caps'] as $i => $cap ) {
116
  $name = $cap['args'][0];
 
 
 
 
 
117
  $parts = array_filter( preg_split( '#[_/-]#', $name ) );
118
  $this->data['caps'][ $i ]['parts'] = $parts;
119
  $this->data['caps'][ $i ]['name'] = $name;
114
 
115
  foreach ( $this->data['caps'] as $i => $cap ) {
116
  $name = $cap['args'][0];
117
+
118
+ if ( ! is_string( $name ) ) {
119
+ $name = '';
120
+ }
121
+
122
  $parts = array_filter( preg_split( '#[_/-]#', $name ) );
123
  $this->data['caps'][ $i ]['parts'] = $parts;
124
  $this->data['caps'][ $i ]['name'] = $name;
collectors/debug_bar.php CHANGED
@@ -63,7 +63,7 @@ function register_qm_collectors_debug_bar() {
63
  );
64
 
65
  foreach ( $debug_bar->panels as $panel ) {
66
- $panel_id = strtolower( get_class( $panel ) );
67
 
68
  if ( in_array( $panel_id, $redundant, true ) ) {
69
  continue;
63
  );
64
 
65
  foreach ( $debug_bar->panels as $panel ) {
66
+ $panel_id = strtolower( sanitize_html_class( get_class( $panel ) ) );
67
 
68
  if ( in_array( $panel_id, $redundant, true ) ) {
69
  continue;
collectors/environment.php CHANGED
@@ -227,9 +227,15 @@ class QM_Collector_Environment extends QM_Collector {
227
  'name' => $server[0],
228
  'version' => $server_version,
229
  'address' => $address,
230
- 'host' => php_uname( 'n' ),
 
231
  );
232
 
 
 
 
 
 
233
  }
234
 
235
  public function get_extension_version( $extension ) {
227
  'name' => $server[0],
228
  'version' => $server_version,
229
  'address' => $address,
230
+ 'host' => null,
231
+ 'OS' => null,
232
  );
233
 
234
+ if ( function_exists( 'php_uname' ) ) {
235
+ $this->data['server']['host'] = php_uname( 'n' );
236
+ $this->data['server']['OS'] = php_uname( 's' ) . ' ' . php_uname( 'r' );
237
+ }
238
+
239
  }
240
 
241
  public function get_extension_version( $extension ) {
collectors/timing.php CHANGED
@@ -53,7 +53,7 @@ class QM_Collector_Timing extends QM_Collector {
53
  );
54
  return;
55
  }
56
- $this->track_timer[ $function ]->lap( $name );
57
  }
58
 
59
  public function calculate_time( $function ) {
53
  );
54
  return;
55
  }
56
+ $this->track_timer[ $function ]->lap( array(), $name );
57
  }
58
 
59
  public function calculate_time( $function ) {
dispatchers/Html.php CHANGED
@@ -136,7 +136,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
136
  global $wp_locale, $wp_version;
137
 
138
  $deps = array(
139
- 'jquery-core',
140
  );
141
 
142
  if ( defined( 'QM_NO_JQUERY' ) && QM_NO_JQUERY ) {
@@ -322,19 +322,34 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
322
 
323
  echo '<script type="text/javascript">' . "\n\n";
324
  ?>
325
- if ( ( 'undefined' === typeof QM_i18n ) || ( 'undefined' === typeof jQuery ) || ! jQuery ) {
326
- /* Fallback for worst case scenario */
327
- document.getElementById( 'query-monitor' ).className += ' qm-broken';
328
- console.error( document.getElementById( 'qm-broken' ).textContent );
329
- var menu_item = document.getElementById( 'wp-admin-bar-query-monitor' );
330
- if ( menu_item ) {
331
- menu_item.addEventListener( 'click', function() {
332
- document.getElementById( 'query-monitor' ).className += ' qm-show';
333
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  }
335
- } else if ( ! document.getElementById( 'wpadminbar' ) ) {
336
- document.getElementById( 'query-monitor' ).className += ' qm-peek';
337
- }
338
  <?php
339
  echo '</script>' . "\n\n";
340
  echo '<!-- End of Query Monitor output -->' . "\n\n";
136
  global $wp_locale, $wp_version;
137
 
138
  $deps = array(
139
+ 'jquery',
140
  );
141
 
142
  if ( defined( 'QM_NO_JQUERY' ) && QM_NO_JQUERY ) {
322
 
323
  echo '<script type="text/javascript">' . "\n\n";
324
  ?>
325
+ window.addEventListener('load', function() {
326
+ if ( ( 'undefined' === typeof QM_i18n ) || ( 'undefined' === typeof jQuery ) || ! window.jQuery ) {
327
+ /* Fallback for worst case scenario */
328
+ document.getElementById( 'query-monitor' ).className += ' qm-broken';
329
+ console.error( document.getElementById( 'qm-broken' ).textContent );
330
+
331
+ if ( 'undefined' === typeof QM_i18n ) {
332
+ console.error( 'QM error from page: undefined QM_i18n' );
333
+ }
334
+
335
+ if ( 'undefined' === typeof jQuery ) {
336
+ console.error( 'QM error from page: undefined jQuery' );
337
+ }
338
+
339
+ if ( ! window.jQuery ) {
340
+ console.error( 'QM error from page: no jQuery' );
341
+ }
342
+
343
+ var menu_item = document.getElementById( 'wp-admin-bar-query-monitor' );
344
+ if ( menu_item ) {
345
+ menu_item.addEventListener( 'click', function() {
346
+ document.getElementById( 'query-monitor' ).className += ' qm-show';
347
+ } );
348
+ }
349
+ } else if ( ! document.getElementById( 'wpadminbar' ) ) {
350
+ document.getElementById( 'query-monitor' ).className += ' qm-peek';
351
  }
352
+ } );
 
 
353
  <?php
354
  echo '</script>' . "\n\n";
355
  echo '<!-- End of Query Monitor output -->' . "\n\n";
output/Html.php CHANGED
@@ -90,7 +90,7 @@ abstract class QM_Output_Html extends QM_Output {
90
 
91
  $core = __( 'Core', 'query-monitor' );
92
 
93
- if ( 'component' === $name && isset( $values[ $core ] ) ) {
94
  $args['prepend']['non-core'] = __( 'Non-Core', 'query-monitor' );
95
  }
96
 
90
 
91
  $core = __( 'Core', 'query-monitor' );
92
 
93
+ if ( 'component' === $name && count( $values ) > 1 && in_array( $core, $values, true ) ) {
94
  $args['prepend']['non-core'] = __( 'Non-Core', 'query-monitor' );
95
  }
96
 
output/html/caps.php CHANGED
@@ -85,6 +85,10 @@ class QM_Output_Html_Caps extends QM_Output_Html {
85
  $row_attr['data-qm-component'] .= ' non-core';
86
  }
87
 
 
 
 
 
88
  $attr = '';
89
 
90
  foreach ( $row_attr as $a => $v ) {
85
  $row_attr['data-qm-component'] .= ' non-core';
86
  }
87
 
88
+ if ( '' === $row['name'] ) {
89
+ $row_attr['class'] = 'qm-warn';
90
+ }
91
+
92
  $attr = '';
93
 
94
  foreach ( $row_attr as $a => $v ) {
output/html/debug_bar.php CHANGED
@@ -14,7 +14,7 @@ class QM_Output_Html_Debug_Bar extends QM_Output_Html {
14
 
15
  public function output() {
16
 
17
- $target = get_class( $this->collector->get_panel() );
18
 
19
  echo '<div class="qm qm-debug-bar" id="' . esc_attr( $this->collector->id() ) . '">';
20
  echo '<div id="debug-menu-target-' . esc_attr( $target ) . '" class="debug-menu-target qm-debug-bar-output">';
@@ -36,7 +36,7 @@ function register_qm_output_html_debug_bar( array $output, QM_Collectors $collec
36
  }
37
 
38
  foreach ( $debug_bar->panels as $panel ) {
39
- $panel_id = strtolower( get_class( $panel ) );
40
  $collector = QM_Collectors::get( "debug_bar_{$panel_id}" );
41
 
42
  if ( $collector and $collector->is_visible() ) {
14
 
15
  public function output() {
16
 
17
+ $target = sanitize_html_class( get_class( $this->collector->get_panel() ) );
18
 
19
  echo '<div class="qm qm-debug-bar" id="' . esc_attr( $this->collector->id() ) . '">';
20
  echo '<div id="debug-menu-target-' . esc_attr( $target ) . '" class="debug-menu-target qm-debug-bar-output">';
36
  }
37
 
38
  foreach ( $debug_bar->panels as $panel ) {
39
+ $panel_id = strtolower( sanitize_html_class( get_class( $panel ) ) );
40
  $collector = QM_Collectors::get( "debug_bar_{$panel_id}" );
41
 
42
  if ( $collector and $collector->is_visible() ) {
output/html/environment.php CHANGED
@@ -249,36 +249,27 @@ class QM_Output_Html_Environment extends QM_Output_Html {
249
  echo '<div class="qm-section">';
250
  echo '<h2>' . esc_html( 'Server', 'query-monitor' ) . '</h2>';
251
 
 
 
 
 
 
 
 
 
252
  echo '<table>';
253
  echo '<tbody>';
254
 
255
- echo '<tr>';
256
- echo '<th scope="row">' . esc_html__( 'software', 'query-monitor' ) . '</th>';
257
- echo '<td>' . esc_html( $data['server']['name'] ) . '</td>';
258
- echo '</tr>';
259
-
260
- echo '<tr>';
261
- echo '<th scope="row">' . esc_html__( 'version', 'query-monitor' ) . '</th>';
262
- if ( ! empty( $data['server']['version'] ) ) {
263
- echo '<td>' . esc_html( $data['server']['version'] ) . '</td>';
264
- } else {
265
- echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
266
- }
267
- echo '</tr>';
268
-
269
- echo '<tr>';
270
- echo '<th scope="row">' . esc_html__( 'address', 'query-monitor' ) . '</th>';
271
- if ( ! empty( $data['server']['address'] ) ) {
272
- echo '<td>' . esc_html( $data['server']['address'] ) . '</td>';
273
- } else {
274
- echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
275
  }
276
- echo '</tr>';
277
-
278
- echo '<tr>';
279
- echo '<th scope="row">' . esc_html__( 'host', 'query-monitor' ) . '</th>';
280
- echo '<td>' . esc_html( $data['server']['host'] ) . '</td>';
281
- echo '</tr>';
282
 
283
  echo '</tbody>';
284
  echo '</table>';
249
  echo '<div class="qm-section">';
250
  echo '<h2>' . esc_html( 'Server', 'query-monitor' ) . '</h2>';
251
 
252
+ $server = array(
253
+ 'name' => __( 'software', 'query-monitor' ),
254
+ 'version' => __( 'version', 'query-monitor' ),
255
+ 'address' => __( 'address', 'query-monitor' ),
256
+ 'host' => __( 'host', 'query-monitor' ),
257
+ 'OS' => __( 'OS', 'query-monitor' ),
258
+ );
259
+
260
  echo '<table>';
261
  echo '<tbody>';
262
 
263
+ foreach ( $server as $field => $label ) {
264
+ echo '<tr>';
265
+ echo '<th scope="row">' . esc_html( $label ) . '</th>';
266
+ if ( ! empty( $data['server'][ $field ] ) ) {
267
+ echo '<td>' . esc_html( $data['server'][ $field ] ) . '</td>';
268
+ } else {
269
+ echo '<td><em>' . esc_html__( 'Unknown', 'query-monitor' ) . '</em></td>';
270
+ }
271
+ echo '</tr>';
 
 
 
 
 
 
 
 
 
 
 
272
  }
 
 
 
 
 
 
273
 
274
  echo '</tbody>';
275
  echo '</table>';
output/html/http.php CHANGED
@@ -130,6 +130,7 @@ class QM_Output_Html_HTTP extends QM_Output_Html {
130
  'wp_remote_head',
131
  'wp_remote_fopen',
132
  'download_url',
 
133
  'wpcom_vip_file_get_contents',
134
  ), true );
135
  }
130
  'wp_remote_head',
131
  'wp_remote_fopen',
132
  'download_url',
133
+ 'vip_safe_wp_remote_get',
134
  'wpcom_vip_file_get_contents',
135
  ), true );
136
  }
output/html/timing.php CHANGED
@@ -59,7 +59,7 @@ class QM_Output_Html_Timing extends QM_Output_Html {
59
 
60
  printf(
61
  '<td class="qm-num">%s</td>',
62
- esc_html( number_format_i18n( $row['function_time'] * 1000, 4 ) )
63
  );
64
 
65
  $mem = sprintf(
@@ -78,6 +78,33 @@ class QM_Output_Html_Timing extends QM_Output_Html {
78
 
79
  echo '</tr>';
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
  }
83
  if ( ! empty( $data['warning'] ) ) {
59
 
60
  printf(
61
  '<td class="qm-num">%s</td>',
62
+ esc_html( number_format_i18n( $row['function_time'], 4 ) )
63
  );
64
 
65
  $mem = sprintf(
78
 
79
  echo '</tr>';
80
 
81
+ if ( ! empty( $row['laps'] ) ) {
82
+ foreach ( $row['laps'] as $lap_id => $lap ) {
83
+ echo '<tr>';
84
+
85
+ echo '<td class="qm-ltr"><code>&mdash;&nbsp;';
86
+ echo esc_html( $row['function'] . ': ' . $lap_id );
87
+ echo '</code></td>';
88
+
89
+ printf(
90
+ '<td class="qm-num">%s</td>',
91
+ esc_html( number_format_i18n( $lap['time_used'], 4 ) )
92
+ );
93
+
94
+ $mem = sprintf(
95
+ /* translators: %s: Approximate memory used in kilobytes */
96
+ __( '~%s kB', 'query-monitor' ),
97
+ number_format_i18n( $lap['memory_used'] / 1024 )
98
+ );
99
+ printf(
100
+ '<td class="qm-num">%s</td>',
101
+ esc_html( $mem )
102
+ );
103
+ echo '<td class="qm-nowrap"></td>';
104
+
105
+ echo '</tr>';
106
+ }
107
+ }
108
  }
109
  }
110
  if ( ! empty( $data['warning'] ) ) {
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.0.0
14
  * Plugin URI: https://github.com/johnbillion/query-monitor
15
  * Author: John Blackbourn & contributors
16
  * Author URI: https://github.com/johnbillion/query-monitor/graphs/contributors
10
  *
11
  * Plugin Name: Query Monitor
12
  * Description: The Developer Tools panel for WordPress.
13
+ * Version: 3.0.1
14
  * Plugin URI: https://github.com/johnbillion/query-monitor
15
  * Author: John Blackbourn & contributors
16
  * Author URI: https://github.com/johnbillion/query-monitor/graphs/contributors
readme.txt CHANGED
@@ -3,8 +3,9 @@ Contributors: johnbillion
3
  Tags: ajax, debug, debug-bar, debugging, development, developer, performance, profiler, profiling, queries, query monitor, rest-api
4
  Requires at least: 3.7
5
  Tested up to: 4.9
6
- Stable tag: 3.0.0
7
  License: GPLv2 or later
 
8
 
9
  Query Monitor is the Developer Tools panel for WordPress.
10
 
@@ -93,6 +94,16 @@ By default, Query Monitor's output is only shown to Administrators on single-sit
93
 
94
  In addition to this, you can set an authentication cookie which allows you to view Query Monitor output when you're not logged in (or if you're logged in as a non-administrator). See the bottom of Query Monitor's output for details.
95
 
 
 
 
 
 
 
 
 
 
 
96
  == Screenshots ==
97
 
98
  1. The admin toolbar menu showing an overview
3
  Tags: ajax, debug, debug-bar, debugging, development, developer, performance, profiler, profiling, queries, query monitor, rest-api
4
  Requires at least: 3.7
5
  Tested up to: 4.9
6
+ Stable tag: 3.0.1
7
  License: GPLv2 or later
8
+ Requires PHP: 5.3
9
 
10
  Query Monitor is the Developer Tools panel for WordPress.
11
 
94
 
95
  In addition to this, you can set an authentication cookie which allows you to view Query Monitor output when you're not logged in (or if you're logged in as a non-administrator). See the bottom of Query Monitor's output for details.
96
 
97
+ = Privacy Statement =
98
+
99
+ Query Monitor does not persistently store any of the data that it collects. It does not send data to any third party, nor does it include any third party resources.
100
+
101
+ Query Monitor implements an optional browser cookie that allows users to view Query Monitor output when not logged in, or when logged in as another user who cannot usually view Query Monitor's output. This cookie can be set and cleared from the Settings panel in Query Monitor. This cookie operates using the same mechanism as the authentication cookies in WordPress core, and therefore it contains the user's `user_login` field in plain text which should be treated as potentially personally identifiable information. The name of the cookie is `query_monitor_{hash}` where `{hash}` is an identifier unique to the installation of WordPress.
102
+
103
+ Query Monitor stores some user preferences in the browser's Local Storage. It stores the ID of the most recently accessed panel and the height of the panel if the user has resized it. This data is stored using the browser's `localStorage` API, does not get sent with HTTP requests, and does not contain any personally identifiable information.
104
+
105
+ Please note that in a future version of Query Monitor, opt-in features may be introduced which allow a user to choose to persistently store data and/or send data to a third party service. Such features will only ever be opt-in.
106
+
107
  == Screenshots ==
108
 
109
  1. The admin toolbar menu showing an overview