1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* ACF Repeater Field Class |
5
|
|
|
* |
6
|
|
|
* All the logic for this field type |
7
|
|
|
* |
8
|
|
|
* @class acf_field_repeater |
9
|
|
|
* @extends acf_field |
10
|
|
|
* @package ACF |
11
|
|
|
* @subpackage Fields |
12
|
|
|
*/ |
13
|
|
|
|
14
|
|
|
if( ! class_exists('acf_field_repeater') ) : |
15
|
|
|
|
16
|
|
|
class acf_field_repeater extends acf_field { |
|
|
|
|
17
|
|
|
|
18
|
|
|
|
19
|
|
|
/* |
20
|
|
|
* __construct |
21
|
|
|
* |
22
|
|
|
* This function will setup the field type data |
23
|
|
|
* |
24
|
|
|
* @type function |
25
|
|
|
* @date 5/03/2014 |
26
|
|
|
* @since 5.0.0 |
27
|
|
|
* |
28
|
|
|
* @param n/a |
29
|
|
|
* @return n/a |
30
|
|
|
*/ |
|
|
|
|
31
|
|
|
|
32
|
|
|
function __construct() { |
|
|
|
|
33
|
|
|
|
34
|
|
|
// vars |
35
|
|
|
$this->name = 'repeater'; |
|
|
|
|
36
|
|
|
$this->label = __("Repeater",'acf'); |
|
|
|
|
37
|
|
|
$this->category = 'layout'; |
|
|
|
|
38
|
|
|
$this->defaults = array( |
|
|
|
|
39
|
|
|
'sub_fields' => array(), |
40
|
|
|
'min' => 0, |
41
|
|
|
'max' => 0, |
42
|
|
|
'layout' => 'table', |
43
|
|
|
'button_label' => __("Add Row",'acf'), |
44
|
|
|
'collapsed' => '' |
45
|
|
|
); |
46
|
|
|
$this->l10n = array( |
|
|
|
|
47
|
|
|
'min' => __("Minimum rows reached ({min} rows)",'acf'), |
48
|
|
|
'max' => __("Maximum rows reached ({max} rows)",'acf'), |
49
|
|
|
); |
50
|
|
|
|
51
|
|
|
|
52
|
|
|
// do not delete! |
53
|
|
|
parent::__construct(); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
|
57
|
|
|
/* |
58
|
|
|
* load_field() |
59
|
|
|
* |
60
|
|
|
* This filter is appied to the $field after it is loaded from the database |
61
|
|
|
* |
62
|
|
|
* @type filter |
63
|
|
|
* @since 3.6 |
64
|
|
|
* @date 23/01/13 |
65
|
|
|
* |
66
|
|
|
* @param $field - the field array holding all the field options |
67
|
|
|
* |
68
|
|
|
* @return $field - the field array holding all the field options |
69
|
|
|
*/ |
|
|
|
|
70
|
|
|
|
71
|
|
|
function load_field( $field ) { |
|
|
|
|
72
|
|
|
|
73
|
|
|
$field['sub_fields'] = acf_get_fields( $field ); |
74
|
|
|
|
75
|
|
|
|
76
|
|
|
// return |
77
|
|
|
return $field; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
|
81
|
|
|
|
82
|
|
|
/* |
83
|
|
|
* render_field() |
84
|
|
|
* |
85
|
|
|
* Create the HTML interface for your field |
86
|
|
|
* |
87
|
|
|
* @param $field - an array holding all the field's data |
88
|
|
|
* |
89
|
|
|
* @type action |
90
|
|
|
* @since 3.6 |
91
|
|
|
* @date 23/01/13 |
92
|
|
|
*/ |
93
|
|
|
|
94
|
|
|
function render_field( $field ) { |
|
|
|
|
95
|
|
|
|
96
|
|
|
// vars |
97
|
|
|
$div = array( |
98
|
|
|
'class' => 'acf-repeater', |
99
|
|
|
'data-min' => $field['min'], |
100
|
|
|
'data-max' => $field['max'] |
101
|
|
|
); |
102
|
|
|
|
103
|
|
|
|
104
|
|
|
// ensure value is an array |
105
|
|
|
if( empty($field['value']) ) { |
106
|
|
|
|
107
|
|
|
$field['value'] = array(); |
108
|
|
|
|
109
|
|
|
$div['class'] .= ' -empty'; |
110
|
|
|
|
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
|
114
|
|
|
// rows |
115
|
|
|
$field['min'] = empty($field['min']) ? 0 : $field['min']; |
116
|
|
|
$field['max'] = empty($field['max']) ? 0 : $field['max']; |
117
|
|
|
|
118
|
|
|
|
119
|
|
|
// populate the empty row data (used for acfcloneindex and min setting) |
120
|
|
|
$empty_row = array(); |
121
|
|
|
|
122
|
|
|
|
123
|
|
|
// If there are less values than min, populate the extra values |
124
|
|
View Code Duplication |
if( $field['min'] ) { |
|
|
|
|
125
|
|
|
|
126
|
|
|
for( $i = 0; $i < $field['min']; $i++ ) { |
127
|
|
|
|
128
|
|
|
// continue if already have a value |
129
|
|
|
if( array_key_exists($i, $field['value']) ) { |
130
|
|
|
|
131
|
|
|
continue; |
132
|
|
|
|
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
|
136
|
|
|
// populate values |
137
|
|
|
$field['value'][ $i ] = $empty_row; |
138
|
|
|
|
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
|
144
|
|
|
// If there are more values than man, remove some values |
145
|
|
View Code Duplication |
if( $field['max'] ) { |
|
|
|
|
146
|
|
|
|
147
|
|
|
for( $i = 0; $i < count($field['value']); $i++ ) { |
|
|
|
|
148
|
|
|
|
149
|
|
|
if( $i >= $field['max'] ) { |
150
|
|
|
|
151
|
|
|
unset( $field['value'][ $i ] ); |
152
|
|
|
|
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
|
160
|
|
|
// setup values for row clone |
161
|
|
|
$field['value']['acfcloneindex'] = $empty_row; |
162
|
|
|
|
163
|
|
|
|
164
|
|
|
// show columns |
165
|
|
|
$show_order = true; |
166
|
|
|
$show_add = true; |
167
|
|
|
$show_remove = true; |
168
|
|
|
|
169
|
|
|
|
170
|
|
|
if( $field['max'] ) { |
171
|
|
|
|
172
|
|
|
if( $field['max'] == 1 ) { |
173
|
|
|
|
174
|
|
|
$show_order = false; |
175
|
|
|
|
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
if( $field['max'] <= $field['min'] ) { |
179
|
|
|
|
180
|
|
|
$show_remove = false; |
181
|
|
|
$show_add = false; |
182
|
|
|
|
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
|
188
|
|
|
// field wrap |
189
|
|
|
$el = 'td'; |
190
|
|
|
$before_fields = ''; |
191
|
|
|
$after_fields = ''; |
192
|
|
|
|
193
|
|
|
if( $field['layout'] == 'row' ) { |
194
|
|
|
|
195
|
|
|
$el = 'div'; |
196
|
|
|
$before_fields = '<td class="acf-fields -left">'; |
197
|
|
|
$after_fields = '</td>'; |
198
|
|
|
|
199
|
|
|
} elseif( $field['layout'] == 'block' ) { |
200
|
|
|
|
201
|
|
|
$el = 'div'; |
202
|
|
|
|
203
|
|
|
$before_fields = '<td class="acf-fields">'; |
204
|
|
|
$after_fields = '</td>'; |
205
|
|
|
|
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
|
209
|
|
|
// layout |
210
|
|
|
$div['class'] .= ' -' . $field['layout']; |
211
|
|
|
|
212
|
|
|
|
213
|
|
|
// hidden input |
214
|
|
|
acf_hidden_input(array( |
215
|
|
|
'type' => 'hidden', |
216
|
|
|
'name' => $field['name'], |
217
|
|
|
)); |
218
|
|
|
|
219
|
|
|
|
220
|
|
|
// collapsed |
221
|
|
|
$collapsed = array(); |
222
|
|
|
|
223
|
|
|
if( $field['collapsed'] ) { |
224
|
|
|
|
225
|
|
|
// get user setting |
226
|
|
|
$collapsed = acf_get_user_setting('collapsed_' . $field['key'], ''); |
|
|
|
|
227
|
|
|
$collapsed = explode(',', $collapsed); |
228
|
|
|
$collapsed = array_filter($collapsed, 'is_numeric'); |
229
|
|
|
|
230
|
|
|
|
231
|
|
|
// add target class |
232
|
|
|
foreach( array_keys($field['sub_fields']) as $i ) { |
233
|
|
|
|
234
|
|
|
if( $field['sub_fields'][ $i ]['key'] === $field['collapsed'] ) { |
235
|
|
|
|
236
|
|
|
$field['sub_fields'][ $i ]['wrapper']['class'] .= ' -collapsed-target'; |
237
|
|
|
|
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
?> |
245
|
|
|
<div <?php acf_esc_attr_e($div); ?>> |
246
|
|
|
<table class="acf-table"> |
247
|
|
|
|
248
|
|
View Code Duplication |
<?php if( $field['layout'] == 'table' ): ?> |
|
|
|
|
249
|
|
|
<thead> |
250
|
|
|
<tr> |
251
|
|
|
<?php if( $show_order ): ?> |
252
|
|
|
<th class="acf-row-handle"><span></span></th> |
253
|
|
|
<?php endif; ?> |
254
|
|
|
|
255
|
|
|
<?php foreach( $field['sub_fields'] as $sub_field ): |
256
|
|
|
|
257
|
|
|
$atts = array( |
258
|
|
|
'class' => 'acf-th', |
259
|
|
|
'data-key' => $sub_field['key'], |
260
|
|
|
); |
261
|
|
|
|
262
|
|
|
|
263
|
|
|
// add type |
264
|
|
|
$atts['class'] .= ' acf-th-' . $sub_field['type']; |
265
|
|
|
|
266
|
|
|
|
267
|
|
|
// Add custom width |
268
|
|
|
if( $sub_field['wrapper']['width'] ) { |
269
|
|
|
|
270
|
|
|
$atts['data-width'] = $sub_field['wrapper']['width']; |
271
|
|
|
|
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
?> |
275
|
|
|
<th <?php acf_esc_attr_e( $atts ); ?>> |
276
|
|
|
<?php echo acf_get_field_label( $sub_field ); ?> |
277
|
|
|
<?php if( $sub_field['instructions'] ): ?> |
278
|
|
|
<p class="description"><?php echo $sub_field['instructions']; ?></p> |
279
|
|
|
<?php endif; ?> |
280
|
|
|
</th> |
281
|
|
|
|
282
|
|
|
<?php endforeach; ?> |
283
|
|
|
|
284
|
|
|
<?php if( $show_remove ): ?> |
285
|
|
|
<th class="acf-row-handle"><span></span></th> |
286
|
|
|
<?php endif; ?> |
287
|
|
|
</tr> |
288
|
|
|
</thead> |
289
|
|
|
<?php endif; ?> |
290
|
|
|
|
291
|
|
|
<tbody> |
292
|
|
|
<?php foreach( $field['value'] as $i => $row ): |
293
|
|
|
|
294
|
|
|
$row_class = 'acf-row'; |
295
|
|
|
|
296
|
|
|
if( $i === 'acfcloneindex' ) { |
297
|
|
|
|
298
|
|
|
$row_class .= ' acf-clone'; |
299
|
|
|
|
300
|
|
|
} elseif( in_array($i, $collapsed) ) { |
301
|
|
|
|
302
|
|
|
$row_class .= ' -collapsed'; |
303
|
|
|
|
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
?> |
307
|
|
|
<tr class="<?php echo $row_class; ?>" data-id="<?php echo $i; ?>"> |
308
|
|
|
|
309
|
|
|
<?php if( $show_order ): ?> |
310
|
|
|
<td class="acf-row-handle order" title="<?php _e('Drag to reorder','acf'); ?>"> |
311
|
|
|
<?php if( $field['collapsed'] ): ?> |
312
|
|
|
<a class="acf-icon -collapse small" href="#" data-event="collapse-row" title="<?php _e('Click to toggle','acf'); ?>"></a> |
313
|
|
|
<?php endif; ?> |
314
|
|
|
<span><?php echo intval($i) + 1; ?></span> |
315
|
|
|
</td> |
316
|
|
|
<?php endif; ?> |
317
|
|
|
|
318
|
|
|
<?php echo $before_fields; ?> |
319
|
|
|
|
320
|
|
View Code Duplication |
<?php foreach( $field['sub_fields'] as $sub_field ): |
|
|
|
|
321
|
|
|
|
322
|
|
|
// prevent repeater field from creating multiple conditional logic items for each row |
323
|
|
|
if( $i !== 'acfcloneindex' ) { |
324
|
|
|
|
325
|
|
|
$sub_field['conditional_logic'] = 0; |
326
|
|
|
|
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
|
330
|
|
|
// add value |
331
|
|
|
if( isset($row[ $sub_field['key'] ]) ) { |
332
|
|
|
|
333
|
|
|
// this is a normal value |
334
|
|
|
$sub_field['value'] = $row[ $sub_field['key'] ]; |
335
|
|
|
|
336
|
|
|
} elseif( isset($sub_field['default_value']) ) { |
337
|
|
|
|
338
|
|
|
// no value, but this sub field has a default value |
339
|
|
|
$sub_field['value'] = $sub_field['default_value']; |
340
|
|
|
|
341
|
|
|
} |
342
|
|
|
|
343
|
|
|
|
344
|
|
|
// update prefix to allow for nested values |
345
|
|
|
$sub_field['prefix'] = "{$field['name']}[{$i}]"; |
346
|
|
|
|
347
|
|
|
|
348
|
|
|
// render input |
349
|
|
|
acf_render_field_wrap( $sub_field, $el ); ?> |
350
|
|
|
|
351
|
|
|
<?php endforeach; ?> |
352
|
|
|
|
353
|
|
|
<?php echo $after_fields; ?> |
354
|
|
|
|
355
|
|
|
<?php if( $show_remove ): ?> |
356
|
|
|
<td class="acf-row-handle remove"> |
357
|
|
|
<a class="acf-icon -plus small" href="#" data-event="add-row" title="<?php _e('Add row','acf'); ?>"></a> |
358
|
|
|
<a class="acf-icon -minus small" href="#" data-event="remove-row" title="<?php _e('Remove row','acf'); ?>"></a> |
359
|
|
|
</td> |
360
|
|
|
<?php endif; ?> |
361
|
|
|
|
362
|
|
|
</tr> |
363
|
|
|
<?php endforeach; ?> |
364
|
|
|
</tbody> |
365
|
|
|
</table> |
366
|
|
|
<?php if( $show_add ): ?> |
367
|
|
|
|
368
|
|
|
<ul class="acf-hl"> |
369
|
|
|
<li class="acf-fr"> |
370
|
|
|
<a href="#" class="acf-button blue" data-event="add-row"><?php echo $field['button_label']; ?></a> |
371
|
|
|
</li> |
372
|
|
|
</ul> |
373
|
|
|
|
374
|
|
|
<?php endif; ?> |
375
|
|
|
</div> |
376
|
|
|
<?php |
377
|
|
|
|
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
|
381
|
|
|
/* |
382
|
|
|
* render_field_settings() |
383
|
|
|
* |
384
|
|
|
* Create extra options for your field. This is rendered when editing a field. |
385
|
|
|
* The value of $field['name'] can be used (like bellow) to save extra data to the $field |
386
|
|
|
* |
387
|
|
|
* @type action |
388
|
|
|
* @since 3.6 |
389
|
|
|
* @date 23/01/13 |
390
|
|
|
* |
391
|
|
|
* @param $field - an array holding all the field's data |
392
|
|
|
*/ |
393
|
|
|
|
394
|
|
|
function render_field_settings( $field ) { |
|
|
|
|
395
|
|
|
|
396
|
|
|
// vars |
397
|
|
|
$args = array( |
398
|
|
|
'fields' => $field['sub_fields'], |
399
|
|
|
'layout' => $field['layout'], |
400
|
|
|
'parent' => $field['ID'] |
401
|
|
|
); |
402
|
|
|
|
403
|
|
|
|
404
|
|
|
?><tr class="acf-field" data-setting="repeater" data-name="sub_fields"> |
405
|
|
|
<td class="acf-label"> |
406
|
|
|
<label><?php _e("Sub Fields",'acf'); ?></label> |
407
|
|
|
<p class="description"></p> |
408
|
|
|
</td> |
409
|
|
|
<td class="acf-input"> |
410
|
|
|
<?php |
411
|
|
|
|
412
|
|
|
acf_get_view('field-group-fields', $args); |
413
|
|
|
|
414
|
|
|
?> |
415
|
|
|
</td> |
416
|
|
|
</tr> |
417
|
|
|
<?php |
418
|
|
|
|
419
|
|
|
|
420
|
|
|
// rows |
421
|
|
|
$field['min'] = empty($field['min']) ? '' : $field['min']; |
422
|
|
|
$field['max'] = empty($field['max']) ? '' : $field['max']; |
423
|
|
|
|
424
|
|
|
|
425
|
|
|
// preview |
426
|
|
|
$choices = array(); |
427
|
|
|
|
428
|
|
|
if( $field['collapsed'] ) { |
429
|
|
|
|
430
|
|
|
$choices[ $field['collapsed'] ] = $field['collapsed']; |
431
|
|
|
|
432
|
|
|
} |
433
|
|
|
|
434
|
|
|
|
435
|
|
|
acf_render_field_setting( $field, array( |
436
|
|
|
'label' => __('Collapsed','acf'), |
437
|
|
|
'instructions' => __('Select a sub field to show when row is collapsed','acf'), |
438
|
|
|
'type' => 'select', |
439
|
|
|
'name' => 'collapsed', |
440
|
|
|
'allow_null' => 1, |
441
|
|
|
'choices' => $choices |
442
|
|
|
)); |
443
|
|
|
|
444
|
|
|
|
445
|
|
|
// min |
446
|
|
|
acf_render_field_setting( $field, array( |
447
|
|
|
'label' => __('Minimum Rows','acf'), |
448
|
|
|
'instructions' => '', |
449
|
|
|
'type' => 'number', |
450
|
|
|
'name' => 'min', |
451
|
|
|
'placeholder' => '0', |
452
|
|
|
)); |
453
|
|
|
|
454
|
|
|
|
455
|
|
|
// max |
456
|
|
|
acf_render_field_setting( $field, array( |
457
|
|
|
'label' => __('Maximum Rows','acf'), |
458
|
|
|
'instructions' => '', |
459
|
|
|
'type' => 'number', |
460
|
|
|
'name' => 'max', |
461
|
|
|
'placeholder' => '0', |
462
|
|
|
)); |
463
|
|
|
|
464
|
|
|
|
465
|
|
|
// layout |
466
|
|
|
acf_render_field_setting( $field, array( |
467
|
|
|
'label' => __('Layout','acf'), |
468
|
|
|
'instructions' => '', |
469
|
|
|
'class' => 'acf-repeater-layout', |
470
|
|
|
'type' => 'radio', |
471
|
|
|
'name' => 'layout', |
472
|
|
|
'layout' => 'horizontal', |
473
|
|
|
'choices' => array( |
474
|
|
|
'table' => __('Table','acf'), |
475
|
|
|
'block' => __('Block','acf'), |
476
|
|
|
'row' => __('Row','acf') |
477
|
|
|
) |
478
|
|
|
)); |
479
|
|
|
|
480
|
|
|
|
481
|
|
|
// button_label |
482
|
|
|
acf_render_field_setting( $field, array( |
483
|
|
|
'label' => __('Button Label','acf'), |
484
|
|
|
'instructions' => '', |
485
|
|
|
'type' => 'text', |
486
|
|
|
'name' => 'button_label', |
487
|
|
|
)); |
488
|
|
|
|
489
|
|
|
} |
490
|
|
|
|
491
|
|
|
|
492
|
|
|
/* |
493
|
|
|
* load_value() |
494
|
|
|
* |
495
|
|
|
* This filter is applied to the $value after it is loaded from the db |
496
|
|
|
* |
497
|
|
|
* @type filter |
498
|
|
|
* @since 3.6 |
499
|
|
|
* @date 23/01/13 |
500
|
|
|
* |
501
|
|
|
* @param $value (mixed) the value found in the database |
502
|
|
|
* @param $post_id (mixed) the $post_id from which the value was loaded |
503
|
|
|
* @param $field (array) the field array holding all the field options |
504
|
|
|
* @return $value |
505
|
|
|
*/ |
|
|
|
|
506
|
|
|
|
507
|
|
|
function load_value( $value, $post_id, $field ) { |
|
|
|
|
508
|
|
|
|
509
|
|
|
// bail early if no value |
510
|
|
|
if( empty($value) || empty($field['sub_fields']) ) { |
511
|
|
|
|
512
|
|
|
return $value; |
513
|
|
|
|
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
|
517
|
|
|
// convert to int |
518
|
|
|
$value = intval( $value ); |
519
|
|
|
|
520
|
|
|
|
521
|
|
|
// vars |
522
|
|
|
$rows = array(); |
523
|
|
|
|
524
|
|
|
|
525
|
|
|
// check number of rows |
526
|
|
|
if( $value > 0 ) { |
527
|
|
|
|
528
|
|
|
// loop through rows |
529
|
|
|
for( $i = 0; $i < $value; $i++ ) { |
530
|
|
|
|
531
|
|
|
// create empty array |
532
|
|
|
$rows[ $i ] = array(); |
533
|
|
|
|
534
|
|
|
|
535
|
|
|
// loop through sub fields |
536
|
|
|
foreach( array_keys($field['sub_fields']) as $j ) { |
537
|
|
|
|
538
|
|
|
// get sub field |
539
|
|
|
$sub_field = $field['sub_fields'][ $j ]; |
540
|
|
|
|
541
|
|
|
|
542
|
|
|
// update $sub_field name |
543
|
|
|
$sub_field['name'] = "{$field['name']}_{$i}_{$sub_field['name']}"; |
544
|
|
|
|
545
|
|
|
|
546
|
|
|
// get value |
547
|
|
|
$sub_value = acf_get_value( $post_id, $sub_field ); |
548
|
|
|
|
549
|
|
|
|
550
|
|
|
// add value |
551
|
|
|
$rows[ $i ][ $sub_field['key'] ] = $sub_value; |
552
|
|
|
|
553
|
|
|
} |
554
|
|
|
// foreach |
555
|
|
|
|
556
|
|
|
} |
557
|
|
|
// for |
558
|
|
|
|
559
|
|
|
} |
560
|
|
|
// if |
561
|
|
|
|
562
|
|
|
|
563
|
|
|
// return |
564
|
|
|
return $rows; |
565
|
|
|
|
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
|
569
|
|
|
/* |
570
|
|
|
* format_value() |
571
|
|
|
* |
572
|
|
|
* This filter is appied to the $value after it is loaded from the db and before it is returned to the template |
573
|
|
|
* |
574
|
|
|
* @type filter |
575
|
|
|
* @since 3.6 |
576
|
|
|
* @date 23/01/13 |
577
|
|
|
* |
578
|
|
|
* @param $value (mixed) the value which was loaded from the database |
579
|
|
|
* @param $post_id (mixed) the $post_id from which the value was loaded |
580
|
|
|
* @param $field (array) the field array holding all the field options |
581
|
|
|
* |
582
|
|
|
* @return $value (mixed) the modified value |
583
|
|
|
*/ |
|
|
|
|
584
|
|
|
|
585
|
|
|
function format_value( $value, $post_id, $field ) { |
|
|
|
|
586
|
|
|
|
587
|
|
|
// bail early if no value |
588
|
|
|
if( empty($value) || empty($field['sub_fields']) ) { |
589
|
|
|
|
590
|
|
|
return false; |
591
|
|
|
|
592
|
|
|
} |
593
|
|
|
|
594
|
|
|
|
595
|
|
|
// loop over rows |
596
|
|
|
foreach( array_keys($value) as $i ) { |
597
|
|
|
|
598
|
|
|
// loop through sub fields |
599
|
|
View Code Duplication |
foreach( array_keys($field['sub_fields']) as $j ) { |
|
|
|
|
600
|
|
|
|
601
|
|
|
// get sub field |
602
|
|
|
$sub_field = $field['sub_fields'][ $j ]; |
603
|
|
|
|
604
|
|
|
|
605
|
|
|
// extract value |
606
|
|
|
$sub_value = acf_extract_var( $value[ $i ], $sub_field['key'] ); |
607
|
|
|
|
608
|
|
|
|
609
|
|
|
// format value |
610
|
|
|
$sub_value = acf_format_value( $sub_value, $post_id, $sub_field ); |
611
|
|
|
|
612
|
|
|
|
613
|
|
|
// append to $row |
614
|
|
|
$value[ $i ][ $sub_field['name'] ] = $sub_value; |
615
|
|
|
|
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
} |
619
|
|
|
|
620
|
|
|
|
621
|
|
|
// return |
622
|
|
|
return $value; |
623
|
|
|
|
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
|
627
|
|
|
/* |
628
|
|
|
* validate_value |
629
|
|
|
* |
630
|
|
|
* description |
631
|
|
|
* |
632
|
|
|
* @type function |
633
|
|
|
* @date 11/02/2014 |
634
|
|
|
* @since 5.0.0 |
635
|
|
|
* |
636
|
|
|
* @param $post_id (int) |
637
|
|
|
* @return $post_id (int) |
638
|
|
|
*/ |
|
|
|
|
639
|
|
|
|
640
|
|
|
function validate_value( $valid, $value, $field, $input ){ |
|
|
|
|
641
|
|
|
|
642
|
|
|
// remove acfcloneindex |
643
|
|
|
if( isset($value['acfcloneindex']) ) { |
644
|
|
|
|
645
|
|
|
unset($value['acfcloneindex']); |
646
|
|
|
|
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
|
650
|
|
|
// valid |
651
|
|
|
if( $field['required'] && empty($value) ) { |
652
|
|
|
|
653
|
|
|
$valid = false; |
654
|
|
|
|
655
|
|
|
} |
656
|
|
|
|
657
|
|
|
|
658
|
|
|
// check sub fields |
659
|
|
|
if( !empty($field['sub_fields']) && !empty($value) ) { |
660
|
|
|
|
661
|
|
|
$keys = array_keys($value); |
662
|
|
|
|
663
|
|
View Code Duplication |
foreach( $keys as $i ) { |
|
|
|
|
664
|
|
|
|
665
|
|
|
foreach( $field['sub_fields'] as $sub_field ) { |
666
|
|
|
|
667
|
|
|
// vars |
668
|
|
|
$k = $sub_field['key']; |
669
|
|
|
|
670
|
|
|
|
671
|
|
|
// test sub field exists |
672
|
|
|
if( !isset($value[ $i ][ $k ]) ) { |
673
|
|
|
|
674
|
|
|
continue; |
675
|
|
|
|
676
|
|
|
} |
677
|
|
|
|
678
|
|
|
|
679
|
|
|
// validate |
680
|
|
|
acf_validate_value( $value[ $i ][ $k ], $sub_field, "{$input}[{$i}][{$k}]" ); |
681
|
|
|
} |
682
|
|
|
|
683
|
|
|
} |
684
|
|
|
|
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
return $valid; |
688
|
|
|
|
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
|
692
|
|
|
/* |
693
|
|
|
* update_value() |
694
|
|
|
* |
695
|
|
|
* This filter is appied to the $value before it is updated in the db |
696
|
|
|
* |
697
|
|
|
* @type filter |
698
|
|
|
* @since 3.6 |
699
|
|
|
* @date 23/01/13 |
700
|
|
|
* |
701
|
|
|
* @param $value - the value which will be saved in the database |
702
|
|
|
* @param $field - the field array holding all the field options |
703
|
|
|
* @param $post_id - the $post_id of which the value will be saved |
704
|
|
|
* |
705
|
|
|
* @return $value - the modified value |
706
|
|
|
*/ |
|
|
|
|
707
|
|
|
|
708
|
|
|
function update_value( $value, $post_id, $field ) { |
|
|
|
|
709
|
|
|
|
710
|
|
|
// vars |
711
|
|
|
$total = 0; |
712
|
|
|
|
713
|
|
|
|
714
|
|
|
// remove acfcloneindex |
715
|
|
|
if( isset($value['acfcloneindex']) ) { |
716
|
|
|
|
717
|
|
|
unset($value['acfcloneindex']); |
718
|
|
|
|
719
|
|
|
} |
720
|
|
|
|
721
|
|
|
|
722
|
|
|
// update sub fields |
723
|
|
|
if( !empty($value) ) { |
724
|
|
|
|
725
|
|
|
// $i |
726
|
|
|
$i = -1; |
727
|
|
|
|
728
|
|
|
|
729
|
|
|
// loop through rows |
730
|
|
|
foreach( $value as $row ) { |
731
|
|
|
|
732
|
|
|
// $i |
733
|
|
|
$i++; |
734
|
|
|
|
735
|
|
|
|
736
|
|
|
// increase total |
737
|
|
|
$total++; |
738
|
|
|
|
739
|
|
|
|
740
|
|
|
// continue if no sub fields |
741
|
|
|
if( !$field['sub_fields'] ) { |
742
|
|
|
|
743
|
|
|
continue; |
744
|
|
|
|
745
|
|
|
} |
746
|
|
|
|
747
|
|
|
|
748
|
|
|
// loop through sub fields |
749
|
|
View Code Duplication |
foreach( $field['sub_fields'] as $sub_field ) { |
|
|
|
|
750
|
|
|
|
751
|
|
|
// value |
752
|
|
|
$v = false; |
|
|
|
|
753
|
|
|
|
754
|
|
|
|
755
|
|
|
// key (backend) |
756
|
|
|
if( isset($row[ $sub_field['key'] ]) ) { |
757
|
|
|
|
758
|
|
|
$v = $row[ $sub_field['key'] ]; |
759
|
|
|
|
760
|
|
|
} elseif( isset($row[ $sub_field['name'] ]) ) { |
761
|
|
|
|
762
|
|
|
$v = $row[ $sub_field['name'] ]; |
763
|
|
|
|
764
|
|
|
} else { |
765
|
|
|
|
766
|
|
|
// input is not set (hidden by conditioanl logic) |
767
|
|
|
continue; |
768
|
|
|
|
769
|
|
|
} |
770
|
|
|
|
771
|
|
|
|
772
|
|
|
// modify name for save |
773
|
|
|
$sub_field['name'] = "{$field['name']}_{$i}_{$sub_field['name']}"; |
774
|
|
|
|
775
|
|
|
|
776
|
|
|
// update value |
777
|
|
|
acf_update_value( $v, $post_id, $sub_field ); |
778
|
|
|
|
779
|
|
|
} |
780
|
|
|
// foreach |
781
|
|
|
|
782
|
|
|
} |
783
|
|
|
// foreach |
784
|
|
|
|
785
|
|
|
} |
786
|
|
|
// if |
787
|
|
|
|
788
|
|
|
|
789
|
|
|
// get old value (db only) |
790
|
|
|
$old_total = (int) acf_get_metadata( $post_id, $field['name'] ); |
791
|
|
|
|
792
|
|
|
if( $old_total > $total ) { |
793
|
|
|
|
794
|
|
View Code Duplication |
for( $i = $total; $i < $old_total; $i++ ) { |
|
|
|
|
795
|
|
|
|
796
|
|
|
foreach( $field['sub_fields'] as $sub_field ) { |
797
|
|
|
|
798
|
|
|
// modify name for delete |
799
|
|
|
$sub_field['name'] = "{$field['name']}_{$i}_{$sub_field['name']}"; |
800
|
|
|
|
801
|
|
|
|
802
|
|
|
// delete value |
803
|
|
|
acf_delete_value( $post_id, $sub_field ); |
804
|
|
|
|
805
|
|
|
} |
806
|
|
|
// foreach |
807
|
|
|
|
808
|
|
|
} |
809
|
|
|
// for |
810
|
|
|
|
811
|
|
|
} |
812
|
|
|
// if |
813
|
|
|
|
814
|
|
|
|
815
|
|
|
// update $value and return to allow for the normal save function to run |
816
|
|
|
$value = $total; |
817
|
|
|
|
818
|
|
|
|
819
|
|
|
// return |
820
|
|
|
return $value; |
821
|
|
|
} |
822
|
|
|
|
823
|
|
|
|
824
|
|
|
/* |
825
|
|
|
* delete_value |
826
|
|
|
* |
827
|
|
|
* description |
828
|
|
|
* |
829
|
|
|
* @type function |
830
|
|
|
* @date 1/07/2015 |
831
|
|
|
* @since 5.2.3 |
832
|
|
|
* |
833
|
|
|
* @param $post_id (int) |
834
|
|
|
* @return $post_id (int) |
835
|
|
|
*/ |
|
|
|
|
836
|
|
|
|
837
|
|
|
function delete_value( $post_id, $key, $field ) { |
|
|
|
|
838
|
|
|
|
839
|
|
|
// get old value (db only) |
840
|
|
|
$old_total = (int) acf_get_metadata( $post_id, $field['name'] ); |
841
|
|
|
|
842
|
|
|
|
843
|
|
|
// bail early if no rows or no sub fields |
844
|
|
|
if( !$old_total || !$field['sub_fields'] ) { |
845
|
|
|
|
846
|
|
|
return; |
847
|
|
|
|
848
|
|
|
} |
849
|
|
|
|
850
|
|
|
|
851
|
|
View Code Duplication |
for( $i = 0; $i < $old_total; $i++ ) { |
|
|
|
|
852
|
|
|
|
853
|
|
|
foreach( $field['sub_fields'] as $sub_field ) { |
854
|
|
|
|
855
|
|
|
// modify name for delete |
856
|
|
|
$sub_field['name'] = "{$key}_{$i}_{$sub_field['name']}"; |
857
|
|
|
|
858
|
|
|
|
859
|
|
|
// delete value |
860
|
|
|
acf_delete_value( $post_id, $sub_field ); |
861
|
|
|
|
862
|
|
|
} |
863
|
|
|
// foreach |
864
|
|
|
|
865
|
|
|
} |
866
|
|
|
|
867
|
|
|
} |
868
|
|
|
|
869
|
|
|
|
870
|
|
|
/* |
871
|
|
|
* delete_field |
872
|
|
|
* |
873
|
|
|
* description |
874
|
|
|
* |
875
|
|
|
* @type function |
876
|
|
|
* @date 4/04/2014 |
877
|
|
|
* @since 5.0.0 |
878
|
|
|
* |
879
|
|
|
* @param $post_id (int) |
880
|
|
|
* @return $post_id (int) |
881
|
|
|
*/ |
|
|
|
|
882
|
|
|
|
883
|
|
|
function delete_field( $field ) { |
|
|
|
|
884
|
|
|
|
885
|
|
|
// loop through sub fields |
886
|
|
View Code Duplication |
if( !empty($field['sub_fields']) ) { |
|
|
|
|
887
|
|
|
|
888
|
|
|
foreach( $field['sub_fields'] as $sub_field ) { |
889
|
|
|
|
890
|
|
|
acf_delete_field( $sub_field['ID'] ); |
891
|
|
|
|
892
|
|
|
} |
893
|
|
|
|
894
|
|
|
} |
895
|
|
|
|
896
|
|
|
} |
897
|
|
|
|
898
|
|
|
|
899
|
|
|
/* |
900
|
|
|
* update_field() |
901
|
|
|
* |
902
|
|
|
* This filter is appied to the $field before it is saved to the database |
903
|
|
|
* |
904
|
|
|
* @type filter |
905
|
|
|
* @since 3.6 |
906
|
|
|
* @date 23/01/13 |
907
|
|
|
* |
908
|
|
|
* @param $field - the field array holding all the field options |
909
|
|
|
* @param $post_id - the field group ID (post_type = acf) |
910
|
|
|
* |
911
|
|
|
* @return $field - the modified field |
912
|
|
|
*/ |
|
|
|
|
913
|
|
|
|
914
|
|
|
function update_field( $field ) { |
|
|
|
|
915
|
|
|
|
916
|
|
|
// remove sub fields |
917
|
|
|
unset($field['sub_fields']); |
918
|
|
|
|
919
|
|
|
|
920
|
|
|
// return |
921
|
|
|
return $field; |
922
|
|
|
} |
923
|
|
|
|
924
|
|
|
|
925
|
|
|
/* |
926
|
|
|
* duplicate_field() |
927
|
|
|
* |
928
|
|
|
* This filter is appied to the $field before it is duplicated and saved to the database |
929
|
|
|
* |
930
|
|
|
* @type filter |
931
|
|
|
* @since 3.6 |
932
|
|
|
* @date 23/01/13 |
933
|
|
|
* |
934
|
|
|
* @param $field - the field array holding all the field options |
935
|
|
|
* |
936
|
|
|
* @return $field - the modified field |
937
|
|
|
*/ |
|
|
|
|
938
|
|
|
|
939
|
|
|
function duplicate_field( $field ) { |
|
|
|
|
940
|
|
|
|
941
|
|
|
// get sub fields |
942
|
|
|
$sub_fields = acf_extract_var( $field, 'sub_fields' ); |
943
|
|
|
|
944
|
|
|
|
945
|
|
|
// save field to get ID |
946
|
|
|
$field = acf_update_field( $field ); |
947
|
|
|
|
948
|
|
|
|
949
|
|
|
// duplicate sub fields |
950
|
|
|
acf_duplicate_fields( $sub_fields, $field['ID'] ); |
951
|
|
|
|
952
|
|
|
|
953
|
|
|
// return |
954
|
|
|
return $field; |
955
|
|
|
} |
956
|
|
|
|
957
|
|
|
} |
958
|
|
|
|
959
|
|
|
new acf_field_repeater(); |
960
|
|
|
|
961
|
|
|
endif; |
962
|
|
|
|
963
|
|
|
?> |
964
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.