Value_Set   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 254
Duplicated Lines 4.33 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 58.24%

Importance

Changes 0
Metric Value
dl 11
loc 254
ccs 53
cts 91
cp 0.5824
rs 9.92
c 0
b 0
f 0
wmc 31
lcom 1
cbo 1

11 Methods

Rating   Name   Duplication   Size   Complexity  
A get_type() 0 3 1
A keepalive() 0 3 1
A is_empty() 0 3 1
A get_set() 0 3 1
A clear() 0 3 1
A __construct() 0 8 2
A get_formatted_value_set() 0 11 4
B get() 11 33 8
A is_flat_array() 0 10 3
A flat_array_to_raw_value_set() 0 25 5
A set() 0 16 4

How to fix   Duplicated Code   

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:

1
<?php
2
3
namespace Carbon_Fields\Value_Set;
4
5
use Carbon_Fields\Exception\Incorrect_Syntax_Exception;
6
7
/**
8
 * Class representing a field's value/value_set
9
 *
10
 * @see  Internal Glossary in DEVELOPMENT.MD
11
 */
12
class Value_Set {
13
14
	/**
15
	 * Value type which saves a single value
16
	 */
17
	const TYPE_SINGLE_VALUE = 1;
18
19
	/**
20
	 * Value type which saves multiple values with a single property
21
	 */
22
	const TYPE_MULTIPLE_VALUES = 2;
23
24
	/**
25
	 * Value type which saves a single value with multiple proerties
26
	 */
27
	const TYPE_MULTIPLE_PROPERTIES = 3;
28
29
	/**
30
	 * Value type which saves multiple values with multiple propertys
31
	 */
32
	const TYPE_VALUE_SET = 4;
33
34
	/**
35
	 * Default value property required for every value set
36
	 */
37
	const VALUE_PROPERTY = 'value';
38
39
	/**
40
	 * Value set type
41
	 *
42
	 * @var integer static::TYPE_* constant
43
	 */
44
	protected $type = self::TYPE_SINGLE_VALUE;
45
46
	/**
47
	 * Array of valid value set types
48
	 *
49
	 * @var array
50
	 */
51
	protected $valid_types = array( self::TYPE_SINGLE_VALUE, self::TYPE_MULTIPLE_VALUES, self::TYPE_MULTIPLE_PROPERTIES, self::TYPE_VALUE_SET );
52
53
	/**
54
	 * Array of empty values for every type
55
	 *
56
	 * @var array
57
	 */
58
	protected $empty_values = array(
59
		self::TYPE_SINGLE_VALUE => '',
60
		self::TYPE_MULTIPLE_VALUES => array(),
61
		self::TYPE_MULTIPLE_PROPERTIES => array(),
62
		self::TYPE_VALUE_SET => array(),
63
	);
64
65
	/**
66
	 * Registered value set properties (properties) with their default value (when the property is missing in the passed raw_value_set)
67
	 *
68
	 * @var array
69
	 */
70
	protected $properties = array( self::VALUE_PROPERTY => '' );
71
72
	/**
73
	 * Data the value set represents
74
	 *
75
	 * @var null|array
76
	 */
77
	protected $value_set = null;
78
79
	/**
80
	 * Value set constructor
81
	 *
82
	 * @param integer $type static::TYPE_* constant
83
	 * @param array $additional_properties
84
	 */
85 2
	public function __construct( $type = self::TYPE_SINGLE_VALUE, $additional_properties = array() ) {
86 2
		if ( ! in_array( $type, $this->valid_types ) ) {
87 1
			Incorrect_Syntax_Exception::raise( "Invalid type specified for Value_Set: $type" );
88
		}
89
90 1
		$this->type = $type;
91 1
		$this->properties = array_merge( $this->properties, $additional_properties );
92 1
	}
93
94
	/**
95
	 * Format a raw value set into one which guarantees that only (and all) registered properties are present
96
	 *
97
	 * @param array $raw_value_set
98
	 * @return array
99
	 */
100
	protected function get_formatted_value_set( $raw_value_set ) {
101
		$formatted_value_set = array();
102
		foreach ( $raw_value_set as $raw_value ) {
103
			$formatted_value = array();
104
			foreach ( $this->properties as $property => $default_value ) {
105
				$formatted_value[ $property ] = isset( $raw_value[ $property ] ) ? $raw_value[ $property ] : $default_value;
106
			}
107
			$formatted_value_set[] = $formatted_value;
108
		}
109
		return $formatted_value_set;
110
	}
111
112
	/**
113
	 * Return value set type
114
	 *
115
	 * @return int static::TYPE_* constant
116
	 */
117 1
	public function get_type() {
118 1
		return $this->type;
119
	}
120
121
	/**
122
	 * Return whether this value type requires a keepalive key
123
	 *
124
	 * @return boolean
125
	 */
126 2
	public function keepalive() {
127 2
		return ( $this->type !== static::TYPE_SINGLE_VALUE );
128
	}
129
130
	/**
131
	 * Return whether the data is empty
132
	 *
133
	 * @return boolean
134
	 */
135 5
	public function is_empty() {
136 5
		return empty( $this->value_set );
137
	}
138
139
	/**
140
	 * Return data formatted according to the value set $type
141
	 *
142
	 * @return null|string|array String, array of key-value pairs or array of arrays of key-value pairs
143
	 */
144 6
	public function get() {
145 6
		if ( $this->value_set === null ) {
146 2
			return null;
147
		}
148 4
		$value = '';
149 4
		$value_property = static::VALUE_PROPERTY;
150
151 4
		switch ( $this->type ) {
152 4
			case static::TYPE_MULTIPLE_VALUES:
153
				$value = array_map( function( $set ) use ( $value_property ) {
154 1
					return $set[ $value_property ];
155 1
				}, $this->value_set );
156 1
				break;
157 3 View Code Duplication
			case static::TYPE_MULTIPLE_PROPERTIES:
158 1
				$value = array();
159 1
				if ( ! empty( $this->value_set ) ) {
160 1
					$value = $this->value_set[0];
161 1
				}
162 1
				break;
163 2
			case static::TYPE_VALUE_SET:
164 1
				$value = $this->value_set;
165 1
				break;
166
167 1
			case static::TYPE_SINGLE_VALUE:
168 1 View Code Duplication
			default:
169 1
				if ( ! empty( $this->value_set ) ) {
170 1
					$value = $this->value_set[0][ static::VALUE_PROPERTY ];
171 1
				}
172 1
				break;
173 4
		}
174
175 4
		return $value;
176
	}
177
178
	/**
179
	 * Return the full value set data regardless of type
180
	 *
181
	 * @return array<array>
182
	 */
183 1
	public function get_set() {
184 1
		return $this->value_set;
185
	}
186
187
	/**
188
	 * Check if an array is flat
189
	 *
190
	 * @param array $array
191
	 * @return boolean
192
	 */
193
	protected function is_flat_array( $array ) {
194
		$flat = true;
195
		foreach ( $array as $value ) {
196
			if ( is_array( $value ) ) {
197
				$flat = false;
198
				break;
199
			}
200
		}
201
		return $flat;
202
	}
203
204
	/**
205
	 * Convert a flat array to a raw value set
206
	 *
207
	 * @param array $value_array
208
	 * @return array<array>
209
	 */
210
	protected function flat_array_to_raw_value_set( $value_array ) {
211
		$raw_value_set = array();
212
213
		$string_keys = array_filter( array_keys( $value_array ), function( $key ) {
214
			return is_string( $key );
215
		} );
216
217
		if ( empty( $string_keys ) ) {
218
			// the passed array does not contain string keys so we check each item if it's a value or a key=>value array
219
			foreach ( $value_array as $key => $value ) {
220
				if ( ! is_array( $value ) || ! isset( $value[ static::VALUE_PROPERTY ] ) ) {
221
					// the passed array is an array of values so we expand it to a key=>value array
222
					$value = array(
223
						static::VALUE_PROPERTY => $value,
224
					);
225
				}
226
				$raw_value_set[] = $value;
227
			}
228
		} else {
229
			// the passed array contains string keys so we append it to the set
230
			$raw_value_set[] = $value_array;
231
		}
232
233
		return $raw_value_set;
234
	}
235
236
	/**
237
	 * Set the value set data
238
	 * Accepts: single value, array of values, array of key-values, array of arrays of key-values
239
	 *
240
	 * @param null|string|array $raw_value_set String, indexed array, array of key-value pairs or array of arrays of key-value pairs
241
	 */
242 17
	public function set( $raw_value_set ) {
243 17
		if ( $raw_value_set === null ) {
244 2
			$this->value_set = null;
245 2
			return;
246
		}
247
248 15
		if ( ! is_array( $raw_value_set ) ) {
249 2
			$raw_value_set = array( $raw_value_set );
250 2
		}
251
252 15
		if ( $this->is_flat_array( $raw_value_set ) ) {
253 6
			$raw_value_set = $this->flat_array_to_raw_value_set( $raw_value_set );
254 6
		}
255
256 15
		$this->value_set = $this->get_formatted_value_set( $raw_value_set );
257 15
	}
258
259
	/**
260
	 * Clear the value with an appropriate "empty" one
261
	 */
262
	public function clear() {
263
		$this->set( $this->empty_values[ $this->get_type() ] );
264
	}
265
}