Skip to content

Commit f8b3cb9

Browse files
committed
Add QM collector and outputter for SQLite query data
Register a custom QM collector that extracts SQLite queries from $wpdb->queries, re-indexed to match QM's rendered row order, and a client-side HTML outputter that emits the inline JS module used by the QM 4.0 shadow DOM integration. QM auto-serializes the collector data into window.QueryMonitorData.data.sqlite.
1 parent 9866af6 commit f8b3cb9

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

  • packages/plugin-sqlite-database-integration/integrations/query-monitor
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php // phpcs:disable WordPress.Files.FileName.InvalidClassFileName, Generic.Files.OneObjectStructurePerFile.MultipleFound
2+
3+
if ( ! class_exists( 'QM_Collector' ) ) {
4+
return;
5+
}
6+
7+
/**
8+
* Collector for SQLite query data.
9+
*
10+
* Extracts SQLite queries from $wpdb->queries and stores them
11+
* indexed by SQL text for the QM 4.0+ JS integration.
12+
*/
13+
class SQLite_QM_Collector extends QM_Collector {
14+
/** @var string */
15+
public $id = 'sqlite';
16+
17+
public function process(): void {
18+
global $wpdb;
19+
20+
if ( empty( $wpdb->queries ) ) {
21+
return;
22+
}
23+
24+
// Index by SQL rather than row position — robust to filtering, sorting, etc.
25+
$mapped = array();
26+
foreach ( $wpdb->queries as $query ) {
27+
// Query Monitor skips queries with 'wp_admin_bar' in the stack.
28+
if ( false !== strpos( $query[2] ?? '', 'wp_admin_bar' ) ) {
29+
continue;
30+
}
31+
if ( ! empty( $query['sqlite_queries'] ) ) {
32+
$sql = trim( preg_replace( '/\s+/', ' ', $query[0] ) );
33+
$mapped[ $sql ] = array_column( $query['sqlite_queries'], 'sql' );
34+
}
35+
}
36+
$this->data->queries = $mapped;
37+
}
38+
}
39+
40+
/**
41+
* HTML outputter for SQLite query data.
42+
*
43+
* With $client_side_rendered = true, QM auto-serializes the collector data
44+
* into "window.QueryMonitorData.data.sqlite". This outputter's only job is to
45+
* emit the inline JS module that reads that data and injects SQLite query
46+
* details into QM 4.0's shadow DOM DB queries panel.
47+
*/
48+
class SQLite_QM_Output_Html extends QM_Output_Html {
49+
/** @var bool */
50+
public static $client_side_rendered = true;
51+
52+
public function name(): string {
53+
return 'SQLite';
54+
}
55+
56+
public function output(): void {
57+
if ( empty( $this->get_collector()->get_data()->queries ) ) {
58+
return;
59+
}
60+
61+
$js_path = __DIR__ . '/query-monitor-sqlite.js';
62+
if ( is_readable( $js_path ) ) {
63+
echo '<script type="module">';
64+
include $js_path;
65+
echo '</script>';
66+
}
67+
}
68+
}
69+
70+
/**
71+
* Register the SQLite collector.
72+
*/
73+
function register_sqlite_qm_collector( array $collectors ): array {
74+
$collectors['sqlite'] = new SQLite_QM_Collector();
75+
return $collectors;
76+
}
77+
78+
add_filter( 'qm/collectors', 'register_sqlite_qm_collector', 20 );
79+
80+
/**
81+
* Register the SQLite HTML outputter.
82+
*/
83+
function register_sqlite_qm_output_html( array $output, QM_Collectors $collectors ): array {
84+
$collector = QM_Collectors::get( 'sqlite' );
85+
if ( $collector ) {
86+
$output['sqlite'] = new SQLite_QM_Output_Html( $collector );
87+
}
88+
return $output;
89+
}
90+
91+
add_filter( 'qm/outputter/html', 'register_sqlite_qm_output_html', 30, 2 );

0 commit comments

Comments
 (0)