Completed
Pull Request — develop (#1433)
by
unknown
06:00
created

helper-functions.php ➔ gravityview_format_date()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
nc 1
nop 2
dl 0
loc 24
ccs 2
cts 2
cp 1
crap 3
rs 9.536
c 0
b 0
f 0
1
<?php
2
/**
3
 * Functions that don't require GravityView or Gravity Forms API access but are used in the plugin to extend PHP and WP functions
4
 * @since 1.12
5
 */
6
7
8
/**
9
 * Get the URL for a CSS file
10
 * 
11
 * If there's a CSS file with the same name as a GravityView CSS file in the current theme directory, it will be used.
12
 * Place the CSS file in a `/gravityview/css/` sub-directory. 
13
 * 
14
 * Example: /twentysixteen/gravityview/css/gv-default-styles.css
15
 *
16
 * Will use, in order:
17
 * 1) [theme directory]/gravityview/css/
18
 * 2) [gravityview plugin]/css/ (no check performed)
19
 *
20
 * @since 1.17
21
 *
22
 * @uses get_stylesheet_directory()
23
 * @uses get_stylesheet_directory_uri()
24
 *
25
 * @param string $css_file Filename of the CSS file (like gv-default-styles.css)
26
 * @param string $dir_path Absolute path to the directory where the CSS file is stored. If empty, uses default GravityView templates CSS folder.
27
 *
28
 * @return string URL path to the file.
29
 */
30
function gravityview_css_url( $css_file = '', $dir_path = '' ) {
31
32
	// If there's an overriding CSS file in the current template folder, use it.
33
	$template_css_path = trailingslashit( get_stylesheet_directory() ) . 'gravityview/css/' . $css_file;
34
35
	if( file_exists( $template_css_path ) ) {
36
		$path = trailingslashit( get_stylesheet_directory_uri() ) . 'gravityview/css/' . $css_file;
37
		gravityview()->log->debug( 'Stylesheet override ({css_file})', array( 'css_file' => esc_attr( $css_file ) ) );
38
	} else {
39
		// Default: use GravityView CSS file
40
41
		// If no path is provided, assume default plugin templates CSS folder
42
		if( '' === $dir_path ) {
43
			$dir_path = GRAVITYVIEW_DIR . 'templates/css/';
44
		}
45
		
46
		// plugins_url() expects a path to a file, not directory. We append a file to be stripped.
47
		$path = plugins_url( $css_file, trailingslashit( $dir_path )  . 'stripped-by-plugin_basename.php' );
48
	}
49
50
	return $path;
51
}
52
53
/**
54
 * Check whether a variable is not an empty string
55
 *
56
 * @see /templates/fields/product.php Used to check whether the product array is empty or not
57
 *
58
 * @since 1.12
59
 *
60
 * @param mixed $mixed Variable to check
61
 *
62
 * @return bool true: $mixed is *not* an empty string; false: $mixed *is* an empty string
63
 */
64
function gravityview_is_not_empty_string( $mixed = '' ) {
65 5
	return ( $mixed !== '' );
66
}
67
68
/**
69
 * Get `get_permalink()` without the home_url() prepended to it.
70
 *
71
 * get_permalink() does a lot of good stuff: it gets the correct permalink structure for custom post types, pages,
72
 * posts, etc. Instead of using `?p={id}`, `?page_id={id}`, or `?p={id}&post_type={post_type}`, by using
73
 * get_permalink(), we can use `?p=slug` or `?gravityview={slug}`
74
 *
75
 * We could do this in a cleaner fashion, but this prevents a lot of code duplication, checking for URL structure, etc.
76
 *
77
 * @param int|WP_Post $id        Optional. Post ID or post object. Default current post.
78
 *
79
 * @return array URL args, if exists. Empty array if not.
80
 */
81
function gravityview_get_permalink_query_args( $id = 0 ) {
82
83 4
	$parsed_permalink = parse_url( get_permalink( $id ) );
84
85 4
	$permalink_args =  isset( $parsed_permalink['query'] ) ? $parsed_permalink['query'] : false;
86
87 4
	if( empty( $permalink_args ) ) {
88
		return array();
89
	}
90
91 4
	parse_str( $permalink_args, $args );
92
93 4
	return $args;
94
}
95
96
97
/**
98
 * Similar to the WordPress `selected()`, `checked()`, and `disabled()` functions, except it allows arrays to be passed as current value
99
 *
100
 * @see selected() WordPress core function
101
 *
102
 * @param string $value One of the values to compare
103
 * @param mixed $current (true) The other value to compare if not just true
104
 * @param bool $echo Whether to echo or just return the string
105
 * @param string $type The type of checked|selected|disabled we are doing
106
 *
107
 * @return string html attribute or empty string
108
 */
109
function gv_selected( $value, $current, $echo = true, $type = 'selected' ) {
110
111
	$output = '';
112
	if( is_array( $current ) ) {
113
		if( in_array( $value, $current ) ) {
114
			$output = __checked_selected_helper( true, true, false, $type );
115
		}
116
	} else {
117
		$output = __checked_selected_helper( $value, $current, false, $type );
118
	}
119
120
	if( $echo ) {
121
		echo $output;
122
	}
123
124
	return $output;
125
}
126
127
128
if( ! function_exists( 'gravityview_sanitize_html_class' ) ) {
129
130
	/**
131
	 * sanitize_html_class doesn't handle spaces (multiple classes). We remedy that.
132
	 *
133
	 * @uses sanitize_html_class
134
	 *
135
	 * @param  string|array $classes Text or array of classes to sanitize
136
	 *
137
	 * @return string            Sanitized CSS string
138
	 */
139
	function gravityview_sanitize_html_class( $classes ) {
140
141 60
		if ( is_string( $classes ) ) {
142 60
			$classes = explode( ' ', $classes );
143
		}
144
145
		// If someone passes something not string or array, we get outta here.
146 60
		if ( ! is_array( $classes ) ) {
147
			return $classes;
148
		}
149
150 60
		$classes = array_map( 'trim', $classes );
151 60
		$classes = array_map( 'sanitize_html_class', $classes );
152 60
		$classes = array_filter( $classes );
153
154 60
		return implode( ' ', $classes );
155
	}
156
}
157
158
/**
159
 * Replace multiple newlines, tabs, and spaces with a single space
160
 *
161
 * First, runs normalize_whitespace() on a string. This replaces multiple lines with a single line, and tabs with spaces.
162
 * We then strip any tabs or newlines and replace *those* with a single space.
163
 *
164
 * @see normalize_whitespace()
165
 * @see GravityView_Helper_Functions_Test::test_gravityview_strip_whitespace
166
 * @since 1.13
167
 *
168
 * @param string $string String to strip whitespace from
169
 *
170
 * @return string Stripped string!
171
 */
172
function gravityview_strip_whitespace( $string ) {
173 24
	$string = normalize_whitespace( $string );
174 24
	return preg_replace('/[\r\n\t ]+/', ' ', $string );
175
}
176
177
/**
178
 * Get the contents of a file using `include()` and `ob_start()`
179
 *
180
 * @since 1.13
181
 * @since 1.15 Added $object param
182
 *
183
 * @param string $file_path Full path to a file
184
 * @param mixed $object Pass pseudo-global to the included file
185
 * @return string Included file contents
186
 */
187
function gravityview_ob_include( $file_path, $object = NULL ) {
188 22
	if( ! file_exists( $file_path ) ) {
189
		gravityview()->log->error( 'File path does not exist. {path}', array( 'path' => $file_path ) );
190
		return '';
191
	}
192 22
	ob_start();
193 22
	include( $file_path );
194 22
	return ob_get_clean();
195
}
196
197
/**
198
 * Get an image of our intrepid explorer friend
199
 *
200
 * @since 1.12
201
 * @since 2.1 Added $class parameter
202
 *
203
 * @param int $height Height of the cutie in pixels
204
 * @param null|string $css_class If defined, use the passed CSS class (can be empty string). Otherwise, use default alignleft (or alignright, based on RTL).
205
 *
206
 * @return string HTML image tag with floaty's cute mug on it
207
 */
208
function gravityview_get_floaty( $height = 87, $css_class = null ) {
209
210 2
	$width = $height * 0.7586206897;
211
212 2
	if( function_exists('is_rtl') && is_rtl() ) {
213
		$style = 'margin:10px 10px 10px 0; height='. $height .'px; width: '. $width .'px;';
214
		$css_class = is_string( $css_class ) ? $css_class : 'alignright';
215
	} else {
216 2
		$style = 'margin:10px 10px 10px 0; height='. $height .'px; width: '. $width .'px;';
217 2
		$css_class = is_string( $css_class ) ? $css_class : 'alignleft';
218
	}
219
220 2
	return '<img src="'. esc_url( plugins_url( 'assets/images/astronaut-200x263.png', GRAVITYVIEW_FILE ) ) .'" class="'. gravityview_sanitize_html_class( $css_class ).'" height="'.intval( $height ).'" width="'.round( $width, 2 ).'" alt="The GravityView Astronaut Says:" style="'.$style.'" />';
221
}
222
223
/**
224
 * Intelligently format a number
225
 *
226
 * If you don't define the number of decimal places, then it will use the existing number of decimal places. This is done
227
 * in a way that respects the localization of the site.
228
 *
229
 * If you do define decimals, it uses number_format_i18n()
230
 *
231
 * @see number_format_i18n()
232
 *
233
 * @since 1.13
234
 *
235
 * @param int|float|string|double $number A number to format
236
 * @param int|string $decimals Optional. Precision of the number of decimal places. Default '' (use existing number of decimals)
237
 * @param boolean $separator Separate with dots or commas, etc. Default: true.
238
 *
239
 * @return string Converted number in string format.
240
 */
241
function gravityview_number_format( $number, $decimals = '', $separator = true ) {
242 216
	global $wp_locale;
243
244 216
	if( '' === $decimals ) {
245
246 216
		$decimal_point = isset( $wp_locale ) ? $wp_locale->number_format['decimal_point'] : '.';
247
248
		/**
249
		 * Calculate the position of the decimal point in the number
250
		 * @see http://stackoverflow.com/a/2430144/480856
251
		 */
252 216
		$decimals = strlen( substr( strrchr( $number, $decimal_point ), 1 ) );
253
	}
254
255 216
	if ( $separator ) {
256 216
		$number = number_format_i18n( $number, (int)$decimals );
257
	} else {
258 7
		$number = sprintf( "%.{$decimals}f", $number );
259
	}
260
261 216
	return $number;
262
}
263
264
265
/**
266
 * Convert a whole link into a shorter link for display
267
 *
268
 * @since 1.1
269
 *
270
 * @param  string $value Existing URL
271
 * @return string        If parse_url doesn't find a 'host', returns original value. Otherwise, returns formatted link.
272
 */
273
function gravityview_format_link( $value = null ) {
274
275
276 5
	$parts = parse_url( $value );
277
278
	// No domain? Strange...show the original text.
279 5
	if( empty( $parts['host'] ) ) {
280 2
		return $value;
281
	}
282
283
	// Start with empty value for the return URL
284 5
	$return = '';
285
286
	/**
287
	 * @filter `gravityview_anchor_text_striphttp` Strip scheme from the displayed URL?
288
	 * @since 1.5.1
289
	 * @param boolean $enable Whether to strip the scheme. Return false to show scheme. (default: true)\n
290
	 * If true: `http://example.com => example.com`
291
	 */
292 5
	if( false === apply_filters('gravityview_anchor_text_striphttp', true) ) {
293
294
		if( isset( $parts['scheme'] ) ) {
295
			$return .= $parts['scheme'];
296
		}
297
298
	}
299
300
	// The domain, which may contain a subdomain
301 5
	$domain = $parts['host'];
302
303
	/**
304
	 * @filter `gravityview_anchor_text_stripwww` Strip www from the domain?
305
	 * @since 1.5.1
306
	 * @param boolean $enable Whether to strip www. Return false to show www. (default: true)\n
307
	 * If true: `www.example.com => example.com`
308
	 */
309 5
	$strip_www = apply_filters('gravityview_anchor_text_stripwww', true );
310
311 5
	if( $strip_www ) {
312 5
		$domain = str_replace('www.', '', $domain );
313
	}
314
315
	/**
316
	 * @filter `gravityview_anchor_text_nosubdomain` Strip subdomains from the domain?
317
	 * @since 1.5.1
318
	 * @param boolean $enable Whether to strip subdomains. Return false to show subdomains. (default: true)\n
319
	 * If true: `http://demo.example.com => example.com` \n
320
	 * If false: `http://demo.example.com => demo.example.com`
321
	 */
322 5
	$strip_subdomains = apply_filters('gravityview_anchor_text_nosubdomain', true);
323
324 5
	if( $strip_subdomains ) {
325
326 4
		$domain = _gravityview_strip_subdomain( $parts['host'] );
327
328
	}
329
330
	// Add the domain
331 5
	$return .= $domain;
332
333
	/**
334
	 * @filter `gravityview_anchor_text_rootonly` Display link path going only to the base directory, not a sub-directory or file?
335
	 * @since 1.5.1
336
	 * @param boolean $enable Whether to enable "root only". Return false to show full path. (default: true)\n
337
	 * If true: `http://example.com/sub/directory/page.html => example.com`  \n
338
	 * If false: `http://example.com/sub/directory/page.html => example.com/sub/directory/page.html`
339
	 */
340 5
	$root_only = apply_filters('gravityview_anchor_text_rootonly', true);
341
342 5
	if( empty( $root_only ) ) {
343
344 1
		if( isset( $parts['path'] ) ) {
345 1
			$return .= $parts['path'];
346
		}
347
	}
348
349
	/**
350
	 * @filter `gravityview_anchor_text_noquerystring` Strip the query string from the end of the URL?
351
	 * @since 1.5.1
352
	 * @param boolean $enable Whether to enable "root only". Return false to show full path. (default: true)\n
353
	 * If true: `http://example.com/?query=example => example.com`
354
	 */
355 5
	$strip_query_string = apply_filters('gravityview_anchor_text_noquerystring', true );
356
357 5
	if( empty( $strip_query_string ) ) {
358
359 1
		if( isset( $parts['query'] ) ) {
360 1
			$return .= '?'.$parts['query'];
361
		}
362
363
	}
364
365 5
	return $return;
366
}
367
368
/**
369
 * Do a _very_ basic match for second-level TLD domains, like `.co.uk`
370
 *
371
 * Ideally, we'd use https://github.com/jeremykendall/php-domain-parser to check for this, but it's too much work for such a basic functionality. Maybe if it's needed more in the future. So instead, we use [Basic matching regex](http://stackoverflow.com/a/12372310).
372
 * @param  string $domain Domain to check if it's a TLD or subdomain
0 ignored issues
show
Documentation introduced by
There is no parameter named $domain. Did you maybe mean $string_maybe_has_subdomain?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

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

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

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

Loading history...
373
 * @return string         Extracted domain if it has a subdomain
374
 */
375
function _gravityview_strip_subdomain( $string_maybe_has_subdomain ) {
376
377 2
	if( preg_match("/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.(?:com\.|co\.|net\.|org\.|firm\.|me\.|school\.|law\.|gov\.|mod\.|msk\.|irkutsks\.|sa\.|act\.|police\.|plc\.|ac\.|tm\.|asso\.|biz\.|pro\.|cg\.|telememo\.)?[a-z\.]{2,6})$/i", $string_maybe_has_subdomain, $matches ) ) {
378 2
		return $matches['domain'];
379
	} else {
380
		return $string_maybe_has_subdomain;
381
	}
382
}
383
384
/**
385
 * The inverse of gv_empty()
386
 *
387
 * @since 2.0
388
 *
389
 * @param mixed  $value Check whether this is not empty
390
 * @param bool $zero_is_empty Should the number zero be treated as an empty value? Default: `false`
391
 * @param bool $allow_string_booleans Whether to check if 'yes', 'true' => `true` and 'no', 'false' => `false`. Default: `false`
392
 *
393
 * @return bool
394
 */
395
function gv_not_empty( $value, $zero_is_empty = false, $allow_string_booleans = false ) {
396
	return ! gv_empty( $value, $zero_is_empty, $allow_string_booleans );
397
}
398
399
/**
400
 * Is the value empty?
401
 *
402
 * Allows you to pass a function instead of just a variable, like the empty() function insists upon (until PHP 5.5)
403
 *
404
 * Checks whether `false`, `null`, empty string, empty array, object with no vars defined
405
 *
406
 * @since 1.15.1
407
 * @param  mixed  $value Check whether this is empty
408
 * @param boolean $zero_is_empty Should the number zero be treated as an empty value?
409
 * @param boolean $allow_string_booleans Whether to check if 'yes', 'true' => `true` and 'no', 'false' => `false`
410
 * @return boolean        True: empty; false: not empty
411
 */
412
function gv_empty( $value, $zero_is_empty = true, $allow_string_booleans = true ) {
413
414
	/**
415
	 * Arrays with empty values are empty.
416
	 *
417
	 * Consider the a missing product field.
418
	 */
419 48
	if ( is_array( $value ) ) {
420 3
		$values = array();
421 3
		foreach ( $value as $v ) {
422 3
			if ( ! gv_empty( $v, $zero_is_empty, $allow_string_booleans ) ) {
423 3
				return false;
424
			}
425
		}
426 3
		return true;
427
	}
428
429
	if (
430 48
		! isset( $value ) // If it's not set, it's empty!
431 48
		|| false === $value
432 48
		|| null === $value
433 48
	    || '' === $value // Empty string
434 48
		|| array() === $value // Empty array
435 48
		|| ( is_object( $value ) && ! get_object_vars( $value ) ) // Empty object
436
	) {
437 13
		return true;
438
	}
439
440 48
	if ( is_string( $value ) && $allow_string_booleans ) {
441
442 1
		$value = trim( $value );
443 1
		$value = strtolower( $value );
444
445 1
		if ( in_array( $value, array( 'yes', 'true' ), true ) ) {
446
			$value = true;
447 1
		} else if( in_array( $value, array( 'no', 'false' ), true ) ) {
448 1
			$value = false;
449
		}
450
	}
451
452
	// If zero isn't empty, then if $value is a number and it's empty, it's zero. Thus, return false.
453 48
	if ( ! $zero_is_empty && is_numeric( $value ) && empty( $value ) ) {
454 2
		return false;
455
	}
456
457 48
	return empty( $value );
458
}
459
460
/**
461
 * If content is JSON, decode it. Otherwise, return the passed value
462
 *
463
 * @since 2.0
464
 *
465
 * @see json_decode() for more information about the function parameters
466
 *
467
 * @param string $value The string that may be decoded
468
 * @param bool $assoc [optional] When `true`, returned objects will be converted into associative arrays
469
 * @param int $depth [optional] User specified recursion depth.
470
 * @param int $options [optional] Bitmask of JSON decode options. Used only on sites running PHP 5.4+
471
 *
472
 * @return array|mixed|object|string If $value is JSON, returns the response from `json_decode()`. Otherwise, returns original value.
473
 */
474
function gv_maybe_json_decode( $value, $assoc = false, $depth = 512, $options = 0 ) {
475
476
	if( ! is_string( $value ) ) {
477
		return $value;
478
	}
479
480
	if ( version_compare( phpversion(), '5.4.0', '>=' ) ) {
481
		$decoded = json_decode( $value, $assoc, $depth, $options );
482
	} else {
483
		$decoded = json_decode( $value, $assoc, $depth );
484
	}
485
486
	// There was a JSON error (PHP 5.3+)
487
	if( function_exists('json_last_error') && JSON_ERROR_NONE !== json_last_error() ) {
488
		return $value;
489
	}
490
491
	// It wasn't JSON (PHP < 5.3 fallback)
492
	if( is_null( $decoded ) ) {
493
		return $value;
494
	}
495
496
	return $decoded;
497
}
498
499
500
/**
501
 * Maps a function to all non-iterable elements of an array or an object.
502
 *
503
 * @see map_deep() This is an alias of the WP core function `map_deep()`, added in 4.4. Here for legacy purposes.
504
 * @since 1.16.3
505
 *
506
 * @param mixed    $value    The array, object, or scalar.
507
 * @param callable $callback The function to map onto $value.
508
 *
509
 * @return mixed The value with the callback applied to all non-arrays and non-objects inside it.
510
 */
511
function gv_map_deep( $value, $callback ) {
512
513
	// Use the original function, if exists.
514
	// Requires WP 4.4+
515 48
	if( function_exists( 'map_deep') ) {
516 48
		return map_deep( $value, $callback );
517
	}
518
519
	// Exact copy of map_deep() code below:
520
	if ( is_array( $value ) ) {
521
		foreach ( $value as $index => $item ) {
522
			$value[ $index ] = gv_map_deep( $item, $callback );
523
		}
524
	} elseif ( is_object( $value ) ) {
525
		$object_vars = get_object_vars( $value );
526
		foreach ( $object_vars as $property_name => $property_value ) {
527
			$value->$property_name = gv_map_deep( $property_value, $callback );
528
		}
529
	} else {
530
		$value = call_user_func( $callback, $value );
531
	}
532
533
	return $value;
534
}
535
536
/**
537
 * Check whether a string is a expected date format
538
 *
539
 * @since 1.15.2
540
 *
541
 * @param string $datetime The date to check
542
 * @param string $expected_format Check whether the date is formatted as expected. Default: Y-m-d
543
 *
544
 * @return bool True: it's a valid datetime, formatted as expected. False: it's not a date formatted as expected.
545
 */
546
function gravityview_is_valid_datetime( $datetime, $expected_format = 'Y-m-d' ) {
547
548
	/**
549
	 * @var bool|DateTime False if not a valid date, (like a relative date). DateTime if a date was created.
550
	 */
551 1
	$formatted_date = DateTime::createFromFormat( $expected_format, $datetime );
552
553
	/**
554
	 * @see http://stackoverflow.com/a/19271434/480856
555
	 */
556 1
	return ( $formatted_date && $formatted_date->format( $expected_format ) === $datetime );
557
}
558
559
/**
560
 * Format date according to locale and using the timezone offset
561
 *
562
 * `wp_date()` is used if available; otherwise, timezone offset is added to the timestamp before it is passed to `date_i18n()`
563
 *
564
 * @since 2.7.2
565
 *
566
 * @param string $format Date format
567
 * @param string $timestamp Timestamp
568
 *
569
 * @return string|false Formatted date or false if the timestamp is invalid
570
 */
571
function gravityview_format_date( $format, $timestamp ) {
572
573 3
	$timestamp = \GFCommon::get_local_timestamp( $timestamp );
574 3
	return date_i18n( $format, $timestamp );
575
576
	if ( function_exists( 'wp_date' ) ) {
0 ignored issues
show
Unused Code introduced by
if (function_exists('wp_...$format, $timestamp); } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
577
		return wp_date( $format, $timestamp );
578
	}
579
580
	$timezone_str = get_option( 'timezone_string' ) ?: 'UTC';
581
	$timezone     = new \DateTimeZone( $timezone_str );
582
583
	// Get date in local TZ
584
	$date = new \DateTime( null, $timezone );
585
	$date->setTimestamp( $timestamp );
586
	$date_str = $date->format( 'Y-m-d H:i:s' );
587
588
	//  Get UTC timestamp
589
	$utc_timezone = new \DateTimeZone( 'UTC' );
590
	$utc_date     = new \DateTime( $date_str, $utc_timezone );
591
	$timestamp    = $utc_date->getTimestamp();
592
593
	return date_i18n( $format, $timestamp );
594
}
595
596
/**
597
 * Very commonly needed: get the # of the input based on a full field ID.
598
 *
599
 * Example: 12.3 => field #12, input #3. Returns: 3
600
 * Example: 7 => field #7, no input. Returns: 0
601
 *
602
 * @since 1.16.4
603
 *
604
 * @param string $field_id Full ID of field, with or without input ID, like "12.3" or "7".
605
 *
606
 * @return int If field ID has an input, returns that input number. Otherwise, returns false.
607
 */
608
function gravityview_get_input_id_from_id( $field_id = '' ) {
609
610 10
	if ( ! is_numeric( $field_id ) ) {
611 1
		gravityview()->log->error( '$field_id not numeric', array( 'data' => $field_id ) );
612 1
		return false;
613
	}
614
615 10
	$exploded = explode( '.', "{$field_id}" );
616
617 10
	return isset( $exploded[1] ) ? intval( $exploded[1] ) : false;
618
}
619
620
/**
621
 * Get categories formatted in a way used by GravityView and Gravity Forms input choices
622
 *
623
 * @since 1.15.3
624
 *
625
 * @see get_terms()
626
 *
627
 * @param array $args Arguments array as used by the get_terms() function. Filtered using `gravityview_get_terms_choices_args` filter. Defaults: { \n
628
 *   @type string $taxonomy Used as first argument in get_terms(). Default: "category"
629
 *   @type string $fields Default: 'id=>name' to only fetch term ID and Name \n
630
 *   @type int $number  Limit the total number of terms to fetch. Default: 1000 \n
631
 * }
632
 *
633
 * @return array Multidimensional array with `text` (Category Name) and `value` (Category ID) keys.
634
 */
635
function gravityview_get_terms_choices( $args = array() ) {
636
637
	$defaults = array(
638
		'type'         => 'post',
639
		'child_of'     => 0,
640
		'number'       => 1000, // Set a reasonable max limit
641
		'orderby'      => 'name',
642
		'order'        => 'ASC',
643
		'hide_empty'   => 0,
644
		'hierarchical' => 1,
645
		'taxonomy'     => 'category',
646
		'fields'       => 'id=>name',
647
	);
648
649
	$args = wp_parse_args( $args, $defaults );
650
651
	/**
652
	 * @filter `gravityview_get_terms_choices_args` Modify the arguments passed to `get_terms()`
653
	 * @see get_terms()
654
	 * @since 1.15.3
655
	 */
656
	$args = apply_filters( 'gravityview_get_terms_choices_args', $args );
657
658
	$terms = get_terms( $args['taxonomy'], $args );
659
660
	$choices = array();
661
662
	if ( is_array( $terms ) ) {
663
		foreach ( $terms as $term_id => $term_name ) {
664
			$choices[] = array(
665
				'text'  => $term_name,
666
				'value' => $term_id
667
			);
668
		}
669
	}
670
671
	return $choices;
672
}
673
674
/**
675
 * Maybe convert jQuery-serialized fields into array, otherwise return $_POST['fields'] array
676
 *
677
 * Fields are passed as a jQuery-serialized array, created in admin-views.js in the serializeForm method.
678
 *
679
 * @since 1.16.5
680
 *
681
 * @uses GVCommon::gv_parse_str
682
 *
683
 * @return array Array of fields
684
 */
685
function _gravityview_process_posted_fields() {
686
	$fields = array();
687
688
	if( !empty( $_POST['gv_fields'] ) ) {
689
		if ( ! is_array( $_POST['gv_fields'] ) ) {
690
691
			// We are not using parse_str() due to max_input_vars limitation with large View configurations
692
			$fields_holder = array();
693
			GVCommon::gv_parse_str( stripslashes( $_POST['gv_fields'] ), $fields_holder );
694
695
			if ( isset( $fields_holder['fields'] ) ) {
696
				$fields = $fields_holder['fields'];
697
			} else {
698
				gravityview()->log->error( 'No `fields` key was found after parsing $fields string', array( 'data' => $fields_holder ) );
699
			}
700
701
		} else {
702
			$fields = $_POST['gv_fields'];
703
		}
704
	}
705
706
	return $fields;
707
}
708