Completed
Push — milestone/2.0 ( 9939d7...e0608a )
by
unknown
03:03
created

Value_Set::is_flat_array()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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