Skip to content

Commit 8bae35e

Browse files
committed
Implement basic integration with Query Monitor
1 parent 33c9b39 commit 8bae35e

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. Check if we should load Query Monitor (as per the original "db.php" file).
16+
if ( ! defined( 'ABSPATH' ) ) {
17+
exit;
18+
}
19+
20+
if ( ! defined( 'DB_USER' ) ) {
21+
return;
22+
}
23+
24+
if ( defined( 'QM_DISABLED' ) && QM_DISABLED ) {
25+
return;
26+
}
27+
28+
if ( defined( 'WP_INSTALLING' ) && WP_INSTALLING ) {
29+
return;
30+
}
31+
32+
if ( 'cli' === php_sapi_name() && ! defined( 'QM_TESTS' ) ) {
33+
return;
34+
}
35+
36+
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
37+
return;
38+
}
39+
40+
if ( is_admin() ) {
41+
if ( isset( $_GET['action'] ) && 'upgrade-plugin' === $_GET['action'] ) {
42+
return;
43+
}
44+
45+
if ( isset( $_POST['action'] ) && 'update-plugin' === $_POST['action'] ) {
46+
return;
47+
}
48+
}
49+
50+
// 2. Check if Query Monitor is active.
51+
if ( null === $wpdb->options ) {
52+
global $table_prefix;
53+
$wpdb->set_prefix( $table_prefix ?? '' );
54+
}
55+
56+
$query_monitor_active = false;
57+
try {
58+
$value = $wpdb->get_row(
59+
$wpdb->prepare(
60+
"SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1",
61+
'active_plugins'
62+
)
63+
);
64+
$query_monitor_active = in_array(
65+
'query-monitor/query-monitor.php',
66+
unserialize( $value->option_value ),
67+
true
68+
);
69+
} catch ( Throwable $e ) {
70+
return;
71+
}
72+
73+
if ( ! $query_monitor_active ) {
74+
return;
75+
}
76+
77+
// 3. Determine the plugins directory.
78+
if ( defined( 'WP_PLUGIN_DIR' ) ) {
79+
$plugins_dir = WP_PLUGIN_DIR;
80+
} else {
81+
$plugins_dir = WP_CONTENT_DIR . '/plugins';
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)