1
|
|
|
<?php |
|
|
|
|
2
|
|
|
/** |
3
|
|
|
* The GravityView New Search widget |
4
|
|
|
* |
5
|
|
|
* @package GravityView-DataTables-Ext |
6
|
|
|
* @license GPL2+ |
7
|
|
|
* @author Katz Web Services, Inc. |
8
|
|
|
* @link http://gravityview.co |
9
|
|
|
* @copyright Copyright 2014, Katz Web Services, Inc. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
if ( ! defined( 'WPINC' ) ) { |
13
|
|
|
die; |
14
|
|
|
} |
15
|
|
|
|
16
|
|
|
class GravityView_Widget_Search extends GravityView_Widget { |
17
|
|
|
|
18
|
|
|
public static $file; |
19
|
|
|
public static $instance; |
20
|
|
|
|
21
|
|
|
private $search_filters = array(); |
|
|
|
|
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* whether search method is GET or POST ( default: GET ) |
25
|
|
|
* @since 1.16.4 |
26
|
|
|
* @var string |
27
|
|
|
*/ |
28
|
|
|
private $search_method = 'get'; |
29
|
|
|
|
30
|
|
|
public function __construct() { |
31
|
|
|
|
32
|
|
|
$this->widget_description = esc_html__( 'Search form for searching entries.', 'gravityview' ); |
33
|
|
|
|
34
|
|
|
self::$instance = &$this; |
35
|
|
|
|
36
|
|
|
self::$file = plugin_dir_path( __FILE__ ); |
37
|
|
|
|
38
|
|
|
$default_values = array( 'header' => 0, 'footer' => 0 ); |
39
|
|
|
|
40
|
|
|
$settings = array( |
41
|
|
|
'search_layout' => array( |
42
|
|
|
'type' => 'radio', |
43
|
|
|
'full_width' => true, |
44
|
|
|
'label' => esc_html__( 'Search Layout', 'gravityview' ), |
45
|
|
|
'value' => 'horizontal', |
46
|
|
|
'options' => array( |
47
|
|
|
'horizontal' => esc_html__( 'Horizontal', 'gravityview' ), |
48
|
|
|
'vertical' => esc_html__( 'Vertical', 'gravityview' ), |
49
|
|
|
), |
50
|
|
|
), |
51
|
|
|
'search_clear' => array( |
52
|
|
|
'type' => 'checkbox', |
53
|
|
|
'label' => __( 'Show Clear button', 'gravityview' ), |
54
|
|
|
'value' => false, |
55
|
|
|
), |
56
|
|
|
'search_fields' => array( |
57
|
|
|
'type' => 'hidden', |
58
|
|
|
'label' => '', |
59
|
|
|
'class' => 'gv-search-fields-value', |
60
|
|
|
'value' => '[{"field":"search_all","input":"input_text"}]', // Default: Search Everything text box |
61
|
|
|
), |
62
|
|
|
'search_mode' => array( |
63
|
|
|
'type' => 'radio', |
64
|
|
|
'full_width' => true, |
65
|
|
|
'label' => esc_html__( 'Search Mode', 'gravityview' ), |
66
|
|
|
'desc' => __('Should search results match all search fields, or any?', 'gravityview'), |
|
|
|
|
67
|
|
|
'value' => 'any', |
68
|
|
|
'class' => 'hide-if-js', |
69
|
|
|
'options' => array( |
70
|
|
|
'any' => esc_html__( 'Match Any Fields', 'gravityview' ), |
71
|
|
|
'all' => esc_html__( 'Match All Fields', 'gravityview' ), |
72
|
|
|
), |
73
|
|
|
), |
74
|
|
|
); |
75
|
|
|
parent::__construct( esc_html__( 'Search Bar', 'gravityview' ), 'search_bar', $default_values, $settings ); |
76
|
|
|
|
77
|
|
|
// frontend - filter entries |
78
|
|
|
add_filter( 'gravityview_fe_search_criteria', array( $this, 'filter_entries' ), 10, 1 ); |
79
|
|
|
|
80
|
|
|
// frontend - add template path |
81
|
|
|
add_filter( 'gravityview_template_paths', array( $this, 'add_template_path' ) ); |
82
|
|
|
|
83
|
|
|
// Add hidden fields for "Default" permalink structure |
84
|
|
|
add_filter( 'gravityview_widget_search_filters', array( $this, 'add_no_permalink_fields' ), 10, 3 ); |
85
|
|
|
|
86
|
|
|
// admin - add scripts - run at 1100 to make sure GravityView_Admin_Views::add_scripts_and_styles() runs first at 999 |
87
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'add_scripts_and_styles' ), 1100 ); |
88
|
|
|
add_filter( 'gravityview_noconflict_scripts', array( $this, 'register_no_conflict' ) ); |
89
|
|
|
|
90
|
|
|
// ajax - get the searchable fields |
91
|
|
|
add_action( 'wp_ajax_gv_searchable_fields', array( 'GravityView_Widget_Search', 'get_searchable_fields' ) ); |
92
|
|
|
|
93
|
|
|
// calculate the search method (POST / GET) |
94
|
|
|
$this->set_search_method(); |
95
|
|
|
|
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* @return GravityView_Widget_Search |
100
|
|
|
*/ |
101
|
|
|
public static function getInstance() { |
|
|
|
|
102
|
|
|
if ( empty( self::$instance ) ) { |
103
|
|
|
self::$instance = new GravityView_Widget_Search; |
104
|
|
|
} |
105
|
|
|
return self::$instance; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Sets the search method to GET (default) or POST |
110
|
|
|
* @since 1.16.4 |
111
|
|
|
*/ |
112
|
|
|
private function set_search_method() { |
113
|
|
|
/** |
114
|
|
|
* @filter `gravityview/search/method` Modify the search form method (GET / POST) |
115
|
|
|
* @since 1.16.4 |
116
|
|
|
* @param string $search_method Assign an input type according to the form field type. Defaults: `boolean`, `multi`, `select`, `date`, `text` |
117
|
|
|
* @param string $field_type Gravity Forms field type (also the `name` parameter of GravityView_Field classes) |
118
|
|
|
*/ |
119
|
|
|
$method = apply_filters( 'gravityview/search/method', $this->search_method ); |
120
|
|
|
|
121
|
|
|
$method = strtolower( $method ); |
122
|
|
|
|
123
|
|
|
$this->search_method = in_array( $method, array( 'get', 'post' ) ) ? $method : 'get'; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Returns the search method |
128
|
|
|
* @since 1.16.4 |
129
|
|
|
* @return string |
130
|
|
|
*/ |
131
|
|
|
public function get_search_method() { |
132
|
|
|
return $this->search_method; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Add script to Views edit screen (admin) |
138
|
|
|
* @param mixed $hook |
139
|
|
|
*/ |
140
|
|
|
public function add_scripts_and_styles( $hook ) { |
141
|
|
|
global $pagenow; |
|
|
|
|
142
|
|
|
|
143
|
|
|
// Don't process any scripts below here if it's not a GravityView page or the widgets screen |
144
|
|
|
if ( ! gravityview_is_admin_page( $hook ) && ( 'widgets.php' !== $pagenow ) ) { |
145
|
|
|
return; |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
$script_min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; |
149
|
|
|
$script_source = empty( $script_min ) ? '/source' : ''; |
150
|
|
|
|
151
|
|
|
wp_enqueue_script( 'gravityview_searchwidget_admin', plugins_url( 'assets/js'.$script_source.'/admin-search-widget'.$script_min.'.js', __FILE__ ), array( 'jquery', 'gravityview_views_scripts' ), GravityView_Plugin::version ); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* Input Type labels l10n |
156
|
|
|
* @see admin-search-widget.js (getSelectInput) |
157
|
|
|
* @var array |
158
|
|
|
*/ |
159
|
|
|
$input_labels = array( |
160
|
|
|
'input_text' => esc_html__( 'Text', 'gravityview' ), |
161
|
|
|
'date' => esc_html__( 'Date', 'gravityview' ), |
162
|
|
|
'select' => esc_html__( 'Select', 'gravityview' ), |
163
|
|
|
'multiselect' => esc_html__( 'Select (multiple values)', 'gravityview' ), |
164
|
|
|
'radio' => esc_html__( 'Radio', 'gravityview' ), |
165
|
|
|
'checkbox' => esc_html__( 'Checkbox', 'gravityview' ), |
166
|
|
|
'single_checkbox' => esc_html__( 'Checkbox', 'gravityview' ), |
167
|
|
|
'link' => esc_html__( 'Links', 'gravityview' ), |
168
|
|
|
'date_range' => esc_html__( 'Date range', 'gravityview' ), |
169
|
|
|
); |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Input Type groups |
173
|
|
|
* @see admin-search-widget.js (getSelectInput) |
174
|
|
|
* @var array |
175
|
|
|
*/ |
176
|
|
|
$input_types = array( |
177
|
|
|
'text' => array( 'input_text' ), |
178
|
|
|
'address' => array( 'input_text' ), |
179
|
|
|
'date' => array( 'date', 'date_range' ), |
180
|
|
|
'boolean' => array( 'single_checkbox' ), |
181
|
|
|
'select' => array( 'select', 'radio', 'link' ), |
182
|
|
|
'multi' => array( 'select', 'multiselect', 'radio', 'checkbox', 'link' ), |
183
|
|
|
); |
184
|
|
|
|
185
|
|
|
wp_localize_script( 'gravityview_searchwidget_admin', 'gvSearchVar', array( |
186
|
|
|
'nonce' => wp_create_nonce( 'gravityview_ajaxsearchwidget' ), |
187
|
|
|
'label_nofields' => esc_html__( 'No search fields configured yet.', 'gravityview' ), |
188
|
|
|
'label_addfield' => esc_html__( 'Add Search Field', 'gravityview' ), |
189
|
|
|
'label_label' => esc_html__( 'Label', 'gravityview' ), |
190
|
|
|
'label_searchfield' => esc_html__( 'Search Field', 'gravityview' ), |
191
|
|
|
'label_inputtype' => esc_html__( 'Input Type', 'gravityview' ), |
192
|
|
|
'label_ajaxerror' => esc_html__( 'There was an error loading searchable fields. Save the View or refresh the page to fix this issue.', 'gravityview' ), |
193
|
|
|
'input_labels' => json_encode( $input_labels ), |
194
|
|
|
'input_types' => json_encode( $input_types ), |
195
|
|
|
) ); |
196
|
|
|
|
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Add admin script to the whitelist |
201
|
|
|
*/ |
202
|
|
|
public function register_no_conflict( $required ) { |
203
|
|
|
$required[] = 'gravityview_searchwidget_admin'; |
204
|
|
|
return $required; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* Ajax |
209
|
|
|
* Returns the form fields ( only the searchable ones ) |
210
|
|
|
* |
211
|
|
|
* @access public |
212
|
|
|
* @return void |
213
|
|
|
*/ |
214
|
|
|
public static function get_searchable_fields() { |
215
|
|
|
|
216
|
|
|
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'gravityview_ajaxsearchwidget' ) ) { |
|
|
|
|
217
|
|
|
exit( '0' ); |
|
|
|
|
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
$form = ''; |
221
|
|
|
|
222
|
|
|
// Fetch the form for the current View |
223
|
|
|
if ( ! empty( $_POST['view_id'] ) ) { |
224
|
|
|
|
225
|
|
|
$form = gravityview_get_form_id( $_POST['view_id'] ); |
|
|
|
|
226
|
|
|
|
227
|
|
|
} elseif ( ! empty( $_POST['formid'] ) ) { |
228
|
|
|
|
229
|
|
|
$form = (int) $_POST['formid']; |
|
|
|
|
230
|
|
|
|
231
|
|
|
} elseif ( ! empty( $_POST['template_id'] ) && class_exists( 'GravityView_Ajax' ) ) { |
232
|
|
|
|
233
|
|
|
$form = GravityView_Ajax::pre_get_form_fields( $_POST['template_id'] ); |
|
|
|
|
234
|
|
|
|
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
// fetch form id assigned to the view |
238
|
|
|
$response = self::render_searchable_fields( $form ); |
239
|
|
|
|
240
|
|
|
exit( $response ); |
|
|
|
|
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* Generates html for the available Search Fields dropdown |
245
|
|
|
* @param string $form_id |
246
|
|
|
* @param string $current (for future use) |
247
|
|
|
* @return string |
248
|
|
|
*/ |
249
|
|
|
public static function render_searchable_fields( $form_id = null, $current = '' ) { |
250
|
|
|
|
251
|
|
|
if ( is_null( $form_id ) ) { |
252
|
|
|
return ''; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
// Get fields with sub-inputs and no parent |
256
|
|
|
$fields = gravityview_get_form_fields( $form_id, true, true ); |
257
|
|
|
|
258
|
|
|
// start building output |
259
|
|
|
|
260
|
|
|
$output = '<select class="gv-search-fields">'; |
261
|
|
|
|
262
|
|
|
$custom_fields = array( |
263
|
|
|
'search_all' => array( |
264
|
|
|
'text' => esc_html__( 'Search Everything', 'gravityview' ), |
265
|
|
|
'type' => 'text', |
266
|
|
|
), |
267
|
|
|
'entry_date' => array( |
268
|
|
|
'text' => esc_html__( 'Entry Date', 'gravityview' ), |
269
|
|
|
'type' => 'date', |
270
|
|
|
), |
271
|
|
|
'entry_id' => array( |
272
|
|
|
'text' => esc_html__( 'Entry ID', 'gravityview' ), |
273
|
|
|
'type' => 'text', |
274
|
|
|
), |
275
|
|
|
'created_by' => array( |
276
|
|
|
'text' => esc_html__( 'Entry Creator', 'gravityview' ), |
277
|
|
|
'type' => 'select', |
278
|
|
|
) |
279
|
|
|
); |
280
|
|
|
|
281
|
|
|
foreach( $custom_fields as $custom_field_key => $custom_field ) { |
282
|
|
|
$output .= sprintf( '<option value="%s" %s data-inputtypes="%s" data-placeholder="%s">%s</option>', $custom_field_key, selected( $custom_field_key, $current, false ), $custom_field['type'], self::get_field_label( array('field' => $custom_field_key ) ), $custom_field['text'] ); |
|
|
|
|
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
if ( ! empty( $fields ) ) { |
286
|
|
|
|
287
|
|
|
$blacklist_field_types = apply_filters( 'gravityview_blacklist_field_types', array( 'fileupload', 'post_image', 'post_id', 'section' ), null ); |
288
|
|
|
|
289
|
|
|
foreach ( $fields as $id => $field ) { |
290
|
|
|
|
291
|
|
|
if ( in_array( $field['type'], $blacklist_field_types ) ) { |
292
|
|
|
continue; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
$types = self::get_search_input_types( $id, $field['type'] ); |
296
|
|
|
|
297
|
|
|
$output .= '<option value="'. $id .'" '. selected( $id, $current, false ).'data-inputtypes="'. esc_attr( $types ) .'">'. esc_html( $field['label'] ) .'</option>'; |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
$output .= '</select>'; |
302
|
|
|
|
303
|
|
|
return $output; |
304
|
|
|
|
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* Assign an input type according to the form field type |
309
|
|
|
* @see admin-search-widget.js |
310
|
|
|
* |
311
|
|
|
* @param int $id Gravity Forms field ID |
312
|
|
|
* @param string $field_type Gravity Forms field type (also the `name` parameter of GravityView_Field classes) |
313
|
|
|
* |
314
|
|
|
* @return string GV field search input type ('multi', 'boolean', 'select', 'date', 'text') |
315
|
|
|
*/ |
316
|
|
|
public static function get_search_input_types( $id = '', $field_type = null ) { |
317
|
|
|
|
318
|
|
|
// @todo - This needs to be improved - many fields have . including products and addresses |
319
|
|
|
if ( false !== strpos( (string) $id, '.' ) && in_array( $field_type, array( 'checkbox' ) ) || in_array( $id, array( 'is_fulfilled' ) ) ) { |
320
|
|
|
$input_type = 'boolean'; // on/off checkbox |
321
|
|
|
} elseif ( in_array( $field_type, array( 'checkbox', 'post_category', 'multiselect' ) ) ) { |
322
|
|
|
$input_type = 'multi'; //multiselect |
323
|
|
|
} elseif ( in_array( $field_type, array( 'select', 'radio' ) ) ) { |
324
|
|
|
$input_type = 'select'; |
325
|
|
|
} elseif ( in_array( $field_type, array( 'date' ) ) || in_array( $id, array( 'payment_date' ) ) ) { |
326
|
|
|
$input_type = 'date'; |
327
|
|
|
} elseif ( in_array( $field_type, array( 'number' ) ) || in_array( $id, array( 'payment_amount' ) ) ) { |
328
|
|
|
$input_type = 'number'; |
329
|
|
|
} else { |
330
|
|
|
$input_type = 'text'; |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
/** |
334
|
|
|
* @filter `gravityview/extension/search/input_type` Modify the search form input type based on field type |
335
|
|
|
* @since 1.2 |
336
|
|
|
* @param string $input_type Assign an input type according to the form field type. Defaults: `boolean`, `multi`, `select`, `date`, `text` |
337
|
|
|
* @param string $field_type Gravity Forms field type (also the `name` parameter of GravityView_Field classes) |
338
|
|
|
*/ |
339
|
|
|
$input_type = apply_filters( 'gravityview/extension/search/input_type', $input_type, $field_type ); |
340
|
|
|
|
341
|
|
|
return $input_type; |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Display hidden fields to add support for sites using Default permalink structure |
346
|
|
|
* |
347
|
|
|
* @since 1.8 |
348
|
|
|
* @return array Search fields, modified if not using permalinks |
349
|
|
|
*/ |
350
|
|
|
public function add_no_permalink_fields( $search_fields, $object, $widget_args = array() ) { |
351
|
|
|
/** @global WP_Rewrite $wp_rewrite */ |
352
|
|
|
global $wp_rewrite; |
|
|
|
|
353
|
|
|
|
354
|
|
|
// Support default permalink structure |
355
|
|
|
if ( false === $wp_rewrite->using_permalinks() ) { |
356
|
|
|
|
357
|
|
|
// By default, use current post. |
358
|
|
|
$post_id = 0; |
359
|
|
|
|
360
|
|
|
// We're in the WordPress Widget context, and an overriding post ID has been set. |
361
|
|
|
if ( ! empty( $widget_args['post_id'] ) ) { |
362
|
|
|
$post_id = absint( $widget_args['post_id'] ); |
363
|
|
|
} |
364
|
|
|
// We're in the WordPress Widget context, and the base View ID should be used |
365
|
|
|
else if ( ! empty( $widget_args['view_id'] ) ) { |
366
|
|
|
$post_id = absint( $widget_args['view_id'] ); |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
$args = gravityview_get_permalink_query_args( $post_id ); |
370
|
|
|
|
371
|
|
|
// Add hidden fields to the search form |
372
|
|
|
foreach ( $args as $key => $value ) { |
|
|
|
|
373
|
|
|
$search_fields[] = array( |
374
|
|
|
'name' => $key, |
375
|
|
|
'input' => 'hidden', |
376
|
|
|
'value' => $value, |
377
|
|
|
); |
378
|
|
|
} |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
return $search_fields; |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
|
385
|
|
|
/** --- Frontend --- */ |
386
|
|
|
|
387
|
|
|
/** |
388
|
|
|
* Calculate the search criteria to filter entries |
389
|
|
|
* @param array $search_criteria |
390
|
|
|
* @return array |
391
|
|
|
*/ |
392
|
|
|
public function filter_entries( $search_criteria ) { |
393
|
|
|
|
394
|
|
|
if( 'post' === $this->search_method ) { |
395
|
|
|
$get = $_POST; |
|
|
|
|
396
|
|
|
} else { |
397
|
|
|
$get = $_GET; |
|
|
|
|
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
do_action( 'gravityview_log_debug', sprintf( '%s[filter_entries] Requested $_%s: ', get_class( $this ), $this->search_method ), $get ); |
401
|
|
|
|
402
|
|
|
if ( empty( $get ) || ! is_array( $get ) ) { |
403
|
|
|
return $search_criteria; |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
$get = stripslashes_deep( $get ); |
407
|
|
|
|
408
|
|
|
$get = gv_map_deep( $get, 'urldecode' ); |
409
|
|
|
|
410
|
|
|
// add free search |
411
|
|
|
if ( ! empty( $get['gv_search'] ) ) { |
412
|
|
|
|
413
|
|
|
// Search for a piece |
414
|
|
|
$words = explode( ' ', $get['gv_search'] ); |
415
|
|
|
|
416
|
|
|
$words = array_filter( $words ); |
417
|
|
|
|
418
|
|
|
foreach ( $words as $word ) { |
419
|
|
|
$search_criteria['field_filters'][] = array( |
420
|
|
|
'key' => null, // The field ID to search |
421
|
|
|
'value' => $word, // The value to search |
422
|
|
|
'operator' => 'contains', // What to search in. Options: `is` or `contains` |
423
|
|
|
); |
424
|
|
|
} |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
//start date & end date |
428
|
|
|
$curr_start = !empty( $get['gv_start'] ) ? $get['gv_start'] : ''; |
|
|
|
|
429
|
|
|
$curr_end = !empty( $get['gv_start'] ) ? $get['gv_end'] : ''; |
|
|
|
|
430
|
|
|
|
431
|
|
|
/** |
432
|
|
|
* @filter `gravityview_date_created_adjust_timezone` Whether to adjust the timezone for entries. \n |
433
|
|
|
* date_created is stored in UTC format. Convert search date into UTC (also used on templates/fields/date_created.php) |
434
|
|
|
* @since 1.12 |
435
|
|
|
* @param[out,in] boolean $adjust_tz Use timezone-adjusted datetime? If true, adjusts date based on blog's timezone setting. If false, uses UTC setting. Default: true |
436
|
|
|
* @param[in] string $context Where the filter is being called from. `search` in this case. |
437
|
|
|
*/ |
438
|
|
|
$adjust_tz = apply_filters( 'gravityview_date_created_adjust_timezone', true, 'search' ); |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
441
|
|
|
/** |
442
|
|
|
* Don't set $search_criteria['start_date'] if start_date is empty as it may lead to bad query results (GFAPI::get_entries) |
443
|
|
|
*/ |
444
|
|
|
if( !empty( $curr_start ) ) { |
|
|
|
|
445
|
|
|
$search_criteria['start_date'] = $adjust_tz ? get_gmt_from_date( $curr_start ) : $curr_start; |
446
|
|
|
} |
447
|
|
|
if( !empty( $curr_end ) ) { |
|
|
|
|
448
|
|
|
$search_criteria['end_date'] = $adjust_tz ? get_gmt_from_date( $curr_end ) : $curr_end; |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
// search for a specific entry ID |
452
|
|
|
if ( ! empty( $get[ 'gv_id' ] ) ) { |
|
|
|
|
453
|
|
|
$search_criteria['field_filters'][] = array( |
454
|
|
|
'key' => 'id', |
455
|
|
|
'value' => absint( $get[ 'gv_id' ] ), |
|
|
|
|
456
|
|
|
'operator' => '=', |
457
|
|
|
); |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
// search for a specific Created_by ID |
461
|
|
|
if ( ! empty( $get[ 'gv_by' ] ) ) { |
|
|
|
|
462
|
|
|
$search_criteria['field_filters'][] = array( |
463
|
|
|
'key' => 'created_by', |
464
|
|
|
'value' => absint( $get['gv_by'] ), |
465
|
|
|
'operator' => '=', |
466
|
|
|
); |
467
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
470
|
|
|
// Get search mode passed in URL |
471
|
|
|
$mode = isset( $get['mode'] ) && in_array( $get['mode'], array( 'any', 'all' ) ) ? $get['mode'] : 'any'; |
472
|
|
|
|
473
|
|
|
// get the other search filters |
474
|
|
|
foreach ( $get as $key => $value ) { |
475
|
|
|
|
476
|
|
|
if ( 0 !== strpos( $key, 'filter_' ) || empty( $value ) || ( is_array( $value ) && count( $value ) === 1 && empty( $value[0] ) ) ) { |
|
|
|
|
477
|
|
|
continue; |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
// could return simple filter or multiple filters |
481
|
|
|
$filter = $this->prepare_field_filter( $key, $value ); |
482
|
|
|
|
483
|
|
|
if ( isset( $filter[0]['value'] ) ) { |
484
|
|
|
$search_criteria['field_filters'] = array_merge( $search_criteria['field_filters'], $filter ); |
485
|
|
|
|
486
|
|
|
// if date range type, set search mode to ALL |
487
|
|
|
if ( ! empty( $filter[0]['operator'] ) && in_array( $filter[0]['operator'], array( '>=', '<=', '>', '<' ) ) ) { |
488
|
|
|
$mode = 'all'; |
489
|
|
|
} |
490
|
|
|
} elseif( !empty( $filter ) ) { |
|
|
|
|
491
|
|
|
$search_criteria['field_filters'][] = $filter; |
492
|
|
|
} |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
/** |
496
|
|
|
* @filter `gravityview/search/mode` Set the Search Mode (`all` or `any`) |
497
|
|
|
* @since 1.5.1 |
498
|
|
|
* @param[out,in] string $mode Search mode (`any` vs `all`) |
499
|
|
|
*/ |
500
|
|
|
$search_criteria['field_filters']['mode'] = apply_filters( 'gravityview/search/mode', $mode ); |
501
|
|
|
|
502
|
|
|
do_action( 'gravityview_log_debug', sprintf( '%s[filter_entries] Returned Search Criteria: ', get_class( $this ) ), $search_criteria ); |
503
|
|
|
|
504
|
|
|
unset( $get ); |
505
|
|
|
|
506
|
|
|
return $search_criteria; |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
/** |
510
|
|
|
* Prepare the field filters to GFAPI |
511
|
|
|
* |
512
|
|
|
* The type post_category, multiselect and checkbox support multi-select search - each value needs to be separated in an independent filter so we could apply the ANY search mode. |
513
|
|
|
* |
514
|
|
|
* Format searched values |
515
|
|
|
* @param string $key $_GET/$_POST search key |
516
|
|
|
* @param string $value $_GET/$_POST search value |
517
|
|
|
* @return array 1 or 2 deph levels |
518
|
|
|
*/ |
519
|
|
|
public function prepare_field_filter( $key, $value ) { |
520
|
|
|
|
521
|
|
|
$gravityview_view = GravityView_View::getInstance(); |
522
|
|
|
|
523
|
|
|
// calculates field_id, removing 'filter_' and for '_' for advanced fields ( like name or checkbox ) |
524
|
|
|
$field_id = str_replace( '_', '.', str_replace( 'filter_', '', $key ) ); |
525
|
|
|
|
526
|
|
|
// get form field array |
527
|
|
|
$form = $gravityview_view->getForm(); |
528
|
|
|
$form_field = gravityview_get_field( $form, $field_id ); |
529
|
|
|
|
530
|
|
|
$value = gv_map_deep( $value, '_wp_specialchars' ); // Gravity Forms encodes ampersands but not quotes |
531
|
|
|
|
532
|
|
|
// default filter array |
533
|
|
|
$filter = array( |
534
|
|
|
'key' => $field_id, |
535
|
|
|
'value' => $value, |
536
|
|
|
); |
537
|
|
|
|
538
|
|
|
switch ( $form_field['type'] ) { |
539
|
|
|
|
540
|
|
|
case 'select': |
541
|
|
|
case 'radio': |
542
|
|
|
$filter['operator'] = 'is'; |
543
|
|
|
break; |
544
|
|
|
|
545
|
|
|
case 'post_category': |
546
|
|
|
|
547
|
|
|
if ( ! is_array( $value ) ) { |
548
|
|
|
$value = array( $value ); |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
// Reset filter variable |
552
|
|
|
$filter = array(); |
553
|
|
|
|
554
|
|
|
foreach ( $value as $val ) { |
555
|
|
|
$cat = get_term( $val, 'category' ); |
556
|
|
|
$filter[] = array( |
557
|
|
|
'key' => $field_id, |
558
|
|
|
'value' => esc_attr( $cat->name ) . ':' . $val, |
559
|
|
|
'operator' => 'is', |
560
|
|
|
); |
561
|
|
|
} |
562
|
|
|
|
563
|
|
|
break; |
564
|
|
|
|
565
|
|
|
case 'multiselect': |
566
|
|
|
|
567
|
|
|
if ( ! is_array( $value ) ) { |
568
|
|
|
break; |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
// Reset filter variable |
572
|
|
|
$filter = array(); |
573
|
|
|
|
574
|
|
|
foreach ( $value as $val ) { |
575
|
|
|
$filter[] = array( 'key' => $field_id, 'value' => $val ); |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
break; |
579
|
|
|
|
580
|
|
|
case 'checkbox': |
581
|
|
|
// convert checkbox on/off into the correct search filter |
582
|
|
|
if ( false !== strpos( $field_id, '.' ) && ! empty( $form_field['inputs'] ) && ! empty( $form_field['choices'] ) ) { |
583
|
|
|
foreach ( $form_field['inputs'] as $k => $input ) { |
584
|
|
|
if ( $input['id'] == $field_id ) { |
585
|
|
|
$filter['value'] = $form_field['choices'][ $k ]['value']; |
586
|
|
|
$filter['operator'] = 'is'; |
587
|
|
|
break; |
588
|
|
|
} |
589
|
|
|
} |
590
|
|
|
} elseif ( is_array( $value ) ) { |
591
|
|
|
|
592
|
|
|
// Reset filter variable |
593
|
|
|
$filter = array(); |
594
|
|
|
|
595
|
|
|
foreach ( $value as $val ) { |
596
|
|
|
$filter[] = array( |
597
|
|
|
'key' => $field_id, |
598
|
|
|
'value' => $val, |
599
|
|
|
'operator' => 'is', |
600
|
|
|
); |
601
|
|
|
} |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
break; |
605
|
|
|
|
606
|
|
|
case 'name': |
607
|
|
|
case 'address': |
608
|
|
|
|
609
|
|
|
if ( false === strpos( $field_id, '.' ) ) { |
610
|
|
|
|
611
|
|
|
$words = explode( ' ', $value ); |
612
|
|
|
|
613
|
|
|
$filters = array(); |
614
|
|
|
foreach ( $words as $word ) { |
615
|
|
|
if ( ! empty( $word ) && strlen( $word ) > 1 ) { |
616
|
|
|
// Keep the same key for each filter |
617
|
|
|
$filter['value'] = $word; |
618
|
|
|
// Add a search for the value |
619
|
|
|
$filters[] = $filter; |
620
|
|
|
} |
621
|
|
|
} |
622
|
|
|
|
623
|
|
|
$filter = $filters; |
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
break; |
627
|
|
|
|
628
|
|
|
case 'date': |
629
|
|
|
|
630
|
|
|
if ( is_array( $value ) ) { |
631
|
|
|
|
632
|
|
|
// Reset filter variable |
633
|
|
|
$filter = array(); |
634
|
|
|
|
635
|
|
|
foreach ( $value as $k => $date ) { |
636
|
|
|
if ( empty( $date ) ) { |
637
|
|
|
continue; |
638
|
|
|
} |
639
|
|
|
$operator = 'start' === $k ? '>=' : '<='; |
640
|
|
|
|
641
|
|
|
/** |
642
|
|
|
* @hack |
643
|
|
|
* @since 1.16.3 |
644
|
|
|
* Safeguard until GF implements '<=' operator |
645
|
|
|
*/ |
646
|
|
|
if( !GFFormsModel::is_valid_operator( $operator ) && $operator === '<=' ) { |
|
|
|
|
647
|
|
|
$operator = '<'; |
648
|
|
|
$date = date( 'Y-m-d', strtotime( $date . ' +1 day' ) ); |
649
|
|
|
} |
650
|
|
|
|
651
|
|
|
$filter[] = array( |
652
|
|
|
'key' => $field_id, |
653
|
|
|
'value' => self::get_formatted_date( $date, 'Y-m-d' ), |
654
|
|
|
'operator' => $operator, |
655
|
|
|
); |
656
|
|
|
} |
657
|
|
|
} else { |
658
|
|
|
$filter['value'] = self::get_formatted_date( $value, 'Y-m-d' ); |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
break; |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
664
|
|
|
} // switch field type |
665
|
|
|
|
666
|
|
|
return $filter; |
667
|
|
|
} |
668
|
|
|
|
669
|
|
|
/** |
670
|
|
|
* Get the Field Format form GravityForms |
671
|
|
|
* |
672
|
|
|
* @param GF_Field_Date $field The field object |
673
|
|
|
* @since 1.10 |
674
|
|
|
* |
675
|
|
|
* @return string Format of the date in the database |
676
|
|
|
*/ |
677
|
|
|
public static function get_date_field_format( GF_Field_Date $field ) { |
678
|
|
|
$format = 'm/d/Y'; |
679
|
|
|
$datepicker = array( |
680
|
|
|
'mdy' => 'm/d/Y', |
681
|
|
|
'dmy' => 'd/m/Y', |
682
|
|
|
'dmy_dash' => 'd-m-Y', |
683
|
|
|
'dmy_dot' => 'm.d.Y', |
684
|
|
|
'ymd_slash' => 'Y/m/d', |
685
|
|
|
'ymd_dash' => 'Y-m-d', |
686
|
|
|
'ymd_dot' => 'Y.m.d', |
687
|
|
|
); |
688
|
|
|
|
689
|
|
|
if ( ! empty( $field->dateFormat ) && isset( $datepicker[ $field->dateFormat ] ) ){ |
690
|
|
|
$format = $datepicker[ $field->dateFormat ]; |
691
|
|
|
} |
692
|
|
|
|
693
|
|
|
return $format; |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
/** |
697
|
|
|
* Format a date value |
698
|
|
|
* |
699
|
|
|
* @param string $value Date value input |
700
|
|
|
* @param string $format Wanted formatted date |
701
|
|
|
* @return string |
702
|
|
|
*/ |
703
|
|
|
public static function get_formatted_date( $value = '', $format = 'Y-m-d' ) { |
704
|
|
|
$date = date_create( $value ); |
705
|
|
|
if ( empty( $date ) ) { |
706
|
|
|
do_action( 'gravityview_log_debug', sprintf( '%s[get_formatted_date] Date format not valid: ', get_class( self::$instance ) ), $value ); |
707
|
|
|
return ''; |
708
|
|
|
} |
709
|
|
|
return $date->format( $format ); |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
|
713
|
|
|
/** |
714
|
|
|
* Include this extension templates path |
715
|
|
|
* @param array $file_paths List of template paths ordered |
716
|
|
|
*/ |
717
|
|
|
public function add_template_path( $file_paths ) { |
718
|
|
|
|
719
|
|
|
// Index 100 is the default GravityView template path. |
720
|
|
|
$file_paths[102] = self::$file . 'templates/'; |
721
|
|
|
|
722
|
|
|
return $file_paths; |
723
|
|
|
} |
724
|
|
|
|
725
|
|
|
/** |
726
|
|
|
* Renders the Search Widget |
727
|
|
|
* @param type $widget_args |
728
|
|
|
* @param type $content |
729
|
|
|
* @param type $context |
730
|
|
|
* @return type |
731
|
|
|
*/ |
732
|
|
|
public function render_frontend( $widget_args, $content = '', $context = '' ) { |
733
|
|
|
/** @var GravityView_View $gravityview_view */ |
734
|
|
|
$gravityview_view = GravityView_View::getInstance(); |
735
|
|
|
|
736
|
|
|
if ( empty( $gravityview_view ) ) { |
737
|
|
|
do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend]: $gravityview_view not instantiated yet.', get_class( $this ) ) ); |
738
|
|
|
return; |
739
|
|
|
} |
740
|
|
|
|
741
|
|
|
// get configured search fields |
742
|
|
|
$search_fields = ! empty( $widget_args['search_fields'] ) ? json_decode( $widget_args['search_fields'], true ) : ''; |
743
|
|
|
|
744
|
|
|
if ( empty( $search_fields ) || ! is_array( $search_fields ) ) { |
745
|
|
|
do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend] No search fields configured for widget:', get_class( $this ) ), $widget_args ); |
746
|
|
|
return; |
747
|
|
|
} |
748
|
|
|
|
749
|
|
|
$has_date = false; |
750
|
|
|
|
751
|
|
|
// prepare fields |
752
|
|
|
foreach ( $search_fields as $k => $field ) { |
753
|
|
|
|
754
|
|
|
$updated_field = $field; |
755
|
|
|
|
756
|
|
|
if ( in_array( $field['input'], array( 'date', 'date_range' ) ) ) { |
757
|
|
|
$has_date = true; |
758
|
|
|
} |
759
|
|
|
|
760
|
|
|
$updated_field = $this->get_search_filter_details( $updated_field ); |
761
|
|
|
|
762
|
|
|
switch ( $field['field'] ) { |
763
|
|
|
|
764
|
|
|
case 'search_all': |
765
|
|
|
$updated_field['key'] = 'search_all'; |
766
|
|
|
$updated_field['input'] = 'search_all'; |
767
|
|
|
$updated_field['value'] = $this->rgget_or_rgpost( 'gv_search' ); |
768
|
|
|
break; |
769
|
|
|
|
770
|
|
|
case 'entry_date': |
771
|
|
|
$updated_field['key'] = 'entry_date'; |
772
|
|
|
$updated_field['input'] = 'entry_date'; |
773
|
|
|
$updated_field['value'] = array( |
774
|
|
|
'start' => $this->rgget_or_rgpost( 'gv_start' ), |
775
|
|
|
'end' => $this->rgget_or_rgpost( 'gv_end' ), |
776
|
|
|
); |
777
|
|
|
$has_date = true; |
778
|
|
|
break; |
779
|
|
|
|
780
|
|
|
case 'entry_id': |
781
|
|
|
$updated_field['key'] = 'entry_id'; |
782
|
|
|
$updated_field['input'] = 'entry_id'; |
783
|
|
|
$updated_field['value'] = $this->rgget_or_rgpost( 'gv_id' ); |
784
|
|
|
break; |
785
|
|
|
|
786
|
|
|
case 'created_by': |
787
|
|
|
$updated_field['key'] = 'created_by'; |
788
|
|
|
$updated_field['name'] = 'gv_by'; |
789
|
|
|
$updated_field['value'] = $this->rgget_or_rgpost( 'gv_by' ); |
790
|
|
|
$updated_field['choices'] = self::get_created_by_choices(); |
791
|
|
|
break; |
792
|
|
|
} |
793
|
|
|
|
794
|
|
|
$search_fields[ $k ] = $updated_field; |
795
|
|
|
} |
796
|
|
|
|
797
|
|
|
do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend] Calculated Search Fields: ', get_class( $this ) ), $search_fields ); |
798
|
|
|
|
799
|
|
|
/** |
800
|
|
|
* @filter `gravityview_widget_search_filters` Modify what fields are shown. The order of the fields in the $search_filters array controls the order as displayed in the search bar widget. |
801
|
|
|
* @param array $search_fields Array of search filters with `key`, `label`, `value`, `type` keys |
802
|
|
|
* @param GravityView_Widget_Search $this Current widget object |
803
|
|
|
* @param array $widget_args Args passed to this method. {@since 1.8} |
804
|
|
|
* @var array |
805
|
|
|
*/ |
806
|
|
|
$gravityview_view->search_fields = apply_filters( 'gravityview_widget_search_filters', $search_fields, $this, $widget_args ); |
807
|
|
|
|
808
|
|
|
$gravityview_view->search_layout = ! empty( $widget_args['search_layout'] ) ? $widget_args['search_layout'] : 'horizontal'; |
809
|
|
|
|
810
|
|
|
/** @since 1.14 */ |
811
|
|
|
$gravityview_view->search_mode = ! empty( $widget_args['search_mode'] ) ? $widget_args['search_mode'] : 'any'; |
812
|
|
|
|
813
|
|
|
$custom_class = ! empty( $widget_args['custom_class'] ) ? $widget_args['custom_class'] : ''; |
814
|
|
|
|
815
|
|
|
$gravityview_view->search_class = self::get_search_class( $custom_class ); |
816
|
|
|
|
817
|
|
|
$gravityview_view->search_clear = ! empty( $widget_args['search_clear'] ) ? $widget_args['search_clear'] : false; |
818
|
|
|
|
819
|
|
|
if ( $has_date ) { |
820
|
|
|
// enqueue datepicker stuff only if needed! |
821
|
|
|
$this->enqueue_datepicker(); |
822
|
|
|
} |
823
|
|
|
|
824
|
|
|
$gravityview_view->render( 'widget', 'search', false ); |
825
|
|
|
} |
826
|
|
|
|
827
|
|
|
/** |
828
|
|
|
* Get the search class for a search form |
829
|
|
|
* |
830
|
|
|
* @since 1.5.4 |
831
|
|
|
* |
832
|
|
|
* @return string Sanitized CSS class for the search form |
833
|
|
|
*/ |
834
|
|
|
public static function get_search_class( $custom_class = '' ) { |
835
|
|
|
$gravityview_view = GravityView_View::getInstance(); |
836
|
|
|
|
837
|
|
|
$search_class = 'gv-search-'.$gravityview_view->search_layout; |
838
|
|
|
|
839
|
|
|
if ( ! empty( $custom_class ) ) { |
840
|
|
|
$search_class .= ' '.$custom_class; |
841
|
|
|
} |
842
|
|
|
|
843
|
|
|
/** |
844
|
|
|
* Modify the CSS class for the search form |
845
|
|
|
* |
846
|
|
|
* @param string $search_class The CSS class for the search form |
847
|
|
|
*/ |
848
|
|
|
$search_class = apply_filters( 'gravityview_search_class', $search_class ); |
849
|
|
|
|
850
|
|
|
// Is there an active search being performed? Used by fe-views.js |
851
|
|
|
$search_class .= GravityView_frontend::getInstance()->isSearch() ? ' gv-is-search' : ''; |
852
|
|
|
|
853
|
|
|
return gravityview_sanitize_html_class( $search_class ); |
854
|
|
|
} |
855
|
|
|
|
856
|
|
|
|
857
|
|
|
/** |
858
|
|
|
* Calculate the search form action |
859
|
|
|
* @since 1.6 |
860
|
|
|
* |
861
|
|
|
* @return string |
862
|
|
|
*/ |
863
|
|
|
public static function get_search_form_action() { |
864
|
|
|
$gravityview_view = GravityView_View::getInstance(); |
865
|
|
|
|
866
|
|
|
$post_id = $gravityview_view->getPostId() ? $gravityview_view->getPostId() : $gravityview_view->getViewId(); |
867
|
|
|
|
868
|
|
|
$url = add_query_arg( array(), get_permalink( $post_id ) ); |
869
|
|
|
|
870
|
|
|
return esc_url( $url ); |
871
|
|
|
} |
872
|
|
|
|
873
|
|
|
/** |
874
|
|
|
* Get the label for a search form field |
875
|
|
|
* @param array $field Field setting as sent by the GV configuration - has `field`, `input` (input type), and `label` keys |
876
|
|
|
* @param array $form_field Form field data, as fetched by `gravityview_get_field()` |
877
|
|
|
* @return string Label for the search form |
878
|
|
|
*/ |
879
|
|
|
private static function get_field_label( $field, $form_field = array() ) { |
880
|
|
|
|
881
|
|
|
$label = rgget( 'label', $field ); |
882
|
|
|
|
883
|
|
|
if( '' === $label ) { |
884
|
|
|
|
885
|
|
|
$label = isset( $form_field['label'] ) ? $form_field['label'] : ''; |
886
|
|
|
|
887
|
|
|
switch( $field['field'] ) { |
888
|
|
|
case 'search_all': |
889
|
|
|
$label = __( 'Search Entries:', 'gravityview' ); |
890
|
|
|
break; |
891
|
|
|
case 'entry_date': |
892
|
|
|
$label = __( 'Filter by date:', 'gravityview' ); |
893
|
|
|
break; |
894
|
|
|
case 'entry_id': |
895
|
|
|
$label = __( 'Entry ID:', 'gravityview' ); |
896
|
|
|
break; |
897
|
|
|
case 'created_by': |
898
|
|
|
$label = __( 'Submitted by:', 'gravityview' ); |
899
|
|
|
break; |
900
|
|
|
case 'is_fulfilled': |
901
|
|
|
$label = __( 'Is Fulfilled', 'gravityview' ); |
902
|
|
|
break; |
903
|
|
|
default: |
904
|
|
|
// If this is a field input, not a field |
905
|
|
|
if ( strpos( $field['field'], '.' ) > 0 && ! empty( $form_field['inputs'] ) ) { |
906
|
|
|
|
907
|
|
|
// Get the label for the field in question, which returns an array |
908
|
|
|
$items = wp_list_filter( $form_field['inputs'], array( 'id' => $field['field'] ) ); |
909
|
|
|
|
910
|
|
|
// Get the item with the `label` key |
911
|
|
|
$values = wp_list_pluck( $items, 'label' ); |
912
|
|
|
|
913
|
|
|
// There will only one item in the array, but this is easier |
914
|
|
|
foreach ( $values as $value ) { |
915
|
|
|
$label = $value; |
916
|
|
|
break; |
917
|
|
|
} |
918
|
|
|
} |
919
|
|
|
} |
920
|
|
|
} |
921
|
|
|
|
922
|
|
|
/** |
923
|
|
|
* @filter `gravityview_search_field_label` Modify the label for a search field. Supports returning HTML |
924
|
|
|
* @param[in,out] string $label Existing label text, sanitized. |
925
|
|
|
* @param[in] array $form_field Gravity Forms field array, as returned by `GFFormsModel::get_field()` |
926
|
|
|
*/ |
927
|
|
|
$label = apply_filters( 'gravityview_search_field_label', esc_attr( $label ), $form_field ); |
928
|
|
|
|
929
|
|
|
return $label; |
930
|
|
|
} |
931
|
|
|
|
932
|
|
|
/** |
933
|
|
|
* Prepare search fields to frontend render with other details (label, field type, searched values) |
934
|
|
|
* |
935
|
|
|
* @param array $field |
936
|
|
|
* @return array |
937
|
|
|
*/ |
938
|
|
|
private function get_search_filter_details( $field ) { |
939
|
|
|
|
940
|
|
|
$gravityview_view = GravityView_View::getInstance(); |
941
|
|
|
|
942
|
|
|
$form = $gravityview_view->getForm(); |
943
|
|
|
|
944
|
|
|
// for advanced field ids (eg, first name / last name ) |
945
|
|
|
$name = 'filter_' . str_replace( '.', '_', $field['field'] ); |
946
|
|
|
|
947
|
|
|
// get searched value from $_GET/$_POST (string or array) |
948
|
|
|
$value = $this->rgget_or_rgpost( $name ); |
949
|
|
|
|
950
|
|
|
// get form field details |
951
|
|
|
$form_field = gravityview_get_field( $form, $field['field'] ); |
952
|
|
|
|
953
|
|
|
$filter = array( |
954
|
|
|
'key' => $field['field'], |
955
|
|
|
'name' => $name, |
956
|
|
|
'label' => self::get_field_label( $field, $form_field ), |
957
|
|
|
'input' => $field['input'], |
958
|
|
|
'value' => $value, |
959
|
|
|
'type' => $form_field['type'], |
960
|
|
|
); |
961
|
|
|
|
962
|
|
|
// collect choices |
963
|
|
|
if ( 'post_category' === $form_field['type'] && ! empty( $form_field['displayAllCategories'] ) && empty( $form_field['choices'] ) ) { |
964
|
|
|
$filter['choices'] = gravityview_get_terms_choices(); |
965
|
|
|
} elseif ( ! empty( $form_field['choices'] ) ) { |
966
|
|
|
$filter['choices'] = $form_field['choices']; |
967
|
|
|
} |
968
|
|
|
|
969
|
|
|
if ( 'date_range' === $field['input'] && empty( $value ) ) { |
970
|
|
|
$filter['value'] = array( 'start' => '', 'end' => '' ); |
971
|
|
|
} |
972
|
|
|
|
973
|
|
|
return $filter; |
974
|
|
|
|
975
|
|
|
} |
976
|
|
|
|
977
|
|
|
/** |
978
|
|
|
* Calculate the search choices for the users |
979
|
|
|
* |
980
|
|
|
* @since 1.8 |
981
|
|
|
* |
982
|
|
|
* @return array Array of user choices (value = ID, text = display name) |
983
|
|
|
*/ |
984
|
|
|
private static function get_created_by_choices() { |
985
|
|
|
|
986
|
|
|
/** |
987
|
|
|
* filter gravityview/get_users/search_widget |
988
|
|
|
* @see \GVCommon::get_users |
989
|
|
|
*/ |
990
|
|
|
$users = GVCommon::get_users( 'search_widget', array( 'fields' => array( 'ID', 'display_name' ) ) ); |
991
|
|
|
|
992
|
|
|
$choices = array(); |
993
|
|
|
foreach ( $users as $user ) { |
994
|
|
|
$choices[] = array( |
995
|
|
|
'value' => $user->ID, |
996
|
|
|
'text' => $user->display_name, |
997
|
|
|
); |
998
|
|
|
} |
999
|
|
|
|
1000
|
|
|
return $choices; |
1001
|
|
|
} |
1002
|
|
|
|
1003
|
|
|
|
1004
|
|
|
/** |
1005
|
|
|
* Output the Clear Search Results button |
1006
|
|
|
* @since 1.5.4 |
1007
|
|
|
*/ |
1008
|
|
|
public static function the_clear_search_button() { |
1009
|
|
|
$gravityview_view = GravityView_View::getInstance(); |
1010
|
|
|
|
1011
|
|
|
if ( $gravityview_view->search_clear ) { |
1012
|
|
|
|
1013
|
|
|
$url = strtok( add_query_arg( array() ), '?' ); |
1014
|
|
|
|
1015
|
|
|
echo gravityview_get_link( $url, esc_html__( 'Clear', 'gravityview' ), 'class=button gv-search-clear' ); |
|
|
|
|
1016
|
|
|
|
1017
|
|
|
} |
1018
|
|
|
} |
1019
|
|
|
|
1020
|
|
|
/** |
1021
|
|
|
* Based on the search method, fetch the value for a specific key |
1022
|
|
|
* |
1023
|
|
|
* @since 1.16.4 |
1024
|
|
|
* |
1025
|
|
|
* @param string $name Name of the request key to fetch the value for |
1026
|
|
|
* |
1027
|
|
|
* @return mixed|string Value of request at $name key. Empty string if empty. |
1028
|
|
|
*/ |
1029
|
|
|
private function rgget_or_rgpost( $name ) { |
1030
|
|
|
$value = 'get' === $this->search_method ? rgget( $name ) : rgpost( $name ); |
1031
|
|
|
|
1032
|
|
|
$value = stripslashes_deep( $value ); |
1033
|
|
|
|
1034
|
|
|
$value = gv_map_deep( $value, 'urldecode' ); |
1035
|
|
|
|
1036
|
|
|
$value = gv_map_deep( $value, '_wp_specialchars' ); |
1037
|
|
|
|
1038
|
|
|
return $value; |
1039
|
|
|
} |
1040
|
|
|
|
1041
|
|
|
|
1042
|
|
|
/** |
1043
|
|
|
* Require the datepicker script for the frontend GV script |
1044
|
|
|
* @param array $js_dependencies Array of existing required scripts for the fe-views.js script |
1045
|
|
|
*/ |
1046
|
|
|
public function add_datepicker_js_dependency( $js_dependencies ) { |
1047
|
|
|
|
1048
|
|
|
$js_dependencies[] = 'jquery-ui-datepicker'; |
1049
|
|
|
|
1050
|
|
|
return $js_dependencies; |
1051
|
|
|
} |
1052
|
|
|
|
1053
|
|
|
/** |
1054
|
|
|
* Modify the array passed to wp_localize_script() |
1055
|
|
|
* |
1056
|
|
|
* @param array $js_localization The data padded to the Javascript file |
|
|
|
|
1057
|
|
|
* @param array $view_data View data array with View settings |
1058
|
|
|
* |
1059
|
|
|
* @return array |
1060
|
|
|
*/ |
1061
|
|
|
public function add_datepicker_localization( $localizations = array(), $view_data = array() ) { |
1062
|
|
|
global $wp_locale; |
|
|
|
|
1063
|
|
|
|
1064
|
|
|
/** |
1065
|
|
|
* @filter `gravityview_datepicker_settings` Modify the datepicker settings |
1066
|
|
|
* @see http://api.jqueryui.com/datepicker/ Learn what settings are available |
1067
|
|
|
* @see http://www.renegadetechconsulting.com/tutorials/jquery-datepicker-and-wordpress-i18n Thanks for the helpful information on $wp_locale |
1068
|
|
|
* @param array $js_localization The data padded to the Javascript file |
1069
|
|
|
* @param array $view_data View data array with View settings |
1070
|
|
|
*/ |
1071
|
|
|
$datepicker_settings = apply_filters( 'gravityview_datepicker_settings', array( |
1072
|
|
|
'yearRange' => '-5:+5', |
1073
|
|
|
'changeMonth' => true, |
1074
|
|
|
'changeYear' => true, |
1075
|
|
|
'closeText' => esc_attr_x( 'Close', 'Close calendar', 'gravityview' ), |
1076
|
|
|
'prevText' => esc_attr_x( 'Prev', 'Previous month in calendar', 'gravityview' ), |
1077
|
|
|
'nextText' => esc_attr_x( 'Next', 'Next month in calendar', 'gravityview' ), |
1078
|
|
|
'currentText' => esc_attr_x( 'Today', 'Today in calendar', 'gravityview' ), |
1079
|
|
|
'weekHeader' => esc_attr_x( 'Week', 'Week in calendar', 'gravityview' ), |
1080
|
|
|
'monthStatus' => __( 'Show a different month', 'gravityview' ), |
1081
|
|
|
'monthNames' => array_values( $wp_locale->month ), |
1082
|
|
|
'monthNamesShort' => array_values( $wp_locale->month_abbrev ), |
1083
|
|
|
'dayNames' => array_values( $wp_locale->weekday ), |
1084
|
|
|
'dayNamesShort' => array_values( $wp_locale->weekday_abbrev ), |
1085
|
|
|
'dayNamesMin' => array_values( $wp_locale->weekday_initial ), |
1086
|
|
|
// get the start of week from WP general setting |
1087
|
|
|
'firstDay' => get_option( 'start_of_week' ), |
1088
|
|
|
// is Right to left language? default is false |
1089
|
|
|
'isRTL' => is_rtl(), |
1090
|
|
|
), $view_data ); |
1091
|
|
|
|
1092
|
|
|
$localizations['datepicker'] = $datepicker_settings; |
1093
|
|
|
|
1094
|
|
|
return $localizations; |
1095
|
|
|
|
1096
|
|
|
} |
1097
|
|
|
|
1098
|
|
|
/** |
1099
|
|
|
* Enqueue the datepicker script |
1100
|
|
|
* |
1101
|
|
|
* It sets the $gravityview->datepicker_class parameter |
1102
|
|
|
* |
1103
|
|
|
* @todo Use own datepicker javascript instead of GF datepicker.js - that way, we can localize the settings and not require the changeMonth and changeYear pickers. |
1104
|
|
|
* @return void |
1105
|
|
|
*/ |
1106
|
|
|
public function enqueue_datepicker() { |
1107
|
|
|
$gravityview_view = GravityView_View::getInstance(); |
1108
|
|
|
|
1109
|
|
|
wp_enqueue_script( 'jquery-ui-datepicker' ); |
1110
|
|
|
|
1111
|
|
|
add_filter( 'gravityview_js_dependencies', array( $this, 'add_datepicker_js_dependency' ) ); |
1112
|
|
|
add_filter( 'gravityview_js_localization', array( $this, 'add_datepicker_localization' ), 10, 2 ); |
1113
|
|
|
|
1114
|
|
|
$scheme = is_ssl() ? 'https://' : 'http://'; |
1115
|
|
|
wp_enqueue_style( 'jquery-ui-datepicker', $scheme.'ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/smoothness/jquery-ui.css' ); |
1116
|
|
|
|
1117
|
|
|
/** |
1118
|
|
|
* @filter `gravityview_search_datepicker_class` |
1119
|
|
|
* Modify the CSS class for the datepicker, used by the CSS class is used by Gravity Forms' javascript to determine the format for the date picker. The `gv-datepicker` class is required by the GravityView datepicker javascript. |
1120
|
|
|
* @param string $css_class CSS class to use. Default: `gv-datepicker datepicker mdy` \n |
1121
|
|
|
* Options are: |
1122
|
|
|
* - `mdy` (mm/dd/yyyy) |
1123
|
|
|
* - `dmy` (dd/mm/yyyy) |
1124
|
|
|
* - `dmy_dash` (dd-mm-yyyy) |
1125
|
|
|
* - `dmy_dot` (dd.mm.yyyy) |
1126
|
|
|
* - `ymp_slash` (yyyy/mm/dd) |
1127
|
|
|
* - `ymd_dash` (yyyy-mm-dd) |
1128
|
|
|
* - `ymp_dot` (yyyy.mm.dd) |
1129
|
|
|
*/ |
1130
|
|
|
$datepicker_class = apply_filters( 'gravityview_search_datepicker_class', 'gv-datepicker datepicker mdy' ); |
1131
|
|
|
|
1132
|
|
|
$gravityview_view->datepicker_class = $datepicker_class; |
1133
|
|
|
|
1134
|
|
|
} |
1135
|
|
|
|
1136
|
|
|
|
1137
|
|
|
} // end class |
1138
|
|
|
|
1139
|
|
|
new GravityView_Widget_Search; |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.