Completed
Push — update/search/phpdoc-and-code-... ( fdcff5...961067 )
by Alex
200:59 queued 192:47
created

Jetpack_Search_Widget::widget_admin_setup()   B

Complexity

Conditions 3
Paths 1

Size

Total Lines 37
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 25
nc 1
nop 0
dl 0
loc 37
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Jetpack Search: Jetpack_Search_Widget class
4
 *
5
 * @package    Jetpack
6
 * @subpackage Jetpack Search
7
 * @since      5.0.0
8
 */
9
10
/**
11
 * Provides a widget to show available/selected filters on searches.
12
 *
13
 * @since 5.0.0
14
 *
15
 * @see   WP_Widget
16
 */
17
class Jetpack_Search_Widget extends WP_Widget {
18
19
	/**
20
	 * The Jetpack_Search instance.
21
	 *
22
	 * @since 5.7.0
23
	 * @var Jetpack_Search
24
	 */
25
	protected $jetpack_search;
26
27
	/**
28
	 * Number of aggregations (filters) to show by default.
29
	 *
30
	 * @since 5.8.0
31
	 * @var int
32
	 */
33
	const DEFAULT_FILTER_COUNT = 5;
34
35
	/**
36
	 * Default sort order for search results.
37
	 *
38
	 * @since 5.8.0
39
	 * @var string
40
	 */
41
	const DEFAULT_SORT = 'relevance_desc';
42
43
	/**
44
	 * Jetpack_Search_Widget constructor.
45
	 *
46
	 * @since 5.0.0
47
	 */
48
	function __construct() {
49
		if ( ! class_exists( 'Jetpack_Search' ) ) {
50
			return;
51
		}
52
53
		parent::__construct(
54
			'jetpack-search-filters',
55
			/** This filter is documented in modules/widgets/facebook-likebox.php */
56
			apply_filters( 'jetpack_widget_name', esc_html__( 'Search', 'jetpack' ) ),
57
			array(
58
				'classname'   => 'jetpack-filters widget_search',
59
				'description' => __( 'Displays Jetpack Search box and filters.', 'jetpack' ),
60
			)
61
		);
62
63
		$this->jetpack_search = Jetpack_Search::instance();
64
65
		if ( is_admin() ) {
66
			add_action( 'sidebar_admin_setup', array( $this, 'widget_admin_setup' ) );
67
		} else {
68
			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
69
		}
70
71
		add_action( 'jetpack_search_render_filters_widget_title', array( 'Jetpack_Search_Template_Tags', 'render_widget_title' ), 10, 3 );
72
		add_action( 'jetpack_search_render_filters', array( 'Jetpack_Search_Template_Tags', 'render_available_filters' ), 10, 2 );
73
	}
74
75
	/**
76
	 * Enqueues the scripts and styles needed for the customizer.
77
	 *
78
	 * @since 5.7.0
79
	 */
80
	function widget_admin_setup() {
81
		wp_enqueue_style( 'widget-jetpack-search-filters', plugins_url( 'css/search-widget-admin-ui.css', __FILE__ ) );
82
83
		// Required for Tracks
84
		wp_register_script(
85
			'jp-tracks',
86
			'//stats.wp.com/w.js',
87
			array(),
88
			gmdate( 'YW' ),
89
			true
90
		);
91
92
		wp_register_script(
93
			'jp-tracks-functions',
94
			plugins_url( '_inc/lib/tracks/tracks-callables.js', JETPACK__PLUGIN_FILE ),
95
			array(),
96
			JETPACK__VERSION,
97
			false
98
		);
99
100
		wp_register_script(
101
			'jetpack-search-widget-admin',
102
			plugins_url( 'js/search-widget-admin.js', __FILE__ ),
103
			array( 'jquery', 'jquery-ui-sortable', 'jp-tracks', 'jp-tracks-functions' ),
104
			JETPACK__VERSION
105
		);
106
107
		wp_localize_script( 'jetpack-search-widget-admin', 'jetpack_search_filter_admin', array(
108
			'defaultFilterCount' => self::DEFAULT_FILTER_COUNT,
109
			'tracksUserData'     => Jetpack_Tracks_Client::get_connected_user_tracks_identity(),
110
			'tracksEventData'    => array(
111
				'is_customizer' => ( function_exists( 'is_customize_preview' ) && is_customize_preview() ) ? 1 : 0,
112
			),
113
		) );
114
115
		wp_enqueue_script( 'jetpack-search-widget-admin' );
116
	}
117
118
	/**
119
	 * Enqueue scripts and styles for the frontend.
120
	 *
121
	 * @since 5.8.0
122
	 */
123
	public function enqueue_frontend_scripts() {
124
		if ( ! is_active_widget( false, false, $this->id_base, true ) ) {
125
			return;
126
		}
127
128
		wp_enqueue_script(
129
			'jetpack-search-widget',
130
			plugins_url( 'js/search-widget.js', __FILE__ ),
131
			array( 'jquery' ),
132
			JETPACK__VERSION,
133
			true
134
		);
135
136
		wp_enqueue_style( 'jetpack-search-widget', plugins_url( 'modules/search/css/search-widget-frontend.css', JETPACK__PLUGIN_FILE ) );
137
	}
138
139
	/**
140
	 * Get the list of valid sort types/orders.
141
	 *
142
	 * @since 5.8.0
143
	 *
144
	 * @return array The sort orders.
145
	 */
146
	private function get_sort_types() {
147
		return array(
148
			'relevance|DESC' => is_admin() ? esc_html__( 'Relevance (recommended)', 'jetpack' ) : esc_html__( 'Relevance', 'jetpack' ),
149
			'date|DESC'      => esc_html__( 'Newest first', 'jetpack' ),
150
			'date|ASC'       => esc_html__( 'Oldest first', 'jetpack' )
151
		);
152
	}
153
154
	/**
155
	 * Callback for an array_filter() call in order to only get filters for the current widget.
156
	 *
157
	 * @see   Jetpack_Search_Widget::widget()
158
	 *
159
	 * @since 5.7.0
160
	 *
161
	 * @param array $item Filter item.
162
	 *
163
	 * @return bool Whether the current filter item is for the current widget.
164
	 */
165
	function is_for_current_widget( $item ) {
166
		return isset( $item['widget_id'] ) && $this->id == $item['widget_id'];
167
	}
168
169
	/**
170
	 * This method returns a boolean for whether the widget should show site-wide filters for the site.
171
	 *
172
	 * This is meant to provide backwards-compatibility for VIP, and other professional plan users, that manually
173
	 * configured filters via `Jetpack_Search::set_filters()`.
174
	 *
175
	 * @since 5.7.0
176
	 *
177
	 * @return bool Whether the widget should display site-wide filters or not.
178
	 */
179
	function should_display_sitewide_filters() {
180
		$filter_widgets = get_option( 'widget_jetpack-search-filters' );
181
182
		// This shouldn't be empty, but just for sanity
183
		if ( empty( $filter_widgets ) ) {
184
			return false;
185
		}
186
187
		// If any widget has any filters, return false
188
		foreach ( $filter_widgets as $number => $widget ) {
189
			$widget_id = sprintf( 'jetpack-search-filters-%d', $number );
190
			if ( ! empty( $widget['filters'] ) && is_active_widget( false, $widget_id, 'jetpack-search-filters' ) ) {
191
				return false;
192
			}
193
		}
194
195
		return true;
196
	}
197
198
	/**
199
	 * Responsible for rendering the widget on the frontend.
200
	 *
201
	 * @since 5.0.0
202
	 *
203
	 * @param array $args     Widgets args supplied by the theme.
204
	 * @param array $instance The current widget instance.
205
	 */
206
	public function widget( $args, $instance ) {
207
		$display_filters = false;
208
209
		if ( is_search() ) {
210
			if ( Jetpack_Search_Helpers::should_rerun_search_in_customizer_preview( $instance, $this->id ) ) {
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Search_Helpers::...in_customizer_preview() has too many arguments starting with $instance.

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...
211
				$this->jetpack_search->update_search_results_aggregations();
212
			}
213
214
			$filters = $this->jetpack_search->get_filters();
215
216
			if ( ! $this->jetpack_search->are_filters_by_widget_disabled() && ! $this->should_display_sitewide_filters() ) {
217
				$filters = array_filter( $filters, array( $this, 'is_for_current_widget' ) );
218
			}
219
220
			if ( ! empty( $filters ) ) {
221
				$display_filters = true;
222
			}
223
		}
224
225
		if ( ! $display_filters && empty( $instance['search_box_enabled'] ) && empty( $instance['user_sort_enabled'] ) ) {
226
			return;
227
		}
228
229
		$title = isset( $instance['title'] ) ? $instance['title'] : '';
230
231
		if ( empty( $title ) ) {
232
			$title = '';
233
		}
234
235
		/** This filter is documented in core/src/wp-includes/default-widgets.php */
236
		$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
237
238
		echo $args['before_widget'];
239
240
		if ( ! empty( $title ) ) {
241
			/**
242
			 * Responsible for displaying the title of the Jetpack Search filters widget.
243
			 *
244
			 * @module search
245
			 *
246
			 * @since  5.7.0
247
			 *
248
			 * @param string $title                The widget's title
249
			 * @param string $args['before_title'] The HTML tag to display before the title
250
			 * @param string $args['after_title']  The HTML tag to display after the title
251
			 */
252
			do_action( 'jetpack_search_render_filters_widget_title', $title, $args['before_title'], $args['after_title'] );
253
		}
254
255
		$default_sort = isset( $instance['sort'] ) ? $instance['sort'] : self::DEFAULT_SORT;
256
		list( $orderby, $order ) = $this->sorting_to_wp_query_param( $default_sort );
257
		$current_sort = "{$orderby}|{$order}";
258
259
		// we need to dynamically inject the sort field into the search box when the search box is enabled, and display
260
		// it separately when it's not.
261
		if ( ! empty( $instance['search_box_enabled'] ) ) {
262
			Jetpack_Search_Template_Tags::render_widget_search_form( $instance['post_types'], $orderby, $order );
263
		}
264
265
		if ( ! empty( $instance['search_box_enabled'] ) && ! empty( $instance['user_sort_enabled'] ) ): ?>
266
			<h4 class="jetpack-search-filters-widget__sub-heading"><?php esc_html_e( 'Sort by', 'jetpack' ); ?></h4>
267
			<div class="jetpack-search-sort-wrapper">
268
				<select class="jetpack-search-sort">
269 View Code Duplication
					<?php foreach ( $this->get_sort_types() as $sort => $label ) { ?>
270
						<option value="<?php echo esc_attr( $sort ); ?>" <?php selected( $current_sort, $sort ); ?>>
271
							<?php echo esc_html( $label ); ?>
272
						</option>
273
					<?php } ?>
274
				</select>
275
			</div>
276
		<?php endif;
277
278
		if ( $display_filters ) {
279
			/**
280
			 * Responsible for rendering filters to narrow down search results.
281
			 *
282
			 * @module search
283
			 *
284
			 * @since  5.8.0
285
			 *
286
			 * @param array $filters    The possible filters for the current query.
287
			 * @param array $post_types An array of post types to limit filtering to.
288
			 */
289
			do_action(
290
				'jetpack_search_render_filters',
291
				$filters,
0 ignored issues
show
Bug introduced by
The variable $filters does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
292
				isset( $instance['post_types'] ) ? $instance['post_types'] : null
293
			);
294
		}
295
296
		$this->maybe_render_sort_javascript( $instance, $order, $orderby );
297
298
		echo $args['after_widget'];
299
	}
300
301
	/**
302
	 * Renders JavaScript for the sorting controls on the frontend.
303
	 *
304
	 * This JS is a bit complicated, but here's what it's trying to do:
305
	 * - find the search form
306
	 * - find the orderby/order fields and set default values
307
	 * - detect changes to the sort field, if it exists, and use it to set the order field values
308
	 *
309
	 * @param array  $instance The current widget instance.
310
	 * @param string $order    The order to initialize the select with.
311
	 * @param string $orderby  The orderby to initialize the select with.
312
	 */
313
	private function maybe_render_sort_javascript( $instance, $order, $orderby ) {
314
		if ( ! empty( $instance['user_sort_enabled'] ) ) :
315
		?>
316
		<script type="text/javascript">
317
				jQuery( document ).ready( function( $ ) {
318
					var orderByDefault = <?php echo wp_json_encode( $orderby ); ?>,
319
						orderDefault   = <?php echo wp_json_encode( $order ); ?>,
320
						widgetId       = <?php echo wp_json_encode( $this->id ); ?>,
321
						currentSearch  = <?php echo wp_json_encode( isset( $_GET['s'] ) ? $_GET['s'] : '' ); ?>;
322
323
					var container = $('#' + widgetId);
324
					var form = container.find('.jetpack-search-form form');
325
					var orderBy = form.find( 'input[name=orderby]');
326
					var order = form.find( 'input[name=order]');
327
					orderBy.val(orderByDefault);
328
					order.val(orderDefault);
329
330
					container.find( '.jetpack-search-sort' ).change( function( event ) {
331
						var values  = event.target.value.split( '|' );
332
						orderBy.val( values[0] );
333
						order.val( values[1] );
334
335
						if ( currentSearch ) {
336
							form.submit();
337
						}
338
					});
339
				});
340
			</script>
341
		<?php endif;
342
	}
343
344
	/**
345
	 * Convert a sort string into the separate order by and order parts.
346
	 *
347
	 * @param string $sort A sort string.
348
	 *
349
	 * @return array Order by and order.
350
	 */
351
	private function sorting_to_wp_query_param( $sort ) {
352
		$parts   = explode( '|', $sort );
353
		$orderby = isset( $_GET['orderby'] )
354
			? $_GET['orderby']
355
			: $parts[0];
356
357
		$order = isset( $_GET['order'] )
358
			? strtoupper( $_GET['order'] )
359
			: ( ( isset( $parts[1] ) && 'ASC' === strtoupper( $parts[1] ) ) ? 'ASC' : 'DESC' );
360
361
		return array( $orderby, $order );
362
	}
363
364
	/**
365
	 * Updates a particular instance of the widget. Validates and sanitizes the options.
366
	 *
367
	 * @since 5.0.0
368
	 *
369
	 * @param array $new_instance New settings for this instance as input by the user via Jetpack_Search_Widget::form().
370
	 * @param array $old_instance Old settings for this instance.
371
	 *
372
	 * @return array Settings to save.
373
	 */
374
	function update( $new_instance, $old_instance ) {
375
		$instance = array();
376
377
		$instance['title']              = sanitize_text_field( $new_instance['title'] );
378
		$instance['search_box_enabled'] = empty( $new_instance['search_box_enabled'] ) ? '0' : '1';
379
		$instance['user_sort_enabled']  = empty( $new_instance['user_sort_enabled'] ) ? '0' : '1';
380
		$instance['sort']               = $new_instance['sort'];
381
		$instance['post_types']         = empty( $new_instance['post_types'] ) || empty( $instance['search_box_enabled'] )
382
			? array()
383
			: array_map( 'sanitize_key', $new_instance['post_types'] );
384
385
		$filters = array();
386
		foreach ( (array) $new_instance['filter_type'] as $index => $type ) {
387
			$count = intval( $new_instance['num_filters'][ $index ] );
388
			$count = min( 50, $count ); // Set max boundary at 20
389
			$count = max( 1, $count );  // Set min boundary at 1
390
391
			switch ( $type ) {
392
				case 'taxonomy':
393
					$filters[] = array(
394
						'name'     => sanitize_text_field( $new_instance['filter_name'][ $index ] ),
395
						'type'     => 'taxonomy',
396
						'taxonomy' => sanitize_key( $new_instance['taxonomy_type'][ $index ] ),
397
						'count'    => $count,
398
					);
399
					break;
400
				case 'post_type':
401
					$filters[] = array(
402
						'name'  => sanitize_text_field( $new_instance['filter_name'][ $index ] ),
403
						'type'  => 'post_type',
404
						'count' => $count,
405
					);
406
					break;
407
				case 'date_histogram':
408
					$filters[] = array(
409
						'name'     => sanitize_text_field( $new_instance['filter_name'][ $index ] ),
410
						'type'     => 'date_histogram',
411
						'count'    => $count,
412
						'field'    => sanitize_key( $new_instance['date_histogram_field'][ $index ] ),
413
						'interval' => sanitize_key( $new_instance['date_histogram_interval'][ $index ] ),
414
					);
415
					break;
416
			}
417
		}
418
419
		if ( ! empty( $filters ) ) {
420
			$instance['filters'] = $filters;
421
		}
422
423
		return $instance;
424
	}
425
426
	/**
427
	 * Outputs the settings update form.
428
	 *
429
	 * @since 5.0.0
430
	 *
431
	 * @param array $instance Current settings.
432
	 */
433
	function form( $instance ) {
434
		$instance = wp_parse_args( (array) $instance, array(
435
			'title'   => '',
436
			'filters' => array( array() )
437
		) );
438
439
		$title = strip_tags( $instance['title'] );
440
441
		$hide_filters       = $this->jetpack_search->are_filters_by_widget_disabled();
442
		$search_box_enabled = ! isset( $instance['search_box_enabled'] ) || ! empty( $instance['search_box_enabled'] );
443
		$user_sort_enabled  = ! empty( $instance['user_sort_enabled'] );
444
		$sort               = isset( $instance['sort'] ) ? $instance['sort'] : self::DEFAULT_SORT;
445
		$classes            = sprintf(
446
			'jetpack-search-filters-widget %s %s %s',
447
			$hide_filters ? 'hide-filters' : '',
448
			$search_box_enabled ? '' : 'hide-post-types',
449
			$this->id
450
		);
451
		?>
452
		<div class="<?php echo esc_attr( $classes ); ?>">
453
			<p>
454
				<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
455
					<?php esc_html_e( 'Title (optional):', 'jetpack' ); ?>
456
				</label>
457
				<input
458
					class="widefat"
459
					id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
460
					name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
461
					type="text"
462
					value="<?php echo esc_attr( $title ); ?>"
463
				/>
464
			</p>
465
466
			<p>
467
				<label>
468
					<input
469
						type="checkbox"
470
						class="jetpack-search-filters-widget__search-box-enabled"
471
						name="<?php echo esc_attr( $this->get_field_name( 'search_box_enabled' ) ); ?>"
472
						<?php checked( $search_box_enabled ); ?>
473
					/>
474
					<?php esc_html_e( 'Show search box', 'jetpack' ); ?>
475
				</label>
476
			</p>
477
			<p>
478
				<label>
479
					<input
480
						type="checkbox"
481
						class="jetpack-search-filters-widget__sort-controls-enabled"
482
						name="<?php echo esc_attr( $this->get_field_name( 'user_sort_enabled' ) ); ?>"
483
						<?php checked( $user_sort_enabled ); ?>
484
					/>
485
					<?php esc_html_e( 'Show sort selection dropdown', 'jetpack' ); ?>
486
				</label>
487
			</p>
488
489
			<p class="jetpack-search-filters-widget__post-types-select">
490
				<label><?php esc_html_e( 'Post types to search (minimum of 1):', 'jetpack' ); ?></label>
491
				<?php foreach ( get_post_types( array( 'exclude_from_search' => false ), 'objects' ) as $post_type ) : ?>
492
					<label>
493
						<input
494
							type="checkbox"
495
							value="<?php echo esc_attr( $post_type->name ); ?>"
496
							name="<?php echo esc_attr( $this->get_field_name( 'post_types' ) ); ?>[]"
497
							<?php checked( empty( $instance['post_types'] ) || in_array( $post_type->name, $instance['post_types'] ) ); ?>
498
						/>&nbsp;
499
						<?php echo esc_html( $post_type->label ); ?>
500
					</label>
501
				<?php endforeach; ?>
502
			</p>
503
504
			<p>
505
				<label>
506
					<?php esc_html_e( 'Default sort order:', 'jetpack' ); ?>
507
					<select
508
						name="<?php echo esc_attr( $this->get_field_name( 'sort' ) ); ?>"
509
						class="widefat jetpack-search-filters-widget__sort-order">
510 View Code Duplication
						<?php foreach ( $this->get_sort_types() as $sort_type => $label ) { ?>
511
							<option value="<?php echo esc_attr( $sort_type ); ?>" <?php selected( $sort, $sort_type ); ?>>
512
								<?php echo esc_html( $label ); ?>
513
							</option>
514
						<?php } ?>
515
					</select>
516
				</label>
517
			</p>
518
519
			<?php if ( ! $hide_filters ): ?>
520
				<script class="jetpack-search-filters-widget__filter-template" type="text/template">
521
					<?php echo $this->render_widget_edit_filter( array(), true ); ?>
522
				</script>
523
				<div class="jetpack-search-filters-widget__filters">
524
					<?php foreach ( (array) $instance['filters'] as $filter ) : ?>
525
						<?php $this->render_widget_edit_filter( $filter ); ?>
526
					<?php endforeach; ?>
527
				</div>
528
				<p class="jetpack-search-filters-widget__add-filter-wrapper">
529
					<a class="button jetpack-search-filters-widget__add-filter" href="#">
530
						<?php esc_html_e( 'Add a filter', 'jetpack' ); ?>
531
					</a>
532
				</p>
533
				<noscript>
534
					<p class="jetpack-search-filters-help">
535
						<?php echo esc_html_e( 'Adding filters requires JavaScript!', 'jetpack' ); ?>
536
					</p>
537
				</noscript>
538
				<?php if ( is_customize_preview() ) : ?>
539
					<p class="jetpack-search-filters-help">
540
						<a href="https://jetpack.com/support/search/#filters-not-showing-up" target="_blank">
541
							<?php esc_html_e( "Why aren't my filters appearing?", 'jetpack' ); ?>
542
						</a>
543
					</p>
544
				<?php endif; ?>
545
			<?php endif; ?>
546
		</div>
547
		<?php
548
	}
549
550
	/**
551
	 * We basically render the values in two formats:
552
	 * - underscore template
553
	 * - native PHP
554
	 *
555
	 * This is so we can use the same code to render a client-side and server-side template.
556
	 */
557
	private function render_widget_attr( $name, $value, $is_template ) {
558
		echo $is_template ? "<%= $name %>" : esc_attr( $value );
559
	}
560
561
	/**
562
	 * See above ^^
563
	 */
564
	private function render_widget_option_selected( $name, $value, $compare, $is_template ) {
565
		$compare_json = json_encode( $compare );
566
		echo $is_template ? "<%= $compare_json === $name ? 'selected=\"selected\"' : '' %>" : selected( $value, $compare );
567
	}
568
569
	/**
570
	 * Responsible for rendering a single filter in the customizer or the widget administration screen in wp-admin.
571
	 *
572
	 * We use this method for two purposes - rendering the fields server-side, and also rendering a script template for underscore.
573
	 *
574
	 * @since 5.7.0
575
	 *
576
	 * @param array $filter
577
	 */
578
	function render_widget_edit_filter( $filter, $is_template = false ) {
579
		$args = wp_parse_args( $filter, array(
580
			'name' => '',
581
			'type' => 'taxonomy',
582
			'taxonomy' => '',
583
			'post_type' => '',
584
			'field' => '',
585
			'interval' => '',
586
			'count' => self::DEFAULT_FILTER_COUNT,
587
		) );
588
589
		$args['name_placeholder'] = Jetpack_Search_Helpers::generate_widget_filter_name( $args );
590
591
		?>
592
		<div class="jetpack-search-filters-widget__filter is-<?php $this->render_widget_attr( 'type', $args['type'], $is_template ); ?>">
593
			<p class="jetpack-search-filters-widget__type-select">
594
				<label>
595
					<?php esc_html_e( 'Filter Type:', 'jetpack' ); ?>
596
					<select name="<?php echo esc_attr( $this->get_field_name( 'filter_type' ) ); ?>[]" class="widefat filter-select">
597
						<option value="taxonomy" <?php $this->render_widget_option_selected( 'type', $args['type'], 'taxonomy', $is_template ); ?>>
598
							<?php esc_html_e( 'Taxonomy', 'jetpack' ); ?>
599
						</option>
600
						<option value="post_type" <?php $this->render_widget_option_selected( 'type', $args['type'], 'post_type', $is_template ); ?>>
601
							<?php esc_html_e( 'Post Type', 'jetpack' ); ?>
602
						</option>
603
						<option value="date_histogram" <?php $this->render_widget_option_selected( 'type', $args['type'], 'date_histogram', $is_template ); ?>>
604
							<?php esc_html_e( 'Date', 'jetpack' ); ?>
605
						</option>
606
					</select>
607
				</label>
608
			</p>
609
610
			<p class="jetpack-search-filters-widget__taxonomy-select">
611
				<label>
612
					<?php esc_html_e( 'Choose a taxonomy:', 'jetpack' ); $seen_taxonomy_labels = array(); ?>
0 ignored issues
show
Coding Style introduced by
It is generally recommended to place each PHP statement on a line by itself.

Let’s take a look at an example:

// Bad
$a = 5; $b = 6; $c = 7;

// Good
$a = 5;
$b = 6;
$c = 7;
Loading history...
613
					<select name="<?php echo esc_attr( $this->get_field_name( 'taxonomy_type' ) ); ?>[]" class="widefat taxonomy-select">
614
						<?php foreach ( get_taxonomies( array( 'public' => true ), 'objects' ) as $taxonomy ) : ?>
615
							<option value="<?php echo esc_attr( $taxonomy->name ); ?>" <?php $this->render_widget_option_selected( 'taxonomy', $args['taxonomy'], $taxonomy->name, $is_template ); ?>>
616
								<?php
617
									$label = in_array( $taxonomy->label, $seen_taxonomy_labels )
618
										? sprintf(
619
											/* translators: %1$s is the taxonomy name, %2s is the name of its type to help distinguish between several taxonomies with the same name, e.g. category and tag. */
620
											_x( '%1$s (%2$s)', 'A label for a taxonomy selector option', 'jetpack' ),
621
											$taxonomy->label,
622
											$taxonomy->name
623
										)
624
										: $taxonomy->label;
625
									echo esc_html( $label );
626
									$seen_taxonomy_labels[] = $taxonomy->label;
627
								?>
628
							</option>
629
						<?php endforeach; ?>
630
					</select>
631
				</label>
632
			</p>
633
634
			<p class="jetpack-search-filters-widget__date-histogram-select">
635
				<label>
636
					<?php esc_html_e( 'Choose a field:', 'jetpack' ); ?>
637
					<select name="<?php echo esc_attr( $this->get_field_name( 'date_histogram_field' ) ); ?>[]" class="widefat date-field-select">
638
						<option value="post_date" <?php $this->render_widget_option_selected( 'field', $args['field'], 'post_date', $is_template ); ?>>
639
							<?php esc_html_e( 'Date', 'jetpack' ); ?>
640
						</option>
641
						<option value="post_date_gmt" <?php $this->render_widget_option_selected( 'field', $args['field'], 'post_date_gmt', $is_template ); ?>>
642
							<?php esc_html_e( 'Date GMT', 'jetpack' ); ?>
643
						</option>
644
						<option value="post_modified" <?php $this->render_widget_option_selected( 'field', $args['field'], 'post_modified', $is_template ); ?>>
645
							<?php esc_html_e( 'Modified', 'jetpack' ); ?>
646
						</option>
647
						<option value="post_modified_gmt" <?php $this->render_widget_option_selected( 'field', $args['field'], 'post_modified_gmt', $is_template ); ?>>
648
							<?php esc_html_e( 'Modified GMT', 'jetpack' ); ?>
649
						</option>
650
					</select>
651
				</label>
652
			</p>
653
654
			<p class="jetpack-search-filters-widget__date-histogram-select">
655
				<label>
656
					<?php esc_html_e( 'Choose an interval:' ); ?>
657
					<select name="<?php echo esc_attr( $this->get_field_name( 'date_histogram_interval' ) ); ?>[]" class="widefat date-interval-select">
658
						<option value="month" <?php $this->render_widget_option_selected( 'interval', $args['interval'], 'month', $is_template ); ?>>
659
							<?php esc_html_e( 'Month', 'jetpack' ); ?>
660
						</option>
661
						<option value="year" <?php $this->render_widget_option_selected( 'interval', $args['interval'], 'year', $is_template ); ?>>
662
							<?php esc_html_e( 'Year', 'jetpack' ); ?>
663
						</option>
664
					</select>
665
				</label>
666
			</p>
667
668
			<p class="jetpack-search-filters-widget__title">
669
				<label>
670
					<?php esc_html_e( 'Title:', 'jetpack' ); ?>
671
					<input
672
						class="widefat"
673
						type="text"
674
						name="<?php echo esc_attr( $this->get_field_name( 'filter_name' ) ); ?>[]"
675
						value="<?php $this->render_widget_attr( 'name', $args['name'], $is_template ); ?>"
676
						placeholder="<?php $this->render_widget_attr( 'name_placeholder', $args['name_placeholder'], $is_template ); ?>"
677
					/>
678
				</label>
679
			</p>
680
681
			<p>
682
				<label>
683
					<?php esc_html_e( 'Maximum number of filters (1-50):', 'jetpack' ); ?>
684
					<input
685
						class="widefat filter-count"
686
						name="<?php echo esc_attr( $this->get_field_name( 'num_filters' ) ); ?>[]"
687
						type="number"
688
						value="<?php $this->render_widget_attr( 'count', $args['count'], $is_template ); ?>"
689
						min="1"
690
						max="50"
691
						step="1"
692
						required
693
					/>
694
				</label>
695
			</p>
696
697
			<p class="jetpack-search-filters-widget__controls">
698
				<a href="#" class="delete"><?php esc_html_e( 'Remove', 'jetpack' ); ?></a>
699
			</p>
700
		</div>
701
	<?php }
702
}
703