Completed
Pull Request — master (#1930)
by Aristeides
08:20 queued 04:16
created

kirkiDependencies.evaluate   F

Complexity

Conditions 28
Paths 17

Size

Total Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 4 Features 0
Metric Value
cc 28
nc 17
nop 3
dl 0
loc 65
rs 0
c 5
b 4
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A 0 6 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like kirkiDependencies.evaluate 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.

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.

1
var kirkiDependencies = {
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
2
3
	listenTo: {},
4
5
	init: function() {
6
		var self = this;
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
7
8
		wp.customize.control.each( function( control ) {
9
			self.showKirkiControl( control );
10
		} );
11
12
		_.each( self.listenTo, function( slaves, master ) {
13
			_.each( slaves, function( slave ) {
14
				wp.customize( master, function( setting ) {
15
					var setupControl = function( control ) {
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
16
						var setActiveState,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
17
							isDisplayed;
18
19
						isDisplayed = function() {
20
							return self.showKirkiControl( wp.customize.control( slave ) );
21
						};
22
						setActiveState = function() {
23
							control.active.set( isDisplayed() );
24
						};
25
26
						setActiveState();
27
						setting.bind( setActiveState );
28
						control.active.validate = isDisplayed;
29
					};
30
					wp.customize.control( slave, setupControl );
31
				} );
32
			} );
33
		} );
34
	},
35
36
	/**
37
	 * Should we show the control?
38
	 *
39
	 * @since 3.0.17
40
	 * @param {string|object} control - The control-id or the control object.
41
	 * @returns {bool}
42
	 */
43
	showKirkiControl: function( control ) {
44
		var self     = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
45
			show     = true,
46
			isOption = (
47
				control.params && // Check if control.params exists.
48
				control.params.kirkiOptionType &&  // Check if option_type exists.
49
				'option' === control.params.kirkiOptionType &&  // We're using options.
50
				control.params.kirkiOptionName && // Check if option_name exists.
51
				! _.isEmpty( control.params.kirkiOptionName ) // Check if option_name is not empty.
52
			),
53
			i;
54
55
56
		if ( _.isString( control ) ) {
57
			control = wp.customize.control( control );
0 ignored issues
show
Comprehensibility Best Practice introduced by
This re-assigns to the parameter control. Re-assigning to parameters often makes code less readable, consider introducing a new variable instead.
Loading history...
58
		}
59
60
		// Exit early if control not found or if "required" argument is not defined.
61
		if ( 'undefined' === typeof control || ( control.params && _.isEmpty( control.params.required ) ) ) {
62
			return true;
63
		}
64
65
		// Loop control requirements.
66
		for ( i = 0; i < control.params.required.length; i++ ) {
67
			if ( ! self.checkCondition( control.params.required[ i ], control, isOption, 'AND' ) ) {
68
				show = false;
69
			}
70
		}
71
		return show;
72
	},
73
74
	/**
75
	 * Check a condition.
76
	 *
77
	 * @param {Object} requirement - The requirement, inherited from showKirkiControl.
78
	 * @param {Object} control - The control object.
79
	 * @param {bool}   isOption - Whether it's an option or not.
80
	 * @param {string} relation - Can be one of 'AND' or 'OR'.
81
	 */
82
	checkCondition: function( requirement, control, isOption, relation ) {
83
		var self          = this,
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
84
			childRelation = ( 'AND' === relation ) ? 'OR' : 'AND',
85
			nestedItems,
86
			i;
87
88
		// Tweak for using active callbacks with serialized options instead of theme_mods.
89
		if ( isOption && requirement.setting ) {
90
91
			// Make sure we don't already have the option_name in there.
92
			if ( -1 === requirement.setting.indexOf( control.params.kirkiOptionName + '[' ) ) {
93
				requirement.setting = control.params.kirkiOptionName + '[' + requirement.setting + ']';
94
			}
95
		}
96
97
		// If an array of other requirements nested, we need to process them separately.
98
		if ( 'undefined' !== typeof requirement[0] && 'undefined' === typeof requirement.setting ) {
99
			nestedItems = [];
100
101
			// Loop sub-requirements.
102
			for ( i = 0; i < requirement.length; i++ ) {
103
				nestedItems.push( self.checkCondition( requirement[ i ], control, isOption, childRelation ) );
104
			}
105
106
			// OR relation. Check that true is part of the array.
107
			if ( 'OR' === childRelation ) {
108
				return ( -1 !== nestedItems.indexOf( true ) );
109
			}
110
111
			// AND relation. Check that false is not part of the array.
112
			return ( -1 === nestedItems.indexOf( false ) );
113
		}
114
115
		// Early exit if setting is not defined.
116
		if ( 'undefined' === typeof wp.customize.control( requirement.setting ) ) {
117
			return true;
118
		}
119
120
		self.listenTo[ requirement.setting ] = self.listenTo[ requirement.setting ] || [];
121
		if ( -1 === self.listenTo[ requirement.setting ].indexOf( control.id ) ) {
122
			self.listenTo[ requirement.setting ].push( control.id );
123
		}
124
125
		return self.evaluate(
126
			requirement.value,
127
			wp.customize.control( requirement.setting ).setting._value,
128
			requirement.operator
129
		);
130
	},
131
132
	/**
133
	 * Figure out if the 2 values have the relation we want.
134
	 *
135
	 * @since 3.0.17
136
	 * @param {mixed} value1 - The 1st value.
137
	 * @param {mixed} value2 - The 2nd value.
138
	 * @param {string} operator - The comparison to use.
139
	 * @returns {bool}
140
	 */
141
	evaluate: function( value1, value2, operator ) {
142
		var found = false;
0 ignored issues
show
Coding Style introduced by
As per coding-style, prefer block-scoped variables using let or const which have better semantics than var.

Since ECMAScript 6, you can create block-scoped vars or constants with the keywords let or const. These variables/constants are only valid in the code block where they have been declared.

Consider the following two pieces of code:

if (true)
 {
    var x = "Hello, Stonehenge!";
}

console.log(x); //prints Hello, Stonehenge! to the console

and

if (true)
 {
    let x = "Hello, Stonehenge!";
}

console.log(x); //ReferenceError: x is not defined

The variable is not defined otuside of its block. This limits bleeding of variables into other contexts.

To know more about this ECMA6 feature, look at the MDN pages on let and const.

Loading history...
143
144
		if ( '===' === operator ) {
145
			return value1 === value2;
146
		}
147
		if ( '==' === operator || '=' === operator || 'equals' === operator || 'equal' === operator ) {
148
			return value1 == value2;
149
		}
150
		if ( '!==' === operator ) {
151
			return value1 !== value2;
152
		}
153
		if ( '!=' === operator || 'not equal' === operator ) {
154
			return value1 != value2;
155
		}
156
		if ( '>=' === operator || 'greater or equal' === operator || 'equal or greater' === operator ) {
157
			return value2 >= value1;
158
		}
159
		if ( '<=' === operator || 'smaller or equal' === operator || 'equal or smaller' === operator ) {
160
			return value2 <= value1;
161
		}
162
		if ( '>' === operator || 'greater' === operator ) {
163
			return value2 > value1;
164
		}
165
		if ( '<' === operator || 'smaller' === operator ) {
166
			return value2 < value1;
167
		}
168
		if ( 'contains' === operator || 'in' === operator ) {
169
			if ( _.isArray( value1 ) && _.isArray( value2 ) ) {
170
				_.each( value2, function( value ) {
171
					if ( value1.includes( value ) ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if value1.includes(value) is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
172
						found = true;
173
						return false;
174
					}
175
                } );
176
				return found;
177
			}
178
			if ( _.isArray( value2 ) ) {
179
				_.each( value2, function( value ) {
180
					if ( value == value1 ) { // jshint ignore:line
181
						found = true;
182
					}
183
				} );
184
				return found;
185
			}
186
			if ( _.isObject( value2 ) ) {
187
				if ( ! _.isUndefined( value2[ value1 ] ) ) {
188
					found = true;
189
				}
190
				_.each( value2, function( subValue ) {
191
					if ( value1 === subValue ) {
192
						found = true;
193
					}
194
				} );
195
				return found;
196
			}
197
			if ( _.isString( value2 ) ) {
198
				if ( _.isString( value1 ) ) {
199
					return ( -1 < value1.indexOf( value2 ) && -1 < value2.indexOf( value1 ) );
200
				}
201
				return -1 < value1.indexOf( value2 );
202
			}
203
		}
204
		return value1 == value2;
205
	}
206
};
207
208
jQuery( document ).ready( function() {
209
	kirkiDependencies.init();
210
} );
211