PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.2-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.2-a.1
16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / jetpack_vendor / automattic / jetpack-search / src / initializers / class-initializer.php
jetpack / jetpack_vendor / automattic / jetpack-search / src / initializers Last commit date
class-initializer.php 1 month ago
class-initializer.php
335 lines
1 <?php
2 /**
3 * Initializer base class.
4 *
5 * @package @automattic/jetpack-search
6 */
7
8 namespace Automattic\Jetpack\Search;
9
10 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
11 use WP_Error;
12 /**
13 * Base class for the initializer pattern.
14 */
15 class Initializer {
16
17 /**
18 * Whether a block-driven experience owns the search results this request
19 * — Embedded, or the experimental blocks Overlay. Set to `true` in
20 * `init_search_blocks()` only when the `jetpack_search_blocks_enabled`
21 * gate is on AND the saved experience is one of those (the Overlay arm
22 * additionally requires `jetpack_search_overlay_block_template_enabled`).
23 * In those experiences both Classic and Instant Search are suppressed, so
24 * `init_search()` returns falsy by design; `init()` reads this flag to
25 * treat that as a no-op rather than a real failure. Anchoring on the
26 * actually-wired-up state (not a filter read) prevents the abort carve-out
27 * from being bypassed on a site that doesn't have Search Blocks registered.
28 *
29 * @var bool
30 */
31 private static $block_search_active = false;
32
33 /**
34 * Initialize the search package.
35 *
36 * The method is called from the `Config` class.
37 */
38 public static function init() {
39 // Load compatibility files - at this point all plugins are already loaded.
40 static::include_compatibility_files();
41
42 // Set up package version hook.
43 add_filter( 'jetpack_package_versions', __NAMESPACE__ . '\Package::send_version_to_tracker' );
44
45 /**
46 * The filter allows abortion of the Jetpack Search package initialization.
47 *
48 * @since 0.11.2
49 *
50 * @param boolean $init_search_package Default value is true.
51 */
52 if ( ! apply_filters( 'jetpack_search_init_search_package', true ) ) {
53 /**
54 * Fires when the Jetpack Search fails and would fallback to MySQL.
55 *
56 * @since Jetpack 7.9.0
57 * @param string $reason Reason for Search fallback.
58 * @param mixed $data Data associated with the request, such as attempted search parameters.
59 */
60 do_action( 'jetpack_search_abort', 'jetpack_search_init_search_package_filter', null );
61 return;
62 }
63
64 static::init_before_connection();
65
66 // Check whether Jetpack Search should be initialized in the first place .
67 if ( ! static::is_connected() || ! static::is_search_supported() ) {
68 /** This filter is documented in search/src/initalizers/class-initalizer.php */
69 do_action( 'jetpack_search_abort', 'inactive', null );
70 return;
71 }
72
73 // Register the Search 3.0 Interactivity API blocks. Connection +
74 // plan are already guaranteed by the abort above; this call only
75 // layers the Phase 1 feature flag on top, mirroring how
76 // `init_search()` layers `is_instant_search_enabled` on top of
77 // the same upstream gate.
78 static::init_search_blocks();
79
80 $blog_id = Helper::get_wpcom_site_id();
81 if ( ! $blog_id ) {
82 /** This filter is documented in search/src/initalizers/class-initalizer.php */
83 do_action( 'jetpack_search_abort', 'no_blog_id', null );
84 return;
85 }
86
87 if ( ! ( new Module_Control() )->is_active() ) {
88 /** This filter is documented in search/src/initalizers/class-initalizer.php */
89 do_action( 'jetpack_search_abort', 'module_inactive', null );
90 return;
91 }
92
93 // Initialize search package. The block-driven experiences (Embedded /
94 // blocks Overlay) intentionally skip both instant and classic init
95 // (Search_Blocks owns the UI), so a falsy return there is by design —
96 // not an abort. Anything else falsy is a real failure. Anchor on the
97 // actually-wired-up flag (set in `init_search_blocks()` only when the
98 // blocks gate passed) rather than a filter read, so flipping a filter
99 // without the blocks gate can never bypass the abort.
100 $initialized = static::init_search( $blog_id )
101 || self::$block_search_active;
102
103 if ( ! $initialized ) {
104 /** This filter is documented in search/src/initalizers/class-initalizer.php */
105 do_action( 'jetpack_search_abort', 'jetpack_search_init_search', null );
106 return;
107 }
108
109 /**
110 * Fires when the Jetpack Search package has been initialized.
111 *
112 * @since 0.11.2
113 */
114 do_action( 'jetpack_search_loaded' );
115 }
116
117 /**
118 * Extra tweaks to make Jetpack Search play well with others.
119 */
120 public static function include_compatibility_files() {
121 if ( class_exists( 'Jetpack' ) ) {
122 require_once Package::get_installed_path() . 'compatibility/jetpack.php';
123 }
124 require_once Package::get_installed_path() . 'compatibility/search-0.15.2.php';
125 require_once Package::get_installed_path() . 'compatibility/search-0.17.0.php';
126 require_once Package::get_installed_path() . 'compatibility/unsupported-browsers.php';
127 }
128
129 /**
130 * Init functionality required for connection.
131 */
132 protected static function init_before_connection() {
133 // Set up Search API endpoints.
134 add_action( 'rest_api_init', array( REST_Controller::class, 'register' ) );
135 // The dashboard has to be initialized before connection.
136 ( new Dashboard() )->init_hooks();
137 ( new AI_Answers() )->init();
138 }
139
140 /**
141 * Register the Search 3.0 Interactivity API blocks on this request,
142 * gated by the Phase 1 feature flag.
143 *
144 * Called from `init()` after the upstream connection + Search-plan
145 * abort, so on entry the site is guaranteed to be connected and on a
146 * plan that supports Search (paid plans or the free
147 * `jetpack_search_free` product). The remaining gate is the
148 * feature-flag opt-in.
149 *
150 * Sits before the blog_id and module-active checks because admins
151 * should be able to configure Search blocks in the editor regardless
152 * of which runtime experience is enabled — matching how Instant
153 * Search layers its own opt-in on top of the same connection + plan
154 * gate further down in `init_search()`.
155 */
156 protected static function init_search_blocks() {
157 /**
158 * Filter whether the Jetpack Search 3.0 Interactivity API blocks are enabled.
159 *
160 * Necessary but not sufficient on its own — registration also
161 * requires the site to be connected and on a plan that supports
162 * Search (paid plans or the free `jetpack_search_free` product).
163 *
164 * @param bool $enabled Default true.
165 */
166 if ( ! apply_filters( 'jetpack_search_blocks_enabled', true ) ) {
167 return;
168 }
169
170 Search_Blocks::init();
171
172 // When the Search blocks own the front-end results (Embedded / blocks
173 // Overlay), Classic Search would otherwise run a server-side
174 // Elasticsearch query plus a WP_Query to hydrate the posts on every
175 // search request — work the blocks immediately discard. Suppress it so
176 // it never runs, the same way Instant Search replaces Classic;
177 // `Search_Blocks::filter__posts_pre_query` then short-circuits the
178 // remaining core database search. With both handlers gone `init_search()`
179 // returns false by design, so this flag tells `init()` not to treat that
180 // as an abort.
181 //
182 // Front-end only, matching the `posts_pre_query` registration guard:
183 // leaving Classic Search to initialize normally in wp-admin keeps the
184 // change scoped to the search page and avoids dropping admin-side hooks.
185 if ( ! is_admin() && Search_Blocks::owns_search_results() ) {
186 add_filter( 'jetpack_search_classic_search_enabled', '__return_false' );
187 self::$block_search_active = true;
188 }
189
190 // Experimental block-template overlay (available by default, opt-in
191 // via the Experience Selector; see
192 // `Search_Blocks::is_block_template_overlay_enabled()`): bypass the
193 // preact `SearchApp` so it doesn't race the block overlay for
194 // `?s=`, popstate, and theme search-trigger selectors. Suppressing
195 // at the init filter is cleaner than dequeuing post-enqueue. Gated on
196 // the overlay path specifically — Embedded never enables Instant Search,
197 // so there is nothing to suppress there.
198 if ( Search_Blocks::is_block_template_overlay_enabled() ) {
199 add_filter( 'jetpack_search_init_instant_search', '__return_false' );
200 }
201 }
202
203 /**
204 * Init the search package.
205 *
206 * @param int $blog_id WPCOM blog ID.
207 */
208 protected static function init_search( $blog_id ) {
209 // We could provide CLI to enable search/instant search, so init them regardless of whether the module is active or not.
210 static::init_cli();
211
212 $success = false;
213 $is_instant_search_enabled = ( new Module_Control() )->is_instant_search_enabled();
214 if ( $is_instant_search_enabled ) {
215 // Enable Instant search experience.
216 $success = static::init_instant_search( $blog_id );
217 }
218 /**
219 * Filter whether classic search should be enabled. By this stage, search module would be enabled already.
220 *
221 * @since 0.39.6
222 * @param boolean initial value whether classic search is enabled.
223 * @param boolean filtered result whether classic search is enabled.
224 */
225 if ( apply_filters( 'jetpack_search_classic_search_enabled', ! $is_instant_search_enabled ) ) {
226 // Enable the classic search experience.
227 $success = static::init_classic_search( $blog_id );
228 }
229
230 if ( $success ) {
231 // registers Jetpack Search widget.
232 add_action( 'widgets_init', array( static::class, 'jetpack_search_widget_init' ) );
233 }
234
235 return $success;
236 }
237
238 /**
239 * Init Instant Search and its dependencies.
240 *
241 * @param int $blog_id WPCOM blog ID.
242 */
243 protected static function init_instant_search( $blog_id ) {
244 /**
245 * The filter allows abortion of the Instant Search initialization.
246 *
247 * @since 0.11.2
248 *
249 * @param boolean $init_instant_search Default value is true.
250 */
251 if ( ! apply_filters( 'jetpack_search_init_instant_search', true ) ) {
252 return;
253 }
254
255 // Enable the instant search experience.
256 Instant_Search::initialize( $blog_id );
257 // Register instant search configurables as WordPress settings.
258 new Settings();
259 // Instantiate "Customberg", the live search configuration interface.
260 Customberg::instance();
261 // Enable configuring instant search within the Customizer iff it's not using a block theme.
262 if ( ! wp_is_block_theme() ) {
263 new Customizer();
264 }
265 return true;
266 }
267
268 /**
269 * Init Classic Search.
270 *
271 * @param int $blog_id WPCOM blog ID.
272 */
273 protected static function init_classic_search( $blog_id ) {
274 /**
275 * The filter allows abortion of the Classic Search initialization.
276 *
277 * @since 0.11.2
278 *
279 * @param boolean $init_instant_search Default value is true.
280 */
281 if ( ! apply_filters( 'jetpack_search_init_classic_search', true ) ) {
282 return;
283 }
284 Inline_Search::get_instance_maybe_fallback_to_classic( $blog_id );
285
286 return true;
287 }
288
289 /**
290 * Register jetpack-search CLI if `\CLI` exists.
291 *
292 * @return void
293 */
294 protected static function init_cli() {
295 if ( defined( 'WP_CLI' ) && \WP_CLI ) {
296 \WP_CLI::add_command( 'jetpack-search', __NAMESPACE__ . '\CLI' );
297 }
298 }
299
300 /**
301 * Register the widget if Jetpack Search is available and enabled.
302 */
303 public static function jetpack_search_widget_init() {
304 register_widget( 'Automattic\Jetpack\Search\Search_Widget' );
305 }
306
307 /**
308 * Check if site has been connected.
309 */
310 protected static function is_connected() {
311 return ( new Connection_Manager( Package::SLUG ) )->is_connected();
312 }
313
314 /**
315 * Check if search is supported by current plan.
316 */
317 protected static function is_search_supported() {
318 return ( new Plan() )->supports_search();
319 }
320
321 /**
322 * Perform necessary initialization steps for classic and instant search in the constructor.
323 *
324 * @deprecated
325 */
326 public static function initialize() {
327 return new WP_Error(
328 'invalid-method',
329 /* translators: %s: Method name. */
330 sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'jetpack-search-pkg' ), __METHOD__ ),
331 array( 'status' => 405 )
332 );
333 }
334 }
335