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
|
|
|
|
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.
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.