Completed
Pull Request — 2.x (#4370)
by
unknown
05:02
created

PodsField_Number::schema()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 2
nop 1
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package Pods\Fields
4
 */
5
class PodsField_Number extends PodsField {
6
7
    /**
8
     * Field Type Group
9
     *
10
     * @var string
11
     * @since 2.0
12
     */
13
    public static $group = 'Number';
14
15
    /**
16
     * Field Type Identifier
17
     *
18
     * @var string
19
     * @since 2.0
20
     */
21
    public static $type = 'number';
22
23
    /**
24
     * Field Type Label
25
     *
26
     * @var string
27
     * @since 2.0
28
     */
29
    public static $label = 'Plain Number';
30
31
    /**
32
     * Field Type Preparation
33
     *
34
     * @var string
35
     * @since 2.0
36
     */
37
    public static $prepare = '%d';
38
39
    /**
40
     * Do things like register/enqueue scripts and stylesheets
41
     *
42
     * @since 2.0
43
     */
44
    public function __construct () {
45
	    self::$label = __( 'Plain Number', 'pods' );
46
    }
47
48
    /**
49
     * Add options and set defaults to
50
     *
51
     * @return array
52
     *
53
     * @since 2.0
54
     */
55
    public function options () {
56
        $options = array(
57
            static::$type . '_repeatable' => array(
58
                'label' => __( 'Repeatable Field', 'pods' ),
59
                'default' => 0,
60
                'type' => 'boolean',
61
                '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' ),
62
                'boolean_yes_label' => '',
63
                'dependency' => true,
64
                'developer_mode' => true
65
            ),
66
            static::$type . '_format_type' => array(
67
                'label' => __( 'Input Type', 'pods' ),
68
                'default' => 'number',
69
                'type' => 'pick',
70
                'data' => array(
71
                    'number' => __( 'Freeform Number', 'pods' ),
72
                    'slider' => __( 'Slider', 'pods' )
73
                ),
74
                'dependency' => true
75
            ),
76
            static::$type . '_format' => array(
77
                'label' => __( 'Format', 'pods' ),
78
                'default' => apply_filters( 'pods_form_ui_field_number_format_default', 'i18n' ),
79
                'type' => 'pick',
80
                'data' => array(
81
                    'i18n' => __( 'Localized Default', 'pods' ),
82
                    '9,999.99' => '1,234.00',
83
                    '9.999,99' => '1.234,00',
84
                    '9 999,99' => '1 234,00',
85
                    '9999.99' => '1234.00',
86
                    '9999,99' => '1234,00'
87
                )
88
            ),
89
            static::$type . '_decimals' => array(
90
                'label' => __( 'Decimals', 'pods' ),
91
                'default' => 0,
92
                'type' => 'number',
93
	            'dependency' => true
94
            ),
95
            static::$type . '_format_soft' => array(
96
	            'label'      => __( 'Soft format?', 'pods' ),
97
	            'help'       => __( 'Remove trailing decimals (0)', 'pods' ),
98
	            'default'    => 0,
99
	            'type'       => 'boolean',
100
	            'excludes-on' => array( static::$type . '_decimals' => 0 ),
101
            ),
102
            static::$type . '_step' => array(
103
                'label' => __( 'Slider Increment (Step)', 'pods' ),
104
                'depends-on' => array( static::$type . '_format_type' => 'slider' ),
105
                'default' => 1,
106
                'type' => 'text'
107
            ),
108
            static::$type . '_min' => array(
109
                'label' => __( 'Minimum Number', 'pods' ),
110
                'depends-on' => array( static::$type . '_format_type' => 'slider' ),
111
                'default' => 0,
112
                'type' => 'text'
113
            ),
114
            static::$type . '_max' => array(
115
                'label' => __( 'Maximum Number', 'pods' ),
116
                'depends-on' => array( static::$type . '_format_type' => 'slider' ),
117
                'default' => 100,
118
                'type' => 'text'
119
            ),
120
            static::$type . '_max_length' => array(
121
                'label' => __( 'Maximum Length', 'pods' ),
122
                'default' => 12,
123
                'type' => 'number',
124
                'help' => __( 'Set to -1 for no limit', 'pods' )
125
            ),
126
			static::$type . '_placeholder' => array(
127
				'label' => __( 'HTML Placeholder', 'pods' ),
128
				'default' => '',
129
				'type' => 'text',
130
				'help' => array(
131
					__( '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' ),
132
					'https://www.w3.org/WAI/tutorials/forms/instructions/#placeholder-text',
133
				),
134
			),/*,
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
135
            static::$type . '_size' => array(
136
                'label' => __( 'Field Size', 'pods' ),
137
                'default' => 'medium',
138
                'type' => 'pick',
139
                'data' => array(
140
                    'small' => __( 'Small', 'pods' ),
141
                    'medium' => __( 'Medium', 'pods' ),
142
                    'large' => __( 'Large', 'pods' )
143
                )
144
            )*/
145
        );
146
        return $options;
147
    }
148
149
	/**
150
	 * Define the current field's schema for DB table storage
151
	 *
152
	 * @param array $options
153
	 *
154
	 * @return string
155
	 * @since 2.0
156
	 */
157
	public function schema( $options = null ) {
158
159
		$length = (int) pods_v( static::$type . '_max_length', $options, 12, true );
160
161
		if ( $length < 1 || 64 < $length ) {
162
			$length = 64;
163
		}
164
165
		$decimals = $this->get_max_decimals( $options );
166
167
		$schema = 'DECIMAL(' . $length . ',' . $decimals . ')';
168
169
		return $schema;
170
171
	}
172
173
	/**
174
	 * Define the current field's preparation for sprintf
175
	 *
176
	 * @param array $options
177
	 *
178
	 * @return string
179
	 * @since 2.0
180
	 */
181
	public function prepare( $options = null ) {
182
183
		$format = static::$prepare;
184
185
		$decimals = $this->get_max_decimals( $options );
186
187
		if ( 0 < $decimals ) {
188
			$format = '%01.' . $decimals . 'F';
189
		}
190
191
		return $format;
192
193
	}
194
195
	/**
196
	 * {@inheritdoc}
197
	 */
198
	public function is_empty( $value = null ) {
199
200
		$is_empty = false;
201
202
		$value += 0;
203
204
		if ( empty( $value ) ) {
205
			$is_empty = true;
206
		}
207
208
		return $is_empty;
209
210
	}
211
212
    /**
213
     * Change the way the value of the field is displayed with Pods::get
214
     *
215
     * @param mixed $value
216
     * @param string $name
217
     * @param array $options
218
     * @param array $pod
219
     * @param int $id
220
     *
221
     * @return mixed|null|string
222
     * @since 2.0
223
     */
224
    public function display ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
225
        $value = $this->format( $value, $name, $options, $pod, $id );
226
227
        return $value;
228
    }
229
230
	/**
231
	 * Customize output of the form field
232
	 *
233
	 * @param string $name
234
	 * @param mixed $value
235
	 * @param array $options
236
	 * @param array $pod
237
	 * @param int $id
238
	 *
239
	 * @since 2.0
240
	 */
241
	public function input( $name, $value = null, $options = null, $pod = null, $id = null ) {
242
243
		$options = (array) $options;
244
		$form_field_type = PodsForm::$field_type;
0 ignored issues
show
Bug introduced by
The property field_type cannot be accessed from this context as it is declared private in class PodsForm.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
245
246
		if ( is_array( $value ) ) {
247
			$value = implode( '', $value );
248
		}
249
250
		if ( 'slider' == pods_v( static::$type . '_format_type', $options, 'number' ) ) {
251
			$field_type = 'slider';
252
		}
253
		else {
254
			$field_type = static::$type;
255
		}
256
257
		if ( isset( $options[ 'name' ] ) && false === PodsForm::permission( static::$type, $options[ 'name' ], $options, null, $pod, $id ) ) {
258
			if ( pods_v( 'read_only', $options, false ) ) {
259
				$options[ 'readonly' ] = true;
260
261
				$field_type = 'text';
262
263
				$value = $this->format( $value, $name, $options, $pod, $id );
264
			}
265
			else {
266
				return;
267
			}
268
		}
269
		elseif ( !pods_has_permissions( $options ) && pods_v( 'read_only', $options, false ) ) {
270
			$options[ 'readonly' ] = true;
271
272
			$field_type = 'text';
273
274
			$value = $this->format( $value, $name, $options, $pod, $id );
275
		}
276
277
		pods_view( PODS_DIR . 'ui/fields/' . $field_type . '.php', compact( array_keys( get_defined_vars() ) ) );
278
279
	}
280
281
    /**
282
     * Build regex necessary for JS validation
283
     *
284
     * @param mixed $value
285
     * @param string $name
286
     * @param array $options
287
     * @param string $pod
288
     * @param int $id
289
     *
290
     * @return bool|string
291
     * @since 2.0
292
     */
293
    public function regex ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
294
295
	    $format_args = $this->get_number_format_args( $options );
296
	    $thousands   = $format_args['thousands'];
297
	    $dot         = $format_args['dot'];
298
299
        return '\-*[0-9\\' . implode( '\\', array_filter( array( $dot, $thousands ) ) ) . ']+';
300
    }
301
302
    /**
303
     * Validate a value before it's saved
304
     *
305
     * @param mixed $value
306
     * @param string $name
307
     * @param array $options
308
     * @param array $fields
309
     * @param array $pod
310
     * @param int $id
311
     * @param null $params
312
     *
313
     * @return bool|mixed
314
     * @since 2.0
315
     */
316
    public function validate ( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
317
318
	    $format_args = $this->get_number_format_args( $options );
319
	    $thousands   = $format_args['thousands'];
320
	    $dot         = $format_args['dot'];
321
322
	    $check = str_replace(
323
	    	array( $thousands, $dot, html_entity_decode( $thousands ) ),
324
		    array( '', '.', '' ),
325
		    $value
326
	    );
327
        $check = trim( $check );
328
329
        $check = preg_replace( '/[0-9\.\-\s]/', '', $check );
330
331
        $label = pods_v( 'label', $options, ucwords( str_replace( '_', ' ', $name ) ) );
332
333
        if ( 0 < strlen( $check ) ) {
334
	        return sprintf( __( '%s is not numeric', 'pods' ), $label );
335
        }
336
337
        return true;
338
    }
339
340
    /**
341
     * Change the value or perform actions after validation but before saving to the DB
342
     *
343
     * @param mixed $value
344
     * @param int $id
345
     * @param string $name
346
     * @param array $options
347
     * @param array $fields
348
     * @param array $pod
349
     * @param object $params
350
     *
351
     * @return mixed|string
352
     * @since 2.0
353
     */
354
    public function pre_save ( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
355
356
	    $format_args = $this->get_number_format_args( $options );
357
	    $thousands   = $format_args['thousands'];
358
	    $dot         = $format_args['dot'];
359
	    $decimals    = $format_args['decimals'];
360
361
        $value = str_replace( array( $thousands, $dot ), array( '', '.' ), $value );
362
        $value = trim( $value );
363
364
        $value = preg_replace( '/[^0-9\.\-]/', '', $value );
365
366
        $value = number_format( (float) $value, $decimals, '.', '' );
367
368
        return $value;
369
    }
370
371
    /**
372
     * Customize the Pods UI manage table column output
373
     *
374
     * @param int $id
375
     * @param mixed $value
376
     * @param string $name
377
     * @param array $options
378
     * @param array $fields
379
     * @param array $pod
380
     *
381
     * @return mixed|null|string
382
     * @since 2.0
383
     */
384
    public function ui ( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
385
        return $this->display( $value, $name, $options, $pod, $id );
386
    }
387
388
    /**
389
     * Reformat a number to the way the value of the field is displayed
390
     *
391
     * @param mixed $value
392
     * @param string $name
393
     * @param array $options
394
     * @param array $pod
395
     * @param int $id
396
     *
397
     * @return string
398
     * @since 2.0
399
     */
400
    public function format ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
401
402
	    if ( null === $value ) {
403
		    // Don't enforce a default value here.
404
		    return null;
405
	    }
406
407
	    $format_args = $this->get_number_format_args( $options );
408
	    $thousands   = $format_args['thousands'];
409
	    $dot         = $format_args['dot'];
410
	    $decimals    = $format_args['decimals'];
411
412 View Code Duplication
	    if ( 'i18n' == pods_v( static::$type . '_format', $options ) ) {
413
		    $value = number_format_i18n( (float) $value, $decimals );
414
	    }
415
	    else {
416
		    $value = number_format( (float) $value, $decimals, $dot, $thousands );
417
	    }
418
419
        // Optionally remove trailing decimal zero's.
420
        if ( pods_v( static::$type . '_format_soft', $options, 0 ) ) {
421
        	$parts = explode( $dot, $value );
422
        	if ( isset( $parts[1] ) ) {
423
        		$parts[1] = rtrim( $parts[1], '0' );
424
        		$parts = array_filter( $parts );
425
	        }
426
	        $value = implode( $dot, $parts );
427
        }
428
429
        return $value;
430
    }
431
432
	/**
433
	 * Get the formatting arguments for numbers.
434
	 * @since 2.7
435
	 * @param array $options Field options.
436
	 * @return array {
437
	 *     @type string $thousands
438
	 *     @type string $dot
439
	 *     @type int    $decimals
440
	 * }
441
	 */
442
    public function get_number_format_args( $options ) {
443
	    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...
444
445
	    if ( '9.999,99' == pods_v( static::$type . '_format', $options ) ) {
446
		    $thousands = '.';
447
		    $dot = ',';
448
	    }
449 View Code Duplication
	    elseif ( '9,999.99' == pods_v( static::$type . '_format', $options ) ) {
450
		    $thousands = ',';
451
		    $dot = '.';
452
	    }
453 View Code Duplication
	    elseif ( '9\'999.99' == pods_v( static::$type . '_format', $options ) ) {
454
		    $thousands = '\'';
455
		    $dot = '.';
456
	    }
457 View Code Duplication
	    elseif ( '9 999,99' == pods_v( static::$type . '_format', $options ) ) {
458
		    $thousands = ' ';
459
		    $dot = ',';
460
	    }
461
	    elseif ( '9999.99' == pods_v( static::$type . '_format', $options ) ) {
462
		    $thousands = '';
463
		    $dot = '.';
464
	    }
465 View Code Duplication
	    elseif ( '9999,99' == pods_v( static::$type . '_format', $options ) ) {
466
		    $thousands = '';
467
		    $dot = ',';
468
	    }
469
	    else {
470
		    $thousands = $wp_locale->number_format[ 'thousands_sep' ];
471
		    $dot = $wp_locale->number_format[ 'decimal_point' ];
472
	    }
473
474
	    $decimals = $this->get_max_decimals( $options );
475
476
	    return array(
477
	    	'thousands' => $thousands,
478
	        'dot'       => $dot,
479
	        'decimals'  => $decimals,
480
	    );
481
    }
482
483
    /**
484
     * Get the max allowed decimals.
485
     *
486
     * @since 2.7
487
     * @param array $options
488
     * @return int
489
     */
490 View Code Duplication
    public function get_max_decimals( $options ) {
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...
491
492
	    $length = (int) pods_v( static::$type . '_max_length', $options, 12, true );
493
494
	    if ( $length < 1 || 64 < $length ) {
495
		    $length = 64;
496
	    }
497
498
	    $decimals = (int) pods_v( static::$type . '_decimals', $options, 0 );
499
500
	    if ( $decimals < 1 ) {
501
		    $decimals = 0;
502
	    }
503
	    elseif ( 30 < $decimals ) {
504
		    $decimals = 30;
505
	    }
506
507
	    if ( $length < $decimals ) {
508
		    $decimals = $length;
509
	    }
510
511
	    return $decimals;
512
    }
513
}
514