Query Monitor - Version 2.6.7

Version Description

  • Various tweaks under the hood. No shiny new features just yet.

=

Download this release

Release Info

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

Code changes from version 2.6.6 to 2.6.7

Backtrace.php CHANGED
@@ -65,6 +65,15 @@ class QM_Backtrace {
65
  ), $args );
66
  $this->trace = debug_backtrace( false );
67
  $this->ignore( 1 ); # Self-awareness
 
 
 
 
 
 
 
 
 
68
 
69
  if ( $args['ignore_items'] )
70
  $this->ignore( $args['ignore_items'] );
65
  ), $args );
66
  $this->trace = debug_backtrace( false );
67
  $this->ignore( 1 ); # Self-awareness
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 ( $this->trace[0]['function'] === 'error_handler' ) {
74
+ $this->ignore( 1 );
75
+ }
76
+
77
 
78
  if ( $args['ignore_items'] )
79
  $this->ignore( $args['ignore_items'] );
Collector.php CHANGED
@@ -32,10 +32,13 @@ abstract class QM_Collector {
32
  }
33
 
34
  public static function format_bool_constant( $constant ) {
35
- if ( !defined( $constant ) or !constant( $constant ) )
 
 
36
  return 'false';
37
- else
38
  return 'true';
 
39
  }
40
 
41
  final public function get_data() {
32
  }
33
 
34
  public static function format_bool_constant( $constant ) {
35
+ if ( !defined( $constant ) ) {
36
+ return 'undefined';
37
+ } else if ( !constant( $constant ) ) {
38
  return 'false';
39
+ } else {
40
  return 'true';
41
+ }
42
  }
43
 
44
  final public function get_data() {
Dispatcher.php CHANGED
@@ -21,7 +21,7 @@ abstract class QM_Dispatcher {
21
  $this->qm = $qm;
22
  }
23
 
24
- abstract public function active();
25
 
26
  public function init() {
27
  // nothing
21
  $this->qm = $qm;
22
  }
23
 
24
+ abstract public function is_active();
25
 
26
  public function init() {
27
  // nothing
Util.php CHANGED
@@ -19,6 +19,7 @@ class QM_Util {
19
 
20
  protected static $file_components = array();
21
  protected static $file_dirs = array();
 
22
 
23
  private function __construct() {}
24
 
@@ -45,11 +46,13 @@ class QM_Util {
45
  public static function standard_dir( $dir, $abspath_replace = null ) {
46
 
47
  $dir = str_replace( '\\', '/', $dir );
48
- $dir = preg_replace( '|/+|', '/', $dir );
49
 
50
  if ( is_string( $abspath_replace ) ) {
51
- # @TODO cache the value of self::standard_dir( ABSPATH )
52
- $dir = str_replace( self::standard_dir( ABSPATH ), $abspath_replace, $dir );
 
 
53
  }
54
 
55
  return $dir;
@@ -174,10 +177,6 @@ class QM_Util {
174
  return false;
175
  }
176
 
177
- public static function wpv() {
178
- return 'qm-wp-' . ( floatval( $GLOBALS['wp_version'] ) * 10 );
179
- }
180
-
181
  public static function get_admins() {
182
  if ( is_multisite() )
183
  return false;
19
 
20
  protected static $file_components = array();
21
  protected static $file_dirs = array();
22
+ protected static $abspath = null;
23
 
24
  private function __construct() {}
25
 
46
  public static function standard_dir( $dir, $abspath_replace = null ) {
47
 
48
  $dir = str_replace( '\\', '/', $dir );
49
+ $dir = str_replace( '//', '/', $dir );
50
 
51
  if ( is_string( $abspath_replace ) ) {
52
+ if ( !self::$abspath ) {
53
+ self::$abspath = self::standard_dir( ABSPATH );
54
+ }
55
+ $dir = str_replace( self::$abspath, $abspath_replace, $dir );
56
  }
57
 
58
  return $dir;
177
  return false;
178
  }
179
 
 
 
 
 
180
  public static function get_admins() {
181
  if ( is_multisite() )
182
  return false;
collectors/authentication.php CHANGED
@@ -30,31 +30,41 @@ class QM_Collector_Authentication extends QM_Collector {
30
  public function action_plugins_loaded() {
31
 
32
  if ( !defined( 'QM_COOKIE' ) )
33
- define( 'QM_COOKIE', 'qm_' . COOKIEHASH );
34
 
35
  }
36
 
37
- public function user_can_view() {
38
  if ( isset( $_COOKIE[QM_COOKIE] ) )
39
- return $this->verify_nonce( $_COOKIE[QM_COOKIE], 'view_query_monitor' );
40
  return false;
41
  }
42
 
43
- public function create_nonce( $action ) {
44
- # This is just WordPress' nonce implementation minus the user ID
45
- # check so a nonce can be set in a cookie and used cross-user
46
- $i = wp_nonce_tick();
47
- return substr( wp_hash( $i . $action, 'nonce' ), -12, 10 );
 
 
 
48
  }
49
 
50
- public function verify_nonce( $nonce, $action ) {
 
 
 
 
 
 
 
 
51
 
52
- $i = wp_nonce_tick();
53
 
54
- if ( substr( wp_hash( $i . $action, 'nonce' ), -12, 10 ) === $nonce )
55
- return true;
56
- if ( substr( wp_hash( ( $i - 1 ) . $action, 'nonce' ), -12, 10 ) === $nonce )
57
- return true;
58
 
59
  return false;
60
 
30
  public function action_plugins_loaded() {
31
 
32
  if ( !defined( 'QM_COOKIE' ) )
33
+ define( 'QM_COOKIE', 'query_monitor_' . COOKIEHASH );
34
 
35
  }
36
 
37
+ public function user_verified() {
38
  if ( isset( $_COOKIE[QM_COOKIE] ) )
39
+ return $this->verify_cookie( stripslashes( $_COOKIE[QM_COOKIE] ) );
40
  return false;
41
  }
42
 
43
+ public function get_cookie_attributes() {
44
+
45
+ return array(
46
+ 'name' => QM_COOKIE,
47
+ 'path' => COOKIEPATH,
48
+ 'domain' => COOKIE_DOMAIN,
49
+ );
50
+
51
  }
52
 
53
+ public function get_cookie_content() {
54
+
55
+ $expires = time() + 172800; # 48 hours
56
+ $value = wp_generate_auth_cookie( get_current_user_id(), $expires, 'logged_in' );
57
+ $secure = apply_filters( 'secure_logged_in_cookie', false, get_current_user_id(), is_ssl() );
58
+
59
+ return compact( 'expires', 'value', 'secure' );
60
+
61
+ }
62
 
63
+ public function verify_cookie( $value ) {
64
 
65
+ if ( $old_user_id = wp_validate_auth_cookie( $value, 'logged_in' ) ) {
66
+ return user_can( $old_user_id, 'view_query_monitor' );
67
+ }
 
68
 
69
  return false;
70
 
collectors/environment.php CHANGED
@@ -141,27 +141,8 @@ class QM_Collector_Environment extends QM_Collector {
141
 
142
  }
143
 
144
- if ( function_exists( 'posix_getpwuid' ) ) {
145
-
146
- $u = posix_getpwuid( posix_getuid() );
147
- $g = posix_getgrgid( $u['gid'] );
148
- $php_u = esc_html( $u['name'] . ':' . $g['name'] );
149
-
150
- } else if ( isset( $_SERVER['USER'] ) ) {
151
-
152
- $php_u = esc_html( $_SERVER['USER'] );
153
-
154
- } else if ( function_exists( 'exec' ) ) {
155
-
156
- $php_u = esc_html( exec( 'whoami' ) );
157
-
158
- }
159
-
160
- if ( empty( $php_u ) )
161
- $php_u = '<em>' . __( 'Unknown', 'query-monitor' ) . '</em>';
162
-
163
  $this->data['php']['version'] = phpversion();
164
- $this->data['php']['user'] = $php_u;
165
 
166
  foreach ( $this->php_vars as $setting )
167
  $this->data['php']['variables'][$setting]['after'] = ini_get( $setting );
@@ -184,12 +165,12 @@ class QM_Collector_Environment extends QM_Collector {
184
  if ( isset( $server[1] ) )
185
  $server_version = $server[1];
186
  else
187
- $server_version = '<em>' . __( 'Unknown', 'query-monitor' ) . '</em>';
188
 
189
  if ( isset( $_SERVER['SERVER_ADDR'] ) )
190
  $address = $_SERVER['SERVER_ADDR'];
191
  else
192
- $address = '<em>' . __( 'Unknown', 'query-monitor' ) . '</em>';
193
 
194
  $this->data['server'] = array(
195
  'name' => $server[0],
@@ -200,6 +181,39 @@ class QM_Collector_Environment extends QM_Collector {
200
 
201
  }
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  }
204
 
205
  function register_qm_collector_environment( array $qm ) {
141
 
142
  }
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  $this->data['php']['version'] = phpversion();
145
+ $this->data['php']['user'] = self::get_current_user();
146
 
147
  foreach ( $this->php_vars as $setting )
148
  $this->data['php']['variables'][$setting]['after'] = ini_get( $setting );
165
  if ( isset( $server[1] ) )
166
  $server_version = $server[1];
167
  else
168
+ $server_version = null;
169
 
170
  if ( isset( $_SERVER['SERVER_ADDR'] ) )
171
  $address = $_SERVER['SERVER_ADDR'];
172
  else
173
+ $address = null;
174
 
175
  $this->data['server'] = array(
176
  'name' => $server[0],
181
 
182
  }
183
 
184
+ protected static function get_current_user() {
185
+
186
+ $php_u = null;
187
+
188
+ if ( function_exists( 'posix_getpwuid' ) ) {
189
+ $u = posix_getpwuid( posix_getuid() );
190
+ $g = posix_getgrgid( $u['gid'] );
191
+ $php_u = $u['name'] . ':' . $g['name'];
192
+ }
193
+
194
+ if ( empty( $php_u ) and isset( $_ENV['APACHE_RUN_USER'] ) ) {
195
+ $php_u = $_ENV['APACHE_RUN_USER'];
196
+ if ( isset( $_ENV['APACHE_RUN_GROUP'] ) ) {
197
+ $php_u .= ':' . $_ENV['APACHE_RUN_GROUP'];
198
+ }
199
+ }
200
+
201
+ if ( empty( $php_u ) and isset( $_SERVER['USER'] ) ) {
202
+ $php_u = $_SERVER['USER'];
203
+ }
204
+
205
+ if ( empty( $php_u ) and function_exists( 'exec' ) ) {
206
+ $php_u = exec( 'whoami' );
207
+ }
208
+
209
+ if ( empty( $php_u ) and function_exists( 'getenv' ) ) {
210
+ $php_u = getenv( 'USERNAME' );
211
+ }
212
+
213
+ return $php_u;
214
+
215
+ }
216
+
217
  }
218
 
219
  function register_qm_collector_environment( array $qm ) {
collectors/php_errors.php CHANGED
@@ -105,6 +105,10 @@ class QM_Collector_PHP_Errors extends QM_Collector {
105
 
106
  }
107
 
 
 
 
 
108
  }
109
 
110
  function register_qm_collector_php_errors( array $qm ) {
105
 
106
  }
107
 
108
+ public function process() {
109
+ restore_error_handler();
110
+ }
111
+
112
  }
113
 
114
  function register_qm_collector_php_errors( array $qm ) {
dispatchers/Headers.php CHANGED
@@ -58,7 +58,7 @@ class QM_Dispatcher_Headers extends QM_Dispatcher {
58
  return new QM_Output_Headers( $collector );
59
  }
60
 
61
- public function active() {
62
 
63
  if ( ! $this->qm->user_can_view() ) {
64
  return false;
58
  return new QM_Output_Headers( $collector );
59
  }
60
 
61
+ public function is_active() {
62
 
63
  if ( ! $this->qm->user_can_view() ) {
64
  return false;
dispatchers/Html.php CHANGED
@@ -33,7 +33,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
33
  return;
34
  }
35
 
36
- $class = implode( ' ', array( 'hide-if-js', QM_Util::wpv() ) );
37
  $title = __( 'Query Monitor', 'query-monitor' );
38
 
39
  $wp_admin_bar->add_menu( array(
@@ -152,7 +152,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
152
 
153
  public function js_admin_bar_menu() {
154
 
155
- $class = implode( ' ', apply_filters( 'query_monitor_class', array( QM_Util::wpv() ) ) );
156
  $title = implode( '&nbsp;&nbsp;&nbsp;', apply_filters( 'query_monitor_title', array() ) );
157
 
158
  if ( empty( $title ) )
@@ -173,7 +173,7 @@ class QM_Dispatcher_Html extends QM_Dispatcher {
173
 
174
  }
175
 
176
- public function active() {
177
 
178
  if ( ! $this->qm->user_can_view() ) {
179
  return false;
33
  return;
34
  }
35
 
36
+ $class = implode( ' ', array( 'hide-if-js' ) );
37
  $title = __( 'Query Monitor', 'query-monitor' );
38
 
39
  $wp_admin_bar->add_menu( array(
152
 
153
  public function js_admin_bar_menu() {
154
 
155
+ $class = implode( ' ', apply_filters( 'query_monitor_class', array() ) );
156
  $title = implode( '&nbsp;&nbsp;&nbsp;', apply_filters( 'query_monitor_title', array() ) );
157
 
158
  if ( empty( $title ) )
173
 
174
  }
175
 
176
+ public function is_active() {
177
 
178
  if ( ! $this->qm->user_can_view() ) {
179
  return false;
output/html/authentication.php CHANGED
@@ -28,15 +28,17 @@ class QM_Output_Html_Authentication extends QM_Output_Html {
28
  echo '</thead>';
29
  echo '<tbody>';
30
 
31
- $name = QM_COOKIE;
32
- $domain = COOKIE_DOMAIN;
33
- $path = COOKIEPATH;
34
 
35
- if ( !isset( $_COOKIE[$name] ) or !$this->collector->verify_nonce( $_COOKIE[$name], 'view_query_monitor' ) ) {
36
 
37
- $value = $this->collector->create_nonce( 'view_query_monitor' );
38
- $text = esc_js( __( 'Authentication cookie set. You can now view Query Monitor output while logged out or while logged in as a different user.', 'query-monitor' ) );
39
- $link = "document.cookie='{$name}={$value}; domain={$domain}; path={$path}'; alert('{$text}'); return false;";
 
 
 
 
40
 
41
  echo '<tr>';
42
  echo '<td>' . __( 'You can set an authentication cookie which allows you to view Query Monitor output when you&rsquo;re not logged in.', 'query-monitor' ) . '</td>';
@@ -47,8 +49,9 @@ class QM_Output_Html_Authentication extends QM_Output_Html {
47
 
48
  } else {
49
 
50
- $text = esc_js( __( 'Authentication cookie cleared.', 'query-monitor' ) );
51
- $link = "document.cookie='{$name}=; expires=' + new Date(0).toUTCString() + '; domain={$domain}; path={$path}'; alert('{$text}'); return false;";
 
52
 
53
  echo '<tr>';
54
  echo '<td>' . __( 'You currently have an authentication cookie which allows you to view Query Monitor output.', 'query-monitor' ) . '</td>';
28
  echo '</thead>';
29
  echo '<tbody>';
30
 
31
+ $atts = $this->collector->get_cookie_attributes();
 
 
32
 
33
+ if ( !$this->collector->user_verified() ) {
34
 
35
+ $cookie = $this->collector->get_cookie_content();
36
+ $text = esc_js( __( 'Authentication cookie set. You can now view Query Monitor output while logged out or while logged in as a different user.', 'query-monitor' ) );
37
+ $value = "{$atts['name']}={$cookie['value']}; domain={$atts['domain']}; path={$atts['path']}";
38
+ if ( $cookie['secure'] ) {
39
+ $value .= '; secure';
40
+ }
41
+ $link = "document.cookie='{$value}'; alert('{$text}'); return false;";
42
 
43
  echo '<tr>';
44
  echo '<td>' . __( 'You can set an authentication cookie which allows you to view Query Monitor output when you&rsquo;re not logged in.', 'query-monitor' ) . '</td>';
49
 
50
  } else {
51
 
52
+ $text = esc_js( __( 'Authentication cookie cleared.', 'query-monitor' ) );
53
+ $value = "{$atts['name']}=; expires=' + new Date(0).toUTCString() + '; domain={$atts['domain']}; path={$atts['path']}";
54
+ $link = "document.cookie='{$value}'; alert('{$text}'); return false;";
55
 
56
  echo '<tr>';
57
  echo '<td>' . __( 'You currently have an authentication cookie which allows you to view Query Monitor output.', 'query-monitor' ) . '</td>';
output/html/environment.php CHANGED
@@ -43,7 +43,11 @@ class QM_Output_Html_Environment extends QM_Output_Html {
43
  echo '</tr>';
44
  echo '<tr>';
45
  echo '<td>user</td>';
46
- echo "<td>{$data['php']['user']}</td>";
 
 
 
 
47
  echo '</tr>';
48
 
49
  foreach ( $data['php']['variables'] as $key => $val ) {
@@ -200,12 +204,20 @@ class QM_Output_Html_Environment extends QM_Output_Html {
200
 
201
  echo '<tr>';
202
  echo '<td>version</td>';
203
- echo "<td>{$data['server']['version']}</td>";
 
 
 
 
204
  echo '</tr>';
205
 
206
  echo '<tr>';
207
  echo '<td>address</td>';
208
- echo "<td>{$data['server']['address']}</td>";
 
 
 
 
209
  echo '</tr>';
210
 
211
  echo '<tr>';
43
  echo '</tr>';
44
  echo '<tr>';
45
  echo '<td>user</td>';
46
+ if ( !empty( $data['php']['user'] ) ) {
47
+ echo '<td>' . esc_html( $data['php']['user'] ) . '</td>';
48
+ } else {
49
+ echo '<td><em>' . __( 'Unknown', 'query-monitor' ) . '</em></td>';
50
+ }
51
  echo '</tr>';
52
 
53
  foreach ( $data['php']['variables'] as $key => $val ) {
204
 
205
  echo '<tr>';
206
  echo '<td>version</td>';
207
+ if ( !empty( $data['server']['version'] ) ) {
208
+ echo '<td>' . esc_html( $data['server']['version'] ) . '</td>';
209
+ } else {
210
+ echo '<td><em>' . __( 'Unknown', 'query-monitor' ) . '</em></td>';
211
+ }
212
  echo '</tr>';
213
 
214
  echo '<tr>';
215
  echo '<td>address</td>';
216
+ if ( !empty( $data['server']['address'] ) ) {
217
+ echo '<td>' . esc_html( $data['server']['address'] ) . '</td>';
218
+ } else {
219
+ echo '<td><em>' . __( 'Unknown', 'query-monitor' ) . '</em></td>';
220
+ }
221
  echo '</tr>';
222
 
223
  echo '<tr>';
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.6.6
6
  Plugin URI: https://github.com/johnbillion/query-monitor
7
  Author: John Blackbourn
8
  Author URI: https://johnblackbourn.com/
@@ -42,8 +42,9 @@ class QueryMonitor extends QM_Plugin {
42
  protected function __construct( $file ) {
43
 
44
  # Actions
45
- add_action( 'init', array( $this, 'action_init' ) );
46
- add_action( 'shutdown', array( $this, 'action_shutdown' ), 0 );
 
47
 
48
  # Filters
49
  add_filter( 'pre_update_option_active_plugins', array( $this, 'filter_active_plugins' ) );
@@ -63,6 +64,10 @@ class QueryMonitor extends QM_Plugin {
63
  foreach ( apply_filters( 'query_monitor_collectors', array() ) as $collector )
64
  $this->add_collector( $collector );
65
 
 
 
 
 
66
  # Dispatchers:
67
  foreach ( glob( $this->plugin_path( 'dispatchers/*.php' ) ) as $dispatcher )
68
  include $dispatcher;
@@ -126,15 +131,12 @@ class QueryMonitor extends QM_Plugin {
126
  if ( !did_action( 'plugins_loaded' ) )
127
  return false;
128
 
129
- if ( is_multisite() ) {
130
- if ( current_user_can( 'manage_network_options' ) )
131
- return true;
132
- } else if ( current_user_can( 'view_query_monitor' ) ) {
133
  return true;
134
  }
135
 
136
  if ( $auth = self::get_collector( 'authentication' ) )
137
- return $auth->user_can_view();
138
 
139
  return false;
140
 
@@ -168,7 +170,7 @@ class QueryMonitor extends QM_Plugin {
168
  foreach ( $this->get_dispatchers() as $dispatcher ) {
169
 
170
  # At least one dispatcher is active, so we need to process:
171
- if ( $dispatcher->active() ) {
172
  return true;
173
  }
174
 
@@ -190,7 +192,7 @@ class QueryMonitor extends QM_Plugin {
190
 
191
  foreach ( $this->get_dispatchers() as $dispatcher ) {
192
 
193
- if ( ! $dispatcher->active() ) {
194
  continue;
195
  }
196
 
2
  /*
3
  Plugin Name: Query Monitor
4
  Description: Monitoring of database queries, hooks, conditionals and more.
5
+ Version: 2.6.7
6
  Plugin URI: https://github.com/johnbillion/query-monitor
7
  Author: John Blackbourn
8
  Author URI: https://johnblackbourn.com/
42
  protected function __construct( $file ) {
43
 
44
  # Actions
45
+ add_action( 'plugins_loaded', array( $this, 'action_plugins_loaded' ) );
46
+ add_action( 'init', array( $this, 'action_init' ) );
47
+ add_action( 'shutdown', array( $this, 'action_shutdown' ), 0 );
48
 
49
  # Filters
50
  add_filter( 'pre_update_option_active_plugins', array( $this, 'filter_active_plugins' ) );
64
  foreach ( apply_filters( 'query_monitor_collectors', array() ) as $collector )
65
  $this->add_collector( $collector );
66
 
67
+ }
68
+
69
+ public function action_plugins_loaded() {
70
+
71
  # Dispatchers:
72
  foreach ( glob( $this->plugin_path( 'dispatchers/*.php' ) ) as $dispatcher )
73
  include $dispatcher;
131
  if ( !did_action( 'plugins_loaded' ) )
132
  return false;
133
 
134
+ if ( current_user_can( 'view_query_monitor' ) ) {
 
 
 
135
  return true;
136
  }
137
 
138
  if ( $auth = self::get_collector( 'authentication' ) )
139
+ return $auth->user_verified();
140
 
141
  return false;
142
 
170
  foreach ( $this->get_dispatchers() as $dispatcher ) {
171
 
172
  # At least one dispatcher is active, so we need to process:
173
+ if ( $dispatcher->is_active() ) {
174
  return true;
175
  }
176
 
192
 
193
  foreach ( $this->get_dispatchers() as $dispatcher ) {
194
 
195
+ if ( ! $dispatcher->is_active() ) {
196
  continue;
197
  }
198
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: johnbillion
3
  Tags: debug, debugging, development, developer, performance, profiler, profiling, queries, query monitor
4
  Requires at least: 3.5
5
  Tested up to: 3.9
6
- Stable tag: 2.6.6
7
  License: GPLv2 or later
8
 
9
  View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
@@ -145,8 +145,19 @@ Please use [the issue tracker on Query Monitor's GitHub repo](https://github.com
145
 
146
  No, I do not accept donations. If you like the plugin, I'd love for you to [leave a review](http://wordpress.org/support/view/plugin-reviews/query-monitor). Tell all your friends about the plugin too!
147
 
 
 
 
 
 
148
  == Changelog ==
149
 
 
 
 
 
 
 
150
  = 2.6.6 =
151
  * More robust support for alternative database drivers (including `mysqli` in core)
152
  * Avoid warnings and notices when a custom database class is in place and it's not saving queries (ie. HyperDB)
3
  Tags: debug, debugging, development, developer, performance, profiler, profiling, queries, query monitor
4
  Requires at least: 3.5
5
  Tested up to: 3.9
6
+ Stable tag: 2.6.7
7
  License: GPLv2 or later
8
 
9
  View debugging and performance information on database queries, hooks, conditionals, HTTP requests, redirects and more.
145
 
146
  No, I do not accept donations. If you like the plugin, I'd love for you to [leave a review](http://wordpress.org/support/view/plugin-reviews/query-monitor). Tell all your friends about the plugin too!
147
 
148
+ == Upgrade Notice ==
149
+
150
+ = 2.6.7 =
151
+ * Various tweaks under the hood. No shiny new features just yet.
152
+
153
  == Changelog ==
154
 
155
+ = 2.6.7 =
156
+ * Use an actual authentication cookie instead of a nonce in the Authentication component
157
+ * Implement some extra methods of determining the current user/group
158
+ * Move the loading of dispatchers to the `plugins_loaded` hook so plugins can add their own
159
+ * Misc performance improvements
160
+
161
  = 2.6.6 =
162
  * More robust support for alternative database drivers (including `mysqli` in core)
163
  * Avoid warnings and notices when a custom database class is in place and it's not saving queries (ie. HyperDB)