Completed
Push — develop ( 2288ab...2733ee )
by Aristeides
02:48 queued 15s
created

Kirki_Active_Callback   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 167
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 167
rs 5.1724
c 0
b 0
f 0
wmc 57
lcom 0
cbo 1

3 Methods

Rating   Name   Duplication   Size   Complexity  
B evaluate() 0 27 6
C compare() 0 66 40
C evaluate_requirement() 0 45 11

How to fix   Complexity   

Complex Class

Complex classes like Kirki_Active_Callback 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 Kirki_Active_Callback, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Active callback used with the "required" argument in fields
4
 *
5
 * @package     Kirki
6
 * @category    Core
7
 * @author      Aristeides Stathopoulos
8
 * @copyright   Copyright (c) 2016, Aristeides Stathopoulos
9
 * @license     http://opensource.org/licenses/https://opensource.org/licenses/MIT
10
 */
11
12
/**
13
 * Callback class for use with the "required" argument
14
 */
15
class Kirki_Active_Callback {
16
17
	/**
18
	 * Figure out whether the current object should be displayed or not.
19
	 *
20
	 * @param  WP_Customize_Setting $object The current field.
21
	 * @return boolean
22
	 */
23
	public static function evaluate( $object ) {
24
25
		// Get all fields.
26
		$fields = Kirki::$fields;
27
28
		// Make sure the current object matches a registered field.
29
		if ( ! isset( $object->setting->id ) || ! isset( $fields[ $object->setting->id ] ) ) {
30
			return true;
31
		}
32
33
		$field = $fields[ $object->setting->id ];
34
35
		if ( isset( $field['required'] ) ) {
36
37
			foreach ( $field['required'] as $requirement ) {
38
				// Handles "AND" functionality.
39
				$show = self::evaluate_requirement( $object, $field, $requirement );
40
				// No need to process further if one requirement returns false.
41
				if ( ! $show ) {
42
					return false;
43
				}
44
			}
45
		}
46
47
		return true;
48
49
	}
50
51
	/**
52
	 * Figure out whether the current object should be displayed or not.
53
	 * We're only parsing a single requirement here from the array of requirements.
54
	 * This is a proxy function that facilitates evaluating and/or conditions.
55
	 *
56
	 * @param  WP_Customize_Setting $object      The current field.
57
	 * @param  object               $field       The current object.
58
	 * @param  array                $requirement A single requirement.
59
	 * @return boolean
60
	 */
61
	private static function evaluate_requirement( $object, $field, $requirement ) {
62
63
		// Test for callables first.
64
		if ( is_callable( $requirement ) ) {
65
			return call_user_func_array( $requirement, array( $field, $object ) );
66
		}
67
68
		// Look for comparison array.
69
		if ( is_array( $requirement ) && isset( $requirement['operator'], $requirement['value'], $requirement['setting'] ) ) {
70
71
			if ( isset( $field['option_name'] ) && '' !== $field['option_name'] ) {
72
				if ( false === strpos( $requirement['setting'], '[' ) ) {
73
					$requirement['setting'] = $field['option_name'] . '[' . $requirement['setting'] . ']';
74
				}
75
			}
76
77
			$current_setting = $object->manager->get_setting( $requirement['setting'] );
78
79
			/**
80
			 * Depending on the 'operator' argument we use,
81
			 * we'll need to perform the appropriate comparison
82
			 * and figure out if the control will be shown or not.
83
			 */
84
			$show = self::compare( $requirement['value'], $current_setting->value(), $requirement['operator'] );
85
86
		} else {
87
			if ( ! is_array( $requirement ) ) {
88
				return true;
89
			}
90
91
			if ( is_array( $requirement ) ) {
92
				// Handles "OR" functionality.
93
				$show = false;
94
				foreach ( $requirement as $sub_requirement ) {
95
					$show = self::evaluate_requirement( $object, $field, $sub_requirement );
96
					// No need to go on if one sub_requirement returns true.
97
					if ( $show ) {
98
						return true;
99
					}
100
				}
101
			}
102
		}
103
104
		return $show;
0 ignored issues
show
Bug introduced by
The variable $show does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
105
	}
106
107
	/**
108
	 * Compares the 2 values given the condition
109
	 *
110
	 * @param mixed  $value1   The 1st value in the comparison.
111
	 * @param mixed  $value2   The 2nd value in the comparison.
112
	 * @param string $operator The operator we'll use for the comparison.
113
	 * @return boolean whether The comparison has succeded (true) or failed (false).
114
	 */
115
	public static function compare( $value1, $value2, $operator ) {
116
		switch ( $operator ) {
117
			case '===':
118
				$show = ( $value1 === $value2 ) ? true : false;
119
				break;
120
			case '==':
121
			case '=':
122
			case 'equals':
123
			case 'equal':
124
				$show = ( $value1 == $value2 ) ? true : false;
125
				break;
126
			case '!==':
127
				$show = ( $value1 !== $value2 ) ? true : false;
128
				break;
129
			case '!=':
130
			case 'not equal':
131
				$show = ( $value1 != $value2 ) ? true : false;
132
				break;
133
			case '>=':
134
			case 'greater or equal':
135
			case 'equal or greater':
136
				$show = ( $value1 >= $value2 ) ? true : false;
137
				break;
138
			case '<=':
139
			case 'smaller or equal':
140
			case 'equal or smaller':
141
				$show = ( $value1 <= $value2 ) ? true : false;
142
				break;
143
			case '>':
144
			case 'greater':
145
				$show = ( $value1 > $value2 ) ? true : false;
146
				break;
147
			case '<':
148
			case 'smaller':
149
				$show = ( $value1 < $value2 ) ? true : false;
150
				break;
151
			case 'contains':
152
			case 'in':
153
				if ( is_array( $value1 ) && ! is_array( $value2 ) ) {
154
					$array  = $value1;
155
					$string = $value2;
156
				} elseif ( is_array( $value2 ) && ! is_array( $value1 ) ) {
157
					$array  = $value2;
158
					$string = $value1;
159
				}
160
				if ( isset( $array ) && isset( $string ) ) {
161
					if ( ! in_array( $string, $array ) ) {
162
						$show = false;
163
					}
164
				} else {
165
					if ( false === strrpos( $value1, $value2 ) && false === strpos( $value2, $value1 ) ) {
166
						$show = false;
167
					}
168
				}
169
				break;
170
			default:
171
				$show = ( $value1 == $value2 ) ? true : false;
172
173
		}
174
175
		if ( isset( $show ) ) {
176
			return $show;
177
		}
178
179
		return true;
180
	}
181
}
182