Completed
Push — master ( 5d7bd1...022e44 )
by Zack
04:13
created

GravityView_Widget_Search::render_frontend()   F

Complexity

Conditions 16
Paths 707

Size

Total Lines 96
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 16
eloc 52
c 2
b 0
f 0
nc 707
nop 3
dl 0
loc 96
rs 2.3966

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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