Completed
Push — develop ( 6c202f...281de0 )
by Zack
04:23
created

add_scripts_and_styles()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 9
nop 1
dl 0
loc 26
rs 8.439
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
		/**
160
		 * @filter `gravityview/search/input_types` Change the types of search fields available to a field type
161
		 * @see GravityView_Widget_Search::get_search_input_labels() for the available input types
162
		 * @param array $input_types Associative array: key is field `name`, value is array of GravityView input types (note: use `input_text` for `text`)
163
		 */
164
		$input_types = apply_filters( 'gravityview/search/input_types', $input_types );
165
166
		return $input_types;
167
	}
168
169
	/**
170
	 * Get labels for different types of search bar inputs
171
	 *
172
	 * @since 1.17.5
173
	 *
174
	 * @return array [input type] => input type label
175
	 */
176
	public static function get_search_input_labels() {
177
		/**
178
		 * Input Type labels l10n
179
		 * @see admin-search-widget.js (getSelectInput)
180
		 * @var array
181
		 */
182
		$input_labels = array(
183
			'input_text' => esc_html__( 'Text', 'gravityview' ),
184
			'date' => esc_html__( 'Date', 'gravityview' ),
185
			'select' => esc_html__( 'Select', 'gravityview' ),
186
			'multiselect' => esc_html__( 'Select (multiple values)', 'gravityview' ),
187
			'radio' => esc_html__( 'Radio', 'gravityview' ),
188
			'checkbox' => esc_html__( 'Checkbox', 'gravityview' ),
189
			'single_checkbox' => esc_html__( 'Checkbox', 'gravityview' ),
190
			'link' => esc_html__( 'Links', 'gravityview' ),
191
			'date_range' => esc_html__( 'Date range', 'gravityview' ),
192
		);
193
194
		/**
195
		 * @filter `gravityview/search/input_types` Change the label of search field input types
196
		 * @param array $input_types Associative array: key is input type name, value is label
197
		 */
198
		$input_labels = apply_filters( 'gravityview/search/input_labels', $input_labels );
199
200
		return $input_labels;
201
	}
202
203
	public static function get_search_input_label( $input_type ) {
204
		$labels = self::get_search_input_labels();
205
206
		return rgar( $labels, $input_type, false );
207
	}
208
209
	/**
210
	 * Add script to Views edit screen (admin)
211
	 * @param  mixed $hook
212
	 */
213
	public function add_scripts_and_styles( $hook ) {
214
		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...
215
216
		// Don't process any scripts below here if it's not a GravityView page or the widgets screen
217
		if ( ! gravityview_is_admin_page( $hook ) && ( 'widgets.php' !== $pagenow ) ) {
218
			return;
219
		}
220
221
		$script_min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
222
		$script_source = empty( $script_min ) ? '/source' : '';
223
224
		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 );
225
226
		wp_localize_script( 'gravityview_searchwidget_admin', 'gvSearchVar', array(
227
			'nonce' => wp_create_nonce( 'gravityview_ajaxsearchwidget' ),
228
			'label_nofields' => esc_html__( 'No search fields configured yet.', 'gravityview' ),
229
			'label_addfield' => esc_html__( 'Add Search Field', 'gravityview' ),
230
			'label_label' => esc_html__( 'Label', 'gravityview' ),
231
			'label_searchfield' => esc_html__( 'Search Field', 'gravityview' ),
232
			'label_inputtype' => esc_html__( 'Input Type', 'gravityview' ),
233
			'label_ajaxerror' => esc_html__( 'There was an error loading searchable fields. Save the View or refresh the page to fix this issue.', 'gravityview' ),
234
			'input_labels' => json_encode( self::get_search_input_labels() ),
235
			'input_types' => json_encode( self::get_input_types_by_field_type() ),
236
		) );
237
238
	}
239
240
	/**
241
	 * Add admin script to the no-conflict scripts whitelist
242
	 * @param array $allowed Scripts allowed in no-conflict mode
243
	 * @return array Scripts allowed in no-conflict mode, plus the search widget script
244
	 */
245
	public function register_no_conflict( $allowed ) {
246
		$allowed[] = 'gravityview_searchwidget_admin';
247
		return $allowed;
248
	}
249
250
	/**
251
	 * Ajax
252
	 * Returns the form fields ( only the searchable ones )
253
	 *
254
	 * @access public
255
	 * @return void
256
	 */
257
	public static function get_searchable_fields() {
258
259
		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...
260
			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...
261
		}
262
263
		$form = '';
264
265
		// Fetch the form for the current View
266
		if ( ! empty( $_POST['view_id'] ) ) {
267
268
			$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...
269
270
		} elseif ( ! empty( $_POST['formid'] ) ) {
271
272
			$form = (int) $_POST['formid'];
0 ignored issues
show
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
273
274
		} elseif ( ! empty( $_POST['template_id'] ) && class_exists( 'GravityView_Ajax' ) ) {
275
276
			$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...
277
278
		}
279
280
		// fetch form id assigned to the view
281
		$response = self::render_searchable_fields( $form );
282
283
		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...
284
	}
285
286
	/**
287
	 * Generates html for the available Search Fields dropdown
288
	 * @param  int $form_id
289
	 * @param  string $current (for future use)
290
	 * @return string
291
	 */
292
	public static function render_searchable_fields( $form_id = null, $current = '' ) {
293
294
		if ( is_null( $form_id ) ) {
295
			return '';
296
		}
297
298
		// start building output
299
300
		$output = '<select class="gv-search-fields">';
301
302
		$custom_fields = array(
303
			'search_all' => array(
304
				'text' => esc_html__( 'Search Everything', 'gravityview' ),
305
				'type' => 'text',
306
			),
307
			'entry_date' => array(
308
				'text' => esc_html__( 'Entry Date', 'gravityview' ),
309
				'type' => 'date',
310
			),
311
			'entry_id' => array(
312
				'text' => esc_html__( 'Entry ID', 'gravityview' ),
313
				'type' => 'text',
314
			),
315
			'created_by' => array(
316
				'text' => esc_html__( 'Entry Creator', 'gravityview' ),
317
				'type' => 'select',
318
			)
319
		);
320
321
		foreach( $custom_fields as $custom_field_key => $custom_field ) {
322
			$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...
323
		}
324
325
		// Get fields with sub-inputs and no parent
326
		$fields = gravityview_get_form_fields( $form_id, true, true );
327
328
		/**
329
		 * @filter `gravityview/search/searchable_fields` Modify the fields that are displayed as searchable in the Search Bar dropdown\n
330
		 * @since 1.17
331
		 * @see gravityview_get_form_fields() Used to fetch the fields
332
		 * @see GravityView_Widget_Search::get_search_input_types See this method to modify the type of input types allowed for a field
333
		 * @param array $fields Array of searchable fields, as fetched by gravityview_get_form_fields()
334
		 * @param  int $form_id
335
		 */
336
		$fields = apply_filters( 'gravityview/search/searchable_fields', $fields, $form_id );
337
338
		if ( ! empty( $fields ) ) {
339
340
			$blacklist_field_types = apply_filters( 'gravityview_blacklist_field_types', array( 'fileupload', 'post_image', 'post_id', 'section' ), null );
341
342
			foreach ( $fields as $id => $field ) {
343
344
				if ( in_array( $field['type'], $blacklist_field_types ) ) {
345
					continue;
346
				}
347
348
				$types = self::get_search_input_types( $id, $field['type'] );
349
350
				$output .= '<option value="'. $id .'" '. selected( $id, $current, false ).'data-inputtypes="'. esc_attr( $types ) .'">'. esc_html( $field['label'] ) .'</option>';
351
			}
352
		}
353
354
		$output .= '</select>';
355
356
		return $output;
357
358
	}
359
360
	/**
361
	 * Assign an input type according to the form field type
362
	 *
363
	 * @see admin-search-widget.js
364
	 *
365
	 * @param string|int|float $field_id Gravity Forms field ID
366
	 * @param string $field_type Gravity Forms field type (also the `name` parameter of GravityView_Field classes)
367
	 *
368
	 * @return string GV field search input type ('multi', 'boolean', 'select', 'date', 'text')
369
	 */
370
	public static function get_search_input_types( $field_id = '', $field_type = null ) {
371
372
		// @todo - This needs to be improved - many fields have . including products and addresses
373
		if ( false !== strpos( (string) $field_id, '.' ) && in_array( $field_type, array( 'checkbox' ) ) || in_array( $field_id, array( 'is_fulfilled' ) ) ) {
374
			$input_type = 'boolean'; // on/off checkbox
375
		} elseif ( in_array( $field_type, array( 'checkbox', 'post_category', 'multiselect' ) ) ) {
376
			$input_type = 'multi'; //multiselect
377
		} elseif ( in_array( $field_type, array( 'select', 'radio' ) ) ) {
378
			$input_type = 'select';
379
		} elseif ( in_array( $field_type, array( 'date' ) ) || in_array( $field_id, array( 'payment_date' ) ) ) {
380
			$input_type = 'date';
381
		} elseif ( in_array( $field_type, array( 'number' ) ) || in_array( $field_id, array( 'payment_amount' ) ) ) {
382
			$input_type = 'number';
383
		} else {
384
			$input_type = 'text';
385
		}
386
387
		/**
388
		 * @filter `gravityview/extension/search/input_type` Modify the search form input type based on field type
389
		 * @since 1.2
390
		 * @since 1.19.2 Added $field_id parameter
391
		 * @param string $input_type Assign an input type according to the form field type. Defaults: `boolean`, `multi`, `select`, `date`, `text`
392
		 * @param string $field_type Gravity Forms field type (also the `name` parameter of GravityView_Field classes)
393
		 * @param string|int|float $field_id ID of the field being processed
394
		 */
395
		$input_type = apply_filters( 'gravityview/extension/search/input_type', $input_type, $field_type, $field_id );
396
397
		return $input_type;
398
	}
399
400
	/**
401
	 * Display hidden fields to add support for sites using Default permalink structure
402
	 *
403
	 * @since 1.8
404
	 * @return array Search fields, modified if not using permalinks
405
	 */
406
	public function add_no_permalink_fields( $search_fields, $object, $widget_args = array() ) {
407
		/** @global WP_Rewrite $wp_rewrite */
408
		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...
409
410
		// Support default permalink structure
411
		if ( false === $wp_rewrite->using_permalinks() ) {
412
413
			// By default, use current post.
414
			$post_id = 0;
415
416
			// We're in the WordPress Widget context, and an overriding post ID has been set.
417
			if ( ! empty( $widget_args['post_id'] ) ) {
418
				$post_id = absint( $widget_args['post_id'] );
419
			}
420
			// We're in the WordPress Widget context, and the base View ID should be used
421
			else if ( ! empty( $widget_args['view_id'] ) ) {
422
				$post_id = absint( $widget_args['view_id'] );
423
			}
424
425
			$args = gravityview_get_permalink_query_args( $post_id );
426
427
			// Add hidden fields to the search form
428
			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...
429
				$search_fields[] = array(
430
					'name'  => $key,
431
					'input' => 'hidden',
432
					'value' => $value,
433
				);
434
			}
435
		}
436
437
		return $search_fields;
438
	}
439
440
441
	/** --- Frontend --- */
442
443
	/**
444
	 * Calculate the search criteria to filter entries
445
	 * @param  array $search_criteria
446
	 * @return array
447
	 */
448
	public function filter_entries( $search_criteria ) {
449
450
		if( 'post' === $this->search_method ) {
451
			$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...
452
		} else {
453
			$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...
454
		}
455
456
		do_action( 'gravityview_log_debug', sprintf( '%s[filter_entries] Requested $_%s: ', get_class( $this ), $this->search_method ), $get );
457
458
		if ( empty( $get ) || ! is_array( $get ) ) {
459
			return $search_criteria;
460
		}
461
462
		$get = stripslashes_deep( $get );
463
464
		$get = gv_map_deep( $get, 'rawurldecode' );
465
466
		// add free search
467
		if ( ! empty( $get['gv_search'] ) ) {
468
469
			// Search for a piece
470
			$words = explode( ' ', $get['gv_search'] );
471
472
			$words = array_filter( $words );
473
474
			foreach ( $words as $word ) {
475
				$search_criteria['field_filters'][] = array(
476
					'key' => null, // The field ID to search
477
					'value' => $word, // The value to search
478
					'operator' => 'contains', // What to search in. Options: `is` or `contains`
479
				);
480
			}
481
		}
482
483
		//start date & end date
484
		$curr_start = !empty( $get['gv_start'] ) ? $get['gv_start'] : '';
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
485
		$curr_end = !empty( $get['gv_start'] ) ? $get['gv_end'] : '';
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
486
487
		/**
488
		 * @filter `gravityview_date_created_adjust_timezone` Whether to adjust the timezone for entries. \n
489
		 * date_created is stored in UTC format. Convert search date into UTC (also used on templates/fields/date_created.php)
490
		 * @since 1.12
491
		 * @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
492
		 * @param[in] string $context Where the filter is being called from. `search` in this case.
493
		 */
494
		$adjust_tz = apply_filters( 'gravityview_date_created_adjust_timezone', true, 'search' );
495
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
496
497
		/**
498
		 * Don't set $search_criteria['start_date'] if start_date is empty as it may lead to bad query results (GFAPI::get_entries)
499
		 */
500
		if( !empty( $curr_start ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
501
			$search_criteria['start_date'] = $adjust_tz ? get_gmt_from_date( $curr_start ) : $curr_start;
502
		}
503
		if( !empty( $curr_end ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
504
			$search_criteria['end_date'] = $adjust_tz ? get_gmt_from_date( $curr_end ) : $curr_end;
505
		}
506
507
		// search for a specific entry ID
508
		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...
509
			$search_criteria['field_filters'][] = array(
510
				'key' => 'id',
511
				'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...
512
				'operator' => '=',
513
			);
514
		}
515
516
		// search for a specific Created_by ID
517
		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...
518
			$search_criteria['field_filters'][] = array(
519
				'key' => 'created_by',
520
				'value' => absint( $get['gv_by'] ),
521
				'operator' => '=',
522
			);
523
		}
524
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
525
526
		// Get search mode passed in URL
527
		$mode = isset( $get['mode'] ) && in_array( $get['mode'], array( 'any', 'all' ) ) ?  $get['mode'] : 'any';
528
529
		// get the other search filters
530
		foreach ( $get as $key => $value ) {
531
532
			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...
533
				continue;
534
			}
535
536
			// could return simple filter or multiple filters
537
			$filter = $this->prepare_field_filter( $key, $value );
538
539
			if ( isset( $filter[0]['value'] ) ) {
540
				$search_criteria['field_filters'] = array_merge( $search_criteria['field_filters'], $filter );
541
542
				// if date range type, set search mode to ALL
543
				if ( ! empty( $filter[0]['operator'] ) && in_array( $filter[0]['operator'], array( '>=', '<=', '>', '<' ) ) ) {
544
					$mode = 'all';
545
				}
546
			} elseif( !empty( $filter ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
547
				$search_criteria['field_filters'][] = $filter;
548
			}
549
		}
550
551
		/**
552
		 * @filter `gravityview/search/mode` Set the Search Mode (`all` or `any`)
553
		 * @since 1.5.1
554
		 * @param[out,in] string $mode Search mode (`any` vs `all`)
555
		 */
556
		$search_criteria['field_filters']['mode'] = apply_filters( 'gravityview/search/mode', $mode );
557
558
		do_action( 'gravityview_log_debug', sprintf( '%s[filter_entries] Returned Search Criteria: ', get_class( $this ) ), $search_criteria );
559
560
		unset( $get );
561
562
		return $search_criteria;
563
	}
564
565
	/**
566
	 * Prepare the field filters to GFAPI
567
	 *
568
	 * 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.
569
	 *
570
	 * Format searched values
571
	 * @param  string $key   $_GET/$_POST search key
572
	 * @param  string $value $_GET/$_POST search value
573
	 * @return array        1 or 2 deph levels
574
	 */
575
	public function prepare_field_filter( $key, $value ) {
576
577
		$gravityview_view = GravityView_View::getInstance();
578
579
		$field_id = str_replace( 'filter_', '', $key );
580
581
		// calculates field_id, removing 'filter_' and for '_' for advanced fields ( like name or checkbox )
582
		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...
583
			$field_id = str_replace( '_', '.', $field_id );
584
		}
585
586
		// get form field array
587
		$form = $gravityview_view->getForm();
588
		$form_field = gravityview_get_field( $form, $field_id );
589
590
		// default filter array
591
		$filter = array(
592
			'key' => $field_id,
593
			'value' => $value,
594
		);
595
596
		switch ( $form_field['type'] ) {
597
598
			case 'select':
599
			case 'radio':
600
				$filter['operator'] = 'is';
601
				break;
602
603
			case 'post_category':
604
605
				if ( ! is_array( $value ) ) {
606
					$value = array( $value );
607
				}
608
609
				// Reset filter variable
610
				$filter = array();
611
612
				foreach ( $value as $val ) {
613
					$cat = get_term( $val, 'category' );
614
					$filter[] = array(
615
						'key' => $field_id,
616
						'value' => esc_attr( $cat->name ) . ':' . $val,
617
						'operator' => 'is',
618
					);
619
				}
620
621
				break;
622
623
			case 'multiselect':
624
625
				if ( ! is_array( $value ) ) {
626
					break;
627
				}
628
629
				// Reset filter variable
630
				$filter = array();
631
632
				foreach ( $value as $val ) {
633
					$filter[] = array( 'key' => $field_id, 'value' => $val );
634
				}
635
636
				break;
637
638
			case 'checkbox':
639
				// convert checkbox on/off into the correct search filter
640
				if ( false !== strpos( $field_id, '.' ) && ! empty( $form_field['inputs'] ) && ! empty( $form_field['choices'] ) ) {
641
					foreach ( $form_field['inputs'] as $k => $input ) {
642
						if ( $input['id'] == $field_id ) {
643
							$filter['value'] = $form_field['choices'][ $k ]['value'];
644
							$filter['operator'] = 'is';
645
							break;
646
						}
647
					}
648
				} elseif ( is_array( $value ) ) {
649
650
					// Reset filter variable
651
					$filter = array();
652
653
					foreach ( $value as $val ) {
654
						$filter[] = array(
655
							'key'   => $field_id,
656
							'value' => $val,
657
							'operator' => 'is',
658
						);
659
					}
660
				}
661
662
				break;
663
664
			case 'name':
665
			case 'address':
666
667
				if ( false === strpos( $field_id, '.' ) ) {
668
669
					$words = explode( ' ', $value );
670
671
					$filters = array();
672
					foreach ( $words as $word ) {
673
						if ( ! empty( $word ) && strlen( $word ) > 1 ) {
674
							// Keep the same key for each filter
675
							$filter['value'] = $word;
676
							// Add a search for the value
677
							$filters[] = $filter;
678
						}
679
					}
680
681
					$filter = $filters;
682
				}
683
684
				break;
685
686
			case 'date':
687
688
				if ( is_array( $value ) ) {
689
690
					// Reset filter variable
691
					$filter = array();
692
693
					foreach ( $value as $k => $date ) {
694
						if ( empty( $date ) ) {
695
							continue;
696
						}
697
						$operator = 'start' === $k ? '>=' : '<=';
698
699
						/**
700
						 * @hack
701
						 * @since 1.16.3
702
						 * Safeguard until GF implements '<=' operator
703
						 */
704
						if( !GFFormsModel::is_valid_operator( $operator ) && $operator === '<=' ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
705
							$operator = '<';
706
							$date = date( 'Y-m-d', strtotime( $date . ' +1 day' ) );
707
						}
708
709
						$filter[] = array(
710
							'key' => $field_id,
711
							'value' => self::get_formatted_date( $date, 'Y-m-d' ),
712
							'operator' => $operator,
713
						);
714
					}
715
				} else {
716
					$filter['value'] = self::get_formatted_date( $value, 'Y-m-d' );
717
				}
718
719
				break;
720
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
721
722
		} // switch field type
723
724
		return $filter;
725
	}
726
727
	/**
728
	 * Get the Field Format form GravityForms
729
	 *
730
	 * @param GF_Field_Date $field The field object
731
	 * @since 1.10
732
	 *
733
	 * @return string Format of the date in the database
734
	 */
735
	public static function get_date_field_format( GF_Field_Date $field ) {
736
		$format = 'm/d/Y';
737
		$datepicker = array(
738
			'mdy' => 'm/d/Y',
739
			'dmy' => 'd/m/Y',
740
			'dmy_dash' => 'd-m-Y',
741
			'dmy_dot' => 'm.d.Y',
742
			'ymd_slash' => 'Y/m/d',
743
			'ymd_dash' => 'Y-m-d',
744
			'ymd_dot' => 'Y.m.d',
745
		);
746
747
		if ( ! empty( $field->dateFormat ) && isset( $datepicker[ $field->dateFormat ] ) ){
748
			$format = $datepicker[ $field->dateFormat ];
749
		}
750
751
		return $format;
752
	}
753
754
	/**
755
	 * Format a date value
756
	 *
757
	 * @param string $value Date value input
758
	 * @param string $format Wanted formatted date
759
	 * @return string
760
	 */
761
	public static function get_formatted_date( $value = '', $format = 'Y-m-d' ) {
762
		$date = date_create( $value );
763
		if ( empty( $date ) ) {
764
			do_action( 'gravityview_log_debug', sprintf( '%s[get_formatted_date] Date format not valid: ', get_class( self::$instance ) ), $value );
765
			return '';
766
		}
767
		return $date->format( $format );
768
	}
769
770
771
	/**
772
	 * Include this extension templates path
773
	 * @param array $file_paths List of template paths ordered
774
	 */
775
	public function add_template_path( $file_paths ) {
776
777
		// Index 100 is the default GravityView template path.
778
		$file_paths[102] = self::$file . 'templates/';
779
780
		return $file_paths;
781
	}
782
783
	/**
784
	 * Check whether the configured search fields have a date field
785
	 *
786
	 * @since 1.17.5
787
	 *
788
	 * @param array $search_fields
789
	 *
790
	 * @return bool True: has a `date` or `date_range` field
791
	 */
792
	private function has_date_field( $search_fields ) {
793
794
		$has_date = false;
795
796
		foreach ( $search_fields as $k => $field ) {
797
			if ( in_array( $field['input'], array( 'date', 'date_range', 'entry_date' ) ) ) {
798
				$has_date = true;
799
				break;
800
			}
801
		}
802
803
		return $has_date;
804
	}
805
806
	/**
807
	 * Renders the Search Widget
808
	 * @param array $widget_args
809
	 * @param string $content
810
	 * @param string $context
811
	 *
812
	 * @return void
813
	 */
814
	public function render_frontend( $widget_args, $content = '', $context = '' ) {
815
		/** @var GravityView_View $gravityview_view */
816
		$gravityview_view = GravityView_View::getInstance();
817
818
		if ( empty( $gravityview_view ) ) {
819
			do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend]: $gravityview_view not instantiated yet.', get_class( $this ) ) );
820
			return;
821
		}
822
823
		// get configured search fields
824
		$search_fields = ! empty( $widget_args['search_fields'] ) ? json_decode( $widget_args['search_fields'], true ) : '';
825
826
		if ( empty( $search_fields ) || ! is_array( $search_fields ) ) {
827
			do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend] No search fields configured for widget:', get_class( $this ) ), $widget_args );
828
			return;
829
		}
830
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
831
832
		// prepare fields
833
		foreach ( $search_fields as $k => $field ) {
834
835
			$updated_field = $field;
836
837
			$updated_field = $this->get_search_filter_details( $updated_field );
838
839
			switch ( $field['field'] ) {
840
841
				case 'search_all':
842
					$updated_field['key'] = 'search_all';
843
					$updated_field['input'] = 'search_all';
844
					$updated_field['value'] = $this->rgget_or_rgpost( 'gv_search' );
845
					break;
846
847
				case 'entry_date':
848
					$updated_field['key'] = 'entry_date';
849
					$updated_field['input'] = 'entry_date';
850
					$updated_field['value'] = array(
851
						'start' => $this->rgget_or_rgpost( 'gv_start' ),
852
						'end' => $this->rgget_or_rgpost( 'gv_end' ),
853
					);
854
					break;
855
856
				case 'entry_id':
857
					$updated_field['key'] = 'entry_id';
858
					$updated_field['input'] = 'entry_id';
859
					$updated_field['value'] = $this->rgget_or_rgpost( 'gv_id' );
860
					break;
861
862
				case 'created_by':
863
					$updated_field['key'] = 'created_by';
864
					$updated_field['name'] = 'gv_by';
865
					$updated_field['value'] = $this->rgget_or_rgpost( 'gv_by' );
866
					$updated_field['choices'] = self::get_created_by_choices();
867
					break;
868
			}
869
870
			$search_fields[ $k ] = $updated_field;
871
		}
872
873
		do_action( 'gravityview_log_debug', sprintf( '%s[render_frontend] Calculated Search Fields: ', get_class( $this ) ), $search_fields );
874
875
		/**
876
		 * @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.
877
		 * @param array $search_fields Array of search filters with `key`, `label`, `value`, `type` keys
878
		 * @param GravityView_Widget_Search $this Current widget object
879
		 * @param array $widget_args Args passed to this method. {@since 1.8}
880
		 * @var array
881
		 */
882
		$gravityview_view->search_fields = apply_filters( 'gravityview_widget_search_filters', $search_fields, $this, $widget_args );
883
884
		$gravityview_view->search_layout = ! empty( $widget_args['search_layout'] ) ? $widget_args['search_layout'] : 'horizontal';
885
886
		/** @since 1.14 */
887
		$gravityview_view->search_mode = ! empty( $widget_args['search_mode'] ) ? $widget_args['search_mode'] : 'any';
888
889
		$custom_class = ! empty( $widget_args['custom_class'] ) ? $widget_args['custom_class'] : '';
890
891
		$gravityview_view->search_class = self::get_search_class( $custom_class );
892
893
		$gravityview_view->search_clear = ! empty( $widget_args['search_clear'] ) ? $widget_args['search_clear'] : false;
894
895
		if ( $this->has_date_field( $search_fields ) ) {
896
			// enqueue datepicker stuff only if needed!
897
			$this->enqueue_datepicker();
898
		}
899
900
		$this->maybe_enqueue_flexibility();
901
902
		$gravityview_view->render( 'widget', 'search', false );
903
	}
904
905
	/**
906
	 * Get the search class for a search form
907
	 *
908
	 * @since 1.5.4
909
	 *
910
	 * @return string Sanitized CSS class for the search form
911
	 */
912
	public static function get_search_class( $custom_class = '' ) {
913
		$gravityview_view = GravityView_View::getInstance();
914
915
		$search_class = 'gv-search-'.$gravityview_view->search_layout;
916
917
		if ( ! empty( $custom_class )  ) {
918
			$search_class .= ' '.$custom_class;
919
		}
920
921
		/**
922
		 * @filter `gravityview_search_class` Modify the CSS class for the search form
923
		 * @param string $search_class The CSS class for the search form
924
		 */
925
		$search_class = apply_filters( 'gravityview_search_class', $search_class );
926
927
		// Is there an active search being performed? Used by fe-views.js
928
		$search_class .= GravityView_frontend::getInstance()->isSearch() ? ' gv-is-search' : '';
929
930
		return gravityview_sanitize_html_class( $search_class );
931
	}
932
933
934
	/**
935
	 * Calculate the search form action
936
	 * @since 1.6
937
	 *
938
	 * @return string
939
	 */
940
	public static function get_search_form_action() {
941
		$gravityview_view = GravityView_View::getInstance();
942
943
		$post_id = $gravityview_view->getPostId() ? $gravityview_view->getPostId() : $gravityview_view->getViewId();
944
945
		$url = add_query_arg( array(), get_permalink( $post_id ) );
946
947
		return esc_url( $url );
948
	}
949
950
	/**
951
	 * Get the label for a search form field
952
	 * @param  array $field      Field setting as sent by the GV configuration - has `field`, `input` (input type), and `label` keys
953
	 * @param  array $form_field Form field data, as fetched by `gravityview_get_field()`
954
	 * @return string             Label for the search form
955
	 */
956
	private static function get_field_label( $field, $form_field = array() ) {
957
958
		$label = rgget( 'label', $field );
959
960
		if( '' === $label ) {
961
962
			$label = isset( $form_field['label'] ) ? $form_field['label'] : '';
963
964
			switch( $field['field'] ) {
965
				case 'search_all':
966
					$label = __( 'Search Entries:', 'gravityview' );
967
					break;
968
				case 'entry_date':
969
					$label = __( 'Filter by date:', 'gravityview' );
970
					break;
971
				case 'entry_id':
972
					$label = __( 'Entry ID:', 'gravityview' );
973
					break;
974
				default:
975
					// If this is a field input, not a field
976
					if ( strpos( $field['field'], '.' ) > 0 && ! empty( $form_field['inputs'] ) ) {
977
978
						// Get the label for the field in question, which returns an array
979
						$items = wp_list_filter( $form_field['inputs'], array( 'id' => $field['field'] ) );
980
981
						// Get the item with the `label` key
982
						$values = wp_list_pluck( $items, 'label' );
983
984
						// There will only one item in the array, but this is easier
985
						foreach ( $values as $value ) {
986
							$label = $value;
987
							break;
988
						}
989
					}
990
			}
991
		}
992
993
		/**
994
		 * @filter `gravityview_search_field_label` Modify the label for a search field. Supports returning HTML
995
		 * @since 1.17.3 Added $field parameter
996
		 * @param[in,out] string $label Existing label text, sanitized.
997
		 * @param[in] array $form_field Gravity Forms field array, as returned by `GFFormsModel::get_field()`
998
		 * @param[in] array $field Field setting as sent by the GV configuration - has `field`, `input` (input type), and `label` keys
999
		 */
1000
		$label = apply_filters( 'gravityview_search_field_label', esc_attr( $label ), $form_field, $field );
1001
1002
		return $label;
1003
	}
1004
1005
	/**
1006
	 * Prepare search fields to frontend render with other details (label, field type, searched values)
1007
	 *
1008
	 * @param array $field
1009
	 * @return array
1010
	 */
1011
	private function get_search_filter_details( $field ) {
1012
1013
		$gravityview_view = GravityView_View::getInstance();
1014
1015
		$form = $gravityview_view->getForm();
1016
1017
		// for advanced field ids (eg, first name / last name )
1018
		$name = 'filter_' . str_replace( '.', '_', $field['field'] );
1019
1020
		// get searched value from $_GET/$_POST (string or array)
1021
		$value = $this->rgget_or_rgpost( $name );
1022
1023
		// get form field details
1024
		$form_field = gravityview_get_field( $form, $field['field'] );
1025
1026
		$filter = array(
1027
			'key' => $field['field'],
1028
			'name' => $name,
1029
			'label' => self::get_field_label( $field, $form_field ),
1030
			'input' => $field['input'],
1031
			'value' => $value,
1032
			'type' => $form_field['type'],
1033
		);
1034
1035
		// collect choices
1036
		if ( 'post_category' === $form_field['type'] && ! empty( $form_field['displayAllCategories'] ) && empty( $form_field['choices'] ) ) {
1037
			$filter['choices'] = gravityview_get_terms_choices();
1038
		} elseif ( ! empty( $form_field['choices'] ) ) {
1039
			$filter['choices'] = $form_field['choices'];
1040
		}
1041
1042
		if ( 'date_range' === $field['input'] && empty( $value ) ) {
1043
			$filter['value'] = array( 'start' => '', 'end' => '' );
1044
		}
1045
1046
		return $filter;
1047
1048
	}
1049
1050
	/**
1051
	 * Calculate the search choices for the users
1052
	 *
1053
	 * @since 1.8
1054
	 *
1055
	 * @return array Array of user choices (value = ID, text = display name)
1056
	 */
1057
	private static function get_created_by_choices() {
1058
1059
		/**
1060
		 * filter gravityview/get_users/search_widget
1061
		 * @see \GVCommon::get_users
1062
		 */
1063
		$users = GVCommon::get_users( 'search_widget', array( 'fields' => array( 'ID', 'display_name' ) ) );
1064
1065
		$choices = array();
1066
		foreach ( $users as $user ) {
1067
			$choices[] = array(
1068
				'value' => $user->ID,
1069
				'text' => $user->display_name,
1070
			);
1071
		}
1072
1073
		return $choices;
1074
	}
1075
1076
1077
	/**
1078
	 * Output the Clear Search Results button
1079
	 * @since 1.5.4
1080
	 */
1081
	public static function the_clear_search_button() {
1082
		$gravityview_view = GravityView_View::getInstance();
1083
1084
		if ( $gravityview_view->search_clear ) {
1085
1086
			$url = strtok( add_query_arg( array() ), '?' );
1087
1088
			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...
1089
1090
		}
1091
	}
1092
1093
	/**
1094
	 * Based on the search method, fetch the value for a specific key
1095
	 *
1096
	 * @since 1.16.4
1097
	 *
1098
	 * @param string $name Name of the request key to fetch the value for
1099
	 *
1100
	 * @return mixed|string Value of request at $name key. Empty string if empty.
1101
	 */
1102
	private function rgget_or_rgpost( $name ) {
1103
		$value = 'get' === $this->search_method ? rgget( $name ) : rgpost( $name );
1104
1105
		$value = stripslashes_deep( $value );
1106
1107
		$value = gv_map_deep( $value, 'rawurldecode' );
1108
1109
		$value = gv_map_deep( $value, '_wp_specialchars' );
1110
1111
		return $value;
1112
	}
1113
1114
1115
	/**
1116
	 * Require the datepicker script for the frontend GV script
1117
	 * @param array $js_dependencies Array of existing required scripts for the fe-views.js script
1118
	 * @return array Array required scripts, with `jquery-ui-datepicker` added
1119
	 */
1120
	public function add_datepicker_js_dependency( $js_dependencies ) {
1121
1122
		$js_dependencies[] = 'jquery-ui-datepicker';
1123
1124
		return $js_dependencies;
1125
	}
1126
1127
	/**
1128
	 * Modify the array passed to wp_localize_script()
1129
	 *
1130
	 * @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...
1131
	 * @param array $view_data View data array with View settings
1132
	 *
1133
	 * @return array
1134
	 */
1135
	public function add_datepicker_localization( $localizations = array(), $view_data = array() ) {
1136
		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...
1137
1138
		/**
1139
		 * @filter `gravityview_datepicker_settings` Modify the datepicker settings
1140
		 * @see http://api.jqueryui.com/datepicker/ Learn what settings are available
1141
		 * @see http://www.renegadetechconsulting.com/tutorials/jquery-datepicker-and-wordpress-i18n Thanks for the helpful information on $wp_locale
1142
		 * @param array $js_localization The data padded to the Javascript file
1143
		 * @param array $view_data View data array with View settings
1144
		 */
1145
		$datepicker_settings = apply_filters( 'gravityview_datepicker_settings', array(
1146
			'yearRange' => '-5:+5',
1147
			'changeMonth' => true,
1148
			'changeYear' => true,
1149
			'closeText' => esc_attr_x( 'Close', 'Close calendar', 'gravityview' ),
1150
			'prevText' => esc_attr_x( 'Prev', 'Previous month in calendar', 'gravityview' ),
1151
			'nextText' => esc_attr_x( 'Next', 'Next month in calendar', 'gravityview' ),
1152
			'currentText' => esc_attr_x( 'Today', 'Today in calendar', 'gravityview' ),
1153
			'weekHeader' => esc_attr_x( 'Week', 'Week in calendar', 'gravityview' ),
1154
			'monthStatus'       => __( 'Show a different month', 'gravityview' ),
1155
			'monthNames'        => array_values( $wp_locale->month ),
1156
			'monthNamesShort'   => array_values( $wp_locale->month_abbrev ),
1157
			'dayNames'          => array_values( $wp_locale->weekday ),
1158
			'dayNamesShort'     => array_values( $wp_locale->weekday_abbrev ),
1159
			'dayNamesMin'       => array_values( $wp_locale->weekday_initial ),
1160
			// get the start of week from WP general setting
1161
			'firstDay'          => get_option( 'start_of_week' ),
1162
			// is Right to left language? default is false
1163
			'isRTL'             => is_rtl(),
1164
		), $view_data );
1165
1166
		$localizations['datepicker'] = $datepicker_settings;
1167
1168
		return $localizations;
1169
1170
	}
1171
1172
	/**
1173
	 * Register search widget scripts, including Flexibility
1174
	 *
1175
	 * @see https://github.com/10up/flexibility
1176
	 *
1177
	 * @since 1.17
1178
	 *
1179
	 * @return void
1180
	 */
1181
	public function register_scripts() {
1182
1183
		wp_register_script( 'gv-flexibility', plugins_url( 'assets/lib/flexibility/dist/flexibility.js', GRAVITYVIEW_FILE ), array(), GravityView_Plugin::version, true );
1184
1185
	}
1186
1187
	/**
1188
	 * If the current visitor is running IE 8 or 9, enqueue Flexibility
1189
	 *
1190
	 * @since 1.17
1191
	 *
1192
	 * @return void
1193
	 */
1194
	private function maybe_enqueue_flexibility() {
1195
		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...
1196
			wp_enqueue_script( 'gv-flexibility' );
1197
		}
1198
	}
1199
1200
	/**
1201
	 * Enqueue the datepicker script
1202
	 *
1203
	 * It sets the $gravityview->datepicker_class parameter
1204
	 *
1205
	 * @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.
1206
	 * @return void
1207
	 */
1208
	public function enqueue_datepicker() {
1209
		$gravityview_view = GravityView_View::getInstance();
1210
1211
		wp_enqueue_script( 'jquery-ui-datepicker' );
1212
1213
		add_filter( 'gravityview_js_dependencies', array( $this, 'add_datepicker_js_dependency' ) );
1214
		add_filter( 'gravityview_js_localization', array( $this, 'add_datepicker_localization' ), 10, 2 );
1215
1216
		$scheme = is_ssl() ? 'https://' : 'http://';
1217
		wp_enqueue_style( 'jquery-ui-datepicker', $scheme.'ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/smoothness/jquery-ui.css' );
1218
1219
		/**
1220
		 * @filter `gravityview_search_datepicker_class`
1221
		 * 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.
1222
		 * @param string $css_class CSS class to use. Default: `gv-datepicker datepicker mdy` \n
1223
		 * Options are:
1224
		 * - `mdy` (mm/dd/yyyy)
1225
		 * - `dmy` (dd/mm/yyyy)
1226
		 * - `dmy_dash` (dd-mm-yyyy)
1227
		 * - `dmy_dot` (dd.mm.yyyy)
1228
		 * - `ymp_slash` (yyyy/mm/dd)
1229
		 * - `ymd_dash` (yyyy-mm-dd)
1230
		 * - `ymp_dot` (yyyy.mm.dd)
1231
		 */
1232
		$datepicker_class = apply_filters( 'gravityview_search_datepicker_class', 'gv-datepicker datepicker mdy' );
1233
1234
		$gravityview_view->datepicker_class = $datepicker_class;
1235
1236
	}
1237
1238
1239
} // end class
1240
1241
new GravityView_Widget_Search;