Completed
Push — fusion-sync/jsnmoon/r220057-wp... ( 6ecdc1 )
by
unknown
46:44 queued 36:23
created

inject_polyfill_js_options()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Jetpack Search: Instant Front-End Search and Filtering
4
 *
5
 * @since 8.3.0
6
 * @package jetpack
7
 */
8
9
/**
10
 * Class to load Instant Search experience on the site.
11
 *
12
 * @since 8.3.0
13
 */
14
class Jetpack_Instant_Search extends Jetpack_Search {
15
16
	/**
17
	 * Loads the php for this version of search
18
	 *
19
	 * @since 8.3.0
20
	 */
21
	public function load_php() {
22
		$this->base_load_php();
23
24
		if ( class_exists( 'WP_Customize_Manager' ) ) {
25
			require_once __DIR__ . '/class-jetpack-search-customize.php';
26
			new Jetpack_Search_Customize();
27
		}
28
	}
29
30
	/**
31
	 * Setup the various hooks needed for the plugin to take over search duties.
32
	 *
33
	 * @since 5.0.0
34
	 */
35 View Code Duplication
	public function init_hooks() {
36
		if ( ! is_admin() ) {
37
			add_filter( 'posts_pre_query', array( $this, 'filter__posts_pre_query' ), 10, 2 );
38
			add_action( 'parse_query', array( $this, 'action__parse_query' ), 10, 1 );
39
40
			add_action( 'init', array( $this, 'set_filters_from_widgets' ) );
41
42
			add_action( 'wp_enqueue_scripts', array( $this, 'load_assets' ) );
43
			add_action( 'wp_footer', array( $this, 'print_instant_search_sidebar' ) );
44
		} else {
45
			add_action( 'update_option', array( $this, 'track_widget_updates' ), 10, 3 );
46
		}
47
48
		add_action( 'widgets_init', array( $this, 'register_jetpack_instant_sidebar' ) );
49
		add_action( 'jetpack_deactivate_module_search', array( $this, 'move_search_widgets_to_inactive' ) );
50
	}
51
52
	/**
53
	 * Loads assets for Jetpack Instant Search Prototype featuring Search As You Type experience.
54
	 */
55
	public function load_assets() {
56
		$polyfill_relative_path = '_inc/build/instant-search/jp-search-ie11-polyfill-loader.bundle.js';
57
		$script_relative_path   = '_inc/build/instant-search/jp-search-main.bundle.js';
58
		$style_relative_path    = '_inc/build/instant-search/jp-search-main.bundle.css';
59
		if (
60
			! file_exists( JETPACK__PLUGIN_DIR . $polyfill_relative_path ) ||
61
			! file_exists( JETPACK__PLUGIN_DIR . $script_relative_path ) ||
62
			! file_exists( JETPACK__PLUGIN_DIR . $style_relative_path )
63
		) {
64
			return;
65
		}
66
67
		$polyfill_version = Jetpack_Search_Helpers::get_asset_version( $polyfill_relative_path );
68
		$polyfill_path    = plugins_url( $polyfill_relative_path, JETPACK__PLUGIN_FILE );
69
		wp_enqueue_script( 'jetpack-instant-search-ie11', $polyfill_path, array(), $polyfill_version, true );
70
71
		$script_version = Jetpack_Search_Helpers::get_asset_version( $script_relative_path );
72
		$script_path    = plugins_url( $script_relative_path, JETPACK__PLUGIN_FILE );
73
		wp_enqueue_script( 'jetpack-instant-search', $script_path, array(), $script_version, true );
74
		wp_set_script_translations( 'jetpack-instant-search', 'jetpack' );
75
		$this->load_and_initialize_tracks();
76
		$this->inject_javascript_options();
77
78
		$style_version = Jetpack_Search_Helpers::get_asset_version( $style_relative_path );
79
		$style_path    = plugins_url( $style_relative_path, JETPACK__PLUGIN_FILE );
80
		wp_enqueue_style( 'jetpack-instant-search', $style_path, array(), $style_version );
81
	}
82
83
	/**
84
	 * Passes all options to the JS app.
85
	 */
86
	protected function inject_javascript_options() {
87
		$widget_options = Jetpack_Search_Helpers::get_widgets_from_option();
88
		if ( is_array( $widget_options ) ) {
89
			$widget_options = end( $widget_options );
0 ignored issues
show
Unused Code introduced by
$widget_options is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
90
		}
91
92
		$overlay_widget_ids      = is_active_sidebar( 'jetpack-instant-search-sidebar' ) ?
93
			wp_get_sidebars_widgets()['jetpack-instant-search-sidebar'] : array();
94
		$filters                 = Jetpack_Search_Helpers::get_filters_from_widgets();
95
		$widgets                 = array();
96
		$widgets_outside_overlay = array();
97
		foreach ( $filters as $key => &$filter ) {
98
			$filter['filter_id'] = $key;
99
100
			if ( in_array( $filter['widget_id'], $overlay_widget_ids, true ) ) {
101 View Code Duplication
				if ( ! isset( $widgets[ $filter['widget_id'] ] ) ) {
102
					$widgets[ $filter['widget_id'] ]['filters']   = array();
103
					$widgets[ $filter['widget_id'] ]['widget_id'] = $filter['widget_id'];
104
				}
105
				$widgets[ $filter['widget_id'] ]['filters'][] = $filter;
106
			} else {
107 View Code Duplication
				if ( ! isset( $widgets_outside_overlay[ $filter['widget_id'] ] ) ) {
108
					$widgets_outside_overlay[ $filter['widget_id'] ]['filters']   = array();
109
					$widgets_outside_overlay[ $filter['widget_id'] ]['widget_id'] = $filter['widget_id'];
110
				}
111
				$widgets_outside_overlay[ $filter['widget_id'] ]['filters'][] = $filter;
112
			}
113
		}
114
		unset( $filter );
115
116
		$post_type_objs   = get_post_types( array( 'exclude_from_search' => false ), 'objects' );
117
		$post_type_labels = array();
118
		foreach ( $post_type_objs as $key => $obj ) {
119
			$post_type_labels[ $key ] = array(
120
				'singular_name' => $obj->labels->singular_name,
121
				'name'          => $obj->labels->name,
122
			);
123
		}
124
125
		$prefix         = Jetpack_Search_Options::OPTION_PREFIX;
126
		$posts_per_page = (int) get_option( 'posts_per_page' );
127
		if ( ( $posts_per_page > 20 ) || ( $posts_per_page <= 0 ) ) {
128
			$posts_per_page = 20;
129
		}
130
131
		$excluded_post_types   = get_option( $prefix . 'excluded_post_types' ) ? explode( ',', get_option( $prefix . 'excluded_post_types', '' ) ) : array();
132
		$post_types            = array_values(
133
			get_post_types(
134
				array(
135
					'exclude_from_search' => false,
136
					'public'              => true,
137
				)
138
			)
139
		);
140
		$unexcluded_post_types = array_diff( $post_types, $excluded_post_types );
141
		// NOTE: If all post types are being excluded, ignore the option value.
142
		if ( count( $unexcluded_post_types ) === 0 ) {
143
			$excluded_post_types = array();
144
		}
145
146
		$polyfill_relative_path = '_inc/build/instant-search/jp-search-ie11-polyfill-payload.bundle.js';
147
		$polyfill_path          = plugins_url( $polyfill_relative_path, JETPACK__PLUGIN_FILE );
148
149
		$options = array(
150
			'overlayOptions'        => array(
151
				'colorTheme'      => get_option( $prefix . 'color_theme', 'light' ),
152
				'enableInfScroll' => get_option( $prefix . 'inf_scroll', '1' ) === '1',
153
				'enableSort'      => get_option( $prefix . 'enable_sort', '1' ) === '1',
154
				'highlightColor'  => get_option( $prefix . 'highlight_color', '#FFC' ),
155
				'opacity'         => (int) get_option( $prefix . 'opacity', 97 ),
156
				'overlayTrigger'  => get_option( $prefix . 'overlay_trigger', 'immediate' ),
157
				'resultFormat'    => get_option( $prefix . 'result_format', 'minimal' ),
158
				'showPoweredBy'   => get_option( $prefix . 'show_powered_by', '1' ) === '1',
159
			),
160
161
			// core config.
162
			'homeUrl'               => home_url(),
163
			'locale'                => str_replace( '_', '-', Jetpack_Search_Helpers::is_valid_locale( get_locale() ) ? get_locale() : 'en_US' ),
164
			'postsPerPage'          => $posts_per_page,
165
			'siteId'                => $this->jetpack_blog_id,
166
			'postTypes'             => $post_type_labels,
167
			'webpackPublicPath'     => plugins_url( '_inc/build/instant-search/', JETPACK__PLUGIN_FILE ),
168
169
			// config values related to private site support.
170
			'apiRoot'               => esc_url_raw( rest_url() ),
171
			'apiNonce'              => wp_create_nonce( 'wp_rest' ),
172
			'isPrivateSite'         => '-1' === get_option( 'blog_public' ),
173
			'isWpcom'               => defined( 'IS_WPCOM' ) && IS_WPCOM,
174
175
			// search options.
176
			'defaultSort'           => get_option( $prefix . 'default_sort', 'relevance' ),
177
			'excludedPostTypes'     => $excluded_post_types,
178
179
			// widget info.
180
			'hasOverlayWidgets'     => count( $overlay_widget_ids ) > 0,
181
			'widgets'               => array_values( $widgets ),
182
			'widgetsOutsideOverlay' => array_values( $widgets_outside_overlay ),
183
		);
184
185
		/**
186
		 * Customize Instant Search Options.
187
		 *
188
		 * @module search
189
		 *
190
		 * @since 7.7.0
191
		 *
192
		 * @param array $options Array of parameters used in Instant Search queries.
193
		 */
194
		$options = apply_filters( 'jetpack_instant_search_options', $options );
195
196
		// Use wp_add_inline_script instead of wp_localize_script, see https://core.trac.wordpress.org/ticket/25280.
197
		wp_add_inline_script( 'jetpack-instant-search', 'var JetpackInstantSearchOptions=JSON.parse(decodeURIComponent("' . rawurlencode( wp_json_encode( $options ) ) . '"));', 'before' );
198
		wp_add_inline_script( 'jetpack-instant-search-ie11', 'var JetpackInstantSearchIe11PolyfillPath=decodeURIComponent("' . rawurlencode( $polyfill_path ) . '");', 'before' );
199
	}
200
201
	/**
202
	 * Passes options to the polyfill loader script.
203
	 */
204
	protected function inject_polyfill_js_options( $polyfill_payload_path ) {
205
		wp_add_inline_script( 'jetpack-instant-search-ie11', 'var JetpackInstantSearchIe11PolyfillPath=decodeURIComponent("' . rawurlencode( $polyfill_payload_path ) . '");', 'before' );
206
	}
207
208
	/**
209
	 * Registers a widget sidebar for Instant Search.
210
	 */
211
	public function register_jetpack_instant_sidebar() {
212
		$args = array(
213
			'name'          => __( 'Jetpack Search Sidebar', 'jetpack' ),
214
			'id'            => 'jetpack-instant-search-sidebar',
215
			'description'   => __( 'Customize the sidebar inside the Jetpack Search overlay', 'jetpack' ),
216
			'class'         => '',
217
			'before_widget' => '<div id="%1$s" class="widget %2$s">',
218
			'after_widget'  => '</div>',
219
			'before_title'  => '<h2 class="widgettitle">',
220
			'after_title'   => '</h2>',
221
		);
222
		register_sidebar( $args );
223
	}
224
225
	/**
226
	 * Prints Instant Search sidebar.
227
	 */
228
	public function print_instant_search_sidebar() {
229
		?>
230
		<div class="jetpack-instant-search__widget-area" style="display: none">
231
			<?php if ( is_active_sidebar( 'jetpack-instant-search-sidebar' ) ) { ?>
232
				<?php dynamic_sidebar( 'jetpack-instant-search-sidebar' ); ?>
233
			<?php } ?>
234
		</div>
235
		<?php
236
	}
237
238
	/**
239
	 * Loads scripts for Tracks analytics library
240
	 */
241
	public function load_and_initialize_tracks() {
242
		wp_enqueue_script( 'jp-tracks', '//stats.wp.com/w.js', array(), gmdate( 'YW' ), true );
243
	}
244
245
	/**
246
	 * Bypass the normal Search query since we will run it with instant search.
247
	 *
248
	 * @since 8.3.0
249
	 *
250
	 * @param array    $posts Current array of posts (still pre-query).
251
	 * @param WP_Query $query The WP_Query being filtered.
252
	 *
253
	 * @return array Array of matching posts.
254
	 */
255
	public function filter__posts_pre_query( $posts, $query ) {
256
		if ( ! $this->should_handle_query( $query ) ) {
257
			// Intentionally not adding the 'jetpack_search_abort' action since this should fire for every request except for search.
258
			return $posts;
259
		}
260
261
		/**
262
		 * Bypass the main query and return dummy data
263
		 *  WP Core doesn't call the set_found_posts and its filters when filtering
264
		 *  posts_pre_query like we do, so need to do these manually.
265
		 */
266
		$query->found_posts   = 1;
267
		$query->max_num_pages = 1;
268
269
		return array();
270
	}
271
272
	/**
273
	 * Run the aggregations API query for any filtering
274
	 *
275
	 * @since 8.3.0
276
	 */
277
	public function action__parse_query() {
278
		if ( ! empty( $this->search_result ) ) {
279
			return;
280
		}
281
282
		if ( is_admin() ) {
283
			return;
284
		}
285
286
		if ( empty( $this->aggregations ) ) {
287
			return;
288
		}
289
290
		jetpack_require_lib( 'jetpack-wpes-query-builder/jetpack-wpes-query-builder' );
291
292
		$builder = new Jetpack_WPES_Query_Builder();
293
		$this->add_aggregations_to_es_query_builder( $this->aggregations, $builder );
294
		$this->search_result = $this->instant_api(
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->instant_api(array...ze' => 0, 'from' => 0)) of type object is incompatible with the declared type array of property $search_result.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
295
			array(
296
				'aggregations' => $builder->build_aggregation(),
297
				'size'         => 0,
298
				'from'         => 0,
299
			)
300
		);
301
	}
302
303
	/**
304
	 * Run an instant search on the WordPress.com public API.
305
	 *
306
	 * @since 8.3.0
307
	 *
308
	 * @param array $args Args conforming to the WP.com v1.3/sites/<blog_id>/search endpoint.
309
	 *
310
	 * @return object|WP_Error The response from the public API, or a WP_Error.
311
	 */
312
	public function instant_api( array $args ) {
313
		global $wp_version;
314
		$start_time = microtime( true );
315
316
		// Cache locally to avoid remote request slowing the page.
317
		$transient_name = 'jetpack_instant_search_cache_' . md5( wp_json_encode( $args ) );
318
		$cache          = get_transient( $transient_name );
319
		if ( false !== $cache ) {
320
			return $cache;
321
		}
322
323
		$service_url = add_query_arg(
324
			$args,
325
			sprintf(
326
				'https://public-api.wordpress.com/rest/v1.3/sites/%d/search',
327
				$this->jetpack_blog_id
328
			)
329
		);
330
331
		$request_args = array(
332
			'timeout'    => 10,
333
			'user-agent' => "WordPress/{$wp_version} | Jetpack/" . constant( 'JETPACK__VERSION' ),
334
		);
335
336
		$request  = wp_remote_get( esc_url_raw( $service_url ), $request_args );
337
		$end_time = microtime( true );
338
339
		if ( is_wp_error( $request ) ) {
340
			return $request;
341
		}
342
343
		$response_code = wp_remote_retrieve_response_code( $request );
344
		$response      = json_decode( wp_remote_retrieve_body( $request ), true );
345
346 View Code Duplication
		if ( ! $response_code || $response_code < 200 || $response_code >= 300 ) {
347
			/**
348
			 * Fires after a search query request has failed
349
			 *
350
			 * @module search
351
			 *
352
			 * @since  5.6.0
353
			 *
354
			 * @param array Array containing the response code and response from the failed search query
355
			 */
356
			do_action(
357
				'failed_jetpack_search_query',
358
				array(
359
					'response_code' => $response_code,
360
					'json'          => $response,
361
				)
362
			);
363
364
			return new WP_Error( 'invalid_search_api_response', 'Invalid response from API - ' . $response_code );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_search_api_response'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
365
		}
366
367
		$took = is_array( $response ) && ! empty( $response['took'] )
368
			? $response['took']
369
			: null;
370
371
		$query = array(
372
			'args'          => $args,
373
			'response'      => $response,
374
			'response_code' => $response_code,
375
			'elapsed_time'  => ( $end_time - $start_time ) * 1000, // Convert from float seconds to ms.
376
			'es_time'       => $took,
377
			'url'           => $service_url,
378
		);
379
380
		/**
381
		 * Fires after a search request has been performed.
382
		 *
383
		 * Includes the following info in the $query parameter:
384
		 *
385
		 * array args Array of Elasticsearch arguments for the search
386
		 * array response Raw API response, JSON decoded
387
		 * int response_code HTTP response code of the request
388
		 * float elapsed_time Roundtrip time of the search request, in milliseconds
389
		 * float es_time Amount of time Elasticsearch spent running the request, in milliseconds
390
		 * string url API url that was queried
391
		 *
392
		 * @module search
393
		 *
394
		 * @since  5.0.0
395
		 * @since  5.8.0 This action now fires on all queries instead of just successful queries.
396
		 *
397
		 * @param array $query Array of information about the query performed
398
		 */
399
		do_action( 'did_jetpack_search_query', $query );
400
401
		// Update local cache.
402
		set_transient( $transient_name, $response, 1 * HOUR_IN_SECONDS );
403
404
		return $response;
405
	}
406
407
	/**
408
	 * Get the raw Aggregation results from the Elasticsearch response.
409
	 *
410
	 * @since  8.4.0
411
	 *
412
	 * @return array Array of Aggregations performed on the search.
413
	 */
414
	public function get_search_aggregations_results() {
415
		if ( empty( $this->search_result ) || is_wp_error( $this->search_result ) || ! isset( $this->search_result['aggregations'] ) ) {
416
			return array();
417
		}
418
419
		return $this->search_result['aggregations'];
420
	}
421
422
	/**
423
	 * Automatically configure necessary settings for instant search
424
	 *
425
	 * @since  8.3.0
426
	 */
427
	public function auto_config_search() {
428
		if ( ! current_user_can( 'edit_theme_options' ) ) {
429
			return;
430
		}
431
432
		// Set default result format to "expanded".
433
		update_option( Jetpack_Search_Options::OPTION_PREFIX . 'result_format', 'expanded' );
434
435
		$this->auto_config_excluded_post_types();
436
		$this->auto_config_overlay_sidebar_widgets();
437
	}
438
439
	/**
440
	 * Automatically copy configured search widgets into the overlay sidebar
441
	 *
442
	 * @since  8.8.0
443
	 */
444
	public function auto_config_overlay_sidebar_widgets() {
445
		global $wp_registered_sidebars;
446
		$sidebars = get_option( 'sidebars_widgets', array() );
447
		$slug     = Jetpack_Search_Helpers::FILTER_WIDGET_BASE;
448
449
		if ( isset( $sidebars['jetpack-instant-search-sidebar'] ) ) {
450
			foreach ( (array) $sidebars['jetpack-instant-search-sidebar'] as $widget_id ) {
451
				if ( 0 === strpos( $widget_id, $slug ) ) {
452
					// Already configured.
453
					return;
454
				}
455
			}
456
		}
457
458
		$has_sidebar           = isset( $wp_registered_sidebars['sidebar-1'] );
459
		$sidebar_id            = false;
460
		$sidebar_searchbox_idx = false;
461
		if ( $has_sidebar ) {
462
			if ( empty( $sidebars['sidebar-1'] ) ) {
463
				// Adding to an empty sidebar is generally a bad idea.
464
				$has_sidebar = false;
465
			}
466
			foreach ( (array) $sidebars['sidebar-1'] as $idx => $widget_id ) {
467
				if ( 0 === strpos( $widget_id, 'search-' ) ) {
468
					$sidebar_searchbox_idx = $idx;
469
				}
470
				if ( 0 === strpos( $widget_id, $slug ) ) {
471
					$sidebar_id = (int) str_replace( Jetpack_Search_Helpers::FILTER_WIDGET_BASE . '-', '', $widget_id );
472
					break;
473
				}
474
			}
475
		}
476
477
		$next_id         = 1;
478
		$widget_opt_name = Jetpack_Search_Helpers::get_widget_option_name();
479
		$widget_options  = get_option( $widget_opt_name, array() );
480
		foreach ( $widget_options as $id => $w ) {
481
			if ( $id >= $next_id ) {
482
				$next_id = $id + 1;
483
			}
484
		}
485
486
		// Copy sidebar settings to overlay.
487
		if ( ( false !== $sidebar_id ) && isset( $widget_options[ $sidebar_id ] ) ) {
488
			$widget_options[ $next_id ] = $widget_options[ $sidebar_id ];
489
			update_option( $widget_opt_name, $widget_options );
490
491
			if ( ! isset( $sidebars['jetpack-instant-search-sidebar'] ) ) {
492
				$sidebars['jetpack-instant-search-sidebar'] = array();
493
			}
494
			array_unshift( $sidebars['jetpack-instant-search-sidebar'], Jetpack_Search_Helpers::build_widget_id( $next_id ) );
495
			update_option( 'sidebars_widgets', $sidebars );
496
497
			return;
498
		}
499
500
		// Configure overlay and sidebar (if it exists).
501
		$preconfig_opts = $this->get_preconfig_widget_options();
502
		if ( ! isset( $sidebars['jetpack-instant-search-sidebar'] ) ) {
503
			$sidebars['jetpack-instant-search-sidebar'] = array();
504
		}
505
		if ( $has_sidebar ) {
506
			$widget_options[ $next_id ] = $preconfig_opts;
507
			if ( false !== $sidebar_searchbox_idx ) {
508
				// Replace Core search box.
509
				$sidebars['sidebar-1'][ $sidebar_searchbox_idx ] = Jetpack_Search_Helpers::build_widget_id( $next_id );
510
			} else {
511
				// Add to top.
512
				array_unshift( $sidebars['sidebar-1'], Jetpack_Search_Helpers::build_widget_id( $next_id ) );
513
			}
514
			$next_id++;
515
		}
516
		$widget_options[ $next_id ] = $preconfig_opts;
517
		array_unshift( $sidebars['jetpack-instant-search-sidebar'], Jetpack_Search_Helpers::build_widget_id( $next_id ) );
518
519
		update_option( $widget_opt_name, $widget_options );
520
		update_option( 'sidebars_widgets', $sidebars );
521
	}
522
523
	/**
524
	 * Autoconfig search by adding filter widgets
525
	 *
526
	 * @since  8.4.0
527
	 *
528
	 * @return array Array of config settings for search widget.
529
	 */
530
	protected function get_preconfig_widget_options() {
531
		$settings = array(
532
			'title'   => '',
533
			'filters' => array(),
534
		);
535
536
		$post_types = get_post_types(
537
			array(
538
				'public'   => true,
539
				'_builtin' => false,
540
			)
541
		);
542
543
		if ( ! empty( $post_types ) ) {
544
			$settings['filters'][] = array(
545
				array(
546
					'name'  => '',
547
					'type'  => 'post_type',
548
					'count' => 5,
549
				),
550
			);
551
		}
552
553
		// Grab a maximum of 3 taxonomies.
554
		$taxonomies = array_slice(
555
			get_taxonomies(
556
				array(
557
					'public'   => true,
558
					'_builtin' => false,
559
				)
560
			),
561
			0,
562
			3
563
		);
564
565
		foreach ( $taxonomies as $t ) {
566
			$settings['filters'][] = array(
567
				'name'     => '',
568
				'type'     => 'taxonomy',
569
				'taxonomy' => $t,
570
				'count'    => 5,
571
			);
572
		}
573
574
		$settings['filters'][] = array(
575
			'name'     => '',
576
			'type'     => 'taxonomy',
577
			'taxonomy' => 'category',
578
			'count'    => 5,
579
		);
580
581
		$settings['filters'][] = array(
582
			'name'     => '',
583
			'type'     => 'taxonomy',
584
			'taxonomy' => 'post_tag',
585
			'count'    => 5,
586
		);
587
588
		$settings['filters'][] = array(
589
			'name'     => '',
590
			'type'     => 'date_histogram',
591
			'count'    => 5,
592
			'field'    => 'post_date',
593
			'interval' => 'year',
594
		);
595
596
		return $settings;
597
	}
598
	/**
599
	 * Automatically configure post types to exclude from one of the search widgets
600
	 *
601
	 * @since  8.8.0
602
	 */
603
	public function auto_config_excluded_post_types() {
604
		$post_types         = get_post_types(
605
			array(
606
				'exclude_from_search' => false,
607
				'public'              => true,
608
			)
609
		);
610
		$enabled_post_types = array();
611
		$widget_options     = get_option( Jetpack_Search_Helpers::get_widget_option_name(), array() );
612
613
		// Prior to Jetpack 8.8, post types were enabled via Jetpack Search widgets rather than disabled via the Customizer.
614
		// To continue supporting post types set up in the old way, we iterate through each Jetpack Search
615
		// widget configuration and append each enabled post type to $enabled_post_types.
616
		foreach ( $widget_options as $widget_option ) {
617
			if ( isset( $widget_option['post_types'] ) && is_array( $widget_option['post_types'] ) ) {
618
				foreach ( $widget_option['post_types'] as $enabled_post_type ) {
619
					$enabled_post_types[ $enabled_post_type ] = $enabled_post_type;
620
				}
621
			}
622
		}
623
624
		if ( ! empty( $enabled_post_types ) ) {
625
			$post_types_to_disable = array_diff( $post_types, $enabled_post_types );
626
			update_option( Jetpack_Search_Options::OPTION_PREFIX . 'excluded_post_types', join( ',', $post_types_to_disable ) );
627
		}
628
	}
629
}
630