1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
<?php declare(strict_types = 1); /** * Ajax request dispatcher. * * @package query-monitor */
if ( ! defined( 'ABSPATH' ) ) { exit; }
class QM_Dispatcher_AJAX extends QM_Dispatcher {
public $id = 'ajax';
public function __construct( QM_Plugin $qm ) { parent::__construct( $qm );
// This dispatcher needs to run on a priority lower than 1 so it can output // its headers before wp_ob_end_flush_all() flushes all the output buffers: // https://github.com/WordPress/wordpress-develop/blob/0a3a3c5119897c6d551a42ae9b5dbfa4f576f2c9/src/wp-includes/default-filters.php#L382 add_action( 'shutdown', array( $this, 'dispatch' ), 0 ); }
/** * @return void */ public function init() {
if ( ! self::user_can_view() ) { return; }
if ( QM_Util::is_ajax() ) { // Start an output buffer for Ajax requests so headers can be output at the end: ob_start(); }
parent::init(); }
/** * @return void */ public function dispatch() {
if ( ! $this->should_dispatch() ) { return; }
$this->before_output();
foreach ( $this->get_outputters( 'headers' ) as $id => $output ) { $output->output(); }
$this->after_output();
}
/** * @return void */ protected function before_output() { foreach ( (array) glob( $this->qm->plugin_path( 'output/headers/*.php' ) ) as $file ) { require_once $file; } }
/** * @return void */ protected function after_output() {
# flush once, because we're nice if ( ob_get_length() ) { ob_flush(); }
}
/** * @return bool */ public function is_active() {
if ( ! QM_Util::is_ajax() ) { return false; }
if ( ! self::user_can_view() ) { return false; }
# If the headers have already been sent then we can't do anything about it if ( headers_sent() ) { return false; }
# Don't process if the minimum required actions haven't fired: if ( is_admin() ) { if ( ! did_action( 'admin_init' ) ) { return false; } } else { if ( ! did_action( 'wp' ) ) { return false; } }
return true;
}
/** * @param string $message * @param mixed[] $e * @phpstan-param array{ * message: string, * file: string, * line: int, * type?: int, * trace?: mixed|null, * } $e */ public function output_fatal( $message, array $e ): void { if ( ! headers_sent() ) { header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) ); }
// @TODO echo wp_json_encode( array( 'code' => 'qm_fatal', 'message' => $message, 'data' => $e, ), JSON_UNESCAPED_SLASHES ); } }
/** * @param array<string, QM_Dispatcher> $dispatchers * @param QM_Plugin $qm * @return array<string, QM_Dispatcher> */ function register_qm_dispatcher_ajax( array $dispatchers, QM_Plugin $qm ) { $dispatchers['ajax'] = new QM_Dispatcher_AJAX( $qm ); return $dispatchers; }
add_filter( 'qm/dispatchers', 'register_qm_dispatcher_ajax', 10, 2 );
|