Skip to content

Commit 36d93a2

Browse files
committed
Implement basic integration with Query Monitor
1 parent fd0d282 commit 36d93a2

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

integrations/query-monitor/boot.php

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
/**
4+
* Boot Query Monitor from the SQLite Database Integration plugin.
5+
*
6+
* When the Query Monitor plugin exists in its standard location, let's check
7+
* if it is active, so we can boot it eagerly. This is a workaround to avoid
8+
* SQLite and Query Monitor competing for the "wp-content/db.php" file.
9+
*
10+
* This file is a modified version of the original Query Monitor "db.php" file.
11+
*
12+
* See: https://github.com/johnbillion/query-monitor/blob/develop/wp-content/db.php
13+
*/
14+
15+
// 1. Determine the plugins directory.
16+
if ( defined( 'WP_PLUGIN_DIR' ) ) {
17+
$plugins_dir = WP_PLUGIN_DIR;
18+
} else {
19+
$plugins_dir = WP_CONTENT_DIR . '/plugins';
20+
}
21+
22+
// 2. Check if we should load Query Monitor (as per the original "db.php" file).
23+
if ( ! defined( 'ABSPATH' ) ) {
24+
exit;
25+
}
26+
27+
if ( ! defined( 'DB_USER' ) ) {
28+
return;
29+
}
30+
31+
if ( defined( 'QM_DISABLED' ) && QM_DISABLED ) {
32+
return;
33+
}
34+
35+
if ( defined( 'WP_INSTALLING' ) && WP_INSTALLING ) {
36+
return;
37+
}
38+
39+
if ( 'cli' === php_sapi_name() && ! defined( 'QM_TESTS' ) ) {
40+
return;
41+
}
42+
43+
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
44+
return;
45+
}
46+
47+
if ( is_admin() ) {
48+
if ( isset( $_GET['action'] ) && 'upgrade-plugin' === $_GET['action'] ) {
49+
return;
50+
}
51+
52+
if ( isset( $_POST['action'] ) && 'update-plugin' === $_POST['action'] ) {
53+
return;
54+
}
55+
}
56+
57+
// 3. Check if Query Monitor is active.
58+
if ( null === $wpdb->options ) {
59+
global $table_prefix;
60+
$wpdb->set_prefix( $table_prefix ?? '' );
61+
}
62+
63+
$query_monitor_active = false;
64+
try {
65+
$value = $wpdb->get_row(
66+
$wpdb->prepare(
67+
"SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1",
68+
'active_plugins'
69+
)
70+
);
71+
$query_monitor_active = in_array(
72+
'query-monitor/query-monitor.php',
73+
unserialize( $value->option_value ),
74+
true
75+
);
76+
} catch ( Throwable $e ) {
77+
return;
78+
}
79+
80+
if ( ! $query_monitor_active ) {
81+
return;
82+
}
83+
84+
// 4. Load Query Monitor (as per the original "db.php" file).
85+
$qm_dir = "{$plugins_dir}/query-monitor";
86+
$qm_php = "{$qm_dir}/classes/PHP.php";
87+
88+
if ( ! is_readable( $qm_php ) ) {
89+
return;
90+
}
91+
require_once $qm_php;
92+
93+
if ( ! QM_PHP::version_met() ) {
94+
return;
95+
}
96+
97+
if ( ! file_exists( "{$qm_dir}/vendor/autoload.php" ) ) {
98+
add_action( 'all_admin_notices', 'QM_PHP::vendor_nope' );
99+
return;
100+
}
101+
102+
require_once "{$qm_dir}/vendor/autoload.php";
103+
104+
if ( ! class_exists( 'QM_Backtrace' ) ) {
105+
return;
106+
}
107+
108+
if ( ! defined( 'SAVEQUERIES' ) ) {
109+
define( 'SAVEQUERIES', true );
110+
}
111+
112+
// 5. Mark the Query Monitor integration as loaded.
113+
define( 'SQLITE_QUERY_MONITOR_LOADED', true );

wp-includes/sqlite/class-wp-sqlite-db.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,12 @@ public function prepare( $query, ...$args ) {
408408
* affected/selected for all other queries. Boolean false on error.
409409
*/
410410
public function query( $query ) {
411+
// Query Monitor integration:
412+
$query_monitor_active = defined( 'SQLITE_QUERY_MONITOR_LOADED' ) && SQLITE_QUERY_MONITOR_LOADED;
413+
if ( $query_monitor_active && $this->show_errors ) {
414+
$this->hide_errors();
415+
}
416+
411417
if ( ! $this->ready ) {
412418
return false;
413419
}
@@ -427,6 +433,9 @@ public function query( $query ) {
427433
// Keep track of the last query for debug.
428434
$this->last_query = $query;
429435

436+
// Save the query count before running another query.
437+
$last_query_count = count( $this->queries ?? array() );
438+
430439
/*
431440
* @TODO: WPDB uses "$this->check_current_query" to check table/column
432441
* charset and strip all invalid characters from the query.
@@ -478,6 +487,28 @@ public function query( $query ) {
478487
$return_val = $num_rows;
479488
}
480489

490+
// Query monitor integration:
491+
if ( $query_monitor_active && class_exists( 'QM_Backtrace' ) ) {
492+
if ( did_action( 'qm/cease' ) ) {
493+
$this->queries = array();
494+
}
495+
496+
$i = $last_query_count;
497+
if ( ! isset( $this->queries[ $i ] ) ) {
498+
return $return_val;
499+
}
500+
501+
$this->queries[ $i ]['trace'] = new QM_Backtrace();
502+
if ( ! isset( $this->queries[ $i ][3] ) ) {
503+
$this->queries[ $i ][3] = $this->time_start;
504+
}
505+
506+
if ( $this->last_error && ! $this->suppress_errors ) {
507+
$this->queries[ $i ]['result'] = new WP_Error( 'qmdb', $this->last_error );
508+
} else {
509+
$this->queries[ $i ]['result'] = (int) $return_val;
510+
}
511+
}
481512
return $return_val;
482513
}
483514

wp-includes/sqlite/db.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,7 @@
6767
$GLOBALS['wpdb'] = new WP_SQLite_Crosscheck_DB( DB_NAME );
6868
} else {
6969
$GLOBALS['wpdb'] = new WP_SQLite_DB( defined( 'DB_NAME' ) ? DB_NAME : '' );
70+
71+
// Boot the Query Monitor plugin if it is active.
72+
require_once dirname( __DIR__, 2 ) . '/integrations/query-monitor/boot.php';
7073
}

0 commit comments

Comments
 (0)