Completed
Push — develop ( b3f345...32c254 )
by Aristeides
03:24
created

Kirki_Active_Callback   D

Complexity

Total Complexity 61

Size/Duplication

Total Lines 173
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 173
rs 4.054
c 0
b 0
f 0
wmc 61
lcom 0
cbo 1

3 Methods

Rating   Name   Duplication   Size   Complexity  
B evaluate() 0 29 6
C evaluate_requirement() 0 48 15
C compare() 0 66 40

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) 2017, 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
		$show = true;
26
27
		// Get all fields.
28
		$fields = Kirki::$fields;
29
30
		// Make sure the current object matches a registered field.
31
		if ( ! isset( $object->setting->id ) || ! isset( $fields[ $object->setting->id ] ) ) {
32
			return true;
33
		}
34
35
		$field = $fields[ $object->setting->id ];
36
37
		if ( isset( $field['required'] ) ) {
38
39
			foreach ( $field['required'] as $requirement ) {
40
				$show = self::evaluate_requirement( $object, $field, $requirement, 'AND' );
41
				// The 1st level uses "AND" so no need to process further
42
				// if one requirement returns false.
43
				if ( ! $show ) {
44
					return false;
45
				}
46
			}
47
		}
48
49
		return true;
50
51
	}
52
53
	/**
54
	 * Figure out whether the current object should be displayed or not.
55
	 * We're only parsing a single requirement here from the array of requirements.
56
	 * This is a proxy function that facilitates evaluating and/or conditions.
57
	 *
58
	 * @param WP_Customize_Setting $object      The current field.
59
	 * @param object               $field       The current object.
60
	 * @param array                $requirement A single requirement.
61
	 * @param string               $relation    Can be "AND" or "OR".
62
	 * @return boolean
63
	 */
64
	private static function evaluate_requirement( $object, $field, $requirement, $relation ) {
65
66
		// Test for callables first.
67
		if ( is_callable( $requirement ) ) {
68
			return call_user_func_array( $requirement, array( $field, $object ) );
69
		}
70
71
		// Look for comparison array.
72
		if ( is_array( $requirement ) && isset( $requirement['operator'], $requirement['value'], $requirement['setting'] ) ) {
73
74
			if ( isset( $field['option_name'] ) && '' !== $field['option_name'] ) {
75
				if ( false === strpos( $requirement['setting'], '[' ) ) {
76
					$requirement['setting'] = $field['option_name'] . '[' . $requirement['setting'] . ']';
77
				}
78
			}
79
80
			$current_setting = $object->manager->get_setting( $requirement['setting'] );
81
82
			/**
83
			 * Depending on the 'operator' argument we use,
84
			 * we'll need to perform the appropriate comparison
85
			 * and figure out if the control will be shown or not.
86
			 */
87
			if ( method_exists( $current_setting, 'value' ) ) {
88
				return self::compare( $requirement['value'], $current_setting->value(), $requirement['operator'] );
89
			}
90
		} else {
91
			if ( ! is_array( $requirement ) ) {
92
				return true;
93
			}
94
95
			// Handles "OR/AND" functionality & switching.
96
			$show = false;
97
			$sub_relation = ( 'AND' === $relation ) ? 'OR' : 'AND';
98
			foreach ( $requirement as $sub_requirement ) {
99
				$show = self::evaluate_requirement( $object, $field, $sub_requirement, $sub_relation );
100
				if ( 'OR' === $sub_relation && $show ) {
101
					return true;
102
				}
103
				if ( 'AND' === $sub_relation && ! $show ) {
104
					return false;
105
				}
106
			}
107
			return $show;
108
		}
109
110
		return true;
111
	}
112
113
	/**
114
	 * Compares the 2 values given the condition
115
	 *
116
	 * @param mixed  $value1   The 1st value in the comparison.
117
	 * @param mixed  $value2   The 2nd value in the comparison.
118
	 * @param string $operator The operator we'll use for the comparison.
119
	 * @return boolean whether The comparison has succeded (true) or failed (false).
120
	 */
121
	public static function compare( $value1, $value2, $operator ) {
122
		switch ( $operator ) {
123
			case '===':
124
				$show = ( $value1 === $value2 ) ? true : false;
125
				break;
126
			case '==':
127
			case '=':
128
			case 'equals':
129
			case 'equal':
130
				$show = ( $value1 == $value2 ) ? true : false;
131
				break;
132
			case '!==':
133
				$show = ( $value1 !== $value2 ) ? true : false;
134
				break;
135
			case '!=':
136
			case 'not equal':
137
				$show = ( $value1 != $value2 ) ? true : false;
138
				break;
139
			case '>=':
140
			case 'greater or equal':
141
			case 'equal or greater':
142
				$show = ( $value2 >= $value1 ) ? true : false;
143
				break;
144
			case '<=':
145
			case 'smaller or equal':
146
			case 'equal or smaller':
147
				$show = ( $value2 <= $value1 ) ? true : false;
148
				break;
149
			case '>':
150
			case 'greater':
151
				$show = ( $value2 > $value1 ) ? true : false;
152
				break;
153
			case '<':
154
			case 'smaller':
155
				$show = ( $value2 < $value1 ) ? true : false;
156
				break;
157
			case 'contains':
158
			case 'in':
159
				if ( is_array( $value1 ) && ! is_array( $value2 ) ) {
160
					$array  = $value1;
161
					$string = $value2;
162
				} elseif ( is_array( $value2 ) && ! is_array( $value1 ) ) {
163
					$array  = $value2;
164
					$string = $value1;
165
				}
166
				if ( isset( $array ) && isset( $string ) ) {
167
					if ( ! in_array( $string, $array, true ) ) {
168
						$show = false;
169
					}
170
				} else {
171
					if ( false === strrpos( $value1, $value2 ) && false === strpos( $value2, $value1 ) ) {
172
						$show = false;
173
					}
174
				}
175
				break;
176
			default:
177
				$show = ( $value1 == $value2 ) ? true : false;
178
179
		} // End switch().
180
181
		if ( isset( $show ) ) {
182
			return $show;
183
		}
184
185
		return true;
186
	}
187
}
188