Passed
Push — master ( 4b094a...bf7929 )
by Brian
05:29 queued 53s
created

AUI_Component_Helper   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 369
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 115
dl 0
loc 369
rs 8.48
c 1
b 0
f 1
wmc 49

15 Methods

Rating   Name   Duplication   Size   Complexity  
A name() 0 9 4
A data_attributes() 0 13 4
A icon() 0 19 5
A element_require() 0 15 2
A help_text() 0 9 2
A id() 0 8 2
A esc_classes() 0 13 3
A title() 0 8 2
A aria_attributes() 0 13 4
A extra_attributes() 0 16 4
A class_attr() 0 11 3
A value() 0 8 2
A _sanitize_html_field() 0 16 3
A sanitize_html_field() 0 27 5
A kses_allowed_html() 0 35 4

How to fix   Complexity   

Complex Class

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

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

1
<?php
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * A class for helping render common component items.
9
 *
10
 * @since 1.0.0
11
 */
12
class AUI_Component_Helper {
13
14
	/**
15
	 * A component helper for generating a input name.
16
	 *
17
	 * @param $text
18
	 * @param $multiple bool If the name is set to be multiple but no brackets found then we add some.
19
	 *
20
	 * @return string
21
	 */
22
	public static function name($text,$multiple = false){
23
		$output = '';
24
25
		if($text){
26
			$is_multiple = strpos($text, '[') === false && $multiple  ? '[]' : '';
27
			$output = ' name="'.esc_attr($text).$is_multiple.'" ';
28
		}
29
30
		return $output;
31
	}
32
33
	/**
34
	 * A component helper for generating a item id.
35
	 *
36
	 * @param $text string The text to be used as the value.
37
	 *
38
	 * @return string The sanitized item.
39
	 */
40
	public static function id($text){
41
		$output = '';
42
43
		if($text){
44
			$output = ' id="'.sanitize_html_class($text).'" ';
45
		}
46
47
		return $output;
48
	}
49
50
	/**
51
	 * A component helper for generating a item title.
52
	 *
53
	 * @param $text string The text to be used as the value.
54
	 *
55
	 * @return string The sanitized item.
56
	 */
57
	public static function title($text){
58
		$output = '';
59
60
		if($text){
61
			$output = ' title="'.esc_attr($text).'" ';
62
		}
63
64
		return $output;
65
	}
66
67
	/**
68
	 * A component helper for generating a item value.
69
	 *
70
	 * @param $text string The text to be used as the value.
71
	 *
72
	 * @return string The sanitized item.
73
	 */
74
	public static function value($text){
75
		$output = '';
76
77
		if($text){
78
			$output = ' value="'.sanitize_text_field($text).'" ';
79
		}
80
81
		return $output;
82
	}
83
84
	/**
85
	 * A component helper for generating a item class attribute.
86
	 *
87
	 * @param $text string The text to be used as the value.
88
	 *
89
	 * @return string The sanitized item.
90
	 */
91
	public static function class_attr($text){
92
		$output = '';
93
94
		if($text){
95
			$classes = self::esc_classes($text);
96
			if(!empty($classes)){
97
				$output = ' class="'.$classes.'" ';
98
			}
99
		}
100
101
		return $output;
102
	}
103
104
	/**
105
	 * Escape a string of classes.
106
	 *
107
	 * @param $text
108
	 *
109
	 * @return string
110
	 */
111
	public static function esc_classes($text){
112
		$output = '';
113
114
		if($text){
115
			$classes = explode(" ",$text);
116
			$classes = array_map("trim",$classes);
117
			$classes = array_map("sanitize_html_class",$classes);
118
			if(!empty($classes)){
119
				$output = implode(" ",$classes);
120
			}
121
		}
122
123
		return $output;
124
125
	}
126
127
	/**
128
	 * @param $args
129
	 *
130
	 * @return string
131
	 */
132
	public static function data_attributes($args){
133
		$output = '';
134
135
		if(!empty($args)){
136
137
			foreach($args as $key => $val){
138
				if(substr( $key, 0, 5 ) === "data-"){
139
					$output .= ' '.sanitize_html_class($key).'="'.esc_attr($val).'" ';
140
				}
141
			}
142
		}
143
144
		return $output;
145
	}
146
147
	/**
148
	 * @param $args
149
	 *
150
	 * @return string
151
	 */
152
	public static function aria_attributes($args){
153
		$output = '';
154
155
		if(!empty($args)){
156
157
			foreach($args as $key => $val){
158
				if(substr( $key, 0, 5 ) === "aria-"){
159
					$output .= ' '.sanitize_html_class($key).'="'.esc_attr($val).'" ';
160
				}
161
			}
162
		}
163
164
		return $output;
165
	}
166
167
	/**
168
	 * Build a font awesome icon from a class.
169
	 *
170
	 * @param $class
171
	 * @param bool $space_after
172
	 * @param array $extra_attributes An array of extra attributes.
173
	 *
174
	 * @return string
175
	 */
176
	public static function icon($class,$space_after = false, $extra_attributes = array()){
177
		$output = '';
178
179
		if($class){
180
			$classes = self::esc_classes($class);
181
			if(!empty($classes)){
182
				$output = '<i class="'.$classes.'" ';
183
				// extra attributes
184
				if(!empty($extra_attributes)){
185
					$output .= AUI_Component_Helper::extra_attributes($extra_attributes);
186
				}
187
				$output .= '></i>';
188
				if($space_after){
189
					$output .= " ";
190
				}
191
			}
192
		}
193
194
		return $output;
195
	}
196
197
	/**
198
	 * @param $args
199
	 *
200
	 * @return string
201
	 */
202
	public static function extra_attributes($args){
203
		$output = '';
204
205
		if(!empty($args)){
206
207
			if( is_array($args) ){
208
				foreach($args as $key => $val){
209
					$output .= ' '.sanitize_html_class($key).'="'.esc_attr($val).'" ';
210
				}
211
			}else{
212
				$output .= ' '.$args.' ';
213
			}
214
215
		}
216
217
		return $output;
218
	}
219
220
	/**
221
	 * @param $args
222
	 *
223
	 * @return string
224
	 */
225
	public static function help_text($text){
226
		$output = '';
227
228
		if($text){
229
			$output .= '<small class="form-text text-muted">'.wp_kses_post($text).'</small>';
230
		}
231
232
233
		return $output;
234
	}
235
236
	/**
237
	 * Replace element require context with JS.
238
	 *
239
	 * @param $input
240
	 *
241
	 * @return string|void
242
	 */
243
	public static function element_require( $input ) {
244
245
		$input = str_replace( "'", '"', $input );// we only want double quotes
246
247
		$output = esc_attr( str_replace( array( "[%", "%]", "%:checked]" ), array(
248
			"jQuery(form).find('[data-argument=\"",
249
			"\"]').find('input,select,textarea').val()",
250
			"\"]').find('input:checked').val()",
251
		), $input ) );
252
253
		if($output){
254
			$output = ' data-element-require="'.$output.'" ';
255
		}
256
257
		return $output;
258
	}
259
260
	/**
261
	 * Returns an array of allowed HTML tags and attributes for a given context.
262
	 *
263
	 * @since 0.1.41
264
	 *
265
	 * @param string|array $context The context for which to retrieve tags. Allowed values are 'post',
266
	 *                              'strip', 'data', 'entities', or the name of a field filter such as
267
	 *                              'pre_user_description'.
268
	 * @param array $input Input.
269
	 * @return array Array of allowed HTML tags and their allowed attributes.
270
	 */
271
	public static function kses_allowed_html( $context = 'post', $input = array() ) {
272
		$allowed_html = wp_kses_allowed_html( $context );
273
274
		if ( is_array( $allowed_html ) ) {
0 ignored issues
show
introduced by
The condition is_array($allowed_html) is always true.
Loading history...
275
			// <iframe>
276
			if ( ! isset( $allowed_html['iframe'] ) && $context == 'post' ) {
277
				$allowed_html['iframe']     = array(
278
					'class'        => true,
279
					'id'           => true,
280
					'src'          => true,
281
					'width'        => true,
282
					'height'       => true,
283
					'frameborder'  => true,
284
					'marginwidth'  => true,
285
					'marginheight' => true,
286
					'scrolling'    => true,
287
					'style'        => true,
288
					'title'        => true,
289
					'allow'        => true,
290
					'allowfullscreen' => true,
291
					'data-*'       => true,
292
				);
293
			}
294
		}
295
296
		/**
297
		 * Filters the allowed html tags.
298
		 *
299
		 * @since 0.1.41
300
		 *
301
		 * @param array[]|string $allowed_html Allowed html tags.
302
		 * @param @param string|array $context The context for which to retrieve tags.
303
		 * @param array $input Input field.
304
		 */
305
		return apply_filters( 'ayecode_ui_kses_allowed_html', $allowed_html, $context, $input );
306
	}
307
308
	/**
309
	 * Filters content and keeps only allowable HTML elements.
310
	 *
311
	 * This function makes sure that only the allowed HTML element names, attribute
312
	 * names and attribute values plus only sane HTML entities will occur in
313
	 * $string. You have to remove any slashes from PHP's magic quotes before you
314
	 * call this function.
315
	 *
316
	 * The default allowed protocols are 'http', 'https', 'ftp', 'mailto', 'news',
317
	 * 'irc', 'gopher', 'nntp', 'feed', 'telnet, 'mms', 'rtsp' and 'svn'. This
318
	 * covers all common link protocols, except for 'javascript' which should not
319
	 * be allowed for untrusted users.
320
	 *
321
	 * @since 0.1.41
322
	 *
323
	 * @param string|array $value Content to filter through kses.
324
	 * @param array  $input       Input Field.
325
	 * @return string Filtered content with only allowed HTML elements.
326
	 */
327
	public static function _sanitize_html_field( $value, $input = array() ) {
328
		if ( $value === '' ) {
329
			return $value;
330
		}
331
332
		$allowed_html = self::kses_allowed_html( 'post', $input );
333
334
		if ( ! is_array( $allowed_html ) ) {
0 ignored issues
show
introduced by
The condition is_array($allowed_html) is always true.
Loading history...
335
			$allowed_html = wp_kses_allowed_html( 'post' );
336
		}
337
338
		$filtered = trim( wp_unslash( $value ) );
0 ignored issues
show
Bug introduced by
It seems like wp_unslash($value) can also be of type string[]; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

338
		$filtered = trim( /** @scrutinizer ignore-type */ wp_unslash( $value ) );
Loading history...
339
		$filtered = wp_kses( $filtered, $allowed_html );
340
		$filtered = balanceTags( $filtered ); // Balances tags
341
342
		return $filtered;
343
	}
344
345
	/**
346
	 * Navigates through an array, object, or scalar, and removes slashes from the values.
347
	 *
348
	 * @since 0.1.41
349
	 *
350
	 * @param mixed $value The value to be stripped.
351
	 * @param array  $input Input Field.
352
	 * @return mixed Stripped value.
353
	 */
354
	public static function sanitize_html_field( $value, $input = array() ) {
355
		$original = $value;
356
357
		if ( is_array( $value ) ) {
358
			foreach ( $value as $index => $item ) {
359
				$value[ $index ] = self::_sanitize_html_field( $value, $input );
360
			}
361
		} elseif ( is_object( $value ) ) {
362
			$object_vars = get_object_vars( $value );
363
364
			foreach ( $object_vars as $property_name => $property_value ) {
365
				$value->$property_name = self::_sanitize_html_field( $property_value, $input );
366
			}
367
		} else {
368
			$value = self::_sanitize_html_field( $value, $input );
369
		}
370
371
		/**
372
		 * Filters content and keeps only allowable HTML elements.
373
		 *
374
		 * @since 0.1.41
375
		 *
376
		 * @param string|array $value Content to filter through kses.
377
		 * @param string|array $value Original content without filter.
378
		 * @param array  $input       Input Field.
379
		 */
380
		return apply_filters( 'ayecode_ui_sanitize_html_field', $value, $original, $input );
381
	}
382
}