Completed
Push — milestone/2_0/react-ui ( c9a76c...950db8 )
by
unknown
02:58
created

Value_Set::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0116

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 2
dl 0
loc 8
ccs 6
cts 7
cp 0.8571
crap 2.0116
rs 9.4285
c 0
b 0
f 0
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
	 * Registered value set properties (properties) with their default value (when the property is missing in the passed raw_value_set)
55
	 *
56
	 * @var array
57
	 */
58
	protected $properties = array( self::VALUE_PROPERTY => '' );
59
60
	/**
61
	 * Data the value set represents
62
	 *
63
	 * @var null|array
64
	 */
65
	protected $value_set = null;
66
67
	/**
68
	 * Value set constructor
69
	 *
70
	 * @param integer $type static::TYPE_* constant
71
	 * @param array $additional_properties
72
	 */
73 2
	public function __construct( $type = self::TYPE_SINGLE_VALUE, $additional_properties = array() ) {
74 2
		if ( ! in_array( $type, $this->valid_types ) ) {
75 1
			Incorrect_Syntax_Exception::raise( "Invalid type specified for Value_Set: $type" );
76
		}
77
78 1
		$this->type = $type;
79 1
		$this->properties = array_merge( $this->properties, $additional_properties );
80 1
	}
81
82
	/**
83
	 * Format a raw value set into one which guarantees that only (and all) registered properties are present
84
	 *
85
	 * @param array $raw_value_set
86
	 * @return array
87
	 */
88
	protected function get_formatted_value_set( $raw_value_set ) {
89
		$formatted_value_set = array();
90
		foreach ( $raw_value_set as $raw_value ) {
91
			$formatted_value = array();
92
			foreach ( $this->properties as $property => $default_value ) {
93
				$formatted_value[ $property ] = isset( $raw_value[ $property ] ) ? $raw_value[ $property ] : $default_value;
94
			}
95
			$formatted_value_set[] = $formatted_value;
96
		}
97
		return $formatted_value_set;
98
	}
99
100
	/**
101
	 * Return value set type
102
	 *
103
	 * @return int static::TYPE_* constant
104
	 */
105 1
	public function get_type() {
106 1
		return $this->type;
107
	}
108
109
	/**
110
	 * Return whether this value type requires a keepalive key
111
	 *
112
	 * @return boolean
113
	 */
114 2
	public function keepalive() {
115 2
		return ( $this->type !== static::TYPE_SINGLE_VALUE );
116
	}
117
118
	/**
119
	 * Return whether the data is empty
120
	 *
121
	 * @return boolean
122
	 */
123 5
	public function is_empty() {
124 5
		return empty( $this->value_set );
125
	}
126
127
	/**
128
	 * Return data formatted according to the value set $type
129
	 *
130
	 * @return null|string|array String, array of key-value pairs or array of arrays of key-value pairs
131
	 */
132 6
	public function get() {
133 6
		if ( $this->value_set === null ) {
134 2
			return null;
135
		}
136 4
		$value = '';
137 4
		$value_property = static::VALUE_PROPERTY;
138
139 4
		switch ( $this->type ) {
140 4
			case static::TYPE_MULTIPLE_VALUES:
141
				$value = array_map( function( $set ) use ( $value_property ) {
142 1
					return $set[ $value_property ];
143 1
				}, $this->value_set );
144 1
				break;
145 3 View Code Duplication
			case static::TYPE_MULTIPLE_PROPERTIES:
146 1
				$value = array();
147 1
				if ( ! empty( $this->value_set ) ) {
148 1
					$value = $this->value_set[0];
149 1
				}
150 1
				break;
151 2
			case static::TYPE_VALUE_SET:
152 1
				$value = $this->value_set;
153 1
				break;
154
155 1
			case static::TYPE_SINGLE_VALUE:
156 1 View Code Duplication
			default:
157 1
				if ( ! empty( $this->value_set ) ) {
158 1
					$value = $this->value_set[0][ static::VALUE_PROPERTY ];
159 1
				}
160 1
				break;
161 4
		}
162
163 4
		return $value;
164
	}
165
166
	/**
167
	 * Return the full value set data regardless of type
168
	 * 
169
	 * @return array<array>
170
	 */
171 1
	public function get_set() {
172 1
		return $this->value_set;
173
	}
174
175
	/**
176
	 * Check if an array is flat
177
	 *
178
	 * @param array $array
179
	 * @return boolean
180
	 */
181
	protected function is_flat_array( $array ) {
182
		$flat = true;
183
		foreach ( $array as $value ) {
184
			if ( is_array( $value ) ) {
185
				$flat = false;
186
				break;
187
			}
188
		}
189
		return $flat;
190
	}
191
192
	/**
193
	 * Convert a flat array to a raw value set
194
	 *
195
	 * @param array $value_array
196
	 * @return array<array>
197
	 */
198
	protected function flat_array_to_raw_value_set( $value_array ) {
199
		$raw_value_set = array();
200
201
		$string_keys = array_filter( array_keys( $value_array ), function( $key ) {
202
			return is_string( $key );
203
		} );
204
205
		if ( empty( $string_keys ) ) {
206
			// the passed array does not contain string keys so we check each item if it's a value or a key=>value array
207
			foreach ( $value_array as $key => $value ) {
208
				if ( ! is_array( $value ) || ! isset( $value[ static::VALUE_PROPERTY ] ) ) {
209
					// the passed array is an array of values so we expand it to a key=>value array
210
					$value = array(
211
						static::VALUE_PROPERTY => $value,
212
					);
213
				}
214
				$raw_value_set[] = $value;
215
			}
216
		} else {
217
			// the passed array contains string keys so we append it to the set
218
			$raw_value_set[] = $value_array;
219
		}
220
221
		return $raw_value_set;
222
	}
223
224
	/**
225
	 * Set the value set data
226
	 * Accepts: single value, array of values, array of key-values, array of arrays of key-values
227
	 *
228
	 * @param null|string|array $raw_value_set String, indexed array, array of key-value pairs or array of arrays of key-value pairs
229
	 */
230 17
	public function set( $raw_value_set ) {
231 17
		if ( $raw_value_set === null ) {
232 2
			$this->value_set = null;
233 2
			return;
234
		}
235
236 15
		if ( ! is_array( $raw_value_set ) ) {
237 2
			$raw_value_set = array( $raw_value_set );
238 2
		}
239
240 15
		if ( $this->is_flat_array( $raw_value_set ) ) {
241 6
			$raw_value_set = $this->flat_array_to_raw_value_set( $raw_value_set );
242 6
		}
243
244 15
		$this->value_set = $this->get_formatted_value_set( $raw_value_set );
245
	}
246
}