Completed
Pull Request — 2.x (#4569)
by Scott Kingsley
04:52
created

PodsField_DateTime::convert_format()   C

Complexity

Conditions 10
Paths 36

Size

Total Lines 93
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
dl 0
loc 93
rs 5.0515
c 0
b 0
f 0
eloc 62
nc 36
nop 2

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
2
3
/**
4
 * @package Pods\Fields
5
 */
6
class PodsField_DateTime extends PodsField {
7
8
	/**
9
	 * Field Type Group
10
	 *
11
	 * @var string
12
	 * @since 2.0
13
	 */
14
	public static $group = 'Date / Time';
15
16
	/**
17
	 * Field Type Identifier
18
	 *
19
	 * @var string
20
	 * @since 2.0
21
	 */
22
	public static $type = 'datetime';
23
24
	/**
25
	 * Field Type Label
26
	 *
27
	 * @var string
28
	 * @since 2.0
29
	 */
30
	public static $label = 'Date / Time';
31
32
	/**
33
	 * Field Type Preparation
34
	 *
35
	 * @var string
36
	 * @since 2.0
37
	 */
38
	public static $prepare = '%s';
39
40
	/**
41
	 * Storage format.
42
	 *
43
	 * @var string
44
	 * @since 2.7
45
	 */
46
	public static $storage_format = 'Y-m-d H:i:s';
47
48
	/**
49
	 * The default empty value (database)
50
	 *
51
	 * @var string
52
	 * @since 2.7
53
	 */
54
	public static $empty_value = '0000-00-00 00:00:00';
55
56
	/**
57
	 * Do things like register/enqueue scripts and stylesheets
58
	 *
59
	 * @since 2.0
60
	 */
61
	public function __construct() {
62
63
		static::$label = __( 'Date / Time', 'pods' );
64
	}
65
66
	/**
67
	 * Add options and set defaults to
68
	 *
69
	 * @return array
70
	 *
71
	 * @since 2.0
72
	 */
73
	public function options() {
74
75
		$options = array(
76
			static::$type . '_repeatable'            => array(
77
				'label'             => __( 'Repeatable Field', 'pods' ),
78
				'default'           => 0,
79
				'type'              => 'boolean',
80
				'help'              => __( 'Making a field repeatable will add controls next to the field which allows users to Add/Remove/Reorder additional values. These values are saved in the database as an array, so searching and filtering by them may require further adjustments".', 'pods' ),
81
				'boolean_yes_label' => '',
82
				'dependency'        => true,
83
				'developer_mode'    => true,
84
			),
85
			static::$type . '_type'                  => array(
86
				'label'                        => __( 'Date Format Type', 'pods' ),
87
				'default'                      => 'format',
88
				// Backwards compatibility
89
										'type' => 'pick',
90
				'help'                         => __( 'WordPress Default is the format used in Settings, General under "Date Format".', 'pods' ) . '<br>' . __( 'Predefined Format will allow you to select from a list of commonly used date formats.', 'pods' ) . '<br>' . __( 'Custom will allow you to enter your own using PHP Date/Time Strings.', 'pods' ),
91
				'data'                         => array(
92
					'wp'     => __( 'WordPress default', 'pods' ) . ': ' . date_i18n( get_option( 'date_format' ) ),
93
					'format' => __( 'Predefined format', 'pods' ),
94
					'custom' => __( 'Custom format', 'pods' ),
95
				),
96
				'dependency'                   => true,
97
			),
98
			static::$type . '_format_custom'         => array(
99
				'label'      => __( 'Date format for display', 'pods' ),
100
				'depends-on' => array( static::$type . '_type' => 'custom' ),
101
				'default'    => '',
102
				'type'       => 'text',
103
				'help'       => '<a href="http://php.net/manual/function.date.php" target="_blank">' . __( 'PHP date documentation', 'pods' ) . '</a>',
104
			),
105
			static::$type . '_format_custom_js'      => array(
106
				'label'      => __( 'Date format for input', 'pods' ),
107
				'depends-on' => array( static::$type . '_type' => 'custom' ),
108
				'default'    => '',
109
				'type'       => 'text',
110
				'help'       => '<a href="https://api.jqueryui.com/datepicker/" target="_blank">' . __( 'jQuery UI datepicker documentation', 'pods' ) . '</a>' . '<br>' . __( 'Leave empty to auto-generate from PHP format.', 'pods' ),
111
			),
112
			static::$type . '_format'                => array(
113
				'label'      => __( 'Date Format', 'pods' ),
114
				'depends-on' => array( static::$type . '_type' => 'format' ),
115
				'default'    => 'mdy',
116
				'type'       => 'pick',
117
				'data'       => array(
118
					'mdy'       => date_i18n( 'm/d/Y' ),
119
					'mdy_dash'  => date_i18n( 'm-d-Y' ),
120
					'mdy_dot'   => date_i18n( 'm.d.Y' ),
121
					'ymd_slash' => date_i18n( 'Y/m/d' ),
122
					'ymd_dash'  => date_i18n( 'Y-m-d' ),
123
					'ymd_dot'   => date_i18n( 'Y.m.d' ),
124
					'fjy'       => date_i18n( 'F j, Y' ),
125
					'fjsy'      => date_i18n( 'F jS, Y' ),
126
					'c'         => date_i18n( 'c' ),
127
				),
128
				'dependency' => true,
129
			),
130
			static::$type . '_time_type'             => array(
131
				'label'                        => __( 'Time Format Type', 'pods' ),
132
				'excludes-on'                  => array( static::$type . '_format' => 'c' ),
133
				'default'                      => '12',
134
				// Backwards compatibility
135
										'type' => 'pick',
136
				'help'                         => __( 'WordPress Default is the format used in Settings, General under "Time Format".', 'pods' ) . '<br>' . __( '12/24 hour will allow you to select from a list of commonly used time formats.', 'pods' ) . '<br>' . __( 'Custom will allow you to enter your own using PHP Date/Time Strings.', 'pods' ),
137
				'data'                         => array(
138
					'wp'     => __( 'WordPress default', 'pods' ) . ': ' . date_i18n( get_option( 'time_format' ) ),
139
					'12'     => __( '12 hour', 'pods' ),
140
					'24'     => __( '24 hour', 'pods' ),
141
					'custom' => __( 'Custom', 'pods' ),
142
				),
143
				'dependency'                   => true,
144
			),
145
			static::$type . '_time_format_custom'    => array(
146
				'label'       => __( 'Time format', 'pods' ),
147
				'depends-on'  => array( static::$type . '_time_type' => 'custom' ),
148
				'excludes-on' => array( static::$type . '_format' => 'c' ),
149
				'default'     => '',
150
				'type'        => 'text',
151
				'help'        => '<a href="http://php.net/manual/function.date.php" target="_blank">' . __( 'PHP date documentation', 'pods' ) . '</a>',
152
			),
153
			static::$type . '_time_format_custom_js' => array(
154
				'label'       => __( 'Time format field input', 'pods' ),
155
				'depends-on'  => array( static::$type . '_time_type' => 'custom' ),
156
				'excludes-on' => array( static::$type . '_format' => 'c' ),
157
				'default'     => '',
158
				'type'        => 'text',
159
				'help'        => '<a href="http://trentrichardson.com/examples/timepicker/#tp-formatting" target="_blank">' . __( 'jQuery UI timepicker documentation', 'pods' ) . '</a>' . '<br>' . __( 'Leave empty to auto-generate from PHP format.', 'pods' ),
160
			),
161
			static::$type . '_time_format'           => array(
162
				'label'       => __( 'Time Format', 'pods' ),
163
				'depends-on'  => array( static::$type . '_time_type' => '12' ),
164
				'excludes-on' => array( static::$type . '_format' => 'c' ),
165
				'default'     => 'h_mma',
166
				'type'        => 'pick',
167
				'data'        => array(
168
					'h_mm_A'     => date_i18n( 'g:i A' ),
169
					'h_mm_ss_A'  => date_i18n( 'g:i:s A' ),
170
					'hh_mm_A'    => date_i18n( 'h:i A' ),
171
					'hh_mm_ss_A' => date_i18n( 'h:i:s A' ),
172
					'h_mma'      => date_i18n( 'g:ia' ),
173
					'hh_mma'     => date_i18n( 'h:ia' ),
174
					'h_mm'       => date_i18n( 'g:i' ),
175
					'h_mm_ss'    => date_i18n( 'g:i:s' ),
176
					'hh_mm'      => date_i18n( 'h:i' ),
177
					'hh_mm_ss'   => date_i18n( 'h:i:s' ),
178
				),
179
			),
180
			static::$type . '_time_format_24'        => array(
181
				'label'       => __( 'Time Format', 'pods' ),
182
				'depends-on'  => array( static::$type . '_time_type' => '24' ),
183
				'excludes-on' => array( static::$type . '_format' => 'c' ),
184
				'default'     => 'hh_mm',
185
				'type'        => 'pick',
186
				'data'        => array(
187
					'hh_mm'    => date_i18n( 'H:i' ),
188
					'hh_mm_ss' => date_i18n( 'H:i:s' ),
189
				),
190
			),
191
			static::$type . '_allow_empty'           => array(
192
				'label'   => __( 'Allow empty value?', 'pods' ),
193
				'default' => 1,
194
				'type'    => 'boolean',
195
			),
196
			static::$type . '_html5'                 => array(
197
				'label'   => __( 'Enable HTML5 Input Field?', 'pods' ),
198
				'default' => apply_filters( 'pods_form_ui_field_html5', 0, static::$type ),
199
				'type'    => 'boolean',
200
			),
201
		);
202
203
		// Check if PHP DateTime::createFromFormat exists for additional supported formats
204 View Code Duplication
		if ( method_exists( 'DateTime', 'createFromFormat' ) || apply_filters( 'pods_form_ui_field_datetime_custom_formatter', false ) ) {
205
			$options[ static::$type . '_format' ]['data'] = array_merge(
206
				$options[ static::$type . '_format' ]['data'], array(
207
					'dmy'      => date_i18n( 'd/m/Y' ),
208
					'dmy_dash' => date_i18n( 'd-m-Y' ),
209
					'dmy_dot'  => date_i18n( 'd.m.Y' ),
210
					'dMy'      => date_i18n( 'd/M/Y' ),
211
					'dMy_dash' => date_i18n( 'd-M-Y' ),
212
				)
213
			);
214
		}
215
216
		$options[ static::$type . '_format' ]['data']    = apply_filters( 'pods_form_ui_field_date_format_options', $options[ static::$type . '_format' ]['data'] );
217
		$options[ static::$type . '_format' ]['default'] = apply_filters( 'pods_form_ui_field_date_format_default', $options[ static::$type . '_format' ]['default'] );
218
219
		$options[ static::$type . '_time_type' ]['default']      = apply_filters( 'pods_form_ui_field_time_format_type_default', $options[ static::$type . '_time_type' ]['default'] );
220
		$options[ static::$type . '_time_format' ]['data']       = apply_filters( 'pods_form_ui_field_time_format_options', $options[ static::$type . '_time_format' ]['data'] );
221
		$options[ static::$type . '_time_format' ]['default']    = apply_filters( 'pods_form_ui_field_time_format_default', $options[ static::$type . '_time_format' ]['default'] );
222
		$options[ static::$type . '_time_format_24' ]['data']    = apply_filters( 'pods_form_ui_field_time_format_24_options', $options[ static::$type . '_time_format_24' ]['data'] );
223
		$options[ static::$type . '_time_format_24' ]['default'] = apply_filters( 'pods_form_ui_field_time_format_24_default', $options[ static::$type . '_time_format_24' ]['default'] );
224
225
		return $options;
226
	}
227
228
	/**
229
	 * Define the current field's schema for DB table storage
230
	 *
231
	 * @param array $options
232
	 *
233
	 * @return string
234
	 * @since 2.0
235
	 */
236
	public function schema( $options = null ) {
237
238
		$schema = 'DATETIME NOT NULL default "0000-00-00 00:00:00"';
239
240
		return $schema;
241
	}
242
243
	/**
244
	 * {@inheritdoc}
245
	 */
246
	public function is_empty( $value = null ) {
247
248
		$is_empty = false;
249
250
		$value = trim( $value );
251
252
		if ( empty( $value ) || in_array( $value, array( '0000-00-00', '0000-00-00 00:00:00', '00:00:00' ) ) ) {
253
			$is_empty = true;
254
		}
255
256
		return $is_empty;
257
258
	}
259
260
	/**
261
	 * Change the way the value of the field is displayed with Pods::get
262
	 *
263
	 * @param mixed  $value
264
	 * @param string $name
265
	 * @param array  $options
266
	 * @param array  $pod
267
	 * @param int    $id
268
	 *
269
	 * @return mixed|null|string
270
	 * @since 2.0
271
	 */
272
	public function display( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
273
274
		$value = $this->format_value_display( $value, $options, false );
275
276
		return $value;
277
	}
278
279
	/**
280
	 * Customize output of the form field
281
	 *
282
	 * @param string $name
283
	 * @param mixed  $value
284
	 * @param array  $options
285
	 * @param array  $pod
286
	 * @param int    $id
287
	 *
288
	 * @since 2.0
289
	 */
290
	public function input( $name, $value = null, $options = null, $pod = null, $id = null ) {
291
292
		$options         = (array) $options;
293
		$form_field_type = PodsForm::$field_type;
294
295
		if ( is_array( $value ) ) {
296
			$value = implode( ' ', $value );
297
		}
298
299
		// Format Value
300
		$value = $this->format_value_display( $value, $options, true );
301
302
		$field_type = static::$type;
303
304
		if ( isset( $options['name'] ) && false === PodsForm::permission( static::$type, $options['name'], $options, null, $pod, $id ) ) {
305
			if ( pods_v( 'read_only', $options, false ) ) {
306
				$options['readonly'] = true;
307
308
				$field_type = 'text';
309
			} else {
310
				return;
311
			}
312
		} elseif ( ! pods_has_permissions( $options ) && pods_v( 'read_only', $options, false ) ) {
313
			$options['readonly'] = true;
314
315
			$field_type = 'text';
316
		}
317
318
		pods_view( PODS_DIR . 'ui/fields/' . $field_type . '.php', compact( array_keys( get_defined_vars() ) ) );
319
	}
320
321
	/**
322
	 * {@inheritdoc}
323
	 */
324
	public function validate( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
325
326
		if ( ! empty( $value ) && ( 0 == pods_v( static::$type . '_allow_empty', $options, 1 ) || ! in_array(
327
			$value, array(
328
				'0000-00-00',
329
				'0000-00-00 00:00:00',
330
				'00:00:00',
331
			)
332
		) ) ) {
333
			$js = true;
334
335
			if ( 'custom' !== pods_v( static::$type . '_type', $options, 'format' ) ) {
336
				$js = false;
337
			}
338
339
			$format = $this->format( $options, $js );
340
341
			if ( $js ) {
342
				$format = $this->convert_format( $format, array( 'source' => 'jquery_ui' ) );
343
			}
344
345
			$check = $this->convert_date( $value, static::$storage_format, $format, true );
346
347
			if ( false === $check ) {
348
				$label = pods_var( 'label', $options, ucwords( str_replace( '_', ' ', $name ) ) );
349
350
				return sprintf( esc_html__( '%1$s was not provided in a recognizable format: "%2$s"', 'pods' ), $label, $value );
351
			}
352
		}//end if
353
354
		return true;
355
356
	}
357
358
	/**
359
	 * Change the value or perform actions after validation but before saving to the DB
360
	 *
361
	 * @param mixed  $value
362
	 * @param int    $id
363
	 * @param string $name
364
	 * @param array  $options
365
	 * @param array  $fields
366
	 * @param array  $pod
367
	 * @param object $params
368
	 *
369
	 * @return mixed|string
370
	 * @since 2.0
371
	 */
372
	public function pre_save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
373
374
		$js = true;
375
		if ( 'custom' !== pods_v( static::$type . '_type', $options, 'format' ) ) {
376
			$js = false;
377
		}
378
		$format = $this->format( $options, $js );
379
		if ( $js ) {
380
			$format = $this->convert_format( $format, array( 'source' => 'jquery_ui' ) );
381
		}
382
383
		if ( ! empty( $value ) && ( 0 == pods_v( static::$type . '_allow_empty', $options, 1 ) || ! in_array(
384
			$value, array(
385
				'0000-00-00',
386
				'0000-00-00 00:00:00',
387
				'00:00:00',
388
			)
389
		) ) ) {
390
			$value = $this->convert_date( $value, static::$storage_format, $format );
391
		} elseif ( 1 == pods_v( static::$type . '_allow_empty', $options, 1 ) ) {
392
			$value = static::$empty_value;
393
		} else {
394
			$value = date_i18n( static::$storage_format );
395
		}
396
397
		return $value;
398
	}
399
400
	/**
401
	 * Customize the Pods UI manage table column output
402
	 *
403
	 * @param int    $id
404
	 * @param mixed  $value
405
	 * @param string $name
406
	 * @param array  $options
407
	 * @param array  $fields
408
	 * @param array  $pod
409
	 *
410
	 * @return mixed|null|string
411
	 * @since 2.0
412
	 */
413
	public function ui( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
414
415
		$value = $this->display( $value, $name, $options, $pod, $id );
416
417
		if ( 1 == pods_v( static::$type . '_allow_empty', $options, 1 ) && ( empty( $value ) || in_array(
418
			$value, array(
419
				'0000-00-00',
420
				'0000-00-00 00:00:00',
421
				'00:00:00',
422
			)
423
		) ) ) {
424
			$value = false;
425
		}
426
427
		return $value;
428
	}
429
430
	/**
431
	 * Convert value to the correct format for display.
432
	 *
433
	 * @param string $value
434
	 * @param array  $options
435
	 * @param bool   $js Return formatted from jQuery UI format? (only for custom formats).
436
	 *
437
	 * @return string
438
	 * @since 2.7
439
	 */
440
	public function format_value_display( $value, $options, $js = false ) {
441
442
		if ( 'custom' !== pods_v( static::$type . '_type', $options, 'format' ) ) {
443
			$js = false;
444
		}
445
		$format = $this->format( $options, $js );
446
		if ( $js ) {
447
			$format = $this->convert_format( $format, array( 'source' => 'jquery_ui' ) );
448
		}
449
450
		if ( ! empty( $value ) && ! in_array( $value, array( '0000-00-00', '0000-00-00 00:00:00', '00:00:00' ) ) ) {
451
			// Try default storage format.
452
			$date = $this->createFromFormat( static::$storage_format, (string) $value );
453
			// Try field format.
454
			$date_local = $this->createFromFormat( $format, (string) $value );
455
456 View Code Duplication
			if ( $date instanceof DateTime ) {
457
				$value = $date->format( $format );
458
			} elseif ( $date_local instanceof DateTime ) {
459
				$value = $date_local->format( $format );
460
			} else {
461
				$value = date_i18n( $format, strtotime( (string) $value ) );
462
			}
463
		} elseif ( 0 == pods_v( static::$type . '_allow_empty', $options, 1 ) ) {
464
			$value = date_i18n( $format );
465
		} else {
466
			$value = '';
467
		}
468
469
		return $value;
470
	}
471
472
	/**
473
	 * Build date/time format string based on options
474
	 *
475
	 * @param array $options
476
	 * @param bool  $js Return format for jQuery UI?
477
	 *
478
	 * @return string
479
	 * @since 2.0
480
	 */
481
	public function format( $options, $js = false ) {
482
483
		$format = $this->format_date( $options, $js );
484
485
		$type = pods_v( static::$type . '_type', $options, 'format' );
486
487
		if ( 'format' !== $type || 'c' !== pods_v( static::$type . '_format', $options, '' ) ) {
488
			$format .= ' ' . $this->format_time( $options, $js );
489
		}
490
491
		return $format;
492
	}
493
494
	/**
495
	 * Build date format string based on options
496
	 *
497
	 * @since  2.7
498
	 *
499
	 * @param  array $options
500
	 * @param  bool  $js Return format for jQuery UI?
501
	 *
502
	 * @return string
503
	 */
504
	public function format_date( $options, $js = false ) {
505
506
		switch ( (string) pods_v( static::$type . '_type', $options, 'format', true ) ) {
507
			case 'wp':
508
				$format = get_option( 'date_format' );
509
				if ( $js ) {
510
					$format = $this->convert_format( $format, array( 'source' => 'php' ) );
511
				}
512
				break;
513
			case 'custom':
514
				if ( ! $js ) {
515
					$format = pods_v( static::$type . '_format_custom', $options, '' );
516
				} else {
517
					$format = pods_v( static::$type . '_format_custom_js', $options, '' );
518
					if ( empty( $format ) ) {
519
						$format = pods_v( static::$type . '_format_custom', $options, '' );
520
						$format = $this->convert_format( $format, array( 'source' => 'php' ) );
521
					}
522
				}
523
				break;
524
			default:
525
				$date_format = $this->get_date_formats( $js );
526
				$format      = $date_format[ pods_v( static::$type . '_format', $options, 'ymd_dash', true ) ];
527
				break;
528
		}//end switch
529
530
		return $format;
531
	}
532
533
	/**
534
	 * Build time format string based on options
535
	 *
536
	 * @since  2.7
537
	 *
538
	 * @param  array $options
539
	 * @param  bool  $js Return format for jQuery UI?
540
	 *
541
	 * @return string
542
	 */
543 View Code Duplication
	public function format_time( $options, $js = false ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
544
545
		switch ( (string) pods_v( static::$type . '_time_type', $options, '12', true ) ) {
546
			case '12':
547
				$time_format = $this->get_time_formats( $js );
548
				$format      = $time_format[ pods_v( static::$type . '_time_format', $options, 'hh_mm', true ) ];
549
				break;
550
			case '24':
551
				$time_format_24 = $this->get_time_formats_24( $js );
552
				$format         = $time_format_24[ pods_v( static::$type . '_time_format_24', $options, 'hh_mm', true ) ];
553
				break;
554
			case 'custom':
555
				if ( ! $js ) {
556
					$format = pods_v( static::$type . '_time_format_custom', $options, '' );
557
				} else {
558
					$format = pods_v( static::$type . '_time_format_custom_js', $options, '' );
559
					if ( empty( $format ) ) {
560
						$format = pods_v( static::$type . '_time_format_custom', $options, '' );
561
						$format = $this->convert_format( $format, array( 'source' => 'php' ) );
562
					}
563
				}
564
				break;
565
			default:
566
				$format = get_option( 'time_format' );
567
				if ( $js ) {
568
					$format = $this->convert_format( $format, array( 'source' => 'php' ) );
569
				}
570
				break;
571
		}//end switch
572
573
		return $format;
574
	}
575
576
	/**
577
	 * Get the date formats.
578
	 *
579
	 * @since  2.7
580
	 *
581
	 * @param  bool $js Return formats for jQuery UI?
582
	 *
583
	 * @return array
584
	 */
585
	public function get_date_formats( $js = false ) {
586
587
		$date_format = array(
588
			'mdy'       => 'm/d/Y',
589
			'mdy_dash'  => 'm-d-Y',
590
			'mdy_dot'   => 'm.d.Y',
591
			'dmy'       => 'd/m/Y',
592
			'dmy_dash'  => 'd-m-Y',
593
			'dmy_dot'   => 'd.m.Y',
594
			'ymd_slash' => 'Y/m/d',
595
			'ymd_dash'  => 'Y-m-d',
596
			'ymd_dot'   => 'Y.m.d',
597
			'dMy'       => 'd/M/Y',
598
			'dMy_dash'  => 'd-M-Y',
599
			'fjy'       => 'F j, Y',
600
			'fjsy'      => 'F jS, Y',
601
			'y'         => 'Y',
602
		);
603
		$filter      = 'pods_form_ui_field_date_formats';
604
		if ( $js ) {
605
			// @todo Method parameters? (Not supported by array_map)
606
			$date_format = array_map( array( $this, 'convert_format' ), $date_format );
607
			$filter      = 'pods_form_ui_field_date_js_formats';
608
		}
609
610
		return apply_filters( $filter, $date_format );
611
	}
612
613
	/**
614
	 * Get the time formats.
615
	 *
616
	 * @since  2.7
617
	 *
618
	 * @param  bool $js Return formats for jQuery UI?
619
	 *
620
	 * @return array
621
	 */
622
	public function get_time_formats( $js = false ) {
623
624
		$time_format = array(
625
			'h_mm_A'     => 'g:i A',
626
			'h_mm_ss_A'  => 'g:i:s A',
627
			'hh_mm_A'    => 'h:i A',
628
			'hh_mm_ss_A' => 'h:i:s A',
629
			'h_mma'      => 'g:ia',
630
			'hh_mma'     => 'h:ia',
631
			'h_mm'       => 'g:i',
632
			'h_mm_ss'    => 'g:i:s',
633
			'hh_mm'      => 'h:i',
634
			'hh_mm_ss'   => 'h:i:s',
635
		);
636
		$filter      = 'pods_form_ui_field_time_formats';
637
		if ( $js ) {
638
			// @todo Method parameters? (Not supported by array_map)
639
			$time_format = array_map( array( $this, 'convert_format' ), $time_format );
640
			$filter      = 'pods_form_ui_field_time_js_formats';
641
		}
642
643
		return apply_filters( $filter, $time_format );
644
	}
645
646
	/**
647
	 * Get the time formats.
648
	 *
649
	 * @since  2.7
650
	 *
651
	 * @param  bool $js Return formats for jQuery UI?
652
	 *
653
	 * @return array
654
	 */
655
	public function get_time_formats_24( $js = false ) {
656
657
		$time_format_24 = array(
658
			'hh_mm'    => 'H:i',
659
			'hh_mm_ss' => 'H:i:s',
660
		);
661
		$filter         = 'pods_form_ui_field_time_formats_24';
662
		if ( $js ) {
663
			// @todo Method parameters? (Not supported by array_map)
664
			$time_format_24 = array_map( array( $this, 'convert_format' ), $time_format_24 );
665
			$filter         = 'pods_form_ui_field_time_js_formats_24';
666
		}
667
668
		return apply_filters( $filter, $time_format_24 );
669
	}
670
671
	/**
672
	 * @param string  $format
673
	 * @param string  $date             Defaults to time() if empty.
674
	 * @param boolean $return_timestamp Whether to return the strtotime() or createFromFormat result or not
675
	 *
676
	 * @return DateTime|null|int|false
677
	 */
678
	public function createFromFormat( $format, $date, $return_timestamp = false ) {
679
680
		$datetime = null;
681
682
		if ( method_exists( 'DateTime', 'createFromFormat' ) ) {
683
			$timezone = get_option( 'timezone_string' );
684
685
			if ( empty( $timezone ) ) {
686
				$timezone = timezone_name_from_abbr( '', get_option( 'gmt_offset' ) * HOUR_IN_SECONDS, 0 );
687
			}
688
689
			if ( ! empty( $timezone ) ) {
690
				$datetimezone = new DateTimeZone( $timezone );
691
692
				$datetime = DateTime::createFromFormat( $format, (string) $date, $datetimezone );
0 ignored issues
show
Bug introduced by
The method createFromFormat() does not exist on DateTime. Did you maybe mean format()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
693
694
				if ( false === $datetime ) {
695
					$datetime = DateTime::createFromFormat( static::$storage_format, (string) $date, $datetimezone );
0 ignored issues
show
Bug introduced by
The method createFromFormat() does not exist on DateTime. Did you maybe mean format()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
696
				}
697
698
				if ( false !== $datetime && $return_timestamp ) {
699
					return $datetime;
700
				}
701
			}
702
		}//end if
703
704
		if ( in_array( $datetime, array( null, false ), true ) ) {
705
			if ( empty( $date ) ) {
706
				$timestamp = time();
707
			} else {
708
				$timestamp = strtotime( (string) $date );
709
710
				if ( $return_timestamp ) {
711
					return $timestamp;
712
				}
713
			}
714
			if ( $timestamp ) {
715
				$datetime = new DateTime( date_i18n( static::$storage_format, $timestamp ) );
716
			}
717
		}
718
719
		return apply_filters( 'pods_form_ui_field_datetime_formatter', $datetime, $format, $date );
720
	}
721
722
	/**
723
	 * Convert a date from one format to another
724
	 *
725
	 * @param         $value
726
	 * @param         $new_format
727
	 * @param string     $original_format
728
	 * @param boolean    $return_timestamp Whether to return the strtotime() or createFromFormat result or not
729
	 *
730
	 * @return string|int|boolean|DateTime
731
	 */
732
	public function convert_date( $value, $new_format, $original_format = '', $return_timestamp = false ) {
733
734
		if ( empty( $original_format ) ) {
735
			$original_format = static::$storage_format;
736
		}
737
738
		$date = '';
739
740
		if ( ! empty( $value ) && ! in_array( $value, array( '0000-00-00', '0000-00-00 00:00:00', '00:00:00' ) ) ) {
741
			$date = $this->createFromFormat( $original_format, (string) $value, $return_timestamp );
742
743 View Code Duplication
			if ( $date instanceof DateTime ) {
744
				$value = $date->format( $new_format );
745
			} elseif ( false !== $date ) {
746
				$date = strtotime( (string) $value );
747
748
				$value = date_i18n( $new_format, $date );
749
			}
750
		} else {
751
			$value = date_i18n( $new_format );
752
		}
753
754
		// Return timestamp conversion result instead
755
		if ( $return_timestamp ) {
756
			return $date;
757
		}
758
759
		return $value;
760
	}
761
762
	/**
763
	 * Matches each symbol of PHP date format standard with jQuery equivalent codeword.
764
	 *
765
	 * @link   http://stackoverflow.com/questions/16702398/convert-a-php-date-format-to-a-jqueryui-datepicker-date-format
766
	 * @link   https://api.jqueryui.com/datepicker/
767
	 * @link   http://trentrichardson.com/examples/timepicker/
768
	 *
769
	 * @since  2.7
770
	 *
771
	 * @param  string $source_format
772
	 * @param  array  $args
773
	 *
774
	 * @return string
775
	 */
776
	public function convert_format( $source_format, $args = array() ) {
777
778
		// @todo Improve source/target logic.
779
		$args = array_merge(
780
			array(
781
				'source' => 'php',
782
			// 'jquery_ui' for reverse.
783
			), $args
784
		);
785
786
		// Keep keys and values sorted by string length.
787
		$symbols = array(
788
			// Day
789
			'd' => 'dd',
790
			'l' => 'DD',
791
			'D' => 'D',
792
			'j' => 'd',
793
			'N' => '',
794
			'S' => '',
795
			'w' => '',
796
			'z' => 'o',
797
			// Week
798
			'W' => '',
799
			// Month
800
			'F' => 'MM',
801
			'm' => 'mm',
802
			'M' => 'M',
803
			'n' => 'm',
804
			't' => '',
805
			// Year
806
			'L' => '',
807
			'o' => '',
808
			'Y' => 'yy',
809
			'y' => 'y',
810
			// AM/PM
811
			'a' => 'tt',
812
			'A' => 'TT',
813
			// Swatch internet time (not supported)
814
			'B' => '',
815
			// Hour
816
			'h' => 'hh',
817
			'H' => 'HH',
818
			'g' => 'h',
819
			'G' => 'H',
820
			// Minute
821
			'i' => 'mm',
822
			// Second
823
			's' => 'ss',
824
			// Microsecond
825
			'u' => 'c',
826
		);
827
		if ( version_compare( PHP_VERSION, '7.0.0' ) >= 0 ) {
828
			// Millisecond
829
			$symbols['v'] = 'l';
830
		}
831
		if ( 'jquery_ui' === $args['source'] ) {
832
			// Remove empty values.
833
			$symbols = array_filter( $symbols );
834
			$symbols = array_flip( $symbols );
835
		}
836
		$new_format = '';
837
		$escaping   = false;
838
		for ( $i = 0; $i < strlen( $source_format ); $i ++ ) {
839
			$char = $source_format[ $i ];
840
			// PHP date format escaping character
841
			// @todo Do we want to support non-format characters?
842
			if ( $char === '\\' ) {
843
				$i ++;
844
				if ( $escaping ) {
845
					$new_format .= $source_format[ $i ];
846
				} else {
847
					$new_format .= '\'' . $source_format[ $i ];
848
				}
849
				$escaping = true;
850
			} else {
851
				if ( $escaping ) {
852
					$new_format .= "'";
853
					$escaping    = false;
854
				}
855
				// Support 2 characters.
856
				if ( isset( $source_format[ $i + 1 ] ) && isset( $symbols[ $char . $source_format[ $i + 1 ] ] ) ) {
857
					$new_format .= $symbols[ $char . $source_format[ $i + 1 ] ];
858
					$i ++;
859
				} elseif ( isset( $symbols[ $char ] ) ) {
860
					$new_format .= $symbols[ $char ];
861
				} else {
862
					$new_format .= $char;
863
				}
864
			}//end if
865
		}//end for
866
867
		return $new_format;
868
	}
869
870
	/**
871
	 * Enqueue the i18n files for jquery date/timepicker
872
	 *
873
	 * @since  2.7
874
	 */
875
	public function enqueue_jquery_ui_i18n() {
876
877
		static $done = array();
878
879
		$types = array();
880
		switch ( static::$type ) {
881
			case 'time':
882
				$types[] = 'time';
883
				break;
884
			case 'date':
885
				$types[] = 'date';
886
				break;
887
			case 'datetime':
888
				$types[] = 'time';
889
				$types[] = 'date';
890
				break;
891
		}
892
893
		if ( in_array( 'date', $types, true ) && ! in_array( 'date', $done, true ) ) {
894
895
			if ( function_exists( 'wp_localize_jquery_ui_datepicker' ) ) {
896
				wp_localize_jquery_ui_datepicker();
897
			}
898
899
			$done[] = 'date';
900
		}
901
902
		if ( in_array( 'time', $types, true ) && ! in_array( 'time', $done, true ) ) {
903
904
			$locale = str_replace( '_', '-', get_locale() );
905
906
			// Local files.
907
			if ( ! file_exists( PODS_DIR . 'ui/js/timepicker/i18n/jquery-ui-timepicker-' . $locale . '.js' ) ) {
908
				// Fallback to the base language (non-region specific).
909
				$locale = substr( $locale, 0, strpos( $locale, '-' ) );
910
			}
911
912
			if ( ! wp_script_is( 'jquery-ui-timepicker-i18n-' . $locale, 'registered' ) && file_exists( PODS_DIR . 'ui/js/timepicker/i18n/jquery-ui-timepicker-' . $locale . '.js' ) ) {
913
				wp_enqueue_script( 'jquery-ui-timepicker-i18n-' . $locale, PODS_URL . 'ui/js/timepicker/i18n/jquery-ui-timepicker-' . $locale . '.js', array( 'jquery-ui-timepicker' ), '1.6.3' );
914
			}
915
916
			$done[] = 'time';
917
		}
918
	}
919
}
920