Completed
Push — master ( 2cfa6f...8927a4 )
by Zack
10:00 queued 06:05
created

GravityView_Widget_Search::get_formatted_date()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 2
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 16 and the first side effect is on line 13.

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.

Loading history...
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();
0 ignored issues
show
Unused Code introduced by
The property $search_filters is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
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'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
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_action( 'wp_enqueue_scripts', array( $this, 'register_scripts') );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
89
		add_filter( 'gravityview_noconflict_scripts', array( $this, 'register_no_conflict' ) );
90
91
		// ajax - get the searchable fields
92
		add_action( 'wp_ajax_gv_searchable_fields', array( 'GravityView_Widget_Search', 'get_searchable_fields' ) );
93
94
		// calculate the search method (POST / GET)
95
		$this->set_search_method();
96
97
	}
98
99
	/**
100
	 * @return GravityView_Widget_Search
101
	 */
102
	public static function getInstance() {
0 ignored issues
show
Coding Style introduced by
The function name getInstance is in camel caps, but expected get_instance instead as per the coding standard.
Loading history...
103
		if ( empty( self::$instance ) ) {
104
			self::$instance = new GravityView_Widget_Search;
105
		}
106
		return self::$instance;
107
	}
108
109
	/**
110
	 * Sets the search method to GET (default) or POST
111
	 * @since 1.16.4
112
	 */
113
	private function set_search_method() {
114
		/**
115
		 * @filter `gravityview/search/method` Modify the search form method (GET / POST)
116
		 * @since 1.16.4
117
		 * @param string $search_method Assign an input type according to the form field type. Defaults: `boolean`, `multi`, `select`, `date`, `text`
118
		 * @param string $field_type Gravity Forms field type (also the `name` parameter of GravityView_Field classes)
119
		 */
120
		$method = apply_filters( 'gravityview/search/method', $this->search_method );
121
122
		$method = strtolower( $method );
123
124
		$this->search_method = in_array( $method, array( 'get', 'post' ) ) ? $method : 'get';
125
	}
126
127
	/**
128
	 * Returns the search method
129
	 * @since 1.16.4
130
	 * @return string
131
	 */
132
	public function get_search_method() {
133
		return $this->search_method;
134
	}
135
136
	/**
137
	 * Get the input types available for different field types
138
	 *
139
	 * @since 1.17.5
140
	 *
141
	 * @return array [field type name] => (array|string) search bar input types
142
	 */
143
	public static function get_input_types_by_field_type() {
144
		/**
145
		 * Input Type groups
146
		 * @see admin-search-widget.js (getSelectInput)
147
		 * @var array
148
		 */
149
		$input_types = array(
150
			'text' => array( 'input_text' ),
151
			'address' => array( 'input_text' ),
152
			'number' => array( 'input_text' ),
153
			'date' => array( 'date', 'date_range' ),
154
			'boolean' => array( 'single_checkbox' ),
155
			'select' => array( 'select', 'radio', 'link' ),
156
			'multi' => array( 'select', 'multiselect', 'radio', 'checkbox', 'link' ),
157
		);
158
159
		$input_types = apply_filters( 'gravityview/search/input_types', $input_types );
160
161
		return $input_types;
162
	}
163
164
	/**
165
	 * Get labels for different types of search bar inputs
166
	 *
167
	 * @since 1.17.5
168
	 *
169
	 * @return array [input type] => input type label
170
	 */
171
	public static function get_search_input_labels() {
172
		/**
173
		 * Input Type labels l10n
174
		 * @see admin-search-widget.js (getSelectInput)
175
		 * @var array
176
		 */
177
		$input_labels = array(
178
			'input_text' => esc_html__( 'Text', 'gravityview' ),
179
			'date' => esc_html__( 'Date', 'gravityview' ),
180
			'select' => esc_html__( 'Select', 'gravityview' ),
181
			'multiselect' => esc_html__( 'Select (multiple values)', 'gravityview' ),
182
			'radio' => esc_html__( 'Radio', 'gravityview' ),
183
			'checkbox' => esc_html__( 'Checkbox', 'gravityview' ),
184
			'single_checkbox' => esc_html__( 'Checkbox', 'gravityview' ),
185
			'link' => esc_html__( 'Links', 'gravityview' ),
186
			'date_range' => esc_html__( 'Date range', 'gravityview' ),
187
		);
188
189
		$input_labels = apply_filters( 'gravityview/search/input_labels', $input_labels );
190
191
		return $input_labels;
192
	}
193
194
	public static function get_search_input_label( $input_type ) {
195
		$labels = self::get_search_input_labels();
196
197
		return rgar( $labels, $input_type, false );
198
	}
199
200
	/**
201
	 * Add script to Views edit screen (admin)
202
	 * @param  mixed $hook
203
	 */
204
	public function add_scripts_and_styles( $hook ) {
205
		global $pagenow;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
206
207
		// Don't process any scripts below here if it's not a GravityView page or the widgets screen
208
		if ( ! gravityview_is_admin_page( $hook ) && ( 'widgets.php' !== $pagenow ) ) {
209
			return;
210
		}
211
212
		$script_min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
213
		$script_source = empty( $script_min ) ? '/source' : '';
214
215
		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 );
216
217
		wp_localize_script( 'gravityview_searchwidget_admin', 'gvSearchVar', array(
218
			'nonce' => wp_create_nonce( 'gravityview_ajaxsearchwidget' ),
219
			'label_nofields' => esc_html__( 'No search fields configured yet.', 'gravityview' ),
220
			'label_addfield' => esc_html__( 'Add Search Field', 'gravityview' ),
221
			'label_label' => esc_html__( 'Label', 'gravityview' ),
222
			'label_searchfield' => esc_html__( 'Search Field', 'gravityview' ),
223
			'label_inputtype' => esc_html__( 'Input Type', 'gravityview' ),
224
			'label_ajaxerror' => esc_html__( 'There was an error loading searchable fields. Save the View or refresh the page to fix this issue.', 'gravityview' ),
225
			'input_labels' => json_encode( self::get_search_input_labels() ),
226
			'input_types' => json_encode( self::get_input_types_by_field_type() ),
227
		) );
228
229
	}
230
231
	/**
232
	 * Add admin script to the no-conflict scripts whitelist
233
	 * @param array $allowed Scripts allowed in no-conflict mode
234
	 * @return array Scripts allowed in no-conflict mode, plus the search widget script
235
	 */
236
	public function register_no_conflict( $allowed ) {
237
		$allowed[] = 'gravityview_searchwidget_admin';
238
		return $allowed;
239
	}
240
241
	/**
242
	 * Ajax
243
	 * Returns the form fields ( only the searchable ones )
244
	 *
245
	 * @access public
246
	 * @return void
247
	 */
248
	public static function get_searchable_fields() {
249
250
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'gravityview_ajaxsearchwidget' ) ) {
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
251
			exit( '0' );
0 ignored issues
show
Coding Style Compatibility introduced by
The method get_searchable_fields() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
252
		}
253
254
		$form = '';
255
256
		// Fetch the form for the current View
257
		if ( ! empty( $_POST['view_id'] ) ) {
258
259
			$form = gravityview_get_form_id( $_POST['view_id'] );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
260
261
		} elseif ( ! empty( $_POST['formid'] ) ) {
262
263
			$form = (int) $_POST['formid'];
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
264
265
		} elseif ( ! empty( $_POST['template_id'] ) && class_exists( 'GravityView_Ajax' ) ) {
266
267
			$form = GravityView_Ajax::pre_get_form_fields( $_POST['template_id'] );
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
268
269
		}
270
271
		// fetch form id assigned to the view
272
		$response = self::render_searchable_fields( $form );
273
274
		exit( $response );
0 ignored issues
show
Coding Style Compatibility introduced by
The method get_searchable_fields() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
275
	}
276
277
	/**
278
	 * Generates html for the available Search Fields dropdown
279
	 * @param  int $form_id
280
	 * @param  string $current (for future use)
281
	 * @return string
282
	 */
283
	public static function render_searchable_fields( $form_id = null, $current = '' ) {
284
285
		if ( is_null( $form_id ) ) {
286
			return '';
287
		}
288
289
		// start building output
290
291
		$output = '<select class="gv-search-fields">';
292
293
		$custom_fields = array(
294
			'search_all' => array(
295
				'text' => esc_html__( 'Search Everything', 'gravityview' ),
296
				'type' => 'text',
297
			),
298
			'entry_date' => array(
299
				'text' => esc_html__( 'Entry Date', 'gravityview' ),
300
				'type' => 'date',
301
			),
302
			'entry_id' => array(
303
				'text' => esc_html__( 'Entry ID', 'gravityview' ),
304
				'type' => 'text',
305
			),
306
			'created_by' => array(
307
				'text' => esc_html__( 'Entry Creator', 'gravityview' ),
308
				'type' => 'select',
309
			)
310
		);
311
312
		foreach( $custom_fields as $custom_field_key => $custom_field ) {
313
			$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'] );
0 ignored issues
show
introduced by
No space after opening parenthesis of array is bad style
Loading history...
314
		}
315
316
		// Get fields with sub-inputs and no parent
317
		$fields = gravityview_get_form_fields( $form_id, true, true );
318
319
		/**
320
		 * @filter `gravityview/search/searchable_fields` Modify the fields that are displayed as searchable in the Search Bar dropdown\n
321
		 * @since 1.17
322
		 * @see gravityview_get_form_fields() Used to fetch the fields
323
		 * @see GravityView_Widget_Search::get_search_input_types See this method to modify the type of input types allowed for a field
324
		 * @param array $fields Array of searchable fields, as fetched by gravityview_get_form_fields()
325
		 * @param  int $form_id
326
		 */
327
		$fields = apply_filters( 'gravityview/search/searchable_fields', $fields, $form_id );
328
329
		if ( ! empty( $fields ) ) {
330
331
			$blacklist_field_types = apply_filters( 'gravityview_blacklist_field_types', array( 'fileupload', 'post_image', 'post_id', 'section' ), null );
332
333
			foreach ( $fields as $id => $field ) {
334
335
				if ( in_array( $field['type'], $blacklist_field_types ) ) {
336
					continue;
337
				}
338
339
				$types = self::get_search_input_types( $id, $field['type'] );
340
341
				$output .= '<option value="'. $id .'" '. selected( $id, $current, false ).'data-inputtypes="'. esc_attr( $types ) .'">'. esc_html( $field['label'] ) .'</option>';
342
			}
343
		}
344
345
		$output .= '</select>';
346
347
		return $output;
348
349
	}
350
351
	/**
352
	 * Assign an input type according to the form field type
353
	 * @see admin-search-widget.js
354
	 *
355
	 * @param int $id Gravity Forms field ID
356
	 * @param string $field_type Gravity Forms field type (also the `name` parameter of GravityView_Field classes)
357
	 *
358
	 * @return string GV field search input type ('multi', 'boolean', 'select', 'date', 'text')
359
	 */
360
	public static function get_search_input_types( $id = '', $field_type = null ) {
361
362
		// @todo - This needs to be improved - many fields have . including products and addresses
363
		if ( false !== strpos( (string) $id, '.' ) && in_array( $field_type, array( 'checkbox' ) ) || in_array( $id, array( 'is_fulfilled' ) ) ) {
364
			$input_type = 'boolean'; // on/off checkbox
365
		} elseif ( in_array( $field_type, array( 'checkbox', 'post_category', 'multiselect' ) ) ) {
366
			$input_type = 'multi'; //multiselect
367
		} elseif ( in_array( $field_type, array( 'select', 'radio' ) ) ) {
368
			$input_type = 'select';
369
		} elseif ( in_array( $field_type, array( 'date' ) ) || in_array( $id, array( 'payment_date' ) ) ) {
370
			$input_type = 'date';
371
		} elseif ( in_array( $field_type, array( 'number' ) ) || in_array( $id, array( 'payment_amount' ) ) ) {
372
			$input_type = 'number';
373
		} else {
374
			$input_type = 'text';
375
		}
376
377
		/**
378
		 * @filter `gravityview/extension/search/input_type` Modify the search form input type based on field type
379
		 * @since 1.2
380
		 * @param string $input_type Assign an input type according to the form field type. Defaults: `boolean`, `multi`, `select`, `date`, `text`
381
		 * @param string $field_type Gravity Forms field type (also the `name` parameter of GravityView_Field classes)
382
		 */
383
		$input_type = apply_filters( 'gravityview/extension/search/input_type', $input_type, $field_type );
384
385
		return $input_type;
386
	}
387
388
	/**
389
	 * Display hidden fields to add support for sites using Default permalink structure
390
	 *
391
	 * @since 1.8
392
	 * @return array Search fields, modified if not using permalinks
393
	 */
394
	public function add_no_permalink_fields( $search_fields, $object, $widget_args = array() ) {
395
		/** @global WP_Rewrite $wp_rewrite */
396
		global $wp_rewrite;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
397
398
		// Support default permalink structure
399
		if ( false === $wp_rewrite->using_permalinks() ) {
400
401
			// By default, use current post.
402
			$post_id = 0;
403
404
			// We're in the WordPress Widget context, and an overriding post ID has been set.
405
			if ( ! empty( $widget_args['post_id'] ) ) {
406
				$post_id = absint( $widget_args['post_id'] );
407
			}
408
			// We're in the WordPress Widget context, and the base View ID should be used
409
			else if ( ! empty( $widget_args['view_id'] ) ) {
410
				$post_id = absint( $widget_args['view_id'] );
411
			}
412
413
			$args = gravityview_get_permalink_query_args( $post_id );
414
415
			// Add hidden fields to the search form
416
			foreach ( $args as $key => $value ) {
0 ignored issues
show
Bug introduced by
The expression $args of type array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
417
				$search_fields[] = array(
418
					'name'  => $key,
419
					'input' => 'hidden',
420
					'value' => $value,
421
				);
422
			}
423
		}
424
425
		return $search_fields;
426
	}
427
428
429
	/** --- Frontend --- */
430
431
	/**
432
	 * Calculate the search criteria to filter entries
433
	 * @param  array $search_criteria
434
	 * @return array
435
	 */
436
	public function filter_entries( $search_criteria ) {
437
438
		if( 'post' === $this->search_method ) {
439
			$get = $_POST;
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
440
		} else {
441
			$get = $_GET;
0 ignored issues
show
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
442
		}
443
		
444
		do_action( 'gravityview_log_debug', sprintf( '%s[filter_entries] Requested $_%s: ', get_class( $this ), $this->search_method ), $get );
445
446
		if ( empty( $get ) || ! is_array( $get ) ) {
447
			return $search_criteria;
448
		}
449
450
		$get = stripslashes_deep( $get );
451
452
		$get = gv_map_deep( $get, 'rawurldecode' );
453
454
		// add free search
455
		if ( ! empty( $get['gv_search'] ) ) {
456
457
			// Search for a piece
458
			$words = explode( ' ', $get['gv_search'] );
459
460
			$words = array_filter( $words );
461
462
			foreach ( $words as $word ) {
463
				$search_criteria['field_filters'][] = array(
464
					'key' => null, // The field ID to search
465
					'value' => $word, // The value to search
466
					'operator' => 'contains', // What to search in. Options: `is` or `contains`
467
				);
468
			}
469
		}
470
471
		//start date & end date
472
		$curr_start = !empty( $get['gv_start'] ) ? $get['gv_start'] : '';
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
473
		$curr_end = !empty( $get['gv_start'] ) ? $get['gv_end'] : '';
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
474
475
        /**
476
         * @filter `gravityview_date_created_adjust_timezone` Whether to adjust the timezone for entries. \n
477
         * date_created is stored in UTC format. Convert search date into UTC (also used on templates/fields/date_created.php)
478
         * @since 1.12
479
         * @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
480
         * @param[in] string $context Where the filter is being called from. `search` in this case.
481
         */
482
        $adjust_tz = apply_filters( 'gravityview_date_created_adjust_timezone', true, 'search' );
483
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
484
485
		/**
486
		 * Don't set $search_criteria['start_date'] if start_date is empty as it may lead to bad query results (GFAPI::get_entries)
487
		 */
488
		if( !empty( $curr_start ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
489
			$search_criteria['start_date'] = $adjust_tz ? get_gmt_from_date( $curr_start ) : $curr_start;
490
		}
491
		if( !empty( $curr_end ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
492
			$search_criteria['end_date'] = $adjust_tz ? get_gmt_from_date( $curr_end ) : $curr_end;
493
		}
494
495
		// search for a specific entry ID
496
		if ( ! empty( $get[ 'gv_id' ] ) ) {
0 ignored issues
show
introduced by
Array keys should NOT be surrounded by spaces if they only contain a string or an integer.
Loading history...
497
			$search_criteria['field_filters'][] = array(
498
				'key' => 'id',
499
				'value' => absint( $get[ 'gv_id' ] ),
0 ignored issues
show
introduced by
Array keys should NOT be surrounded by spaces if they only contain a string or an integer.
Loading history...
500
				'operator' => '=',
501
			);
502
		}
503
504
		// search for a specific Created_by ID
505
		if ( ! empty( $get[ 'gv_by' ] ) ) {
0 ignored issues
show
introduced by
Array keys should NOT be surrounded by spaces if they only contain a string or an integer.
Loading history...
506
			$search_criteria['field_filters'][] = array(
507
				'key' => 'created_by',
508
				'value' => absint( $get['gv_by'] ),
509
				'operator' => '=',
510
			);
511
		}
512
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
513
514
		// Get search mode passed in URL
515
		$mode = isset( $get['mode'] ) && in_array( $get['mode'], array( 'any', 'all' ) ) ?  $get['mode'] : 'any';
516
517
		// get the other search filters
518
		foreach ( $get as $key => $value ) {
519
520
			if ( 0 !== strpos( $key, 'filter_' ) || empty( $value ) || ( is_array( $value ) && count( $value ) === 1 && empty( $value[0] ) ) ) {
0 ignored issues
show
introduced by
Found "=== 1". Use Yoda Condition checks, you must
Loading history...
521
				continue;
522
			}
523
524
			// could return simple filter or multiple filters
525
			$filter = $this->prepare_field_filter( $key, $value );
526
527
			if ( isset( $filter[0]['value'] ) ) {
528
				$search_criteria['field_filters'] = array_merge( $search_criteria['field_filters'], $filter );
529
530
				// if date range type, set search mode to ALL
531
				if ( ! empty( $filter[0]['operator'] ) && in_array( $filter[0]['operator'], array( '>=', '<=', '>', '<' ) ) ) {
532
					$mode = 'all';
533
				}
534
			} elseif( !empty( $filter ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
535
				$search_criteria['field_filters'][] = $filter;
536
			}
537
		}
538
539
		/**
540
		 * @filter `gravityview/search/mode` Set the Search Mode (`all` or `any`)
541
		 * @since 1.5.1
542
		 * @param[out,in] string $mode Search mode (`any` vs `all`)
543
		 */
544
		$search_criteria['field_filters']['mode'] = apply_filters( 'gravityview/search/mode', $mode );
545
546
		do_action( 'gravityview_log_debug', sprintf( '%s[filter_entries] Returned Search Criteria: ', get_class( $this ) ), $search_criteria );
547
548
		unset( $get );
549
550
		return $search_criteria;
551
	}
552
553
	/**
554
	 * Prepare the field filters to GFAPI
555
	 *
556
	 * 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.
557
	 *
558
	 * Format searched values
559
	 * @param  string $key   $_GET/$_POST search key
560
	 * @param  string $value $_GET/$_POST search value
561
	 * @return array        1 or 2 deph levels
562
	 */
563
	public function prepare_field_filter( $key, $value ) {
564
565
		$gravityview_view = GravityView_View::getInstance();
566
567
		$field_id = str_replace( 'filter_', '', $key );
568
569
		// calculates field_id, removing 'filter_' and for '_' for advanced fields ( like name or checkbox )
570
		if ( preg_match('/^[0-9_]+$/ism', $field_id ) ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
571
			$field_id = str_replace( '_', '.', $field_id );
572
		}
573
574
		// get form field array
575
		$form = $gravityview_view->getForm();
576
		$form_field = gravityview_get_field( $form, $field_id );
577
		
578
		// default filter array
579
		$filter = array(
580
			'key' => $field_id,
581
			'value' => $value,
582
		);
583
584
		switch ( $form_field['type'] ) {
585
586
			case 'select':
587
			case 'radio':
588
				$filter['operator'] = 'is';
589
				break;
590
591
			case 'post_category':
592
593
				if ( ! is_array( $value ) ) {
594
					$value = array( $value );
595
				}
596
597
				// Reset filter variable
598
				$filter = array();
599
600
				foreach ( $value as $val ) {
601
					$cat = get_term( $val, 'category' );
602
					$filter[] = array(
603
						'key' => $field_id,
604
						'value' => esc_attr( $cat->name ) . ':' . $val,
605
						'operator' => 'is',
606
					);
607
				}
608
609
				break;
610
611
			case 'multiselect':
612
613
				if ( ! is_array( $value ) ) {
614
					break;
615
				}
616
617
				// Reset filter variable
618
				$filter = array();
619
620
				foreach ( $value as $val ) {
621
					$filter[] = array( 'key' => $field_id, 'value' => $val );
622
				}
623
624
				break;
625
626
			case 'checkbox':
627
				// convert checkbox on/off into the correct search filter
628
				if ( false !== strpos( $field_id, '.' ) && ! empty( $form_field['inputs'] ) && ! empty( $form_field['choices'] ) ) {
629
					foreach ( $form_field['inputs'] as $k => $input ) {
630
						if ( $input['id'] == $field_id ) {
631
							$filter['value'] = $form_field['choices'][ $k ]['value'];
632
							$filter['operator'] = 'is';
633
							break;
634
						}
635
					}
636
				} elseif ( is_array( $value ) ) {
637
638
					// Reset filter variable
639
					$filter = array();
640
641
					foreach ( $value as $val ) {
642
						$filter[] = array(
643
								'key'   => $field_id,
644
								'value' => $val,
645
								'operator' => 'is',
646
						);
647
					}
648
				}
649
650
				break;
651
652
			case 'name':
653
			case 'address':
654
655
				if ( false === strpos( $field_id, '.' ) ) {
656
657
					$words = explode( ' ', $value );
658
659
					$filters = array();
660
					foreach ( $words as $word ) {
661
						if ( ! empty( $word ) && strlen( $word ) > 1 ) {
662
							// Keep the same key for each filter
663
							$filter['value'] = $word;
664
							// Add a search for the value
665
							$filters[] = $filter;
666
						}
667
					}
668
669
					$filter = $filters;
670
				}
671
672
				break;
673
674
			case 'date':
675
676
				if ( is_array( $value ) ) {
677
678
					// Reset filter variable
679
					$filter = array();
680
681
					foreach ( $value as $k => $date ) {
682
						if ( empty( $date ) ) {
683
							continue;
684
						}
685
						$operator = 'start' === $k ? '>=' : '<=';
686
687
						/**
688
						 * @hack
689
						 * @since 1.16.3
690
						 * Safeguard until GF implements '<=' operator
691
						 */
692
						if( !GFFormsModel::is_valid_operator( $operator ) && $operator === '<=' ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
693
							$operator = '<';
694
							$date = date( 'Y-m-d', strtotime( $date . ' +1 day' ) );
695
						}
696
697
						$filter[] = array(
698
							'key' => $field_id,
699
							'value' => self::get_formatted_date( $date, 'Y-m-d' ),
700
							'operator' => $operator,
701
						);
702
					}
703
				} else {
704
					$filter['value'] = self::get_formatted_date( $value, 'Y-m-d' );
705
				}
706
707
				break;
708
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
709
710
		} // switch field type
711
712
		return $filter;
713
	}
714
715
	/**
716
	 * Get the Field Format form GravityForms
717
	 *
718
	 * @param GF_Field_Date $field The field object
719
	 * @since 1.10
720
	 *
721
	 * @return string Format of the date in the database
722
	 */
723
	public static function get_date_field_format( GF_Field_Date $field ) {
724
		$format = 'm/d/Y';
725
		$datepicker = array(
726
			'mdy' => 'm/d/Y',
727
			'dmy' => 'd/m/Y',
728
			'dmy_dash' => 'd-m-Y',
729
			'dmy_dot' => 'm.d.Y',
730
			'ymd_slash' => 'Y/m/d',
731
			'ymd_dash' => 'Y-m-d',
732
			'ymd_dot' => 'Y.m.d',
733
		);
734
735
		if ( ! empty( $field->dateFormat ) && isset( $datepicker[ $field->dateFormat ] ) ){
736
			$format = $datepicker[ $field->dateFormat ];
737
		}
738
739
		return $format;
740
	}
741
742
	/**
743
	 * Format a date value
744
	 *
745
	 * @param string $value Date value input
746
	 * @param string $format Wanted formatted date
747
	 * @return string
748
	 */
749
	public static function get_formatted_date( $value = '', $format = 'Y-m-d' ) {
750
		$date = date_create( $value );
751
		if ( empty( $date ) ) {
752
			do_action( 'gravityview_log_debug', sprintf( '%s[get_formatted_date] Date format not valid: ', get_class( self::$instance ) ), $value );
753
			return '';
754
		}
755
		return $date->format( $format );
756
	}
757
758
759
	/**
760
	 * Include this extension templates path
761
	 * @param array $file_paths List of template paths ordered
762
	 */
763
	public function add_template_path( $file_paths ) {
764
765
		// Index 100 is the default GravityView template path.
766
		$file_paths[102] = self::$file . 'templates/';
767
768
		return $file_paths;
769
	}
770
771
	/**
772
	 * Check whether the configured search fields have a date field
773
	 *
774
	 * @since 1.17.5
775
	 *
776
	 * @param array $search_fields
777
	 *
778
	 * @return bool True: has a `date` or `date_range` field
779
	 */
780
	private function has_date_field( $search_fields ) {
781
782
		$has_date = false;
783
784
		foreach ( $search_fields as $k => $field ) {
785
			if ( in_array( $field['input'], array( 'date', 'date_range', 'entry_date' ) ) ) {
786
				$has_date = true;
787
				break;
788
			}
789
		}
790
791
		return $has_date;
792
	}
793
794
	/**
795
	 * Renders the Search Widget
796
	 * @param array $widget_args
797
	 * @param string $content
798
	 * @param string $context
799
	 *
800
	 * @return void
801
	 */
802
	public function render_frontend( $widget_args, $content = '', $context = '' ) {
803
		/** @var GravityView_View $gravityview_view */
804
		$gravityview_view = GravityView_View::getInstance();
805
806
		if ( empty( $gravityview_view ) ) {
807
			do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend]: $gravityview_view not instantiated yet.', get_class( $this ) ) );
808
			return;
809
		}
810
811
		// get configured search fields
812
		$search_fields = ! empty( $widget_args['search_fields'] ) ? json_decode( $widget_args['search_fields'], true ) : '';
813
814
		if ( empty( $search_fields ) || ! is_array( $search_fields ) ) {
815
			do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend] No search fields configured for widget:', get_class( $this ) ), $widget_args );
816
			return;
817
		}
818
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
819
820
		// prepare fields
821
		foreach ( $search_fields as $k => $field ) {
822
823
			$updated_field = $field;
824
825
			$updated_field = $this->get_search_filter_details( $updated_field );
826
827
			switch ( $field['field'] ) {
828
829
				case 'search_all':
830
					$updated_field['key'] = 'search_all';
831
					$updated_field['input'] = 'search_all';
832
					$updated_field['value'] = $this->rgget_or_rgpost( 'gv_search' );
833
					break;
834
835
				case 'entry_date':
836
					$updated_field['key'] = 'entry_date';
837
					$updated_field['input'] = 'entry_date';
838
					$updated_field['value'] = array(
839
						'start' => $this->rgget_or_rgpost( 'gv_start' ),
840
						'end' => $this->rgget_or_rgpost( 'gv_end' ),
841
					);
842
					break;
843
844
				case 'entry_id':
845
					$updated_field['key'] = 'entry_id';
846
					$updated_field['input'] = 'entry_id';
847
					$updated_field['value'] = $this->rgget_or_rgpost( 'gv_id' );
848
					break;
849
850
				case 'created_by':
851
					$updated_field['key'] = 'created_by';
852
					$updated_field['name'] = 'gv_by';
853
					$updated_field['value'] = $this->rgget_or_rgpost( 'gv_by' );
854
					$updated_field['choices'] = self::get_created_by_choices();
855
					break;
856
			}
857
858
			$search_fields[ $k ] = $updated_field;
859
		}
860
861
		do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend] Calculated Search Fields: ', get_class( $this ) ), $search_fields );
862
863
		/**
864
		 * @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.
865
		 * @param array $search_fields Array of search filters with `key`, `label`, `value`, `type` keys
866
		 * @param GravityView_Widget_Search $this Current widget object
867
		 * @param array $widget_args Args passed to this method. {@since 1.8}
868
		 * @var array
869
		 */
870
		$gravityview_view->search_fields = apply_filters( 'gravityview_widget_search_filters', $search_fields, $this, $widget_args );
871
872
		$gravityview_view->search_layout = ! empty( $widget_args['search_layout'] ) ? $widget_args['search_layout'] : 'horizontal';
873
874
		/** @since 1.14 */
875
		$gravityview_view->search_mode = ! empty( $widget_args['search_mode'] ) ? $widget_args['search_mode'] : 'any';
876
877
		$custom_class = ! empty( $widget_args['custom_class'] ) ? $widget_args['custom_class'] : '';
878
879
		$gravityview_view->search_class = self::get_search_class( $custom_class );
880
881
		$gravityview_view->search_clear = ! empty( $widget_args['search_clear'] ) ? $widget_args['search_clear'] : false;
882
883
		if ( $this->has_date_field( $search_fields ) ) {
884
			// enqueue datepicker stuff only if needed!
885
			$this->enqueue_datepicker();
886
		}
887
888
		$this->maybe_enqueue_flexibility();
889
890
		$gravityview_view->render( 'widget', 'search', false );
891
	}
892
893
	/**
894
	 * Get the search class for a search form
895
	 *
896
	 * @since 1.5.4
897
	 *
898
	 * @return string Sanitized CSS class for the search form
899
	 */
900
	public static function get_search_class( $custom_class = '' ) {
901
		$gravityview_view = GravityView_View::getInstance();
902
903
		$search_class = 'gv-search-'.$gravityview_view->search_layout;
904
905
		if ( ! empty( $custom_class )  ) {
906
			$search_class .= ' '.$custom_class;
907
		}
908
909
		/**
910
		 * @filter `gravityview_search_class` Modify the CSS class for the search form
911
		 * @param string $search_class The CSS class for the search form
912
		 */
913
		$search_class = apply_filters( 'gravityview_search_class', $search_class );
914
915
		// Is there an active search being performed? Used by fe-views.js
916
		$search_class .= GravityView_frontend::getInstance()->isSearch() ? ' gv-is-search' : '';
917
918
		return gravityview_sanitize_html_class( $search_class );
919
	}
920
921
922
	/**
923
	 * Calculate the search form action
924
	 * @since 1.6
925
	 *
926
	 * @return string
927
	 */
928
	public static function get_search_form_action() {
929
		$gravityview_view = GravityView_View::getInstance();
930
931
		$post_id = $gravityview_view->getPostId() ? $gravityview_view->getPostId() : $gravityview_view->getViewId();
932
933
		$url = add_query_arg( array(), get_permalink( $post_id ) );
934
935
		return esc_url( $url );
936
	}
937
938
	/**
939
	 * Get the label for a search form field
940
	 * @param  array $field      Field setting as sent by the GV configuration - has `field`, `input` (input type), and `label` keys
941
	 * @param  array $form_field Form field data, as fetched by `gravityview_get_field()`
942
	 * @return string             Label for the search form
943
	 */
944
	private static function get_field_label( $field, $form_field = array() ) {
945
946
		$label = rgget( 'label', $field );
947
948
		if( '' === $label ) {
949
950
			$label = isset( $form_field['label'] ) ? $form_field['label'] : '';
951
952
			switch( $field['field'] ) {
953
				case 'search_all':
954
					$label = __( 'Search Entries:', 'gravityview' );
955
					break;
956
				case 'entry_date':
957
					$label = __( 'Filter by date:', 'gravityview' );
958
					break;
959
				case 'entry_id':
960
					$label = __( 'Entry ID:', 'gravityview' );
961
					break;
962
				default:
963
					// If this is a field input, not a field
964
					if ( strpos( $field['field'], '.' ) > 0 && ! empty( $form_field['inputs'] ) ) {
965
966
						// Get the label for the field in question, which returns an array
967
						$items = wp_list_filter( $form_field['inputs'], array( 'id' => $field['field'] ) );
968
969
						// Get the item with the `label` key
970
						$values = wp_list_pluck( $items, 'label' );
971
972
						// There will only one item in the array, but this is easier
973
						foreach ( $values as $value ) {
974
							$label = $value;
975
							break;
976
						}
977
					}
978
			}
979
		}
980
981
		/**
982
		 * @filter `gravityview_search_field_label` Modify the label for a search field. Supports returning HTML
983
		 * @since 1.17.3 Added $field parameter
984
		 * @param[in,out] string $label Existing label text, sanitized.
985
		 * @param[in] array $form_field Gravity Forms field array, as returned by `GFFormsModel::get_field()`
986
		 * @param[in] array $field Field setting as sent by the GV configuration - has `field`, `input` (input type), and `label` keys
987
		 */
988
		$label = apply_filters( 'gravityview_search_field_label', esc_attr( $label ), $form_field, $field );
989
990
		return $label;
991
	}
992
993
	/**
994
	 * Prepare search fields to frontend render with other details (label, field type, searched values)
995
	 *
996
	 * @param array $field
997
	 * @return array
998
	 */
999
	private function get_search_filter_details( $field ) {
1000
1001
		$gravityview_view = GravityView_View::getInstance();
1002
1003
		$form = $gravityview_view->getForm();
1004
1005
		// for advanced field ids (eg, first name / last name )
1006
		$name = 'filter_' . str_replace( '.', '_', $field['field'] );
1007
1008
		// get searched value from $_GET/$_POST (string or array)
1009
		$value = $this->rgget_or_rgpost( $name );
1010
1011
		// get form field details
1012
		$form_field = gravityview_get_field( $form, $field['field'] );
1013
1014
		$filter = array(
1015
			'key' => $field['field'],
1016
			'name' => $name,
1017
			'label' => self::get_field_label( $field, $form_field ),
1018
			'input' => $field['input'],
1019
			'value' => $value,
1020
			'type' => $form_field['type'],
1021
		);
1022
1023
		// collect choices
1024
		if ( 'post_category' === $form_field['type'] && ! empty( $form_field['displayAllCategories'] ) && empty( $form_field['choices'] ) ) {
1025
			$filter['choices'] = gravityview_get_terms_choices();
1026
		} elseif ( ! empty( $form_field['choices'] ) ) {
1027
			$filter['choices'] = $form_field['choices'];
1028
		}
1029
1030
		if ( 'date_range' === $field['input'] && empty( $value ) ) {
1031
			$filter['value'] = array( 'start' => '', 'end' => '' );
1032
		}
1033
1034
		return $filter;
1035
1036
	}
1037
1038
	/**
1039
	 * Calculate the search choices for the users
1040
	 *
1041
	 * @since 1.8
1042
	 *
1043
	 * @return array Array of user choices (value = ID, text = display name)
1044
	 */
1045
	private static function get_created_by_choices() {
1046
1047
		/**
1048
		 * filter gravityview/get_users/search_widget
1049
		 * @see \GVCommon::get_users
1050
		 */
1051
		$users = GVCommon::get_users( 'search_widget', array( 'fields' => array( 'ID', 'display_name' ) ) );
1052
1053
		$choices = array();
1054
		foreach ( $users as $user ) {
1055
			$choices[] = array(
1056
				'value' => $user->ID,
1057
				'text' => $user->display_name,
1058
			);
1059
		}
1060
1061
		return $choices;
1062
	}
1063
1064
1065
	/**
1066
	 * Output the Clear Search Results button
1067
	 * @since 1.5.4
1068
	 */
1069
	public static function the_clear_search_button() {
1070
		$gravityview_view = GravityView_View::getInstance();
1071
1072
		if ( $gravityview_view->search_clear ) {
1073
1074
			$url = strtok( add_query_arg( array() ), '?' );
1075
1076
			echo gravityview_get_link( $url, esc_html__( 'Clear', 'gravityview' ), 'class=button gv-search-clear' );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'gravityview_get_link'
Loading history...
1077
1078
		}
1079
	}
1080
1081
	/**
1082
	 * Based on the search method, fetch the value for a specific key
1083
	 * 
1084
	 * @since 1.16.4
1085
	 *
1086
	 * @param string $name Name of the request key to fetch the value for
1087
	 *
1088
	 * @return mixed|string Value of request at $name key. Empty string if empty.
1089
	 */
1090
	private function rgget_or_rgpost( $name ) {
1091
		$value = 'get' === $this->search_method ? rgget( $name ) : rgpost( $name );
1092
1093
		$value = stripslashes_deep( $value );
1094
1095
		$value = gv_map_deep( $value, 'rawurldecode' );
1096
1097
		$value = gv_map_deep( $value, '_wp_specialchars' );
1098
1099
		return $value;
1100
	}
1101
1102
1103
	/**
1104
	 * Require the datepicker script for the frontend GV script
1105
	 * @param array $js_dependencies Array of existing required scripts for the fe-views.js script
1106
	 * @return array Array required scripts, with `jquery-ui-datepicker` added
1107
	 */
1108
	public function add_datepicker_js_dependency( $js_dependencies ) {
1109
1110
		$js_dependencies[] = 'jquery-ui-datepicker';
1111
1112
		return $js_dependencies;
1113
	}
1114
1115
	/**
1116
	 * Modify the array passed to wp_localize_script()
1117
	 *
1118
	 * @param array $js_localization The data padded to the Javascript file
0 ignored issues
show
Bug introduced by
There is no parameter named $js_localization. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1119
	 * @param array $view_data View data array with View settings
1120
	 *
1121
	 * @return array
1122
	 */
1123
	public function add_datepicker_localization( $localizations = array(), $view_data = array() ) {
1124
		global $wp_locale;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
1125
1126
		/**
1127
		 * @filter `gravityview_datepicker_settings` Modify the datepicker settings
1128
		 * @see http://api.jqueryui.com/datepicker/ Learn what settings are available
1129
		 * @see http://www.renegadetechconsulting.com/tutorials/jquery-datepicker-and-wordpress-i18n Thanks for the helpful information on $wp_locale
1130
		 * @param array $js_localization The data padded to the Javascript file
1131
		 * @param array $view_data View data array with View settings
1132
		 */
1133
		$datepicker_settings = apply_filters( 'gravityview_datepicker_settings', array(
1134
			'yearRange' => '-5:+5',
1135
			'changeMonth' => true,
1136
			'changeYear' => true,
1137
			'closeText' => esc_attr_x( 'Close', 'Close calendar', 'gravityview' ),
1138
			'prevText' => esc_attr_x( 'Prev', 'Previous month in calendar', 'gravityview' ),
1139
			'nextText' => esc_attr_x( 'Next', 'Next month in calendar', 'gravityview' ),
1140
			'currentText' => esc_attr_x( 'Today', 'Today in calendar', 'gravityview' ),
1141
			'weekHeader' => esc_attr_x( 'Week', 'Week in calendar', 'gravityview' ),
1142
			'monthStatus'       => __( 'Show a different month', 'gravityview' ),
1143
			'monthNames'        => array_values( $wp_locale->month ),
1144
			'monthNamesShort'   => array_values( $wp_locale->month_abbrev ),
1145
			'dayNames'          => array_values( $wp_locale->weekday ),
1146
			'dayNamesShort'     => array_values( $wp_locale->weekday_abbrev ),
1147
			'dayNamesMin'       => array_values( $wp_locale->weekday_initial ),
1148
			// get the start of week from WP general setting
1149
			'firstDay'          => get_option( 'start_of_week' ),
1150
			// is Right to left language? default is false
1151
			'isRTL'             => is_rtl(),
1152
		), $view_data );
1153
1154
		$localizations['datepicker'] = $datepicker_settings;
1155
1156
		return $localizations;
1157
1158
	}
1159
1160
	/**
1161
	 * Register search widget scripts, including Flexibility
1162
	 *
1163
	 * @see https://github.com/10up/flexibility
1164
	 *
1165
	 * @since 1.17
1166
	 *
1167
	 * @return void
1168
	 */
1169
	public function register_scripts() {
1170
1171
		wp_register_script( 'gv-flexibility', plugins_url( 'assets/lib/flexibility/dist/flexibility.js', GRAVITYVIEW_FILE ), array(), GravityView_Plugin::version, true );
1172
1173
	}
1174
1175
	/**
1176
	 * If the current visitor is running IE 8 or 9, enqueue Flexibility
1177
	 *
1178
	 * @since 1.17
1179
	 *
1180
	 * @return void
1181
	 */
1182
	private function maybe_enqueue_flexibility() {
1183
		if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && preg_match( '/MSIE [8-9]/', $_SERVER['HTTP_USER_AGENT'] ) ) {
0 ignored issues
show
introduced by
Due to using Batcache, server side based client related logic will not work, use JS instead.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
1184
			wp_enqueue_script( 'gv-flexibility' );
1185
		}
1186
	}
1187
1188
	/**
1189
	 * Enqueue the datepicker script
1190
	 *
1191
	 * It sets the $gravityview->datepicker_class parameter
1192
	 *
1193
	 * @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.
1194
	 * @return void
1195
	 */
1196
	public function enqueue_datepicker() {
1197
		$gravityview_view = GravityView_View::getInstance();
1198
1199
		wp_enqueue_script( 'jquery-ui-datepicker' );
1200
1201
		add_filter( 'gravityview_js_dependencies', array( $this, 'add_datepicker_js_dependency' ) );
1202
		add_filter( 'gravityview_js_localization', array( $this, 'add_datepicker_localization' ), 10, 2 );
1203
1204
		$scheme = is_ssl() ? 'https://' : 'http://';
1205
		wp_enqueue_style( 'jquery-ui-datepicker', $scheme.'ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/smoothness/jquery-ui.css' );
1206
1207
		/**
1208
		 * @filter `gravityview_search_datepicker_class`
1209
		 * 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.
1210
		 * @param string $css_class CSS class to use. Default: `gv-datepicker datepicker mdy` \n
1211
		 * Options are:
1212
		 * - `mdy` (mm/dd/yyyy)
1213
		 * - `dmy` (dd/mm/yyyy)
1214
		 * - `dmy_dash` (dd-mm-yyyy)
1215
		 * - `dmy_dot` (dd.mm.yyyy)
1216
		 * - `ymp_slash` (yyyy/mm/dd)
1217
		 * - `ymd_dash` (yyyy-mm-dd)
1218
		 * - `ymp_dot` (yyyy.mm.dd)
1219
		 */
1220
		$datepicker_class = apply_filters( 'gravityview_search_datepicker_class', 'gv-datepicker datepicker mdy' );
1221
1222
		$gravityview_view->datepicker_class = $datepicker_class;
1223
1224
	}
1225
1226
1227
} // end class
1228
1229
new GravityView_Widget_Search;