├── test.js ├── Untitled-1.png ├── default-image-for-image-field.php ├── change-option-page-location-display.php ├── acf-delete-images-when-removed-from-gallery.php ├── public-taxonomy-location-rule.php ├── is_admin-acf-location-rule.php ├── public-post-type-location-rule.php ├── render-image-in-editor.php ├── acf-form-kses.php ├── unique-repeater-sub-field.php ├── acf-extended-admin-columns.php ├── acf-page-ancestor-location-rule.php ├── correct-number-field-mouse-scrollwheel-action.php ├── acf-load-parent-theme-field-groups.php ├── acf-page-granparent-location-rule.php ├── acf-custom-post-type-filters.php ├── acf-post-category-ancestor-location-rule.php ├── page-nth-level-location-rule.php ├── acf-json-save-based-on-group-key.php ├── customized-options-page.php ├── acf-options-page-w-cpt-children.php ├── acf-image-aspect-ratio-validation.php ├── acf-field-label-functions.php ├── acf-reciprocal-relationship.php ├── acf-reciprocal-relationships-multiple.php └── README.md /test.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Untitled-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hube2/acf-filters-and-functions/master/Untitled-1.png -------------------------------------------------------------------------------- /default-image-for-image-field.php: -------------------------------------------------------------------------------- 1 | 'Default Image', 11 | 'instructions' => 'Appears when creating a new post', 12 | 'type' => 'image', 13 | 'name' => 'default_value', 14 | )); 15 | } 16 | 17 | ?> 18 | -------------------------------------------------------------------------------- /change-option-page-location-display.php: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /acf-delete-images-when-removed-from-gallery.php: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /public-taxonomy-location-rule.php: -------------------------------------------------------------------------------- 1 | public; 29 | if ($rule['operator'] == '==') { 30 | $match = $public; 31 | } elseif ($rule['operator'] == '!=') { 32 | $match = !$public; 33 | } 34 | return $match; 35 | } 36 | 37 | ?> 38 | -------------------------------------------------------------------------------- /is_admin-acf-location-rule.php: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /public-post-type-location-rule.php: -------------------------------------------------------------------------------- 1 | public; 36 | } elseif ($rule['operator'] == '!=') { 37 | $match = !$post_type->public; 38 | } 39 | return $match; 40 | } 41 | 42 | ?> 43 | -------------------------------------------------------------------------------- /render-image-in-editor.php: -------------------------------------------------------------------------------- 1 | '; print_r($field); echo ''; 23 | // get the post id 24 | global $post; 25 | $post_id = $post->ID; 26 | // get the current value of the field 27 | // using get_post_meta to avoid confilcts 28 | $url = get_post_meta($post_id, $field_name, true); 29 | if (!$url) { 30 | // nothing has been entered 31 | ?>
Enter a URL and Update to View.
The URL Entered is Not A Valid Image URL. Enter a Valid Image URL and Update to View.
43 |';
21 | $or_count = 1;
22 | foreach ($location as $or) {
23 | $and_count = 1;
24 | foreach ($or as $and) {
25 | if ($and_count == 1) {
26 | echo ' ';
27 | }
28 | echo $and['param'],' ',$and['operator'],' ',$and['value'];
29 | if ($and_count < count($or)) {
30 | echo "\r\n",'AND ';
31 | }
32 | $and_count++;
33 | }
34 | if ($or_count < count($location)) {
35 | echo "\r\n\r\n",'OR',"\r\n";
36 | }
37 | $or_count++;
38 | }
39 | echo '';
40 | }
41 | break;
42 | } // end switch
43 | }
44 | add_action('manage_acf-field-group_posts_custom_column', 'acf_field_group_columns_content', 10, 2 );
45 |
46 | // some css to pretty up the new columns
47 | add_action('admin_head', 'admin_acf_columns_css');
48 | function admin_acf_columns_css() {
49 | ?>
50 |
66 |
70 |
--------------------------------------------------------------------------------
/acf-page-ancestor-location-rule.php:
--------------------------------------------------------------------------------
1 | 'page'
18 | ));
19 | if (!empty($groups)) {
20 | foreach(array_keys($groups) as $group_title) {
21 | $posts = acf_extract_var($groups, $group_title);
22 | foreach(array_keys($posts) as $post_id) {
23 | $posts[$post_id] = acf_get_post_title($posts[$post_id]);
24 | };
25 | $choices = $posts;
26 | }
27 | }
28 | // end of copy from ACF
29 | return $choices;
30 | }
31 |
32 | add_filter('acf/location/rule_match/page_ancestor', 'acf_location_rules_match_page_ancestor', 10, 3);
33 | function acf_location_rules_match_page_ancestor($match, $rule, $options) {
34 | // this code is with inspiration from
35 | // acf_location::rule_match_page_parent()
36 | // check parents recursively to see if any
37 | // matches the location value
38 | if (isset($options['page_parent']) && $options['page_parent']) {
39 | $page_parent = $options['page_parent'];
40 | unset($options['page_parent']);
41 | } elseif (isset($options['post_id']) && $options['post_id']) {
42 | $post = get_post($options['post_id']);
43 | $page_parent = $post->post_parent;
44 | }
45 | $ancestors = array();
46 | if ($page_parent) {
47 | $ancestors = get_ancestors($page_parent, 'page');
48 | $ancestors[] = $page_parent;
49 | }
50 | if ($rule['operator'] == "==") {
51 | $match = in_array($rule['value'], $ancestors);
52 | } elseif ($rule['operator'] == "!=") {
53 | $match = !in_array($rule['value'], $ancestors);
54 | }
55 | return $match;
56 | }
57 |
58 | ?>
59 |
--------------------------------------------------------------------------------
/correct-number-field-mouse-scrollwheel-action.php:
--------------------------------------------------------------------------------
1 | /*
2 | This function can be added to functions.php in order to correct the mouse scroll wheel action for number fields.
3 |
4 | This is not just an ACF issue, this is a browser issue.
5 | Whenever a number field has focus, scrolling the mousewheel will change the value of a field,
6 | even when this is not the desired effect, for example what you really want to do is scroll
7 | the page but forgot to click off of the number field to remove focus before trying to do so.
8 | This is, in my opinion and that of others, to be incorrect behavior.
9 |
10 | This script will only allow the scrollwheel to alter the field value when
11 | 1) The number field has focus
12 | AND
13 | 2) The mouse is actually over the field
14 |
15 | This is given as a WordPress action, but with a little modification this concept could be used anywhere.
16 |
17 | */
18 |
19 | add_action('admin_footer', 'correct_number_scrollwheel');
20 | function correct_number_scrollwheel() {
21 | ?>
22 |
46 | get_acf_field_groups();
34 | foreach ($files as $file) {
35 | $file_path = $path.'/'.$file;
36 | if (is_dir($file_path) || !preg_match('/\.json$/', $file)) {
37 | continue;
38 | }
39 | $group_key = preg_replace('/\.json$/', '', $file);
40 | if (!isset($groups[$group_key]) &&
41 | ($json = file_get_contents($file_path)) !== false &&
42 | ($field_group = json_decode($json, true)) !== NULL) {
43 | acf_add_local_field_group($field_group);
44 | }
45 | }
46 | // need to delete the ACF cache
47 | wp_cache_delete('get_field_groups', 'acf');
48 | } // end public function include_fields
49 |
50 | private function get_acf_field_groups() {
51 | $groups = array();
52 | $acf_groups = acf_get_field_groups();
53 | if (!count($acf_groups)) {
54 | return;
55 | }
56 | foreach ($acf_groups as $group) {
57 | $groups[$group['key']] = $group['key'];
58 | }
59 | return $groups;
60 | } // end private function get_acf_field_groups
61 |
62 | } // end class acf_load_theme_groups
63 |
64 | ?>
65 |
--------------------------------------------------------------------------------
/acf-page-granparent-location-rule.php:
--------------------------------------------------------------------------------
1 | 'page'
20 | ));
21 | if (!empty($groups)) {
22 | foreach(array_keys($groups) as $group_title) {
23 | $posts = acf_extract_var($groups, $group_title);
24 | foreach(array_keys($posts) as $post_id) {
25 | $posts[$post_id] = acf_get_post_title($posts[$post_id]);
26 | };
27 | $choices = $posts;
28 | }
29 | }
30 | // end of copy from ACF
31 | return $choices;
32 | }
33 |
34 | add_filter('acf/location/rule_match/page_grandparent', 'acf_location_rules_match_page_grandparent', 10, 3);
35 | function acf_location_rules_match_page_grandparent($match, $rule, $options) {
36 | // this code is with inspiration from
37 | // acf_location::rule_match_page_parent()
38 | // with addition of adding grandparent check
39 | $post_grandparent = 0;
40 | if (isset($options['page_parent']) && $options['page_parent']) {
41 | $parent = get_post($options['page_parent']);
42 | if ($parent->post_parent) {
43 | $post_grandparent = $parent->post_parent;
44 | }
45 | } elseif (isset($options['post_id']) && $options['post_id']) {
46 | $post = get_post($options['post_id']);
47 | if ($post->post_parent) {
48 | $parent = get_post($post->post_parent);
49 | if ($parent->post_parent) {
50 | $post_grandparent = $parent->post_parent;
51 | }
52 | }
53 | }
54 | if (!$post_grandparent) {
55 | return false;
56 | }
57 | if ($rule['operator'] == "==") {
58 | $match = ($post_grandparent == $rule['value']);
59 | } elseif ($rule['operator'] == "!=") {
60 | $match = ($post_grandparent != $rule['value']);
61 | }
62 | return $match;
63 | }
64 |
65 | ?>
66 |
--------------------------------------------------------------------------------
/acf-custom-post-type-filters.php:
--------------------------------------------------------------------------------
1 | $value) {
18 | $new_choices[$key] = $value;
19 | if ($key == 'Page') {
20 | $new_choices['My Custom Post Type'] = array();
21 | }
22 | } // end foreach choices
23 | $choices = $new_choices;
24 | } // end if not in choices
25 | if (!isset($choices['My Custom Post Type']['post'])) {
26 | $choices['My Custom Post Type']['my_custom_post_type_post'] = 'My Custom Post Type Post';
27 | }
28 | return $choices;
29 | }
30 |
31 | // add choices
32 | add_filter('acf/location/rule_values/my_custom_post_type_post', 'acf_location_rules_values_my_custom_post_type');
33 | function acf_location_rules_values_my_custom_post_type($choices) {
34 | // adjust the for loop to the number of levels you need
35 | $args = array(
36 | 'post_type' => 'my_custom_post_type',
37 | 'post_status' => 'publish',
38 | 'posts_per_page' => -1,
39 | 'orderby' => array('title' => 'ASC', 'date' => 'DESC'),
40 | );
41 | $query = new WP_Query($args);
42 | //echo ''; print_r($query->posts); echo ''; 43 | if (count($query->posts)) { 44 | foreach ($query->posts as $post) { 45 | $choices[$post->ID] = $post->post_title; 46 | } 47 | } 48 | return $choices; 49 | } 50 | 51 | // use the standard post matching 52 | // this is copied directly form ACF 53 | add_filter('acf/location/rule_match/my_custom_post_type_post', 'acf_location_rule_match_my_custom_post_type_post', 10, 3); 54 | function acf_location_rule_match_my_custom_post_type_post($match, $rule, $options) { 55 | $post_id = $options['post_id']; 56 | if( !$post_id ) { 57 | return false; 58 | } 59 | if ($rule['operator'] == "==") { 60 | $match = ($options['post_id'] == $rule['value']); 61 | } elseif ($rule['operator'] == "!=") { 62 | $match = ($options['post_id'] != $rule['value']); 63 | } 64 | return $match; 65 | } 66 | 67 | ?> 68 | -------------------------------------------------------------------------------- /acf-post-category-ancestor-location-rule.php: -------------------------------------------------------------------------------- 1 | $term_id) { 37 | $terms[$index] = get_term_by('id', intval($term_id), $term->taxonomy); 38 | } 39 | } 40 | if (!is_array($terms) && $options['post_id']) { 41 | $terms = wp_get_post_terms(intval($options['post_id']), $term->taxonomy); 42 | } 43 | if (!is_array($terms)) { 44 | $terms = array($terms); 45 | } 46 | $terms = array_filter($terms); 47 | $match = false; 48 | // collect a list of ancestors 49 | $ancestors = array(); 50 | if (count($terms)) { 51 | foreach ($terms as $term_to_check) { 52 | $ancestors = array_merge(get_ancestors($term_to_check->term_id, $term->taxonomy)); 53 | } // end foreach terms 54 | } // end if 55 | // see if the rule matches any term ancetor 56 | if ($term && in_array($term->term_id, $ancestors)) { 57 | $match = true; 58 | } 59 | 60 | if ($rule['operator'] == '!=') { 61 | // reverse the result 62 | $match = !$match; 63 | } 64 | return $match; 65 | } 66 | ?> 67 | -------------------------------------------------------------------------------- /page-nth-level-location-rule.php: -------------------------------------------------------------------------------- 1 | name = 'page_level'; 16 | $this->label = 'Page (Post) Level'; 17 | $this->category = 'page'; 18 | } // end function initialize 19 | 20 | static function get_operators($rule) { 21 | $operators = array( 22 | '!=' => 'is not equal to', 23 | '<' => 'is less than', 24 | '<=' => 'is less than or equal to', 25 | '==' => 'is equal to', 26 | '>=' => 'is greater and or equal to', 27 | '>' => 'is greater than' 28 | ); 29 | return $operators; 30 | } // end static function get_operators 31 | 32 | public function get_values($rule) { 33 | // value indicates number of ancestors 34 | $value_add = array( 35 | ' (Parent)', 36 | ' (Child)', 37 | ' (Grandchild)' 38 | ); 39 | $values = array(); 40 | for ($i=0; $i<10; $i++) { 41 | $values[$i] = strval($i+1); 42 | if (isset($value_add[$i])) { 43 | $values[$i] .= $value_add[$i]; 44 | } 45 | } // end for 46 | return $values; 47 | } // end public function get_values 48 | 49 | public function match($rule, $screen, $field_group) { 50 | $match = false; 51 | if (!isset($screen['post_id'])) { 52 | return $match; 53 | } 54 | if (!isset($screen['page_parent'])) { 55 | $ancestors = count(get_ancestors($screen['post_id'], $screen['post_type'], 'post_type')); 56 | } else { 57 | $ancestors = count(get_ancestors($screen['page_parent'], $screen['post_type'], 'post_type'))+1; 58 | } 59 | switch ($rule['operator']) { 60 | case '!=': 61 | $match = ($rule['value'] != $ancestors); 62 | break; 63 | case '<': 64 | $match = ($rule['value'] < $ancestors); 65 | break; 66 | case '<=': 67 | $match = ($rule['value'] <= $ancestors); 68 | break; 69 | case '==': 70 | $match = ($rule['value'] == $ancestors); 71 | break; 72 | case '>=': 73 | $match = ($rule['value'] >= $ancestors); 74 | break; 75 | case '>': 76 | $match = ($rule['value'] > $ancestors); 77 | break; 78 | default: 79 | // do nothing 80 | break; 81 | } // end switch 82 | return $match; 83 | } // end public function match 84 | 85 | } // end class location_page_level_jh 86 | 87 | acf_register_location_type('location_page_level_jh'); 88 | 89 | } // end if class exists 90 | -------------------------------------------------------------------------------- /acf-json-save-based-on-group-key.php: -------------------------------------------------------------------------------- 1 | path pairs 19 | // these will be set later 20 | private $groups = array(); 21 | 22 | // this variable will store the current group key 23 | // that is being saved so that we can retrieve it later 24 | private $current_group_being_saved; 25 | 26 | public function __construct() { 27 | 28 | // this init action will set up the save paths 29 | add_action('admin_init', array($this, 'admin_init')); 30 | 31 | // this action is called by ACF before saving a field group 32 | // the priority is set to 1 so that it runs before the internal ACF action 33 | add_action('acf/update_field_group', array($this, 'update_field_group'), 1, 1); 34 | 35 | } // end public function __construct 36 | 37 | public function admin_init() { 38 | 39 | // in this function we set up the paths where we want to store JSON files 40 | // in this example we're creating two folders in the theme header and footer 41 | // change the field groups and keys based on your groups 42 | $footer = get_stylesheet_directory().'/modules/footer'; 43 | $header = get_stylesheet_directory().'/modules/header'; 44 | $this->groups = array( 45 | 'group_584d5b7986f02' => $header, 46 | 'group_584d5b7986f03' => $footer 47 | ); 48 | 49 | } // end public function admin_init 50 | 51 | public function update_field_group($group) { 52 | // the purpose of this function is to see if we want to 53 | // change the location where this group is saved 54 | // and if we to to add a filter to alter the save path 55 | 56 | // first check to see if this is one of our groups 57 | if (!isset($this->groups[$group['key']])) { 58 | // not one or our groups 59 | return $group; 60 | } 61 | 62 | // store the group key and add action 63 | $this->current_group_being_saved = $group['key']; 64 | add_action('acf/settings/save_json', array($this, 'override_json_location'), 9999); 65 | 66 | // don't forget to return the groups 67 | return $group; 68 | 69 | } // end public function update_field_group 70 | 71 | public function override_json_location($path) { 72 | 73 | // alter the path based on group being saved and 74 | // our save locations 75 | $path = $this->groups[$this->current_group_being_saved]; 76 | 77 | return $path; 78 | 79 | } // end public function override_json_location 80 | 81 | } // end class acf_save_json_based_on_group_key 82 | 83 | 84 | ?> 85 | -------------------------------------------------------------------------------- /customized-options-page.php: -------------------------------------------------------------------------------- 1 |
This will be inserted before the <h1>
'; 67 | $content = str_replace('This will be inserted after the <h1>
'; 71 | $content = str_replace('', ''.$my_content, $content, $count); 72 | 73 | // insert something after the form 74 | $my_content = 'This will be inserted after the form
'; 75 | $content = str_replace('', ''.$my_content, $content, $count); 76 | 77 | // output the new content 78 | echo $content; 79 | } 80 | 81 | ?> 82 | -------------------------------------------------------------------------------- /acf-options-page-w-cpt-children.php: -------------------------------------------------------------------------------- 1 | 9 10 | See this note on https://developer.wordpress.org/reference/functions/register_post_type/#show_in_menu 11 | for the "show_in_menu" argument: 12 | 13 | Note: When using 'some string' to show as a submenu of a menu page created by a 14 | plugin, this item will become the first submenu item, and replace the location of 15 | the top-level link. If this isn't desired, the plugin that creates the menu page 16 | needs to set the add_action priority for admin_menu to 9 or lower. 17 | 18 | The Solution: 19 | Add the options page twice, once with ACF and once with the standard WP function add_menu_page() 20 | 21 | But this causes another problem, the menu will be duplicated. 22 | The solution to this is to remove the duplicate 23 | 24 | You should rename these funtions 25 | 26 | */ 27 | 28 | // add an ACF Options Page 29 | add_action('init', 'add_a_test_acf_options_page'); 30 | function add_a_test_acf_options_page() { 31 | if (!function_exists('acf_add_options_page')) { 32 | return; 33 | } 34 | // all of these arguments are identical to the arguments 35 | // used to create in the function add_menu_page() 36 | $args = array( 37 | 'page_title' => 'Test Options Page', 38 | 'menu_title' => 'Test Options Page', 39 | // set the page slug, do not let it be generated 40 | // or you may not be able to find it to remove 41 | 'menu_slug' => 'test-options-page', 42 | 'capability' => 'edit_posts', 43 | // choose a menu postion that you know will not be changed 44 | 'position' => '75.374981', 45 | 'parent_slug' => '', 46 | 'icon_url' => 'dashicons-warning', 47 | 'redirect' => false, 48 | 'post_id' => 'options', 49 | 'autoload' => true 50 | ); 51 | acf_add_options_page($args); 52 | } 53 | 54 | // add a menu page in WP on admin_init with priority < 10 55 | add_action('admin_menu', 'add_a_test_menu_page', 9); 56 | function add_a_test_menu_page() { 57 | // all of these arguments are identical to the arguments 58 | // used to create in the function acf_add_options_page() 59 | $page_title = 'Test Options Page'; 60 | $menu_title = 'Test Options Page'; 61 | $capability = 'edit_posts'; 62 | // choose a menu postions that you know will not be changed 63 | $position = '75.374981'; 64 | // set the page slug, do not let it be generated 65 | // or you may not be able to find it to remove 66 | $menu_slug = 'test-options-page'; 67 | $callback = ''; 68 | $icon = 'dashicons-warning'; 69 | add_menu_page($page_title, $menu_title, $capability, $menu_slug, $callback, $icon, $position); 70 | } 71 | 72 | // remove the duplicate menu item 73 | // ACF uses a priority of 99 for the admin_menu hook 74 | // so we just need to call this with a higher priority 75 | add_action('admin_menu', 'remove_duplicate_admin_menu', 100); 76 | function remove_duplicate_admin_menu() { 77 | global $menu; 78 | // loop trrough the menu and remove one of the duplicates 79 | // this loop is looking for the page slug 80 | foreach ($menu as $key => $values) { 81 | if ($values[2] == 'test-options-page') { 82 | // found our slug, unset the menu item and exit 83 | unset($menu[$key]); 84 | break; 85 | } 86 | } 87 | } 88 | 89 | // add a CPT that is a sub menu item of the options page 90 | // so that we can see that it works 91 | add_action('init', 'add_test_cpt'); 92 | function add_test_cpt() { 93 | $args = array( 94 | 'labels' => array('name' => 'Test CPT', 'singular_name' => 'Test CPT'), 95 | 'show_ui' => true, 96 | 'show_in_menu' => 'test-options-page', 97 | 'map_meta_cap' => true 98 | ); 99 | register_post_type('test-cpt', $args); 100 | } 101 | 102 | 103 | ?> 104 | -------------------------------------------------------------------------------- /acf-image-aspect-ratio-validation.php: -------------------------------------------------------------------------------- 1 | 'ratio_width', 39 | 'type' => 'number', 40 | 'label' => __('Aspect Ratio'), 41 | 'instructions' => __('Restrict which images can be uploaded'), 42 | 'default_value' => 0, 43 | 'min' => 0, 44 | 'step' => 1, 45 | 'prepend' => __('Width'), 46 | ); 47 | acf_render_field_setting($field, $args); 48 | 49 | $args = array( 50 | 'name' => 'ratio_height', 51 | 'type' => 'number', 52 | // notice that there's no label when appending a setting 53 | 'label' => '', 54 | 'default_value' => 0, 55 | 'min' => 0, 56 | 'step' => 1, 57 | 'prepend' => __('Height'), 58 | // this how we append a setting to the previous one 59 | 'wrapper' => array( 60 | 'data-append' => 'ratio_width', 61 | 'width' => '', 62 | 'class' => '', 63 | 'id' => '' 64 | ) 65 | ); 66 | acf_render_field_setting($field, $args); 67 | 68 | $args = array( 69 | 'name' => 'ratio_margin', 70 | 'type' => 'number', 71 | 'label' => '', 72 | 'default_value' => 0, 73 | 'min' => 0, 74 | 'step' => .5, 75 | 'prepend' => __('±'), 76 | 'append' => __('%'), 77 | 'wrapper' => array( 78 | 'data-append' => 'ratio_width', 79 | 'width' => '', 80 | 'class' => '', 81 | 'id' => '' 82 | ) 83 | ); 84 | acf_render_field_setting($field, $args); 85 | } // end function acf_image_aspect_ratio_settings 86 | 87 | // add filter to validate images to ratio 88 | add_filter('acf/validate_attachment/type=image', 'acf_image_aspect_ratio_validate', 20, 4); 89 | function acf_image_aspect_ratio_validate($errors, $file, $attachment, $field) { 90 | // check to make sure everything has a value 91 | if (empty($field['ratio_width']) || empty($field['ratio_height']) || 92 | empty($file['width']) || empty($file['height'])) { 93 | // values we need are not set or otherwise empty 94 | // bail early 95 | return $errors; 96 | } 97 | // make sure all values are numbers, you never know 98 | $ratio_width = intval($field['ratio_width']); 99 | $ratio_height = intval($field['ratio_height']); 100 | // make sure we don't try to divide by 0 101 | if (!$ratio_width || !$ratio_height) { 102 | // cannot do calculations if something is 0 103 | // bail early 104 | return $errors; 105 | } 106 | $width = intval($file['width']); 107 | $height = intval($file['height']); 108 | // do simple ratio math to see how tall 109 | // the image is allowed to be based on width 110 | $allowed_height = $width/$ratio_width*$ratio_height; 111 | // get margin and calc min/max 112 | $margin = 0; 113 | if (!empty($field['ratio_margin'])) { 114 | $margin = floatval($field['ratio_margin']); 115 | } 116 | $margin = $margin/100; // convert % to decimal 117 | $min = round($allowed_height - ($allowed_height*$margin)); 118 | $max = round($allowed_height + ($allowed_height*$margin)); 119 | if ($height < $min || $height > $max) { 120 | // does not meet the requirement, generate an error 121 | $errors['aspect_ratio'] = __('Image does not meet Aspect Ratio Requirements of '). 122 | $ratio_width.__(':').$ratio_height.__('±').$ratio_margin.__('%'); 123 | } 124 | // return the errors 125 | return $errors; 126 | } // end function acf_image_aspect_ratio_validate 127 | 128 | ?> 129 | -------------------------------------------------------------------------------- /acf-field-label-functions.php: -------------------------------------------------------------------------------- 1 | '; 34 | 35 | - get_sub_field_choice_label($selector, $value) 36 | - the_sub_field_choice_label($selector, $value) 37 | 38 | Example: 39 | 40 | if (have_rows('repeater')) { 41 | while(have_rows('repeater')) { 42 | the_row(); 43 | $values = get_sub_field('checkbox'); 44 | if ($values) { 45 | foreach ($values as $value) { 46 | the_sub_field_choice_label('checkbox', $value); 47 | echo '