PluginProbe
Advanced Custom Fields (ACF®) / 3.3.1
Advanced Custom Fields (ACF®) v3.3.1
6.8.9 6.8.8 6.8.7 6.8.6 6.8.5 6.8.4 6.8.3 6.8.2 6.8.1 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 All 230 releases
advanced-custom-fields / core / fields / repeater.php
repeater.php
676 lines 16.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class acf_Repeater extends acf_Field
4 {
5
6 /*--------------------------------------------------------------------------------------
7 *
8 * Constructor
9 *
10 * @author Elliot Condon
11 * @since 1.0.0
12 * @updated 2.2.0
13 *
14 *-------------------------------------------------------------------------------------*/
15
16 function __construct($parent)
17 {
18 parent::__construct($parent);
19
20 $this->name = 'repeater';
21 $this->title = __("Repeater",'acf');
22
23 }
24
25
26 /*--------------------------------------------------------------------------------------
27 *
28 * admin_print_scripts / admin_print_styles
29 *
30 * @author Elliot Condon
31 * @since 3.0.0
32 *
33 *-------------------------------------------------------------------------------------*/
34
35 function admin_print_scripts()
36 {
37 wp_enqueue_script(array(
38 'jquery-ui-sortable',
39 ));
40 }
41
42 function admin_print_styles()
43 {
44
45 }
46
47
48 /*--------------------------------------------------------------------------------------
49 *
50 * create_field
51 *
52 * @author Elliot Condon
53 * @since 2.0.5
54 * @updated 2.2.0
55 *
56 *-------------------------------------------------------------------------------------*/
57
58 function create_field($field)
59 {
60 // vars
61 $defaults = array(
62 'row_limit' => 0,
63 'row_min' => 0,
64 'layout' => 'table',
65 'sub_fields' => array(),
66 'button_label' => __("Add Row",'acf'),
67 'value' => array(),
68 );
69
70 $field = array_merge($defaults, $field);
71
72
73 // validate types
74 $field['row_limit'] = (int) $field['row_limit'];
75 $field['row_min'] = (int) $field['row_min'];
76
77
78 // row limit = 0?
79 if( $field['row_limit'] == 0 )
80 {
81 $field['row_limit'] = 999;
82 }
83
84
85 // min rows
86 if( $field['row_min'] > count($field['value']) )
87 {
88 for( $i = 0; $i < $field['row_min']; $i++ )
89 {
90 if( ! isset($field['value'][$i]) )
91 {
92 $field['value'][$i] = array();
93 }
94 }
95 }
96
97
98 // max rows
99 if( $field['row_limit'] < count($field['value']) )
100 {
101 for( $i = 0; $i < count($field['value']); $i++ )
102 {
103 if( $i >= $field['row_limit'] )
104 {
105 unset( $field['value'][$i] );
106 }
107 }
108 }
109
110
111 // setup values for row clone
112 $field['value'][999] = array();
113 foreach( $field['sub_fields'] as $sub_field)
114 {
115 $sub_value = isset($sub_field['default_value']) ? $sub_field['default_value'] : false;
116 $field['value'][999][$sub_field['name']] = $sub_value;
117 }
118
119
120 ?>
121 <div class="repeater" data-min_rows="<?php echo $field['row_min']; ?>" data-max_rows="<?php echo $field['row_limit']; ?>">
122 <table class="widefat <?php if( $field['layout'] == 'row' ): ?>row_layout<?php endif; ?>">
123 <?php if( $field['layout'] == 'table' ): ?>
124 <thead>
125 <tr><?php
126
127 if( $field['row_limit'] > 1 ): ?><th class="order"></th><?php endif;
128
129 foreach( $field['sub_fields'] as $sub_field_i => $sub_field):
130 ?><th class="<?php echo $sub_field['name']; ?>" <?php if($sub_field_i != 0): ?>style="width:<?php echo 95/count( $field['sub_fields'] ); ?>%;"<?php endif; ?>><span><?php echo $sub_field['label']; ?></span></th><?php
131 endforeach;
132
133 if( $field['row_min'] < $field['row_limit'] ): ?><th class="remove"></th><?php endif;
134
135 ?></tr>
136 </thead>
137 <?php endif; ?>
138 <tbody>
139 <?php if( $field['value'] ): foreach($field['value'] as $i => $value):
140
141 ?><tr class="<?php echo ($i == 999) ? "row-clone" : "row"; ?>"><?php
142
143 if( $field['row_limit'] > 1 ):
144 ?><td class="order"><?php echo $i+1; ?></td><?php
145 endif;
146
147 if( $field['layout'] == 'row' ): ?><td><?php endif;
148
149
150 foreach( $field['sub_fields'] as $j => $sub_field ):
151
152 if( $field['layout'] == 'table'):
153
154 ?><td><?php
155
156 else:
157
158 ?><div class="row-layout-field">
159 <p class="label">
160 <label><?php echo $sub_field['label']; ?></label><?php
161
162 if(!isset($sub_field['instructions']))
163 {
164 $sub_field['instructions'] = "";
165 }
166
167 echo $sub_field['instructions'];
168
169 ?></p><?php
170
171 endif;
172
173 // add value
174 $sub_field['value'] = isset($value[$sub_field['name']]) ? $value[$sub_field['name']] : '';
175
176 // add name
177 $sub_field['name'] = $field['name'] . '[' . $i . '][' . $sub_field['key'] . ']';
178
179 // create field
180 $this->parent->create_field($sub_field);
181
182
183 if( $field['layout'] == 'table' ):
184
185 ?></td><?php
186
187 else:
188
189 ?></div><?php
190
191 endif;
192
193 endforeach;
194
195
196 if( $field['layout'] == 'row' ): ?></td><?php endif;
197
198 if( $field['row_min'] < $field['row_limit'] ):
199
200 ?><td class="remove">
201 <a class="add-row add-row-before" href="javascript:;"></a>
202 <a class="remove-row" href="javascript:;"></a>
203 </td><?php
204
205 endif;
206
207 ?></tr><?php
208
209 endforeach; endif;
210
211 ?>
212 </tbody>
213 </table>
214 <?php if( $field['row_min'] < $field['row_limit'] ): ?>
215
216 <ul class="hl clearfix repeater-footer">
217 <li class="right">
218 <a href="javascript:;" class="add-row-end acf-button"><?php echo $field['button_label']; ?></a>
219 </li>
220 </ul>
221
222 <?php endif; ?>
223 </div>
224 <?php
225 }
226
227
228
229 /*--------------------------------------------------------------------------------------
230 *
231 * create_options
232 *
233 * @author Elliot Condon
234 * @since 2.0.6
235 * @updated 2.2.0
236 *
237 *-------------------------------------------------------------------------------------*/
238
239 function create_options($key, $field)
240 {
241 // vars
242 $fields_names = array();
243 $defaults = array(
244 'row_limit' => '',
245 'row_min' => '0',
246 'layout' => 'table',
247 'sub_fields' => array(),
248 'button_label' => __("Add Row",'acf'),
249 'value' => array(),
250 );
251
252 $field = array_merge($defaults, $field);
253
254
255 // validate types
256 $field['row_min'] = (int) $field['row_min'];
257
258
259 // add clone field
260 $field['sub_fields'][999] = array(
261 'label' => __("New Field",'acf'),
262 'name' => 'new_field',
263 'type' => 'text',
264 'order_no' => '1',
265 'instructions' => '',
266 );
267
268 // get name of all fields for use in field type
269 foreach($this->parent->fields as $f)
270 {
271 $fields_names[$f->name] = $f->title;
272 }
273
274 ?>
275 <tr class="field_option field_option_<?php echo $this->name; ?>">
276 <td class="label">
277 <label><?php _e("Repeater Fields",'acf'); ?></label>
278 </td>
279 <td>
280 <div class="repeater">
281 <div class="fields_header">
282 <table class="acf widefat">
283 <thead>
284 <tr>
285 <th class="field_order"><?php _e('Field Order','acf'); ?></th>
286 <th class="field_label"><?php _e('Field Label','acf'); ?></th>
287 <th class="field_name"><?php _e('Field Name','acf'); ?></th>
288 <th class="field_type"><?php _e('Field Type','acf'); ?></th>
289 </tr>
290 </thead>
291 </table>
292 </div>
293 <div class="fields">
294
295 <div class="no_fields_message" <?php if(count($field['sub_fields']) > 1){ echo 'style="display:none;"'; } ?>>
296 <?php _e("No fields. Click the \"+ Add Sub Field button\" to create your first field.",'acf'); ?>
297 </div>
298
299 <?php foreach($field['sub_fields'] as $key2 => $sub_field): ?>
300 <div class="<?php if($key2 == 999){echo "field_clone";}else{echo "field";} ?> sub_field" data-id="<?php echo $key2; ?>">
301
302 <?php if(isset($sub_field['key'])): ?>
303 <input type="hidden" name="fields[<?php echo $key; ?>][sub_fields][<?php echo $key2; ?>][key]" value="<?php echo $sub_field['key']; ?>" />
304 <?php endif; ?>
305 <div class="field_meta">
306 <table class="acf widefat">
307 <tr>
308 <td class="field_order"><span class="circle"><?php echo ($key2+1); ?></span></td>
309 <td class="field_label">
310 <strong>
311 <a class="acf_edit_field" title="<?php _e("Edit this Field",'acf'); ?>" href="javascript:;"><?php echo $sub_field['label']; ?></a>
312 </strong>
313 <div class="row_options">
314 <span><a class="acf_edit_field" title="<?php _e("Edit this Field",'acf'); ?>" href="javascript:;"><?php _e("Edit",'acf'); ?></a> | </span>
315 <span><a title="<?php _e("Read documentation for this field",'acf'); ?>" href="http://www.advancedcustomfields.com/docs/field-types/" target="_blank"><?php _e("Docs",'acf'); ?></a> | </span>
316 <span><a class="acf_duplicate_field" title="<?php _e("Duplicate this Field",'acf'); ?>" href="javascript:;"><?php _e("Duplicate",'acf'); ?></a> | </span>
317 <span><a class="acf_delete_field" title="<?php _e("Delete this Field",'acf'); ?>" href="javascript:;"><?php _e("Delete",'acf'); ?></a>
318 </div>
319 </td>
320 <td class="field_name"><?php echo $sub_field['name']; ?></td>
321 <td class="field_type"><?php echo $sub_field['type']; ?></td>
322 </tr>
323 </table>
324 </div>
325
326 <div class="field_form_mask">
327 <div class="field_form">
328
329 <table class="acf_input widefat">
330 <tbody>
331 <tr class="field_label">
332 <td class="label">
333 <label><span class="required">*</span><?php _e("Field Label",'acf'); ?></label>
334 <p class="description"><?php _e("This is the name which will appear on the EDIT page",'acf'); ?></p>
335 </td>
336 <td>
337 <?php
338 $this->parent->create_field(array(
339 'type' => 'text',
340 'name' => 'fields['.$key.'][sub_fields]['.$key2.'][label]',
341 'value' => $sub_field['label'],
342 'class' => 'label',
343 ));
344 ?>
345 </td>
346 </tr>
347 <tr class="field_name">
348 <td class="label">
349 <label><span class="required">*</span><?php _e("Field Name",'acf'); ?></label>
350 <p class="description"><?php _e("Single word, no spaces. Underscores and dashes allowed",'acf'); ?></p>
351 </td>
352 <td>
353 <?php
354 $this->parent->create_field(array(
355 'type' => 'text',
356 'name' => 'fields['.$key.'][sub_fields]['.$key2.'][name]',
357 'value' => $sub_field['name'],
358 'class' => 'name',
359 ));
360 ?>
361 </td>
362 </tr>
363 <tr class="field_type">
364 <td class="label"><label><span class="required">*</span><?php _e("Field Type",'acf'); ?></label></td>
365 <td>
366 <?php
367 $this->parent->create_field(array(
368 'type' => 'select',
369 'name' => 'fields['.$key.'][sub_fields]['.$key2.'][type]',
370 'value' => $sub_field['type'],
371 'class' => 'type',
372 'choices' => $fields_names
373 ));
374 ?>
375 </td>
376 </tr>
377 <?php
378
379 $this->parent->fields[$sub_field['type']]->create_options($key.'][sub_fields]['.$key2, $sub_field);
380
381 ?>
382 <tr class="field_save">
383 <td class="label">
384 <!-- <label><?php _e("Save Field",'acf'); ?></label> -->
385 </td>
386 <td>
387 <ul class="hl clearfix">
388 <li>
389 <a class="acf_edit_field acf-button grey" title="<?php _e("Close Field",'acf'); ?>" href="javascript:;"><?php _e("Close Sub Field",'acf'); ?></a>
390 </li>
391 </ul>
392 </td>
393 </tr>
394 </tbody>
395 </table>
396
397 </div><!-- End Form -->
398 </div><!-- End Form Mask -->
399
400 </div>
401 <?php endforeach; ?>
402 </div>
403 <div class="table_footer">
404 <div class="order_message"><?php _e('Drag and drop to reorder','acf'); ?></div>
405 <a href="javascript:;" id="add_field" class="acf-button"><?php _e('+ Add Sub Field','acf'); ?></a>
406 </div>
407 </div>
408 </td>
409 </tr>
410 <tr class="field_option field_option_<?php echo $this->name; ?>">
411 <td class="label">
412 <label><?php _e("Minimum Rows",'acf'); ?></label>
413 </td>
414 <td>
415 <?php
416 $this->parent->create_field(array(
417 'type' => 'text',
418 'name' => 'fields['.$key.'][row_min]',
419 'value' => $field['row_min'],
420 ));
421 ?>
422 </td>
423 </tr>
424 <tr class="field_option field_option_<?php echo $this->name; ?>">
425 <td class="label">
426 <label><?php _e("Maximum Rows",'acf'); ?></label>
427 </td>
428 <td>
429 <?php
430 $this->parent->create_field(array(
431 'type' => 'text',
432 'name' => 'fields['.$key.'][row_limit]',
433 'value' => $field['row_limit'],
434 ));
435 ?>
436 </td>
437 </tr>
438 <tr class="field_option field_option_<?php echo $this->name; ?>">
439 <td class="label">
440 <label><?php _e("Layout",'acf'); ?></label>
441 </td>
442 <td>
443 <?php
444 $this->parent->create_field(array(
445 'type' => 'radio',
446 'name' => 'fields['.$key.'][layout]',
447 'value' => $field['layout'],
448 'layout' => 'horizontal',
449 'choices' => array(
450 'table' => __("Table (default)",'acf'),
451 'row' => __("Row",'acf')
452 )
453 ));
454 ?>
455 </td>
456 </tr>
457 <tr class="field_option field_option_<?php echo $this->name; ?>">
458 <td class="label">
459 <label><?php _e("Button Label",'acf'); ?></label>
460 </td>
461 <td>
462 <?php
463 $this->parent->create_field(array(
464 'type' => 'text',
465 'name' => 'fields['.$key.'][button_label]',
466 'value' => $field['button_label'],
467 ));
468 ?>
469 </td>
470 </tr>
471 <?php
472 }
473
474
475 /*--------------------------------------------------------------------------------------
476 *
477 * pre_save_field
478 * - called just before saving the field to the database.
479 *
480 * @author Elliot Condon
481 * @since 2.2.0
482 *
483 *-------------------------------------------------------------------------------------*/
484
485 function pre_save_field($field)
486 {
487 // format sub_fields
488 if($field['sub_fields'])
489 {
490 // remove dummy field
491 unset($field['sub_fields'][999]);
492
493 // loop through and save fields
494 $i = -1;
495
496 $sub_fields = array();
497
498 foreach($field['sub_fields'] as $f)
499 {
500 $i++;
501
502 // each field has a unique id!
503 if(!isset($f['key'])) $f['key'] = 'field_' . uniqid();
504
505 // order
506 $f['order_no'] = $i;
507
508 // format
509 $f = $this->parent->pre_save_field($f);
510
511 $sub_fields[] = $f;
512 }
513
514 $field['sub_fields'] = $sub_fields;
515 }
516
517 // return updated repeater field
518 return $field;
519
520 }
521
522
523 /*--------------------------------------------------------------------------------------
524 *
525 * update_value
526 *
527 * @author Elliot Condon
528 * @since 2.2.0
529 *
530 *-------------------------------------------------------------------------------------*/
531
532 function update_value($post_id, $field, $value)
533 {
534 $total = 0;
535
536 if($value)
537 {
538 // remove dummy field
539 unset($value[999]);
540
541 $i = -1;
542
543 // loop through rows
544 foreach($value as $row)
545 {
546 $i++;
547
548 // increase total
549 $total++;
550
551 // loop through sub fields
552 foreach($field['sub_fields'] as $sub_field)
553 {
554 // get sub field data
555 $v = isset($row[$sub_field['key']]) ? $row[$sub_field['key']] : '';
556
557 // add to parent value
558 //$parent_value[$i][$sub_field['name']] = $v;
559
560 // update full name
561 $sub_field['name'] = $field['name'] . '_' . $i . '_' . $sub_field['name'];
562
563 // save sub field value
564 $this->parent->update_value($post_id, $sub_field, $v);
565 }
566 }
567 }
568
569 parent::update_value($post_id, $field, $total);
570
571 }
572
573
574 /*--------------------------------------------------------------------------------------
575 *
576 * get_value
577 *
578 * @author Elliot Condon
579 * @since 2.2.0
580 *
581 *-------------------------------------------------------------------------------------*/
582
583 function get_value($post_id, $field)
584 {
585 // vars
586 $values = array();
587 $total = 0;
588
589
590 // get total rows
591 if( is_numeric($post_id) )
592 {
593 $total = (int) get_post_meta($post_id, $field['name'], true);
594 }
595 else
596 {
597 $total = (int) get_option( $post_id . '_' . $field['name'] );
598 }
599
600
601 if($total > 0)
602 {
603 // loop through rows
604 for($i = 0; $i < $total; $i++)
605 {
606 // loop through sub fields
607 foreach($field['sub_fields'] as $sub_field)
608 {
609 // store name
610 $field_name = $sub_field['name'];
611
612 // update full name
613 $sub_field['name'] = $field['name'] . '_' . $i . '_' . $field_name;
614
615 $values[$i][$field_name] = $this->parent->get_value($post_id, $sub_field);
616 }
617 }
618
619 }
620
621 return $values;
622 }
623
624 /*--------------------------------------------------------------------------------------
625 *
626 * get_value_for_api
627 *
628 * @author Elliot Condon
629 * @since 3.0.0
630 *
631 *-------------------------------------------------------------------------------------*/
632
633 function get_value_for_api($post_id, $field)
634 {
635 // vars
636 $values = array();
637 $total = 0;
638
639
640 // get total rows
641 if( is_numeric($post_id) )
642 {
643 $total = (int) get_post_meta($post_id, $field['name'], true);
644 }
645 else
646 {
647 $total = (int) get_option( $post_id . '_' . $field['name'] );
648 }
649
650 if($total > 0)
651 {
652 // loop through rows
653 for($i = 0; $i < $total; $i++)
654 {
655 // loop through sub fields
656 foreach($field['sub_fields'] as $sub_field)
657 {
658 // store name
659 $field_name = $sub_field['name'];
660
661 // update full name
662 $sub_field['name'] = $field['name'] . '_' . $i . '_' . $field_name;
663
664 $values[$i][$field_name] = $this->parent->get_value_for_api($post_id, $sub_field);
665 }
666 }
667
668 return $values;
669 }
670
671 return array();
672 }
673
674 }
675
676 ?>