|
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 ) ) { |
|
|
|
|
|
|
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, |
|
|
|
|
|
|
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
|
|
|
/> |
|
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(); ?> |
|
|
|
|
|
|
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
|
|
|
|
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
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.