Completed
Pull Request — 2.x (#4830)
by Jory
09:21
created

PodsField_Currency::display()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 35
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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

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
require_once PODS_DIR . 'classes/fields/number.php';
3
4
/**
5
 * @package Pods\Fields
6
 */
7
class PodsField_Currency extends PodsField_Number {
8
9
	/**
10
	 * {@inheritdoc}
11
	 */
12
	public static $group = 'Number';
13
14
	/**
15
	 * {@inheritdoc}
16
	 */
17
	public static $type = 'currency';
18
19
	/**
20
	 * {@inheritdoc}
21
	 */
22
	public static $label = 'Currency';
23
24
	/**
25
	 * {@inheritdoc}
26
	 */
27
	public static $prepare = '%d';
28
29
	/**
30
	 * Currency Formats
31
	 *
32
	 * @var array
33
	 * @since 2.0
34
	 */
35
	public static $currencies = array();
36
37
	/**
38
	 * {@inheritdoc}
39
	 */
40
	public function setup() {
41
42
		self::$label = __( 'Currency', 'pods' );
43
		static::data_currencies();
44
	}
45
46
	/**
47
	 * {@inheritdoc}
48
	 */
49
	public function options() {
50
51
		$currency_options = array();
52
		foreach ( static::$currencies as $key => $value ) {
53
			$currency = $value['label'];
54
			if ( $value['label'] !== $value['name'] ) {
55
				$currency .= ': ' . $value['name'];
56
			}
57
			$currency                .= ' (' . $value['sign'] . ')';
58
			$currency_options[ $key ] = $currency;
59
		}
60
61
		$options = array(
62
			static::$type . '_repeatable'       => array(
63
				'label'             => __( 'Repeatable Field', 'pods' ),
64
				'default'           => 0,
65
				'type'              => 'boolean',
66
				'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' ),
67
				'boolean_yes_label' => '',
68
				'dependency'        => true,
69
				'developer_mode'    => true,
70
			),
71
			static::$type . '_format_type'      => array(
72
				'label'      => __( 'Input Type', 'pods' ),
73
				'default'    => 'number',
74
				'type'       => 'pick',
75
				'data'       => array(
76
					'number' => __( 'Freeform Number', 'pods' ),
77
					'slider' => __( 'Slider', 'pods' ),
78
				),
79
				'dependency' => true,
80
			),
81
			static::$type . '_format_sign'      => array(
82
				'label'   => __( 'Currency Sign', 'pods' ),
83
				'default' => apply_filters( 'pods_form_ui_field_number_currency_default', 'usd' ),
84
				'type'    => 'pick',
85
				'data'    => apply_filters( 'pods_form_ui_field_number_currency_options', $currency_options ),
86
			),
87
			static::$type . '_format_placement' => array(
88
				'label'   => __( 'Currency Placement', 'pods' ),
89
				'default' => apply_filters( 'pods_form_ui_field_number_currency_placement_default', 'before' ),
90
				'type'    => 'pick',
91
				'data'    => array(
92
					'before'          => __( 'Before (ex. $100)', 'pods' ),
93
					'after'           => __( 'After (ex. 100$)', 'pods' ),
94
					'none'            => __( 'None (ex. 100)', 'pods' ),
95
					'beforeaftercode' => __( 'Before with Currency Code after (ex. $100 USD)', 'pods' ),
96
				),
97
			),
98
			static::$type . '_format'           => array(
99
				'label'   => __( 'Format', 'pods' ),
100
				'default' => apply_filters( 'pods_form_ui_field_number_currency_format_default', 'i18n' ),
101
				'type'    => 'pick',
102
				'data'    => array(
103
					'i18n'      => __( 'Localized Default', 'pods' ),
104
					'9,999.99'  => '1,234.00',
105
					'9\'999.99' => '1\'234.00',
106
					'9.999,99'  => '1.234,00',
107
					'9 999,99'  => '1 234,00',
108
					'9999.99'   => '1234.00',
109
					'9999,99'   => '1234,00',
110
				),
111
			),
112
			static::$type . '_decimals'         => array(
113
				'label'   => __( 'Decimals', 'pods' ),
114
				'default' => 2,
115
				'type'    => 'number',
116
			),
117
			static::$type . '_decimal_handling' => array(
118
				'label'   => __( 'Decimal handling when zero', 'pods' ),
119
				'default' => 'none',
120
				'type'    => 'pick',
121
				'data'    => array(
122
					'none'   => __( 'Default', 'pods' ),
123
					'remove' => __( 'Remove decimals', 'pods' ),
124
					'dash'   => __( 'Convert to dash', 'pods' ) . ' (-)',
125
				),
126
			),
127
			static::$type . '_step'             => array(
128
				'label'      => __( 'Slider Increment (Step)', 'pods' ),
129
				'depends-on' => array( static::$type . '_format_type' => 'slider' ),
130
				'default'    => 1,
131
				'type'       => 'text',
132
			),
133
			static::$type . '_min'              => array(
134
				'label'      => __( 'Minimum Number', 'pods' ),
135
				'depends-on' => array( static::$type . '_format_type' => 'slider' ),
136
				'default'    => 0,
137
				'type'       => 'text',
138
			),
139
			static::$type . '_max'              => array(
140
				'label'      => __( 'Maximum Number', 'pods' ),
141
				'depends-on' => array( static::$type . '_format_type' => 'slider' ),
142
				'default'    => 1000,
143
				'type'       => 'text',
144
			),
145
			static::$type . '_max_length'       => array(
146
				'label'   => __( 'Maximum Length', 'pods' ),
147
				'default' => 12,
148
				'type'    => 'number',
149
				'help'    => __( 'Set to -1 for no limit', 'pods' ),
150
			),
151
			static::$type . '_placeholder'      => array(
152
				'label'   => __( 'HTML Placeholder', 'pods' ),
153
				'default' => '',
154
				'type'    => 'text',
155
				'help'    => array(
156
					__( 'Placeholders can provide instructions or an example of the required data format for a field. Please note: It is not a replacement for labels or description text, and it is less accessible for people using screen readers.', 'pods' ),
157
					'https://www.w3.org/WAI/tutorials/forms/instructions/#placeholder-text',
158
				),
159
			),
160
		);
161
162
		return $options;
163
164
	}
165
166
	/**
167
	 * {@inheritdoc}
168
	 */
169
	public function display( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
170
171
		$value = $this->format( $value, $name, $options, $pod, $id );
172
173
		$currency = 'usd';
174
175
		if ( isset( static::$currencies[ pods_v( static::$type . '_format_sign', $options, - 1 ) ] ) ) {
176
			$currency = pods_v( static::$type . '_format_sign', $options );
177
		}
178
179
		$currency_sign  = static::$currencies[ $currency ]['sign'];
180
		$currency_label = static::$currencies[ $currency ]['label'];
181
182
		$placement = pods_v( static::$type . '_format_placement', $options, 'before', true );
183
184
		// Currency placement policy
185
		// Single sign currencies: 100$, £100
186
		// Multiple sign currencies: 100 Fr, Kr 100
187
		$currency_gap = '';
188
189
		if ( strlen( $currency_sign ) > 1 && false === strpos( $currency_sign, '&' ) ) {
190
			$currency_gap = ' ';
191
		}
192
193
		if ( 'before' === $placement ) {
194
			$value = $currency_sign . $currency_gap . $value;
195
		} elseif ( 'after' === $placement ) {
196
			$value .= $currency_gap . $currency_sign;
197
		} elseif ( 'beforeaftercode' === $placement ) {
198
			$value = $currency_sign . $currency_gap . $value . ' ' . $currency_label;
199
		}
200
201
		return $value;
202
203
	}
204
205
	/**
206
	 * {@inheritdoc}
207
	 */
208
	public function regex( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
209
210
		$format_args = $this->get_number_format_args( $options );
211
		$thousands   = $format_args['thousands'];
212
		$dot         = $format_args['dot'];
213
214
		$currency = 'usd';
215
216
		if ( isset( static::$currencies[ pods_v( static::$type . '_format_sign', $options, - 1 ) ] ) ) {
217
			$currency = pods_v( static::$type . '_format_sign', $options );
218
		}
219
220
		$currency_sign = static::$currencies[ $currency ]['sign'];
221
222
		return '\-*\\' . $currency_sign . '*[0-9\\' . implode( '\\', array_filter( array( $dot, $thousands ) ) ) . ']+';
223
224
	}
225
226
	/**
227
	 * {@inheritdoc}
228
	 */
229
	public function validate( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
230
231
		$format_args = $this->get_number_format_args( $options );
232
		$thousands   = $format_args['thousands'];
233
		$dot         = $format_args['dot'];
234
235
		$currency = 'usd';
236
237
		if ( isset( static::$currencies[ pods_v( static::$type . '_format_sign', $options, - 1 ) ] ) ) {
238
			$currency = pods_v( static::$type . '_format_sign', $options );
239
		}
240
241
		$currency_sign   = static::$currencies[ $currency ]['sign'];
242
		$currency_entity = static::$currencies[ $currency ]['entity'];
243
244
		// Remove currency and thousands symbols
245
		$check = str_replace(
246
			array(
247
				$thousands,
248
				$currency_sign,
249
				$currency_entity,
250
				html_entity_decode( $thousands ),
251
				html_entity_decode( $currency_sign ),
252
				html_entity_decode( $currency_entity ),
253
			), '', $value
254
		);
255
		// Convert decimal type for numeric type
256
		$check = str_replace( $dot, '.', $check );
257
		$check = trim( $check );
258
259
		$check = preg_replace( '/[0-9\.\-\s]/', '', $check );
260
261
		$label = pods_v( 'label', $options, ucwords( str_replace( '_', ' ', $name ) ) );
262
263
		if ( 0 < strlen( $check ) ) {
264
			return sprintf( __( '%s is not numeric', 'pods' ), $label );
265
		}
266
267
		return true;
268
269
	}
270
271
	/**
272
	 * {@inheritdoc}
273
	 */
274
	public function pre_save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
275
276
		$format_args = $this->get_number_format_args( $options );
277
		$thousands   = $format_args['thousands'];
278
		$dot         = $format_args['dot'];
279
		$decimals    = $format_args['decimals'];
280
281
		$currency = 'usd';
282
283
		if ( isset( static::$currencies[ pods_v( static::$type . '_format_sign', $options, - 1 ) ] ) ) {
284
			$currency = pods_v( static::$type . '_format_sign', $options );
285
		}
286
287
		$currency_sign   = static::$currencies[ $currency ]['sign'];
288
		$currency_entity = static::$currencies[ $currency ]['entity'];
289
290
		// Convert decimal type for numeric type
291
		$value = str_replace(
292
			array(
293
				$thousands,
294
				$currency_sign,
295
				$currency_entity,
296
				html_entity_decode( $thousands ),
297
				html_entity_decode( $currency_sign ),
298
				html_entity_decode( $currency_entity ),
299
			), '', $value
300
		);
301
		// Convert decimal type for numeric type
302
		$value = str_replace( $dot, '.', $value );
303
		$value = trim( $value );
304
305
		$value = preg_replace( '/[^0-9\.\-]/', '', $value );
306
307
		$value = number_format( (float) $value, $decimals, '.', '' );
308
309
		return $value;
310
311
	}
312
313
	/**
314
	 * {@inheritdoc}
315
	 */
316
	public function format( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
317
318
		if ( null === $value ) {
319
			// Don't enforce a default value here
320
			return null;
321
		}
322
323
		$format_args = $this->get_number_format_args( $options );
324
		$thousands   = $format_args['thousands'];
325
		$dot         = $format_args['dot'];
326
		$decimals    = $format_args['decimals'];
327
328
		if ( 'i18n' === pods_v( static::$type . '_format', $options ) ) {
329
			$value = number_format_i18n( (float) $value, $decimals );
330
		} else {
331
			$value = number_format( (float) $value, $decimals, $dot, $thousands );
332
		}
333
334
		// Additional output handling for decimals
335
		$decimal_handling = pods_v( static::$type . '_decimal_handling', $options, 'none' );
336
		if ( 'none' !== $decimal_handling ) {
337
			$value_parts = explode( $dot, $value );
338
			// Make sure decimals are empty.
339
			if ( isset( $value_parts[1] ) && ! (int) $value_parts[1] ) {
340
				if ( 'remove' === $decimal_handling ) {
341
					array_pop( $value_parts );
342
				} elseif ( 'dash' === $decimal_handling ) {
343
					array_pop( $value_parts );
344
					$value_parts[] = '-';
345
				}
346
				$value = implode( $dot, $value_parts );
347
			}
348
		}
349
350
		return $value;
351
352
	}
353
354
	/**
355
	 * Get the currencies and place them in the local property
356
	 *
357
	 * @since  2.6.8
358
	 * @return array
359
	 */
360
	public static function data_currencies() {
361
362
		// If it's already done, do not redo the filter
363
		if ( ! empty( static::$currencies ) ) {
364
			return static::$currencies;
365
		}
366
367
		$default_currencies = array(
368
			'aud'  => array(
369
				'label'  => 'AUD',
370
				'name'   => __( 'Australian Dollar', 'pods' ),
371
				'sign'   => '$',
372
				'entity' => '&#36;',
373
			),
374
			'brl'  => array(
375
				'label'  => 'BRL',
376
				'name'   => __( 'Brazilian Real', 'pods' ),
377
				'sign'   => 'R$',
378
				'entity' => 'R&#36;',
379
			),
380
			'cad'  => array(
381
				'label'  => 'CAD',
382
				'name'   => __( 'Canadian Dollar', 'pods' ),
383
				'sign'   => '$',
384
				'entity' => '&#36;',
385
			),
386
			'chf'  => array(
387
				'label'  => 'CHF',
388
				'name'   => __( 'Swiss Franc', 'pods' ),
389
				'sign'   => 'Fr',
390
				'entity' => 'Fr',
391
			),
392
			'cny'  => array(
393
				'label'  => 'CNY',
394
				'name'   => __( 'Chinese Yuan', 'pods' ),
395
				'sign'   => '¥',
396
				'entity' => '&yen;',
397
			),
398
			'cny2' => array(
399
				'label'  => 'CNY',
400
				'name'   => __( 'Chinese Yuan', 'pods' ),
401
				'sign'   => '元',
402
				'entity' => '&#20803;',
403
			),
404
			'czk'  => array(
405
				'label'  => 'CZK',
406
				'name'   => __( 'Czech Koruna', 'pods' ),
407
				'sign'   => 'Kč',
408
				'entity' => 'K&#x10D;',
409
			),
410
			'dkk'  => array(
411
				'label'  => 'DKK',
412
				'name'   => __( 'Danish Krone', 'pods' ),
413
				'sign'   => 'kr.',
414
				'entity' => 'kr.',
415
			),
416
			'euro' => array(
417
				'label'  => 'EUR',
418
				'name'   => __( 'Euro', 'pods' ),
419
				'sign'   => '€',
420
				'entity' => '&euro;',
421
			),
422
			'gbp'  => array(
423
				'label'  => 'GBP',
424
				'name'   => __( 'British Pound', 'pods' ),
425
				'sign'   => '£',
426
				'entity' => '&pound;',
427
			),
428
			'hkd'  => array(
429
				'label'  => 'HKD',
430
				'name'   => __( 'Hong Kong Dollar', 'pods' ),
431
				'sign'   => '$',
432
				'entity' => '&#36;',
433
			),
434
			'huf'  => array(
435
				'label'  => 'HUF',
436
				'name'   => __( 'Hungarian Forint', 'pods' ),
437
				'sign'   => 'Ft',
438
				'entity' => 'Ft',
439
			),
440
			'ils'  => array(
441
				'label'  => 'ILS',
442
				'name'   => __( 'Israeli New Sheqel', 'pods' ),
443
				'sign'   => '₪',
444
				'entity' => '&#x20AA;',
445
			),
446
			'jpy'  => array(
447
				'label'  => 'JPY',
448
				'name'   => __( 'Japanese Yen', 'pods' ),
449
				'sign'   => '¥',
450
				'entity' => '&yen;',
451
			),
452
			'krw'  => array(
453
				'label'  => 'KRW',
454
				'name'   => __( 'Korean Won', 'pods' ),
455
				'sign'   => '₩',
456
				'entity' => '&#8361;',
457
			),
458
			'myr'  => array(
459
				'label'  => 'MYR',
460
				'name'   => __( 'Malaysian Ringgit', 'pods' ),
461
				'sign'   => 'MR',
462
				'entity' => 'MR',
463
			),
464
			'mxn'  => array(
465
				'label'  => 'MXN',
466
				'name'   => __( 'Mexican Peso', 'pods' ),
467
				'sign'   => '$',
468
				'entity' => '&#36;',
469
			),
470
			'nok'  => array(
471
				'label'  => 'NOK',
472
				'name'   => __( 'Norwegian Krone', 'pods' ),
473
				'sign'   => 'kr',
474
				'entity' => 'kr',
475
			),
476
			'nzd'  => array(
477
				'label'  => 'NZD',
478
				'name'   => __( 'New Zealand Dollar', 'pods' ),
479
				'sign'   => '$',
480
				'entity' => '&#36;',
481
			),
482
			'php'  => array(
483
				'label'  => 'PHP',
484
				'name'   => __( 'Philippine Peso', 'pods' ),
485
				'sign'   => '₱',
486
				'entity' => '&#x20B1;',
487
			),
488
			'pln'  => array(
489
				'label'  => 'PLN',
490
				'name'   => __( 'Polish Złoty', 'pods' ),
491
				'sign'   => 'zł',
492
				'entity' => 'z&#x142;',
493
			),
494
			'rub'  => array(
495
				'label'  => 'RUB',
496
				'name'   => __( 'Russian Ruble', 'pods' ),
497
				'sign'   => '₽',
498
				'entity' => '&#8381;',
499
			),
500
			'sek'  => array(
501
				'label'  => 'SEK',
502
				'name'   => __( 'Swedish Krona', 'pods' ),
503
				'sign'   => 'kr',
504
				'entity' => 'kr',
505
			),
506
			'sgd'  => array(
507
				'label'  => 'SGD',
508
				'name'   => __( 'Singapore Dollar', 'pods' ),
509
				'sign'   => '$',
510
				'entity' => '&#36;',
511
			),
512
			'thb'  => array(
513
				'label'  => 'THB',
514
				'name'   => __( 'Thai Baht', 'pods' ),
515
				'sign'   => '฿',
516
				'entity' => '&#x0E3F;',
517
			),
518
			'trl'  => array(
519
				'label'  => 'TRL',
520
				'name'   => __( 'Turkish Lira', 'pods' ),
521
				'sign'   => '₺',
522
				'entity' => '&#8378;',
523
			),
524
			'twd'  => array(
525
				'label'  => 'TWD',
526
				'name'   => __( 'Taiwan New Dollar', 'pods' ),
527
				'sign'   => '$',
528
				'entity' => '&#36;',
529
			),
530
			'usd'  => array(
531
				'label'  => 'USD',
532
				'name'   => __( 'US Dollar', 'pods' ),
533
				'sign'   => '$',
534
				'entity' => '&#36;',
535
			),
536
			'vnd'  => array(
537
				'label'  => 'VND',
538
				'name'   => __( 'Vietnamese Dong', 'pods' ),
539
				'sign'   => '₫',
540
				'entity' => '&#8363;',
541
			),
542
			'zar'  => array(
543
				'label'  => 'ZAR',
544
				'name'   => __( 'South African Rand', 'pods' ),
545
				'sign'   => 'R',
546
				'entity' => 'R',
547
			),
548
			'inr'  => array(
549
				'label'  => 'INR',
550
				'name'   => __( 'Indian Rupee', 'pods' ),
551
				'sign'   => '₹',
552
				'entity' => '&#x20B9;',
553
			),
554
		);
555
556
		/**
557
		 * Add custom currencies
558
		 *
559
		 * @param  array $options {
560
		 *                        Required array of arrays.
561
		 *
562
		 * @type  array {
563
		 * @type  string $label   The label (example: USD).
564
		 * @type  string $name    The full name (example: US Dollar).
565
		 * @type  string $sign    The sign (example: $).
566
		 * @type  string $entity  The HTML entity (example: &#36;).
567
		 *     }
568
		 * }
569
		 * @return array
570
		 */
571
		static::$currencies = apply_filters( 'pods_form_ui_field_currency_currencies', $default_currencies );
572
573
		// Sort the currencies
574
		ksort( static::$currencies );
575
576
		// Backwards compatibility
577
		foreach ( static::$currencies as $key => $value ) {
578
			if ( is_string( $value ) ) {
579
				static::$currencies[ $key ] = array(
580
					'label'  => strtoupper( $key ),
581
					'name'   => strtoupper( $key ),
582
					'sign'   => $value,
583
					'entity' => $value,
584
				);
585
			} elseif ( is_array( $value ) ) {
586
				// Make sure all required values are set
587
				if ( empty( $value['label'] ) ) {
588
					$value['label'] = $key;
589
				}
590
				if ( empty( $value['name'] ) ) {
591
					$value['name'] = $key;
592
				}
593
				if ( empty( $value['sign'] ) ) {
594
					$value['sign'] = $key;
595
				}
596
				if ( empty( $value['entity'] ) ) {
597
					$value['entity'] = $key;
598
				}
599
			} else {
600
				// Invalid
601
				unset( static::$currencies[ $key ] );
602
			}//end if
603
		}//end foreach
604
605
		return static::$currencies;
606
	}
607
608
	/**
609
	 * Get the max allowed decimals.
610
	 * Overwrites the default value of Number field. 2 decimals instead of 0.
611
	 *
612
	 * @since 2.7
613
	 *
614
	 * @param array $options Field options.
615
	 *
616
	 * @return int
617
	 */
618
	public function get_max_decimals( $options ) {
619
620
		$length = (int) pods_v( static::$type . '_max_length', $options, 12, true );
621
622
		if ( $length < 1 || 64 < $length ) {
623
			$length = 64;
624
		}
625
626
		$decimals = (int) pods_v( static::$type . '_decimals', $options, 2 );
627
628
		if ( $decimals < 1 ) {
629
			$decimals = 0;
630
		} elseif ( 30 < $decimals ) {
631
			$decimals = 30;
632
		}
633
634
		if ( $length < $decimals ) {
635
			$decimals = $length;
636
		}
637
638
		return $decimals;
639
	}
640
}
641