Completed
Pull Request — 2.x (#4192)
by Jory
05:30
created

PodsField_Number   C

Complexity

Total Complexity 64

Size/Duplication

Total Lines 525
Duplicated Lines 33.9 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 178
loc 525
rs 5.8364
c 0
b 0
f 0
wmc 64
lcom 1
cbo 2

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
B options() 0 84 1
B schema() 20 20 6
C prepare() 25 25 7
A display() 0 5 1
C input() 33 33 8
B regex() 24 30 6
C validate() 24 44 7
C pre_save() 24 52 11
A ui() 0 3 1
D format() 28 65 15

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like PodsField_Number often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PodsField_Number, and based on these observations, apply Extract Interface, too.

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
            self::$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
            self::$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
            self::$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
            self::$type . '_decimals' => array(
90
                'label' => __( 'Decimals', 'pods' ),
91
                'default' => 0,
92
                'type' => 'number',
93
	            'dependency' => true
94
            ),
95
            self::$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( self::$type . '_decimals' => 0 ),
101
            ),
102
            self::$type . '_step' => array(
103
                'label' => __( 'Slider Increment (Step)', 'pods' ),
104
                'depends-on' => array( self::$type . '_format_type' => 'slider' ),
105
                'default' => 1,
106
                'type' => 'text'
107
            ),
108
            self::$type . '_min' => array(
109
                'label' => __( 'Minimum Number', 'pods' ),
110
                'depends-on' => array( self::$type . '_format_type' => 'slider' ),
111
                'default' => 0,
112
                'type' => 'text'
113
            ),
114
            self::$type . '_max' => array(
115
                'label' => __( 'Maximum Number', 'pods' ),
116
                'depends-on' => array( self::$type . '_format_type' => 'slider' ),
117
                'default' => 100,
118
                'type' => 'text'
119
            ),
120
            self::$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
            )/*,
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...
126
            self::$type . '_size' => array(
127
                'label' => __( 'Field Size', 'pods' ),
128
                'default' => 'medium',
129
                'type' => 'pick',
130
                'data' => array(
131
                    'small' => __( 'Small', 'pods' ),
132
                    'medium' => __( 'Medium', 'pods' ),
133
                    'large' => __( 'Large', 'pods' )
134
                )
135
            )*/
136
        );
137
        return $options;
138
    }
139
140
    /**
141
     * Define the current field's schema for DB table storage
142
     *
143
     * @param array $options
144
     *
145
     * @return array
146
     * @since 2.0
147
     */
148 View Code Duplication
    public function schema ( $options = null ) {
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...
149
        $length = (int) pods_var( self::$type . '_max_length', $options, 12, null, true );
150
151
        if ( $length < 1 || 64 < $length )
152
            $length = 64;
153
154
        $decimals = (int) pods_var( self::$type . '_decimals', $options, 0, null, true );
155
156
        if ( $decimals < 1 )
157
            $decimals = 0;
158
        elseif ( 30 < $decimals )
159
            $decimals = 30;
160
161
        if ( $length < $decimals )
162
            $decimals = $length;
163
164
        $schema = 'DECIMAL(' . $length . ',' . $decimals . ')';
165
166
        return $schema;
167
    }
168
169
    /**
170
     * Define the current field's preparation for sprintf
171
     *
172
     * @param array $options
173
     *
174
     * @return array
175
     * @since 2.0
176
     */
177 View Code Duplication
    public function prepare ( $options = null ) {
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...
178
        $format = self::$prepare;
179
180
        $length = (int) pods_var( self::$type . '_max_length', $options, 12, null, true );
181
182
        if ( $length < 1 || 64 < $length )
183
            $length = 64;
184
185
        $decimals = (int) pods_var( self::$type . '_decimals', $options, 0, null, true );
186
187
        if ( $decimals < 1 )
188
            $decimals = 0;
189
        elseif ( 30 < $decimals )
190
            $decimals = 30;
191
192
        if ( $length < $decimals )
193
            $decimals = $length;
194
195
        if ( 0 < $decimals )
196
            $format = '%01.' . $decimals . 'f';
197
        else
198
            $format = '%d';
199
200
        return $format;
201
    }
202
203
    /**
204
     * Change the way the value of the field is displayed with Pods::get
205
     *
206
     * @param mixed $value
207
     * @param string $name
208
     * @param array $options
209
     * @param array $pod
210
     * @param int $id
211
     *
212
     * @return mixed|null|string
213
     * @since 2.0
214
     */
215
    public function display ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
216
        $value = $this->format( $value, $name, $options, $pod, $id );
217
218
        return $value;
219
    }
220
221
    /**
222
     * Customize output of the form field
223
     *
224
     * @param string $name
225
     * @param mixed $value
226
     * @param array $options
227
     * @param array $pod
228
     * @param int $id
229
     *
230
     * @since 2.0
231
     */
232 View Code Duplication
    public function input ( $name, $value = null, $options = null, $pod = null, $id = null ) {
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...
233
        $options = (array) $options;
234
        $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...
235
236
        if ( is_array( $value ) )
237
            $value = implode( '', $value );
238
239
        if ( 'slider' == pods_var( self::$type . '_format_type', $options, 'number' ) )
240
            $field_type = 'slider';
241
        else
242
            $field_type = 'number';
243
244
        if ( isset( $options[ 'name' ] ) && false === PodsForm::permission( self::$type, $options[ 'name' ], $options, null, $pod, $id ) ) {
245
            if ( pods_var( 'read_only', $options, false ) )  {
246
                $options[ 'readonly' ] = true;
247
248
                $field_type = 'text';
249
250
                $value = $this->format( $value, $name, $options, $pod, $id );
251
            }
252
            else
253
                return;
254
        }
255
        elseif ( !pods_has_permissions( $options ) && pods_var( 'read_only', $options, false ) ) {
256
            $options[ 'readonly' ] = true;
257
258
            $field_type = 'text';
259
260
            $value = $this->format( $value, $name, $options, $pod, $id );
261
        }
262
263
        pods_view( PODS_DIR . 'ui/fields/' . $field_type . '.php', compact( array_keys( get_defined_vars() ) ) );
264
    }
265
266
    /**
267
     * Build regex necessary for JS validation
268
     *
269
     * @param mixed $value
270
     * @param string $name
271
     * @param array $options
272
     * @param string $pod
273
     * @param int $id
274
     *
275
     * @return bool|string
276
     * @since 2.0
277
     */
278
    public function regex ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
279
        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...
280
281 View Code Duplication
        if ( '9.999,99' == pods_var( self::$type . '_format', $options ) ) {
282
            $thousands = '.';
283
            $dot = ',';
284
        }
285
        elseif ( '9,999.99' == pods_var( self::$type . '_format', $options ) ) {
286
            $thousands = ',';
287
            $dot = '.';
288
        }
289
        elseif ( '9 999,99' == pods_var( self::$type . '_format', $options ) ) {
290
            $thousands = ' ';
291
            $dot = ',';
292
        }
293
        elseif ( '9999.99' == pods_var( self::$type . '_format', $options ) ) {
294
            $thousands = '';
295
            $dot = '.';
296
        }
297
        elseif ( '9999,99' == pods_var( self::$type . '_format', $options ) ) {
298
            $thousands = '';
299
            $dot = ',';
300
        }
301
        else {
302
            $thousands = html_entity_decode( $wp_locale->number_format['thousands_sep'] );
303
            $dot = $wp_locale->number_format[ 'decimal_point' ];
304
        }
305
306
        return '\-*[0-9\\' . implode( '\\', array_filter( array( $dot, $thousands ) ) ) . ']+';
307
    }
308
309
    /**
310
     * Validate a value before it's saved
311
     *
312
     * @param mixed $value
313
     * @param string $name
314
     * @param array $options
315
     * @param array $fields
316
     * @param array $pod
317
     * @param int $id
318
     * @param null $params
319
     *
320
     * @return bool|mixed
321
     * @since 2.0
322
     */
323
    public function validate ( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
324
        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...
325
326 View Code Duplication
        if ( '9.999,99' == pods_var( self::$type . '_format', $options ) ) {
327
            $thousands = '.';
328
            $dot = ',';
329
        }
330
        elseif ( '9,999.99' == pods_var( self::$type . '_format', $options ) ) {
331
            $thousands = ',';
332
            $dot = '.';
333
        }
334
        elseif ( '9 999,99' == pods_var( self::$type . '_format', $options ) ) {
335
            $thousands = ' ';
336
            $dot = ',';
337
        }
338
        elseif ( '9999.99' == pods_var( self::$type . '_format', $options ) ) {
339
            $thousands = ',';
340
            $dot = '.';
341
        }
342
        elseif ( '9999,99' == pods_var( self::$type . '_format', $options ) ) {
343
            $thousands = '.';
344
            $dot = ',';
345
        }
346
        else {
347
            $thousands = html_entity_decode( $wp_locale->number_format['thousands_sep'] );
348
            $dot = $wp_locale->number_format[ 'decimal_point' ];
349
        }
350
351
	    $check = str_replace(
352
	    	array( $thousands, $dot, html_entity_decode($thousands) ),
353
		    array( '', '.', '' ),
354
		    $value
355
	    );
356
        $check = trim( $check );
357
358
        $check = preg_replace( '/[0-9\.\-\s]/', '', $check );
359
360
        $label = pods_var( 'label', $options, ucwords( str_replace( '_', ' ', $name ) ) );
361
362
        if ( 0 < strlen( $check ) )
363
            return sprintf( __( '%s is not numeric', 'pods' ), $label );
364
365
        return true;
366
    }
367
368
    /**
369
     * Change the value or perform actions after validation but before saving to the DB
370
     *
371
     * @param mixed $value
372
     * @param int $id
373
     * @param string $name
374
     * @param array $options
375
     * @param array $fields
376
     * @param array $pod
377
     * @param object $params
378
     *
379
     * @return mixed|string
380
     * @since 2.0
381
     */
382
    public function pre_save ( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
383
        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...
384
385 View Code Duplication
        if ( '9.999,99' == pods_var( self::$type . '_format', $options ) ) {
386
            $thousands = '.';
387
            $dot = ',';
388
        }
389
        elseif ( '9,999.99' == pods_var( self::$type . '_format', $options ) ) {
390
            $thousands = ',';
391
            $dot = '.';
392
        }
393
        elseif ( '9 999,99' == pods_var( self::$type . '_format', $options ) ) {
394
            $thousands = ' ';
395
            $dot = ',';
396
        }
397
        elseif ( '9999.99' == pods_var( self::$type . '_format', $options ) ) {
398
            $thousands = ',';
399
            $dot = '.';
400
        }
401
        elseif ( '9999,99' == pods_var( self::$type . '_format', $options ) ) {
402
            $thousands = '.';
403
            $dot = ',';
404
        }
405
        else {
406
            $thousands = html_entity_decode( $wp_locale->number_format['thousands_sep'] );
407
            $dot = $wp_locale->number_format[ 'decimal_point' ];
408
        }
409
410
        $value = str_replace( array( $thousands, $dot ), array( '', '.' ), $value );
411
	$value = trim( $value );
412
413
        $value = preg_replace( '/[^0-9\.\-]/', '', $value );
414
415
        $length = (int) pods_var( self::$type . '_max_length', $options, 12, null, true );
416
417
        if ( $length < 1 || 64 < $length )
418
            $length = 64;
419
420
        $decimals = (int) pods_var( self::$type . '_decimals', $options, 0, null, true );
421
422
        if ( $decimals < 1 )
423
            $decimals = 0;
424
        elseif ( 30 < $decimals )
425
            $decimals = 30;
426
427
        if ( $length < $decimals )
428
            $decimals = $length;
429
430
        $value = number_format( (float) $value, $decimals, '.', '' );
431
432
        return $value;
433
    }
434
435
    /**
436
     * Customize the Pods UI manage table column output
437
     *
438
     * @param int $id
439
     * @param mixed $value
440
     * @param string $name
441
     * @param array $options
442
     * @param array $fields
443
     * @param array $pod
444
     *
445
     * @return mixed|null|string
446
     * @since 2.0
447
     */
448
    public function ui ( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
449
        return $this->display( $value, $name, $options, $pod, $id );
450
    }
451
452
    /**
453
     * Reformat a number to the way the value of the field is displayed
454
     *
455
     * @param mixed $value
456
     * @param string $name
457
     * @param array $options
458
     * @param array $pod
459
     * @param int $id
460
     *
461
     * @return string
462
     * @since 2.0
463
     */
464
    public function format ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
465
        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...
466
467
	if ( null === $value ) {
468
		// Don't enforce a default value here
469
		return null;
470
	}
471
472 View Code Duplication
        if ( '9.999,99' == pods_var( self::$type . '_format', $options ) ) {
473
            $thousands = '.';
474
            $dot = ',';
475
        }
476
        elseif ( '9,999.99' == pods_var( self::$type . '_format', $options ) ) {
477
            $thousands = ',';
478
            $dot = '.';
479
        }
480
        elseif ( '9 999,99' == pods_var( self::$type . '_format', $options ) ) {
481
            $thousands = ' ';
482
            $dot = ',';
483
        }
484
        elseif ( '9999.99' == pods_var( self::$type . '_format', $options ) ) {
485
            $thousands = '';
486
            $dot = '.';
487
        }
488
        elseif ( '9999,99' == pods_var( self::$type . '_format', $options ) ) {
489
            $thousands = '';
490
            $dot = ',';
491
        }
492
        else {
493
            $thousands = $wp_locale->number_format[ 'thousands_sep' ];
494
            $dot = $wp_locale->number_format[ 'decimal_point' ];
495
        }
496
497
        $length = (int) pods_var( self::$type . '_max_length', $options, 12, null, true );
498
499
        if ( $length < 1 || 64 < $length )
500
            $length = 64;
501
502
        $decimals = (int) pods_var( self::$type . '_decimals', $options, 0, null, true );
503
504
        if ( $decimals < 1 )
505
            $decimals = 0;
506
        elseif ( 30 < $decimals )
507
            $decimals = 30;
508
509
        if ( $length < $decimals )
510
            $decimals = $length;
511
512 View Code Duplication
        if ( 'i18n' == pods_var( self::$type . '_format', $options ) )
513
            $value = number_format_i18n( (float) $value, $decimals );
514
        else
515
            $value = number_format( (float) $value, $decimals, $dot, $thousands );
516
517
        // Optionally remove trailing decimal zero's.
518
        if ( pods_v( self::$type . '_format_soft', $options, 0 ) ) {
519
        	$parts = explode( $dot, $value );
520
        	if ( isset( $parts[1] ) ) {
521
        		$parts[1] = rtrim( $parts[1], '0' );
522
        		$parts = array_filter( $parts );
523
	        }
524
	        $value = implode( $dot, $parts );
525
        }
526
527
        return $value;
528
    }
529
}
530