PluginProbe
Advanced Custom Fields (ACF®) / 4.1.4
Advanced Custom Fields (ACF®) v4.1.4
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 / controllers / field_group.php
field_group.php
937 lines 17.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * acf_field_group
5 *
6 * @description: controller for editing a field group
7 * @since: 3.6
8 * @created: 25/01/13
9 */
10
11 class acf_field_group
12 {
13
14 var $settings;
15
16
17 /*
18 * __construct
19 *
20 * @description:
21 * @since 3.1.8
22 * @created: 23/06/12
23 */
24
25 function __construct()
26 {
27 // actions
28 add_action('admin_enqueue_scripts', array($this,'admin_enqueue_scripts'));
29
30
31 // filters
32 add_filter('acf/get_field_groups', array($this, 'get_field_groups'), 1, 1);
33 add_filter('acf/field_group/get_fields', array($this, 'get_fields'), 5, 2);
34 add_filter('acf/field_group/get_location', array($this, 'get_location'), 5, 2);
35 add_filter('acf/field_group/get_options', array($this, 'get_options'), 5, 2);
36 add_filter('acf/field_group/get_next_field_id', array($this, 'get_next_field_id'), 5, 1);
37
38
39 // save
40 add_filter('name_save_pre', array($this, 'name_save_pre'));
41 add_action('save_post', array($this, 'save_post'));
42
43
44 // ajax
45 add_action('wp_ajax_acf/field_group/render_options', array($this, 'ajax_render_options'));
46 add_action('wp_ajax_acf/field_group/render_location', array($this, 'ajax_render_location'));
47
48 }
49
50
51 /*
52 * get_field_groups
53 *
54 * @description:
55 * @since: 3.6
56 * @created: 27/01/13
57 */
58
59 function get_field_groups( $array )
60 {
61 // cache
62 $cache = wp_cache_get( 'field_groups', 'acf' );
63 if( $cache )
64 {
65 return $cache;
66 }
67
68
69 // get acf's
70 $posts = get_posts(array(
71 'numberposts' => -1,
72 'post_type' => 'acf',
73 'orderby' => 'menu_order title',
74 'order' => 'asc',
75 'suppress_filters' => false,
76 ));
77
78
79 // populate acfs
80 if( $posts ){ foreach( $posts as $post ){
81
82 $array[] = array(
83 'id' => $post->ID,
84 'title' => $post->post_title,
85 'menu_order' => $post->menu_order,
86 );
87
88 }}
89
90
91 // set cache
92 wp_cache_set( 'field_groups', $array, 'acf' );
93
94
95 return $array;
96 }
97
98
99 /*
100 * get_fields
101 *
102 * @description: returns all fields for a field group
103 * @since: 3.6
104 * @created: 26/01/13
105 */
106
107 function get_fields( $fields, $post_id )
108 {
109 // global
110 global $wpdb;
111
112
113 // loaded by PHP already?
114 if( !empty($fields) )
115 {
116 return $fields;
117 }
118
119
120 // get field from postmeta
121 $rows = $wpdb->get_results( $wpdb->prepare("SELECT meta_key FROM $wpdb->postmeta WHERE post_id = %d AND meta_key LIKE %s", $post_id, 'field\_%'), ARRAY_A);
122
123
124 if( $rows )
125 {
126 foreach( $rows as $row )
127 {
128 $field = apply_filters('acf/load_field', false, $row['meta_key'], $post_id );
129
130 $fields[ $field['order_no'] ] = $field;
131 }
132
133 // sort
134 ksort( $fields );
135 }
136
137
138
139 // return
140 return $fields;
141
142 }
143
144
145 /*
146 * get_location
147 *
148 * @description:
149 * @since: 3.6
150 * @created: 26/01/13
151 */
152
153 function get_location( $location, $post_id )
154 {
155 // loaded by PHP already?
156 if( !empty($location) )
157 {
158 return $location;
159 }
160
161
162 // vars
163 $groups = array();
164 $group_no = 0;
165
166
167 // get all rules
168 $rules = get_post_meta($post_id, 'rule', false);
169
170
171 if( is_array($rules) )
172 {
173 foreach( $rules as $rule )
174 {
175 // if field group was duplicated, it may now be a serialized string!
176 $rule = maybe_unserialize($rule);
177
178
179 // does this rule have a group?
180 // + groups were added in 4.0.4
181 if( !isset($rule['group_no']) )
182 {
183 $rule['group_no'] = $group_no;
184
185 // sperate groups?
186 if( get_post_meta($post_id, 'allorany', true) == 'any' )
187 {
188 $group_no++;
189 }
190 }
191
192
193 // add to group
194 $groups[ $rule['group_no'] ][ $rule['order_no'] ] = $rule;
195
196
197 // sort rules
198 ksort( $groups[ $rule['group_no'] ] );
199
200 }
201
202 // sort groups
203 ksort( $groups );
204 }
205
206
207 // return fields
208 return $groups;
209 }
210
211
212 /*
213 * get_options
214 *
215 * @description:
216 * @since: 3.6
217 * @created: 26/01/13
218 */
219
220 function get_options( $options, $post_id )
221 {
222 // loaded by PHP already?
223 if( !empty($options) )
224 {
225 return $options;
226 }
227
228
229 // defaults
230 $options = array(
231 'position' => 'normal',
232 'layout' => 'no_box',
233 'hide_on_screen' => array(),
234 );
235
236
237 // vars
238 $position = get_post_meta($post_id, 'position', true);
239 if( $position )
240 {
241 $options['position'] = $position;
242 }
243
244 $layout = get_post_meta($post_id, 'layout', true);
245 if( $layout )
246 {
247 $options['layout'] = $layout;
248 }
249
250 $hide_on_screen = get_post_meta($post_id, 'hide_on_screen', true);
251 if( $hide_on_screen )
252 {
253 $hide_on_screen = maybe_unserialize($hide_on_screen);
254 $options['hide_on_screen'] = $hide_on_screen;
255 }
256
257
258 // return
259 return $options;
260 }
261
262
263 /*
264 * validate_page
265 *
266 * @description:
267 * @since 3.2.6
268 * @created: 23/06/12
269 */
270
271 function validate_page()
272 {
273 // global
274 global $pagenow, $typenow;
275
276
277 // vars
278 $return = false;
279
280
281 // validate page
282 if( in_array( $pagenow, array('post.php', 'post-new.php') ) )
283 {
284
285 // validate post type
286 if( $typenow == "acf" )
287 {
288 $return = true;
289 }
290
291 }
292
293
294 // return
295 return $return;
296 }
297
298
299 /*
300 * admin_enqueue_scripts
301 *
302 * @description: run after post query but before any admin script / head actions. A good place to register all actions.
303 * @since: 3.6
304 * @created: 26/01/13
305 */
306
307 function admin_enqueue_scripts()
308 {
309 // validate page
310 if( ! $this->validate_page() ){ return; }
311
312
313 // settings
314 $this->settings = apply_filters('acf/get_info', 'all');
315
316
317 // no autosave
318 wp_dequeue_script( 'autosave' );
319
320
321 // custom scripts
322 wp_enqueue_script(array(
323 'acf-field-group',
324 ));
325
326
327 // custom styles
328 wp_enqueue_style(array(
329 'acf-global',
330 'acf-field-group',
331 ));
332
333
334 // actions
335 do_action('acf/field_group/admin_enqueue_scripts');
336 add_action('admin_head', array($this,'admin_head'));
337
338 }
339
340
341 /*
342 * admin_head
343 *
344 * @description:
345 * @since 3.1.8
346 * @created: 23/06/12
347 */
348
349 function admin_head()
350 {
351 global $post;
352
353
354 // add js vars
355 echo '<script type="text/javascript">
356 acf.nonce = "' . wp_create_nonce( 'acf_nonce' ) . '";
357 acf.post_id = ' . $post->ID . ';
358 </script>';
359
360
361 do_action('acf/field_group/admin_head'); // new action
362
363
364 // add metaboxes
365 add_meta_box('acf_fields', __("Fields",'acf'), array($this, 'html_fields'), 'acf', 'normal', 'high');
366 add_meta_box('acf_location', __("Location",'acf'), array($this, 'html_location'), 'acf', 'normal', 'high');
367 add_meta_box('acf_options', __("Options",'acf'), array($this, 'html_options'), 'acf', 'normal', 'high');
368
369
370 // add screen settings
371 add_filter('screen_settings', array($this, 'screen_settings'), 10, 1);
372 }
373
374
375 /*
376 * html_fields
377 *
378 * @description:
379 * @since 1.0.0
380 * @created: 23/06/12
381 */
382
383 function html_fields()
384 {
385 include( $this->settings['path'] . 'core/views/meta_box_fields.php' );
386 }
387
388
389 /*
390 * html_location
391 *
392 * @description:
393 * @since 1.0.0
394 * @created: 23/06/12
395 */
396
397 function html_location()
398 {
399 include( $this->settings['path'] . 'core/views/meta_box_location.php' );
400 }
401
402
403 /*
404 * html_options
405 *
406 * @description:
407 * @since 1.0.0
408 * @created: 23/06/12
409 */
410
411 function html_options()
412 {
413 include( $this->settings['path'] . 'core/views/meta_box_options.php' );
414 }
415
416
417 /*
418 * screen_settings
419 *
420 * @description:
421 * @since: 3.6
422 * @created: 26/01/13
423 */
424
425 function screen_settings( $current )
426 {
427 $current .= '<h5>' . __("Fields",'acf') . '</h5>';
428
429 $current .= '<div class="show-field_key">' . __("Show Field Key:",'acf');
430 $current .= '<label class="show-field_key-no"><input checked="checked" type="radio" value="0" name="show-field_key" />' . __("No",'acf') . '</label>';
431 $current .= '<label class="show-field_key-yes"><input type="radio" value="1" name="show-field_key" />' . __("Yes",'acf') . '</label>';
432 $current .= '</div>';
433
434 return $current;
435 }
436
437
438 /*
439 * ajax_render_options
440 *
441 * @description: creates the HTML for a field's options (field group edit page)
442 * @since 3.1.6
443 * @created: 23/06/12
444 */
445
446 function ajax_render_options()
447 {
448 // vars
449 $options = array(
450 'field_key' => '',
451 'field_type' => '',
452 'post_id' => 0,
453 'nonce' => ''
454 );
455
456 // load post options
457 $options = array_merge($options, $_POST);
458
459
460 // verify nonce
461 if( ! wp_verify_nonce($options['nonce'], 'acf_nonce') )
462 {
463 die(0);
464 }
465
466
467 // required
468 if( ! $options['field_type'] )
469 {
470 die(0);
471 }
472
473
474 // find key (not actual field key, more the html attr name)
475 $options['field_key'] = str_replace("fields[", "", $options['field_key']);
476 $options['field_key'] = str_replace("][type]", "", $options['field_key']) ;
477
478
479 // render options
480 $field = array(
481 'type' => $options['field_type'],
482 'name' => $options['field_key']
483 );
484 do_action('acf/create_field_options', $field );
485
486
487 die();
488
489 }
490
491
492 /*
493 * ajax_render_location
494 *
495 * @description: creates the HTML for the field group location metabox. Called from both Ajax and PHP
496 * @since 3.1.6
497 * @created: 23/06/12
498 */
499
500 function ajax_render_location( $options = array() )
501 {
502 // defaults
503 $defaults = array(
504 'group_id' => 0,
505 'rule_id' => 0,
506 'value' => null,
507 'param' => null,
508 );
509
510 $is_ajax = false;
511 if( isset($_POST['nonce']) && wp_verify_nonce($_POST['nonce'], 'acf_nonce') )
512 {
513 $is_ajax = true;
514 }
515
516
517 // Is AJAX call?
518 if( $is_ajax )
519 {
520 $options = array_merge($defaults, $_POST);
521 }
522 else
523 {
524 $options = array_merge($defaults, $options);
525 }
526
527 // vars
528 $choices = array();
529
530
531 // some case's have the same outcome
532 if($options['param'] == "page_parent")
533 {
534 $options['param'] = "page";
535 }
536
537
538 switch($options['param'])
539 {
540 case "post_type":
541
542 // all post types except attachment
543 $choices = apply_filters('acf/get_post_types', array(), array('attachment'));
544
545 break;
546
547
548 case "page":
549
550 $post_types = get_post_types( array('capability_type' => 'page') );
551 unset( $post_types['attachment'], $post_types['revision'] , $post_types['nav_menu_item'], $post_types['acf'] );
552
553 if( $post_types )
554 {
555 foreach( $post_types as $post_type )
556 {
557 $pages = get_pages(array(
558 'numberposts' => -1,
559 'post_type' => $post_type,
560 'sort_column' => 'menu_order',
561 'order' => 'ASC',
562 'post_status' => array('publish', 'private', 'draft', 'inherit', 'future'),
563 'suppress_filters' => false,
564 ));
565
566 if( $pages )
567 {
568 $choices[$post_type] = array();
569
570 foreach($pages as $page)
571 {
572 $title = '';
573 $ancestors = get_ancestors($page->ID, 'page');
574 if($ancestors)
575 {
576 foreach($ancestors as $a)
577 {
578 $title .= '- ';
579 }
580 }
581
582 $title .= apply_filters( 'the_title', $page->post_title, $page->ID );
583
584
585 // status
586 if($page->post_status != "publish")
587 {
588 $title .= " ($page->post_status)";
589 }
590
591 $choices[$post_type][$page->ID] = $title;
592
593 }
594 // foreach($pages as $page)
595 }
596 // if( $pages )
597 }
598 // foreach( $post_types as $post_type )
599 }
600 // if( $post_types )
601
602 break;
603
604
605 case "page_type" :
606
607 $choices = array(
608 'front_page' => __("Front Page",'acf'),
609 'posts_page' => __("Posts Page",'acf'),
610 'top_level' => __("Top Level Page (parent of 0)",'acf'),
611 'parent' => __("Parent Page (has children)",'acf'),
612 'child' => __("Child Page (has parent)",'acf'),
613 );
614
615 break;
616
617 case "page_template" :
618
619 $choices = array(
620 'default' => __("Default Template",'acf'),
621 );
622
623 $templates = get_page_templates();
624 foreach($templates as $k => $v)
625 {
626 $choices[$v] = $k;
627 }
628
629 break;
630
631 case "post" :
632
633 $post_types = get_post_types( array('capability_type' => 'post') );
634 unset( $post_types['attachment'], $post_types['revision'] , $post_types['nav_menu_item'], $post_types['acf'] );
635
636 if( $post_types )
637 {
638 foreach( $post_types as $post_type )
639 {
640
641 $posts = get_posts(array(
642 'numberposts' => '-1',
643 'post_type' => $post_type,
644 'post_status' => array('publish', 'private', 'draft', 'inherit', 'future'),
645 'suppress_filters' => false,
646 ));
647
648 if( $posts)
649 {
650 $choices[$post_type] = array();
651
652 foreach($posts as $post)
653 {
654 $title = apply_filters( 'the_title', $post->post_title, $post->ID );
655
656 // status
657 if($post->post_status != "publish")
658 {
659 $title .= " ($post->post_status)";
660 }
661
662 $choices[$post_type][$post->ID] = $title;
663
664 }
665 // foreach($posts as $post)
666 }
667 // if( $posts )
668 }
669 // foreach( $post_types as $post_type )
670 }
671 // if( $post_types )
672
673
674 break;
675
676 case "post_category" :
677
678 $category_ids = get_all_category_ids();
679
680 foreach($category_ids as $cat_id)
681 {
682 $cat_name = get_cat_name($cat_id);
683 $choices[$cat_id] = $cat_name;
684 }
685
686 break;
687
688 case "post_format" :
689
690 $choices = get_post_format_strings();
691
692 break;
693
694 case "user_type" :
695
696 global $wp_roles;
697
698 $choices = $wp_roles->get_names();
699
700 break;
701
702 case "taxonomy" :
703
704 $choices = array();
705 $simple_value = true;
706 $choices = apply_filters('acf/get_taxonomies_for_select', $choices, $simple_value);
707
708 break;
709
710 case "ef_taxonomy" :
711
712 $choices = array('all' => __('All', 'acf'));
713 $taxonomies = get_taxonomies( array('public' => true), 'objects' );
714
715 foreach($taxonomies as $taxonomy)
716 {
717 $choices[ $taxonomy->name ] = $taxonomy->labels->name;
718 }
719
720 // unset post_format (why is this a public taxonomy?)
721 if( isset($choices['post_format']) )
722 {
723 unset( $choices['post_format']) ;
724 }
725
726
727 break;
728
729 case "ef_user" :
730
731 global $wp_roles;
732
733 $choices = array_merge( array('all' => __('All', 'acf')), $wp_roles->get_names() );
734
735 break;
736
737
738 case "ef_media" :
739
740 $choices = array('all' => __('All', 'acf'));
741
742 break;
743
744 }
745
746
747 // allow custom location rules
748 $choices = apply_filters( 'acf/location/rule_values/' . $options['param'], $choices );
749
750
751 // create field
752 do_action('acf/create_field', array(
753 'type' => 'select',
754 'name' => 'location[' . $options['group_id'] . '][' . $options['rule_id'] . '][value]',
755 'value' => $options['value'],
756 'choices' => $choices,
757 ));
758
759
760 // ajax?
761 if( $is_ajax )
762 {
763 die();
764 }
765
766 }
767
768
769 /*
770 * name_save_pre
771 *
772 * @description: intercepts the acf post obejct and adds an "acf_" to the start of
773 * it's name to stop conflicts between acf's and page's urls
774 * @since 1.0.0
775 * @created: 23/06/12
776 */
777
778 function name_save_pre($name)
779 {
780 // validate
781 if( !isset($_POST['post_type']) || $_POST['post_type'] != 'acf' )
782 {
783 return $name;
784 }
785
786
787 // need a title
788 if( !$_POST['post_title'] )
789 {
790 $_POST['post_title'] = 'Unnamed Field Group';
791 }
792
793
794 $name = 'acf_' . sanitize_title_with_dashes($_POST['post_title']);
795
796
797 return $name;
798 }
799
800
801 /*
802 * save_post
803 *
804 * @description: Saves the field / location / option data for a field group
805 * @since 1.0.0
806 * @created: 23/06/12
807 */
808
809 function save_post($post_id)
810 {
811 // do not save if this is an auto save routine
812 if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
813 {
814 return $post_id;
815 }
816
817
818 // verify nonce
819 if( !isset($_POST['acf_nonce']) || !wp_verify_nonce($_POST['acf_nonce'], 'field_group') )
820 {
821 return $post_id;
822 }
823
824
825 // only save once! WordPress save's a revision as well.
826 if( wp_is_post_revision($post_id) )
827 {
828 return $post_id;
829 }
830
831
832 /*
833 * save fields
834 */
835
836 // vars
837 $dont_delete = array();
838
839 if( isset($_POST['fields']) && is_array($_POST['fields']) )
840 {
841 $i = -1;
842
843
844 // remove clone field
845 unset( $_POST['fields']['field_clone'] );
846
847
848
849 // loop through and save fields
850 foreach( $_POST['fields'] as $key => $field )
851 {
852 $i++;
853
854
855 // order + key
856 $field['order_no'] = $i;
857 $field['key'] = $key;
858
859
860 // save
861 do_action('acf/update_field', $field, $post_id );
862
863
864 // add to dont delete array
865 $dont_delete[] = $field['key'];
866 }
867 }
868 unset( $_POST['fields'] );
869
870
871 // delete all other field
872 $keys = get_post_custom_keys($post_id);
873 foreach( $keys as $key )
874 {
875 if( strpos($key, 'field_') !== false && !in_array($key, $dont_delete) )
876 {
877 // this is a field, and it wasn't found in the dont_delete array
878 do_action('acf/delete_field', $post_id, $key);
879 }
880 }
881
882
883 /*
884 * save location rules
885 */
886
887 if( isset($_POST['location']) && is_array($_POST['location']) )
888 {
889 delete_post_meta( $post_id, 'rule' );
890
891
892 // clean array keys
893 $_POST['location'] = array_values( $_POST['location'] );
894 foreach( $_POST['location'] as $group_id => $group )
895 {
896 if( is_array($group) )
897 {
898 // clean array keys
899 $group = array_values( $group );
900 foreach( $group as $rule_id => $rule )
901 {
902 $rule['order_no'] = $rule_id;
903 $rule['group_no'] = $group_id;
904
905
906 add_post_meta( $post_id, 'rule', $rule );
907 }
908 }
909 }
910
911 unset( $_POST['location'] );
912 }
913
914
915 /*
916 * save options
917 */
918
919 if( isset($_POST['options']) && is_array($_POST['options']) )
920 {
921 update_post_meta($post_id, 'position', $_POST['options']['position']);
922 update_post_meta($post_id, 'layout', $_POST['options']['layout']);
923 update_post_meta($post_id, 'hide_on_screen', $_POST['options']['hide_on_screen']);
924 }
925
926
927 unset( $_POST['options'] );
928
929
930 }
931
932
933 }
934
935 new acf_field_group();
936
937 ?>