Completed
Push — develop ( 556e46...dfa7d2 )
by Paul
02:07
created

Field::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
namespace GeminiLabs\Castor\Forms;
4
5
class Field
6
{
7
	/**
8
	 * @var array
9
	 */
10
	protected $args;
11
12
	/**
13
	 * @var array
14
	 */
15
	protected $dependencies;
16
17
	public function __construct()
18
	{
19
		$this->args         = [];
20
		$this->dependencies = [];
21
	}
22
23
	/**
24
	 * @param string $property
25
	 *
26
	 * @return mixed
27
	 * @throws Exception
28
	 */
29
	public function __get( $property )
30
	{
31
		switch( $property ) {
32
			case 'args':
33
			case 'dependencies':
34
				return $this->$property;
35
		}
36
		throw new Exception( sprintf( 'Invalid %s property: %s', __CLASS__, $property ));
37
	}
38
39
40
	/**
41
	 * Get a specific Field
42
	 *
43
	 * @return mixed GeminiLabs\SiteReviews\Html\Fields\*
44
	 */
45
	public function getField( array $args = [] )
46
	{
47
		if( empty( $args )) {
48
			$args = $this->args;
49
		}
50
51
		$className = sprintf( 'GeminiLabs\Castor\Forms\Fields\%s', ucfirst( $args['type'] ));
52
53
		if( !class_exists( $className )) {
54
			throw new ReflectionException( "Class does not exist: {$className}" );
55
		}
56
57
		return (new $className( $args ));
58
	}
59
60
	/**
61
	 * Normalize the field arguments
62
	 *
63
	 * @return $this
64
	 */
65
	public function normalize( array $args = [] )
66
	{
67
		$defaults = [
68
			'after'       => '',
69
			'attributes'  => '',
70
			'before'      => '',
71
			'class'       => '',
72
			'default'     => null,
73
			'depends'     => null,
74
			'desc'        => '',
75
			'errors'      => [],
76
			'inline'      => false,
77
			'label'       => '',
78
			'name'        => '',
79
			'options'     => [],
80
			'path'        => '',
81
			'placeholder' => '',
82
			'prefix'      => '',
83
			'render'      => true,
84
			'suffix'      => null,
85
			'type'        => 'text',
86
			'value'       => '',
87
		];
88
89
		$args = $atts = wp_parse_args( $args, $defaults );
90
91
		$args['attributes'] = $this->parseAttributes( $atts );
92
		$args['id']         = $this->parseId( $atts );
93
		$args['inline']     = $this->parseInline( $atts );
94
		$args['type']       = $this->parseType( $atts );
95
		$args['name']       = $this->parseName( $atts );
96
		$args['options']    = (array) $atts['options']; // make sure this is always an array
97
		$args['path']       = $atts['name'];
98
		$args['prefix']     = $this->parsePrefix( $atts );
99
		$args['value']      = $this->parseValue( $atts );
100
101
		$this->args = $args;
102
		$this->dependencies = $this->getField( $args )->dependencies;
103
104
		$this->setDataDepends();
105
		$this->checkForErrors( $atts );
106
107
		return $this;
108
	}
109
110
	/**
111
	 * Render the field
112
	 *
113
	 * @param mixed $print
114
	 *
115
	 * @return string|void
116
	 */
117
	public function render( $print = true )
118
	{
119
		if( $this->args['render'] === false )return;
120
121
		$field = $this->getField();
122
123
		$class  = 'glsr-field';
124
		$class .= $this->args['errors'] ? ' glsr-has-error' : '';
125
126
		$renderedString = '%s';
127
128
		if( ( isset( $field->args['required'] ) && $field->args['required'] )
129
			|| ( isset( $field->args['attributes']['required'] ) || in_array( 'required', $field->args['attributes'] )) ) {
130
			$class .= ' glsr-required';
131
		}
132
133
		if( $field->args['type'] !== 'hidden' ) {
134
			$renderedString = sprintf( '<div class="%s">%%s</div>', $class );
135
		}
136
137
		$rendered = sprintf( $renderedString,
138
			$this->args['before'] .
139
			$field->generateLabel() .
140
			$field->render() .
141
			$this->args['after'] .
142
			$this->args['errors']
143
		);
144
145
		$rendered = apply_filters( 'castor/rendered/field', $rendered, $field->args['type'] );
146
147
		if( !!$print && $print !== 'return' ) {
148
			echo $rendered;
149
		}
150
151
		return $rendered;
152
	}
153
154
	/**
155
	 * Reset the Field
156
	 *
157
	 * @return self
158
	 */
159
	public function reset()
160
	{
161
		$this->args = [];
162
163
		return $this;
164
	}
165
166
	/**
167
	 * Check for form submission field errors
168
	 *
169
	 * @return void
170
	 */
171
	protected function checkForErrors( array $atts )
172
	{
173
		$args = $this->args;
174
175
		if( !array_key_exists( $atts['name'], $args['errors'] )) {
176
			$this->args['errors'] = ''; // set to an empty string
177
			return;
178
		}
179
180
		$field_errors = $args['errors'][ $atts['name'] ];
181
182
		$errors = array_reduce( $field_errors['errors'], function( $carry, $error ) {
183
			return $carry . sprintf( '<span>%s</span> ', $error );
184
		});
185
186
		$this->args['errors'] = sprintf( '<span class="glsr-field-errors">%s</span>', $errors );
187
	}
188
189
	/**
190
	 * Parse the field attributes and convert to an array if needed
191
	 *
192
	 * @return array
193
	 */
194
	protected function parseAttributes( array $args )
195
	{
196
		if( empty( $args['attributes'] )) {
197
			return [];
198
		}
199
200
		$attributes = (array) $args['attributes'];
201
202
		foreach( $attributes as $key => $value ) {
203
			if( is_string( $key ))continue;
204
			unset( $attributes[ $key ] );
205
			if( !isset( $attributes[ $value ] )) {
206
				$attributes[ $value ] = '';
207
			}
208
		}
209
210
		return $attributes;
211
	}
212
213
	/**
214
	 * Parse the field ID from the field path
215
	 *
216
	 * @return null|string
217
	 */
218
	protected function parseId( array $args )
219
	{
220
		if( isset( $args['id'] ) && !$args['id'] )return;
221
222
		!$args['suffix'] ?: $args['suffix'] = "-{$args['suffix']}";
223
224
		return str_replace( ['[]','[',']','.'], ['','-','','-'], $this->parseName( $args ) . $args['suffix'] );
225
	}
226
227
	/**
228
	 * Parse the field inline
229
	 *
230
	 * @return bool
231
	 */
232
	protected function parseInline( array $args )
233
	{
234
		return false !== stripos( $args['type'], '_inline' )
235
			? true
236
			: $args['inline'];
237
	}
238
239
	/**
240
	 * Parse the field name
241
	 *
242
	 * @return string
243
	 */
244
	protected function parseName( array $args )
245
	{
246
		$name   = $args['name'];
247
		$prefix = $this->parsePrefix( $args );
248
249
		if( $prefix === false ) {
250
			return $name;
251
		}
252
253
		$paths = explode( '.', $name );
254
255
		return array_reduce( $paths, function( $result, $value ) {
256
			return $result .= "[$value]";
257
		}, $prefix );
258
	}
259
260
	/**
261
	 * Parse the field prefix
262
	 *
263
	 * @return string|false
264
	 */
265
	protected function parsePrefix( array $args )
266
	{
267
		return $args['prefix'];
268
	}
269
270
	/**
271
	 * Parse the field type
272
	 *
273
	 * @return string
274
	 */
275
	protected function parseType( array $args )
276
	{
277
		$type = $args['type'];
278
279
		return false !== stripos( $type, '_inline' )
280
			? str_replace( '_inline', '', $type )
281
			: $type;
282
	}
283
284
	/**
285
	 * Parse the field value
286
	 *
287
	 * @return string
288
	 */
289
	protected function parseValue( array $args )
290
	{
291
		$default = $args['default'];
292
		$name    = $args['name'];
293
		$prefix  = $args['prefix'];
294
		$value   = $args['value'];
295
296
		if( $default == ':placeholder' ) {
297
			$default = '';
298
		}
299
300
		return ( !empty( $value ) || !$name || $prefix === false )
301
			? $value
302
			: $default;
303
	}
304
305
	/**
306
	 * Get the [data-depends] attribute
307
	 *
308
	 * @return array|null
309
	 */
310
	public function getDataDepends()
311
	{
312
		return $this->setDataDepends();
313
	}
314
315
	/**
316
	 * Set the field value
317
	 *
318
	 * @return self
319
	 */
320
	public function setValue()
321
	{
322
		return $this;
323
	}
324
325
	/**
326
	 * Set the [data-depends] attribute
327
	 *
328
	 * @return null|array
329
	 */
330
	protected function setDataDepends()
331
	{
332
		if( !( $depends = $this->args['depends'] ))return;
333
334
		$name  = $depends;
335
		$value = true;
336
337
		if( is_array( $depends )) {
338
			reset( $depends );
339
			$name  = key( $depends );
340
			$value = $depends[ $name ];
341
		}
342
343
		$name = $this->parseName([
344
			'name'   => $name,
345
			'prefix' => $this->args['prefix'],
346
		]);
347
348
		return $this->args['attributes']['data-depends'] = [
349
			'name'  => $name,
350
			'value' => $value,
351
		];
352
	}
353
}
354