Completed
Push — develop ( efbf23...556e46 )
by Paul
02:08
created

Field::parseValue()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 12
nop 1
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';
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
33
			case 'dependencies';
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
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