Query Monitor - Version 2.7.4

Version Description

  • An unknown component now gets marked as such, not as Core.
  • Support for invokable objects in action and filter callbacks.
  • Fix fatal error when activating Debug Bar plugin after Query Monitor has already been activated.
  • Implement escaping inside QM_Output_Html::format_url() which can deal with unsafe output. Thanks to Stephen Harris for the responsible disclosure.
Download this release

Release Info

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

Code changes from version 2.7.3 to 2.7.4

classes/Util.php CHANGED
@@ -69,6 +69,7 @@ class QM_Util {
69
  self::$file_dirs['template'] = self::standard_dir( get_template_directory() );
70
  self::$file_dirs['other'] = self::standard_dir( WP_CONTENT_DIR );
71
  self::$file_dirs['core'] = self::standard_dir( ABSPATH );
 
72
  }
73
  return self::$file_dirs;
74
  }
@@ -82,7 +83,7 @@ class QM_Util {
82
  }
83
 
84
  foreach ( self::get_file_dirs() as $type => $dir ) {
85
- if ( 0 === strpos( $file, $dir ) ) {
86
  break;
87
  }
88
  }
@@ -129,9 +130,12 @@ class QM_Util {
129
  $context = $file;
130
  break;
131
  case 'core':
132
- default:
133
  $name = __( 'Core', 'query-monitor' );
134
  break;
 
 
 
 
135
  }
136
 
137
  return self::$file_components[$file] = (object) compact( 'type', 'name', 'context' );
@@ -140,11 +144,8 @@ class QM_Util {
140
 
141
  public static function populate_callback( array $callback ) {
142
 
143
- $access = '->';
144
-
145
  if ( is_string( $callback['function'] ) and ( false !== strpos( $callback['function'], '::' ) ) ) {
146
  $callback['function'] = explode( '::', $callback['function'] );
147
- $access = '::';
148
  }
149
 
150
  try {
@@ -152,19 +153,28 @@ class QM_Util {
152
  if ( is_array( $callback['function'] ) ) {
153
 
154
  if ( is_object( $callback['function'][0] ) ) {
155
- $class = get_class( $callback['function'][0] );
 
156
  } else {
157
- $class = $callback['function'][0];
 
158
  }
159
 
160
  $callback['name'] = $class . $access . $callback['function'][1] . '()';
161
  $ref = new ReflectionMethod( $class, $callback['function'][1] );
162
 
163
- } else if ( is_object( $callback['function'] ) and is_a( $callback['function'], 'Closure' ) ) {
164
 
165
- $ref = new ReflectionFunction( $callback['function'] );
166
- $file = trim( QM_Util::standard_dir( $ref->getFileName(), '' ), '/' );
167
- $callback['name'] = sprintf( __( 'Closure on line %1$d of %2$s', 'query-monitor' ), $ref->getStartLine(), $file );
 
 
 
 
 
 
 
168
 
169
  } else {
170
 
69
  self::$file_dirs['template'] = self::standard_dir( get_template_directory() );
70
  self::$file_dirs['other'] = self::standard_dir( WP_CONTENT_DIR );
71
  self::$file_dirs['core'] = self::standard_dir( ABSPATH );
72
+ self::$file_dirs['unknown'] = null;
73
  }
74
  return self::$file_dirs;
75
  }
83
  }
84
 
85
  foreach ( self::get_file_dirs() as $type => $dir ) {
86
+ if ( $dir && ( 0 === strpos( $file, $dir ) ) ) {
87
  break;
88
  }
89
  }
130
  $context = $file;
131
  break;
132
  case 'core':
 
133
  $name = __( 'Core', 'query-monitor' );
134
  break;
135
+ case 'unknown':
136
+ default:
137
+ $name = __( 'Unknown', 'query-monitor' );
138
+ break;
139
  }
140
 
141
  return self::$file_components[$file] = (object) compact( 'type', 'name', 'context' );
144
 
145
  public static function populate_callback( array $callback ) {
146
 
 
 
147
  if ( is_string( $callback['function'] ) and ( false !== strpos( $callback['function'], '::' ) ) ) {
148
  $callback['function'] = explode( '::', $callback['function'] );
 
149
  }
150
 
151
  try {
153
  if ( is_array( $callback['function'] ) ) {
154
 
155
  if ( is_object( $callback['function'][0] ) ) {
156
+ $class = get_class( $callback['function'][0] );
157
+ $access = '->';
158
  } else {
159
+ $class = $callback['function'][0];
160
+ $access = '::';
161
  }
162
 
163
  $callback['name'] = $class . $access . $callback['function'][1] . '()';
164
  $ref = new ReflectionMethod( $class, $callback['function'][1] );
165
 
166
+ } else if ( is_object( $callback['function'] ) ) {
167
 
168
+ if ( is_a( $callback['function'], 'Closure' ) ) {
169
+ $ref = new ReflectionFunction( $callback['function'] );
170
+ $file = trim( QM_Util::standard_dir( $ref->getFileName(), '' ), '/' );
171
+ $callback['name'] = sprintf( __( 'Closure on line %1$d of %2$s', 'query-monitor' ), $ref->getStartLine(), $file );
172
+ } else {
173
+ // the object should have a __invoke() method
174
+ $class = get_class( $callback['function'] );
175
+ $callback['name'] = $class . '->__invoke()';
176
+ $ref = new ReflectionMethod( $class, '__invoke' );
177
+ }
178
 
179
  } else {
180
 
collectors/debug_bar.php CHANGED
@@ -54,7 +54,7 @@ function register_qm_collectors_debug_bar() {
54
 
55
  global $debug_bar;
56
 
57
- if ( class_exists( 'Debug_Bar' ) ) {
58
  return;
59
  }
60
 
@@ -87,4 +87,52 @@ function register_qm_collectors_debug_bar() {
87
 
88
  }
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  add_action( 'init', 'register_qm_collectors_debug_bar' );
54
 
55
  global $debug_bar;
56
 
57
+ if ( class_exists( 'Debug_Bar' ) || qm_debug_bar_being_activated() ) {
58
  return;
59
  }
60
 
87
 
88
  }
89
 
90
+ function qm_debug_bar_being_activated() {
91
+
92
+ if ( ! is_admin() ) {
93
+
94
+ return false;
95
+
96
+ }
97
+
98
+ if ( ! isset( $_REQUEST['action'] ) ) {
99
+
100
+ return false;
101
+
102
+ }
103
+
104
+ if ( isset( $_GET['action'] ) ) {
105
+
106
+ if ( ! isset( $_GET['plugin'] ) || ! isset( $_GET['_wpnonce'] ) ) {
107
+
108
+ return false;
109
+
110
+ }
111
+
112
+ if ( 'activate' === $_GET['action'] && false !== strpos( $_GET['plugin'], 'debug-bar.php' ) ) {
113
+
114
+ return true;
115
+
116
+ }
117
+
118
+ } elseif ( isset( $_POST['action'] ) ) {
119
+
120
+ if ( ! isset( $_POST['checked'] ) || ! is_array( $_POST['checked'] ) || ! isset( $_POST['_wpnonce'] ) ) {
121
+
122
+ return false;
123
+
124
+ }
125
+
126
+ if ( 'activate-selected' === $_POST['action'] && in_array( 'debug-bar/debug-bar.php', $_POST['checked'] ) ) {
127
+
128
+ return true;
129
+
130
+ }
131
+
132
+ }
133
+
134
+ return false;
135
+
136
+ }
137
+
138
  add_action( 'init', 'register_qm_collectors_debug_bar' );
output/Html.php CHANGED
@@ -126,13 +126,13 @@ abstract class QM_Output_Html implements QM_Output {
126
  public static function format_url( $url ) {
127
  $url = str_replace( array(
128
  '=',
129
- '&',
130
  '?',
131
  ), array(
132
  '<span class="qm-equals">=</span>',
133
  '<br><span class="qm-param">&amp;</span>',
134
  '<br><span class="qm-param">?</span>',
135
- ), $url );
136
  return $url;
137
 
138
  }
126
  public static function format_url( $url ) {
127
  $url = str_replace( array(
128
  '=',
129
+ '&amp;',
130
  '?',
131
  ), array(
132
  '<span class="qm-equals">=</span>',
133
  '<br><span class="qm-param">&amp;</span>',
134
  '<br><span class="qm-param">?</span>',
135
+ ), esc_html( $url ) );
136
  return $url;
137
 
138
  }
query-monitor.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Query Monitor
4
  Description: Monitoring of database queries, hooks, conditionals and more.
5
- Version: 2.7.3
6
  Plugin URI: https://querymonitor.com/
7
  Author: John Blackbourn
8
  Author URI: https://johnblackbourn.com/
@@ -30,8 +30,8 @@ if ( defined( 'QM_DISABLED' ) and QM_DISABLED ) {
30
  return;
31
  }
32
 
33
- if ( 'cli' == php_sapi_name() ) {
34
- # For the time being, let's not load QM when using the CLI because we've no persistent storage and no means of
35
  # outputting collected data on the CLI. This will change in a future version of QM.
36
  return;
37
  }
2
  /*
3
  Plugin Name: Query Monitor
4
  Description: Monitoring of database queries, hooks, conditionals and more.
5
+ Version: 2.7.4
6
  Plugin URI: https://querymonitor.com/
7
  Author: John Blackbourn
8
  Author URI: https://johnblackbourn.com/
30
  return;
31
  }
32
 
33
+ if ( defined( 'WP_CLI' ) and WP_CLI ) {
34
+ # For the time being, let's not load QM when using WP-CLI because we've no persistent storage and no means of
35
  # outputting collected data on the CLI. This will change in a future version of QM.
36
  return;
37
  }
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: johnbillion
3
  Tags: debug, debug-bar, debugging, development, developer, performance, profiler, profiling, queries, query monitor
4
  Requires at least: 3.5
5
- Tested up to: 4.2
6
- Stable tag: 2.7.3
7
  License: GPLv2 or later
8
 
9
  View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
@@ -142,9 +142,9 @@ On pages that have an especially high number of database queries (in the hundred
142
 
143
  = Are there any add-on plugins for Query Monitor? =
144
 
145
- Query Monitor transparently supports add-ons for the Debug Bar plugin. If you have any Debug Bar add-ons installed, just deactivate Debug Bar and the add-ons will show up in Query Monitor's menu.
146
 
147
- There's also [Query Monitor bbPress & BuddyPress Conditionals](https://wordpress.org/plugins/query-monitor-bbpress-buddypress-conditionals/) by Stephen Edgar.
148
 
149
  = Where can I suggest a new feature or report a bug? =
150
 
@@ -156,6 +156,12 @@ No, I do not accept donations. If you like the plugin, I'd love for you to [leav
156
 
157
  == Changelog ==
158
 
 
 
 
 
 
 
159
  = 2.7.3 =
160
  * Improvements to the shutdown handler for PHP errors, so it handles syntax and compilation errors too.
161
 
2
  Contributors: johnbillion
3
  Tags: debug, debug-bar, debugging, development, developer, performance, profiler, profiling, queries, query monitor
4
  Requires at least: 3.5
5
+ Tested up to: 4.3
6
+ Stable tag: 2.7.4
7
  License: GPLv2 or later
8
 
9
  View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
142
 
143
  = Are there any add-on plugins for Query Monitor? =
144
 
145
+ [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)
146
 
147
+ In addition, Query Monitor transparently supports add-ons for the Debug Bar plugin. If you have any Debug Bar add-ons installed, just deactivate Debug Bar and the add-ons will show up in Query Monitor's menu.
148
 
149
  = Where can I suggest a new feature or report a bug? =
150
 
156
 
157
  == Changelog ==
158
 
159
+ = 2.7.4 =
160
+ * An unknown component now gets marked as such, not as Core.
161
+ * Support for invokable objects in action and filter callbacks.
162
+ * Fix fatal error when activating Debug Bar plugin after Query Monitor has already been activated.
163
+ * Implement escaping inside `QM_Output_Html::format_url()` which can deal with unsafe output. Thanks to Stephen Harris for the responsible disclosure.
164
+
165
  = 2.7.3 =
166
  * Improvements to the shutdown handler for PHP errors, so it handles syntax and compilation errors too.
167
 
wp-content/db.php CHANGED
@@ -29,8 +29,8 @@ if ( defined( 'QM_DISABLED' ) and QM_DISABLED ) {
29
  return;
30
  }
31
 
32
- if ( 'cli' == php_sapi_name() ) {
33
- # For the time being, let's not load QM when using the CLI because we've no persistent storage and no means of
34
  # outputting collected data on the CLI. This will change in a future version of QM.
35
  return;
36
  }
29
  return;
30
  }
31
 
32
+ if ( defined( 'WP_CLI' ) and WP_CLI ) {
33
+ # For the time being, let's not load QM when using WP-CLI because we've no persistent storage and no means of
34
  # outputting collected data on the CLI. This will change in a future version of QM.
35
  return;
36
  }