Completed
Push — development ( dd39f8...8a59f9 )
by
unknown
02:58
created

Helper   C

Complexity

Total Complexity 58

Size/Duplication

Total Lines 535
Duplicated Lines 4.3 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 0%

Importance

Changes 11
Bugs 4 Features 2
Metric Value
c 11
b 4
f 2
dl 23
loc 535
ccs 0
cts 206
cp 0
rs 6.3005
wmc 58
lcom 1
cbo 2

29 Methods

Rating   Name   Duplication   Size   Complexity  
A get_field() 0 9 2
A get_field_clone() 0 13 3
A get_value() 0 10 2
A set_value() 0 12 3
A get_the_post_meta() 0 3 1
A get_post_meta() 0 3 1
A set_post_meta() 0 3 1
A get_theme_option() 0 3 1
A set_theme_option() 0 3 1
A get_term_meta() 0 3 1
A set_term_meta() 0 3 1
A get_user_meta() 0 3 1
A set_user_meta() 0 3 1
A get_comment_meta() 0 3 1
A set_comment_meta() 0 3 1
A get_nav_menu_item_meta() 0 3 1
A set_nav_menu_item_meta() 0 3 1
A ksort_recursive() 0 10 3
A get_relation_type_from_array() 4 16 4
A normalize_label() 12 12 1
A normalize_type() 7 7 1
A type_to_class() 0 13 2
A class_to_type() 0 12 2
A sanitize_classes() 0 7 2
A is_valid_entity_id() 0 3 2
A get_field_name_characters_pattern() 0 3 1
B get_attachment_id() 0 36 6
C get_attachment_metadata() 0 82 9
A input() 0 5 2

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 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. 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 Helper, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Carbon_Fields\Helper;
4
5
use Carbon_Fields\Datastore\Datastore;
6
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
7
use WP_Query;
8
9
/**
10
 * Helper functions and main initialization class.
11
 */
12
class Helper {
13
14
	/**
15
	 * Get a field from a specific container type or id
16
	 *
17
	 * @param  string  $container_type Container type to search in. Optional if $container_id is supplied
18
	 * @param  string  $container_id   Container id to search in. Optional if $container_type is supplied
19
	 * @param  string  $field_name     Field name to search for
20
	 * @return boolean
21
	 */
22
	public static function get_field( $container_type, $container_id, $field_name ) {
23
		\Carbon_Fields\Carbon_Fields::verify_fields_registered();
24
25
		$repository = \Carbon_Fields\Carbon_Fields::resolve( 'container_repository' );
26
		if ( $container_id ) {
27
			return $repository->get_field_in_container( $field_name, $container_id );
28
		}
29
		return $repository->get_field_in_containers( $field_name, $container_type );
30
	}
31
32
	/**
33
	 * Get a clone of a field with a value loaded
34
	 *
35
	 * @param  int    $object_id      Object id to get value for (e.g. post_id, term_id etc.)
36
	 * @param  string $container_type Container type to search in. Optional if $container_id is supplied
37
	 * @param  string $container_id   Container id to search in. Optional if $container_type is supplied
38
	 * @param  string $field_name     Field name to search for
39
	 * @return mixed
40
	 */
41
	public static function get_field_clone( $object_id, $container_type, $container_id, $field_name ) {
42
		$field = static::get_field( $container_type, $container_id, $field_name );
43
44
		if ( ! $field ) {
45
			return null;
46
		}
47
48
		$clone = clone $field;
49
		if ( $object_id !== null ) {
50
			$clone->get_datastore()->set_object_id( $object_id );
51
		}
52
		return $clone;
53
	}
54
55
	/**
56
	 * Get a value formatted for end-users
57
	 *
58
	 * @param  int    $object_id      Object id to get value for (e.g. post_id, term_id etc.)
59
	 * @param  string $container_type Container type to search in
60
	 * @param  string $container_id
61
	 * @param  string $field_name     Field name
62
	 * @return mixed
63
	 */
64
	public static function get_value( $object_id, $container_type, $container_id, $field_name ) {
65
		$field = static::get_field_clone( $object_id, $container_type, $container_id, $field_name );
66
67
		if ( ! $field ) {
68
			return '';
69
		}
70
71
		$field->load();
72
		return $field->get_formatted_value();
73
	}
74
75
	/**
76
	 * Set value for a field
77
	 *
78
	 * @param int    $object_id      Object id to get value for (e.g. post_id, term_id etc.)
79
	 * @param string $container_type Container type to search in
80
	 * @param string $container_id
81
	 * @param string $field_name     Field name
82
	 * @param array $value Field expects a `value_set`; Complex_Field expects a `value_tree` - refer to DEVELOPMENT.md
83
	 */
84
	public static function set_value( $object_id, $container_type, $container_id, $field_name, $value ) {
85
		$field = static::get_field_clone( $object_id, $container_type, $container_id, $field_name );
86
87
		if ( ! $field ) {
88
			$container_message = $container_id ? 'in container with id "' . $container_id . '"' : 'in containers of type "' . $container_type . '"';
89
			Incorrect_Syntax_Exception::raise( 'Could not find a field which satisfies the supplied pattern ' . $container_message . ': ' . $field_name );
90
			return;
91
		}
92
93
		$field->set_value( $value );
94
		$field->save();
95
	}
96
97
	/**
98
	 * Shorthand for get_post_meta().
99
	 * Uses the ID of the current post in the loop.
100
	 *
101
	 * @param  string $name         Custom field name.
102
	 * @param  string $container_id
103
	 * @return mixed  Meta value.
104
	 */
105
	public static function get_the_post_meta( $name, $container_id = '' ) {
106
		return static::get_post_meta( get_the_ID(), $name, $container_id );
107
	}
108
109
	/**
110
	 * Get post meta field for a post.
111
	 *
112
	 * @param  int    $id           Post ID.
113
	 * @param  string $name         Custom field name.
114
	 * @param  string $container_id
115
	 * @return mixed  Meta value.
116
	 */
117
	public static function get_post_meta( $id, $name, $container_id = '' ) {
118
		return static::get_value( $id, 'post_meta', $container_id, $name );
119
	}
120
121
	/**
122
	 * Set post meta field for a post.
123
	 *
124
	 * @param  int    $id           Post ID
125
	 * @param  string $name         Custom field name
126
	 * @param  array  $value
127
	 * @param  string $container_id
128
	 */
129
	public static function set_post_meta( $id, $name, $value, $container_id = '' ) {
130
		return static::set_value( $id, 'post_meta', $container_id, $name, $value );
131
	}
132
133
	/**
134
	 * Get theme option field value.
135
	 *
136
	 * @param  string $name         Custom field name
137
	 * @param  string $container_id
138
	 * @return mixed  Option        value
139
	 */
140
	public static function get_theme_option( $name, $container_id = '' ) {
141
		return static::get_value( null, 'theme_options', $container_id, $name );
142
	}
143
144
	/**
145
	 * Set theme option field value.
146
	 *
147
	 * @param  string $name         Field name
148
	 * @param  array  $value
149
	 * @param  string $container_id
150
	 */
151
	public static function set_theme_option( $name, $value, $container_id = '' ) {
152
		return static::set_value( null, 'theme_options', $container_id, $name, $value );
153
	}
154
155
	/**
156
	 * Get term meta field for a term.
157
	 *
158
	 * @param  int    $id           Term ID.
159
	 * @param  string $name         Custom field name.
160
	 * @param  string $container_id
161
	 * @return mixed  Meta value.
162
	 */
163
	public static function get_term_meta( $id, $name, $container_id = '' ) {
164
		return static::get_value( $id, 'term_meta', $container_id, $name );
165
	}
166
167
	/**
168
	 * Set term meta field for a term.
169
	 *
170
	 * @param  int    $id           Term ID
171
	 * @param  string $name         Field name
172
	 * @param  array  $value
173
	 * @param  string $container_id
174
	 */
175
	public static function set_term_meta( $id, $name, $value, $container_id = '' ) {
176
		return static::set_value( $id, 'term_meta', $container_id, $name, $value );
177
	}
178
179
	/**
180
	 * Get user meta field for a user.
181
	 *
182
	 * @param  int    $id           User ID.
183
	 * @param  string $name         Custom field name.
184
	 * @param  string $container_id
185
	 * @return mixed  Meta value.
186
	 */
187
	public static function get_user_meta( $id, $name, $container_id = '' ) {
188
		return static::get_value( $id, 'user_meta', $container_id, $name );
189
	}
190
191
	/**
192
	 * Set user meta field for a user.
193
	 *
194
	 * @param  int    $id           User ID
195
	 * @param  string $name         Field name
196
	 * @param  array  $value
197
	 * @param  string $container_id
198
	 */
199
	public static function set_user_meta( $id, $name, $value, $container_id = '' ) {
200
		return static::set_value( $id, 'user_meta', $container_id, $name, $value );
201
	}
202
203
	/**
204
	 * Get comment meta field for a comment.
205
	 *
206
	 * @param  int    $id           Comment ID.
207
	 * @param  string $name         Custom field name.
208
	 * @param  string $container_id
209
	 * @return mixed  Meta value.
210
	 */
211
	public static function get_comment_meta( $id, $name, $container_id = '' ) {
212
		return static::get_value( $id, 'comment_meta', $container_id, $name );
213
	}
214
215
	/**
216
	 * Set comment meta field for a comment.
217
	 *
218
	 * @param  int    $id           Comment ID
219
	 * @param  string $name         Field name
220
	 * @param  array  $value
221
	 * @param  string $container_id
222
	 */
223
	public static function set_comment_meta( $id, $name, $value, $container_id = '' ) {
224
		return static::set_value( $id, 'comment_meta', $container_id, $name, $value );
225
	}
226
227
	/**
228
	 * Get nav menu item meta field for a nav menu item.
229
	 *
230
	 * @param  int    $id           Nav menu item ID.
231
	 * @param  string $name         Custom field name.
232
	 * @param  string $container_id
233
	 * @return mixed  Meta value.
234
	 */
235
	public static function get_nav_menu_item_meta( $id, $name, $container_id = '' ) {
236
		return static::get_value( $id, 'nav_menu_item', $container_id, $name );
237
	}
238
239
	/**
240
	 * Set nav menu item meta field for a nav menu item.
241
	 *
242
	 * @param  int    $id           Nav menu item ID
243
	 * @param  string $name         Field name
244
	 * @param  array  $value
245
	 * @param  string $container_id
246
	 */
247
	public static function set_nav_menu_item_meta( $id, $name, $value, $container_id = '' ) {
248
		return static::set_value( $id, 'nav_menu_item', $container_id, $name, $value );
249
	}
250
251
	/**
252
	 * Recursive sorting function by array key.
253
	 *
254
	 * @param  array   &$array     The input array.
255
	 * @param  int     $sort_flags Flags for controlling sorting behavior.
256
	 * @return boolean
257
	 */
258
	public static function ksort_recursive( &$array, $sort_flags = SORT_REGULAR ) {
259
		if ( ! is_array( $array ) ) {
260
			return false;
261
		}
262
		ksort( $array, $sort_flags );
263
		foreach ( $array as $key => $value ) {
264
			self::ksort_recursive( $array[ $key ], $sort_flags );
265
		}
266
		return true;
267
	}
268
269
	/**
270
	 * Get the relation type from an array similar to how meta_query works in WP_Query
271
	 *
272
	 * @param  array         $array
273
	 * @param  array<string> $allowed_relations
274
	 * @param  string        $relation_key
275
	 * @return string
276
	 */
277
	public static function get_relation_type_from_array( $array, $allowed_relations = array( 'AND', 'OR' ), $relation_key = 'relation' ) {
278
		$allowed_relations = array_values( $allowed_relations );
279
		$allowed_relations = array_map( 'strtoupper', $allowed_relations );
280
		$relation = isset( $allowed_relations[0] ) ? $allowed_relations[0] : '';
281
282
		if ( isset( $array[ $relation_key ] ) ) {
283
			$relation = strtoupper( $array[ $relation_key ] );
284
		}
285
286 View Code Duplication
		if ( ! in_array( $relation, $allowed_relations ) ) {
287
			Incorrect_Syntax_Exception::raise( 'Invalid relation type ' . $relation . '. ' .
288
			'The rule should be one of the following: "' . implode( '", "', $allowed_relations ) . '"' );
289
		}
290
291
		return $relation;
292
	}
293
294
	/**
295
	 * Normalize a label by updating case, stripping common prefixes etc.
296
	 *
297
	 * @param  string $label
298
	 * @return string
299
	 */
300 View Code Duplication
	public static function normalize_label( $label ) {
301
		// remove the leading underscore(if it's there)
302
		$label = preg_replace( '~^_~', '', $label );
303
304
		// remove the leading "crb_"(if it's there)
305
		$label = preg_replace( '~^crb_~', '', $label );
306
307
		// split the name into words and make them capitalized
308
		$label = mb_convert_case( str_replace( '_', ' ', $label ), MB_CASE_TITLE );
309
310
		return $label;
311
	}
312
313
	/**
314
	 * Normalize a type string representing an object type
315
	 *
316
	 * @param  string $type
317
	 * @return string
318
	 */
319 View Code Duplication
	public static function normalize_type( $type ) {
320
		$normalized_type = str_replace( ' ', '_', $type );
321
		$normalized_type = preg_replace( '/[_\s]+/', '_', $normalized_type );
322
		$normalized_type = preg_replace( '/^_|_$/', '', $normalized_type );
323
		$normalized_type = strtolower( $normalized_type );
324
		return $normalized_type;
325
	}
326
327
	/**
328
	 * Convert a string representing an object type to a fully qualified class name
329
	 *
330
	 * @param  string $type
331
	 * @param  string $namespace
332
	 * @param  string $class_suffix
333
	 * @return string
334
	 */
335
	public static function type_to_class( $type, $namespace = '', $class_suffix = '' ) {
336
		$classlike_type = static::normalize_type( $type );
337
		$classlike_type = str_replace( '_', ' ', $classlike_type );
338
		$classlike_type = ucwords( $classlike_type );
339
		$classlike_type = str_replace( ' ', '_', $classlike_type );
340
341
		$class = $classlike_type . $class_suffix;
342
		if ( $namespace ) {
343
			$class = $namespace . '\\' . $class;
344
		}
345
346
		return $class;
347
	}
348
349
	/**
350
	 * Convert a string representing an object type to a fully qualified class name
351
	 *
352
	 * @param  string $class
353
	 * @param  string $class_suffix
354
	 * @return string
355
	 */
356
	public static function class_to_type( $class, $class_suffix = '' ) {
357
		$reflection = new \ReflectionClass( $class );
358
		$type = $reflection->getShortName();
359
360
		if ( $class_suffix ) {
361
			$type = preg_replace( '/(' . preg_quote( $class_suffix, '/' ) . ')$/i', '', $type );
362
		}
363
364
		$type = static::normalize_type( $type );
365
366
		return $type;
367
	}
368
369
	/**
370
	 * Get an array of sanitized html classes
371
	 *
372
	 * @param  string|array<string> $classes
373
	 * @return array<string>
374
	 */
375
	public static function sanitize_classes( $classes ) {
376
		if ( ! is_array( $classes ) ) {
377
			$classes = array_values( array_filter( explode( ' ', $classes ) ) );
378
		}
379
		$classes = array_map( 'sanitize_html_class', $classes );
380
		return $classes;
381
	}
382
383
	/**
384
	 * Check if an id or name for containers and fields is valid
385
	 *
386
	 * @param  string  $id
387
	 * @return boolean
388
	 */
389
	public static function is_valid_entity_id( $id ) {
390
		return ! empty( $id ) && preg_match( '/\A[a-z0-9_\-]+\z/', $id );
391
	}
392
393
	/**
394
	 * Return a partial regex pettern matching allowed field name characters
395
	 *
396
	 * @return string
397
	 */
398
	public static function get_field_name_characters_pattern() {
399
		return 'a-z0-9_\-';
400
	}
401
402
	/**
403
	 * Get an attachment ID given a file URL
404
	 * Modified version of https://wpscholar.com/blog/get-attachment-id-from-wp-image-url/
405
	 *
406
	 * @param  string  $url
407
	 * @return integet
408
	 */
409
	public static function get_attachment_id( $url ) {
410
		$dir = wp_upload_dir();
411
		$filename = basename( $url );
412
413
		if ( strpos( $url, $dir['baseurl'] . '/' ) === false ) {
414
			return 0;
415
		}
416
417
		$query_args = array(
418
			'post_type'   => 'attachment',
419
			'post_status' => 'inherit',
420
			'fields'      => 'ids',
421
			'meta_query'  => array(
422
				array(
423
					'value'   => $filename,
424
					'compare' => 'LIKE',
425
					'key'     => '_wp_attachment_metadata',
426
				),
427
			)
428
		);
429
		$query = new WP_Query( $query_args );
430
431
		if ( $query->have_posts() ) {
432
			foreach ( $query->posts as $post_id ) {
433
				$meta = wp_get_attachment_metadata( $post_id );
434
				$original_file = basename( $meta['file'] );
435
				$cropped_image_files = wp_list_pluck( $meta['sizes'], 'file' );
436
437
				if ( $original_file === $filename || in_array( $filename, $cropped_image_files ) ) {
438
					return intval( $post_id );
439
				}
440
			}
441
		}
442
443
		return 0;
444
	}
445
446
	/**
447
	 * Returns attachment metadata from an ID.
448
	 *
449
	 * @param  string  $id
450
	 * @param  string  $type Value Type. Can be either id or url
451
	 * @return boolean
452
	 */
453
	public static function get_attachment_metadata( $id, $type ) {
454
		$attachment_meta = array(
455
			'thumb_url'         => '',
456
			'default_thumb_url' => '',
457
			'file_ext'          => '',
458
			'file_type'         => '',
459
			'file_name'         => '',
460
			'file_url'          => '',
461
			'edit_nonce'        => '',
462
			'title'             => '',
463
			'caption'           => '',
464
			'description'       => '',
465
			'alt'               => '',
466
			'date'              => '',
467
			'filesize'          => '',
468
			'width'             => '',
469
			'height'            => '',
470
		);
471
472
		// when value_type is set to "url" the $id will hold the url, not the id
473
		if ( $type === 'url' ) {
474
			$attachment_id = static::get_attachment_id( $id );
475
476
			if ( $attachment_id === 0 ) {
477
				$attachment_meta['thumb_url'] = $id;
478
				$attachment_meta['default_thumb_url'] = $id;
479
				$attachment_meta['file_url'] = $id;
480
				return $attachment_meta;
481
			}
482
483
			$id = $attachment_id;
484
		}
485
486
		$attachment = get_post( $id );
487
488
		if ( ! $attachment ) {
489
			return $attachment_meta;
490
		}
491
492
		$meta                           = wp_get_attachment_metadata( $attachment->ID );
493
		list( $src, $width, $height )   = wp_get_attachment_image_src( $attachment->ID, 'full' );
0 ignored issues
show
Unused Code introduced by
The assignment to $src is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
494
495
		$attachment_meta['edit_nonce']  = wp_create_nonce( 'update-post_' . $id );
496
		$attachment_meta['title']       = get_the_title( $id );
497
		$attachment_meta['caption']     = get_post_field( 'post_excerpt', $id );
498
		$attachment_meta['description'] = get_post_field( 'post_content', $id );
499
		$attachment_meta['alt']         = get_post_meta( $id, '_wp_attachment_image_alt', true );
500
		$attachment_meta['date']        = mysql2date( __( 'F j, Y' ), $attachment->post_date );
501
		$attachment_meta['width']       = $width;
502
		$attachment_meta['height']      = $height;
503
		$attachment_meta['file_url']    = is_numeric( $id ) ? wp_get_attachment_url( $id ) : $id;
504
		$attachment_meta['file_name']   = basename( $attachment_meta['file_url'] );
505
		$attachment_meta['filetype']    = wp_check_filetype( $attachment_meta['file_url'] );
506
		$attachment_meta['file_ext']    = $attachment_meta['filetype']['ext']; // png, mp3, etc..
507
		$attachment_meta['file_type']   = preg_replace( '~\/.+$~', '', $attachment_meta['filetype']['type'] ); // image, video, etc..
508
509
		if ( $attachment_meta['file_type'] === 'audio' ) {
510
			$attachment_meta['artist'] = $meta['artist'];
511
			$attachment_meta['album'] = $meta['album'];
512
			$attachment_meta['length'] = $meta['length_formatted'];
513
		}
514
515
		$attachment_meta['default_thumb_url'] = wp_mime_type_icon( $id );
516
517
		if ( $attachment_meta['file_type'] == 'image' ) {
518
			$attachment_meta['thumb_url'] = $attachment_meta['file_url'];
519
520
			if ( $type == 'id' ) {
521
				$thumb_src = wp_get_attachment_image_src( $id, 'thumbnail' );
522
				$attachment_meta['thumb_url'] = $thumb_src[0];
523
			}
524
		} else {
525
			$attachment_meta['thumb_url'] = $attachment_meta['default_thumb_url'];
526
		}
527
528
		$attached_file = get_attached_file( $attachment->ID );
529
		if ( file_exists( $attached_file ) ) {
530
			$attachment_meta['filesize'] = size_format( filesize( $attached_file ) );
531
		}
532
533
		return $attachment_meta;
534
	}
535
536
	/**
537
	 * Get the current $_POST or $_GET input values, merging in compacted values
538
	 *
539
	 * @return array
540
	 */
541
	public static function input() {
542
		$input = $_SERVER['REQUEST_METHOD'] === 'POST' ? $_POST : $_GET;
5 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_SERVER
Loading history...
introduced by
Detected access of super global var $_POST, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
introduced by
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
543
		$input = stripslashes_deep( $input );
544
		return $input;
545
	}
546
}
547