Support

Account

Forum Replies Created

  • I’ve had this issue before and this time I figured it out. I found while using get_field, it was returning “11”. I dug into the source code and found the field was returning false for “acf_get_field”. The chain looks like:

    get_field() -> acf_maybe_get_field() -> acf_get_meta_field() -> acf_get_field()

    It was failing because I deleted the field at one point. I added it back in with all the same settings, but the field key changed.

    I didn’t have anything tied to the field key so I thought it was alright.

    But the problem is existing posts saved with an old field key will not load the new field correctly. For example if I create a “subtitle” acf field I might get the key “field_000001”. And if I delete that and create a new “subtitle” field, it is now key “field_000002”.

    And that matters because when your post saves “subtitle = cats” it also saves “_subtitle = field_000001” (with the underscore).

    Even though you have a new field group with a new subtitle field, it’s not looking for “subtitle”. It is looking for “field_000001”.

    The solution is to update all of the affected posts, there is probably better solutions.

    I hope this helps people in the future, I think it is a bug but so very niche.

  • I ran into this issue today. I sent a support ticket in with some more details. Just wanted to add on here.

    If you have a standard text input with a maxlength, it appears to be validating the string length after encoding HTML entities. That means an & character counts as 5 characters (& a m p ;).

    Unfortunately I couldn’t think of a “clean” solution that doesn’t override all other types of validations. The best I came up with is based on checking if the validation error contains the text “Value must not exceed” – which won’t work if the message changes or if your site is in another language.

    Below is my solution with those limitations in mind. It “fixes” regular text fields and also multi-line textareas. You can just remove the last line if you want to validate textareas normally.

    /**
     * Correct max length validation failures caused by html entities like & and < for text inputs.
     * 
     * @param string|true $valid
     * @param string $value
     * @param array $field
     * @param string $input_name
     *
     * @return string|true
     */
    function rs_fix_acf_length_validation( $valid, $value, $field, $input_name ) {
    	if ( is_string($valid) && strpos($valid, 'Value must not exceed') === 0 ) {
    		if ( !isset($field['maxlength']) ) return $valid; // maxlength should  be present here
    		
    		// decode html entities (& -> &). particularly: &, <, >, ", '
    		$decoded_value = wp_specialchars_decode( $value );
    		
    		// get new string length
    		$decoded_length = mb_strlen(wp_unslash( $decoded_value ));
    		
    		// if the decoded string length fits within the max length, override the validtion.
    		if ( $decoded_length <= $field['maxlength'] ) $valid = true;
    	}
    	return $valid;
    }
    add_filter( 'acf/validate_value/type=text', 'rs_fix_acf_length_validation', 20, 4 ); // Text and Textarea both support maxlength, as of ACF 5.8.11
    add_filter( 'acf/validate_value/type=textarea', 'rs_fix_acf_length_validation', 20, 4 );

    (Sorry if this is a repost, my other comment seems to have disappeared?)

  • I ran into this issue today. I sent a support ticket in with some more details. Just wanted to add on here.

    If you have a standard text input with a maxlength, it appears to be validating the string length after encoding HTML entities. That means an & character counts as 5 characters (& a m p ;).

    Unfortunately I couldn’t think of a “clean” solution that doesn’t override all other types of validations. The best I came up with is based on checking if the validation error contains the text “Value must not exceed” – which won’t work if the message changes or if your site is in another language.

    Below is my solution with those limitations in mind. It “fixes” regular text fields and also multi-line textareas. You can just remove the last line if you want to validate textareas normally.

    /**
     * Correct max length validation failures caused by html entities like & and < for text inputs.
     * 
     * @param string|true $valid
     * @param string $value
     * @param array $field
     * @param string $input_name
     *
     * @return string|true
     */
    function rs_fix_acf_length_validation( $valid, $value, $field, $input_name ) {
    	if ( is_string($valid) && strpos($valid, 'Value must not exceed') === 0 ) {
    		if ( !isset($field['maxlength']) ) return $valid; // maxlength should  be present here
    		
    		// decode html entities (& -> &). particularly: &, <, >, ", '
    		$decoded_value = wp_specialchars_decode( $value );
    		
    		// get new string length
    		$decoded_length = mb_strlen(wp_unslash( $decoded_value ));
    		
    		// if the decoded string length fits within the max length, override the validtion.
    		if ( $decoded_length <= $field['maxlength'] ) $valid = true;
    	}
    	return $valid;
    }
    add_filter( 'acf/validate_value/type=text', 'rs_fix_acf_length_validation', 20, 4 ); // Text and Textarea both support maxlength, as of ACF 5.8.11
    add_filter( 'acf/validate_value/type=textarea', 'rs_fix_acf_length_validation', 20, 4 );
  • I needed to add a custom metabox to an options page myself, but wasn’t satisfied by using output buffer (seems like a hack!)

    I dug through the option page source code and ended up with the following functions to:

    1. Create the (sub-)options page
    2. Register a metabox when on that page
    3. Display content within that metabox
    4. Save the values of that metabox

    It’s all very straightforward in the end. As far as I can tell, there is no hook equivalent to “add_meta_boxes” for ACF. And that hook does not fire on the options page, yet you still use add_meta_box to hook them in.

    Here is the code: https://gist.github.com/RadGH/a1473a24782e93435951ef0f390deb2e

  • Ratatat’s solution worked perfect for me. This is right out of my page template, the oembed is named “video”:

    	$video = get_field( 'video' );
    	
    	if ( $video ) {
    		// Add autoplay functionality to the video code
    		if ( preg_match('/src="(.+?)"/', $video, $matches) ) {
    			// Video source URL
    			$src = $matches[1];
    			
    			// Add option to hide controls, enable HD, and do autoplay -- depending on provider
    			$params = array(
    				'controls'    => 0,
    				'hd'        => 1,
    				'autoplay' => 1
    			);
    			
    			$new_src = add_query_arg($params, $src);
    			
    			$video = str_replace($src, $new_src, $video);
    			
    			// add extra attributes to iframe html
    			$attributes = 'frameborder="0"';
    			
    			$video = str_replace('></iframe>', ' ' . $attributes . '></iframe>', $video);
    		}
    	
    		echo '<div class="video-embed">', $video, '</div>';
    	}
  • Alright, so I have run into this thread numerous times and it never helped solve the issue.

    I usually am writing my own plugin and using get_field seems to stop working with the identical behavior that @corydavidwilliam described. It’s not because of the theme or other plugins. It’s because of my own code. So I’ve isolated the problem and wanted to share, in case others run into the same.

    The following code was the culprit, the cause of my repeater returning string “1” instead of array( ‘date’ => ‘9/20/2017’, ‘time’ => ’12:30pm’ ).

    /**
     * Sort open house in RSS FEEDS by open house date, and hide expired entries.
     *
     * @param $query
     */
    function bn_open_house_sort_rss_by_open_house_date( $query ) {
    	if ( !is_feed() ) return;
    	if ( get_query_var('post_type') != 'open_house' ) return;
    	
    	if ( !($query instanceof WP_Query) ) return;
    	
    	$query->set('order', 'ASC');
    	$query->set('orderby', 'meta_value_num');
    	$query->set('meta_key', 'open_house_date_timestamp');
    
    	$query->set('meta_query', array(
    		array(
    			'key' => 'open_house_date_timestamp',
    			'value' => strtotime('-6 Hours'), // Do not show posts from several hours earlier
    			'compare' => '>=',
    			'type' => 'NUMERIC',
    		)
    	));
    }
    add_action( 'pre_get_posts', 'bn_open_house_sort_rss_by_open_house_date' );

    The problem with the above code is that get_query_var(‘post_type’) returns “open_house” during the loop of an RSS feed, as expected. However, get_field() performs it’s own query which tries to get the post type “acf-field” (the field group or specific field, I assume).

    Because my code is adding a meta_query, the acf field query never returns a result. My meta query should only apply to open houses – not ACF fields!

    The solution is to instead check the post type of the current query, and NOT use get_query_var.

    Replace: if ( get_query_var(‘post_type’) != ‘open_house’ ) return;

    With: if ( $query->get(‘post_type’) != ‘open_house’ ) return;

    This makes it so I still have the same behavior as before, except it doesn’t interfere with the get_field() function.

    Note that this won’t be an exact solution for everyone, but since this pops up so often I’m guessing people need to check into the pre_get_posts hook and see if that’s where the problem is coming from. I didn’t expect get_field() to perform a WP_Query.

  • @klas_e Nice work. I’d just like to point out that getting the field by ID, using the field_key, wouldn’t work in a repeater. There can be multiple of the same field. It doesn’t seem to pass an index to identify what row was invoked either. But for a single field on the page I supposed it would work just fine.

  • @ayama Yeah it should be pretty simple. Just find this line and copy it for each field you need to pass in:

    data.product_id = jQuery(this).closest('.acf-row').find('td.acf-field-589cc27c617ab select').val();

    To keep things simple you probably want to pass all 3 values all the time, then make the serverside logic based on the field that ACF is querying for. Hope that makes sense.

  • @ayama I’ve received a response from Elliot and, although I’m still waiting for some final clarification, I’ve got this to work again.

    Here is the result:

    https://s3-us-west-2.amazonaws.com/elasticbeanstalk-us-west-2-868470985522/ShareX/LimelightDept/2017/02/2017-02-10_16-27-24.mp4

    Here is how to implement this code:

    1. Have a repeater field with two dropdowns (other fields could work but need alteration).

    2. CHANGE: field_589ccdb199add— This is the dropdown’s field key that needs to have the custom data added to the ajax request. It is the one dependent on a different field.

    3. CHANGE: td.acf-field-589cc27c617ab — The TD containing the field which value needs to go to the second field’s ajax request.

    Here is the code:

    // THIS BLOCK MUST COME BEFORE DOCUMENT READY, AFTER ACF JS HAS LOADED.
    if ( typeof acf != 'undefined' ) {
    	// Send ProductID with variation ajax request calls
    	lbd_send_product_id_with_variation_ajax_query();
    }
    	
    function lbd_send_product_id_with_variation_ajax_query() {
    	var fn_originalAjaxData = false;
    
    	var fn_ajaxDataWithProductID = function( e, i ) {
    		// Call the original args.ajax.data() function, which was stored in the element
    		var data = fn_originalAjaxData(e,i);
    
    		// Add the Product ID to the data
    		data.product_id = jQuery(this).closest('.acf-row').find('td.acf-field-589cc27c617ab select').val();
    
    		return data;
    	};
    
    	// Whenever a select2 is initialized, inject our own custom ajax.data() function.
    	acf.add_filter( 'select2_args', function( args, $select, settings ) {
    		// Only apply to the "Variation" dropdowns
    		var select_is_variation = $select.attr('id').indexOf('field_589ccdb199add') >= 0;
    		if ( ! select_is_variation ) return args;
    
    		// Store the original ajax.data function for later
    		if ( fn_originalAjaxData === false ) {
    			fn_originalAjaxData = args.ajax.data;
    		}
    
    		// Overwrite the ajax.data function with one that will get the Product ID.
    		args.ajax.data = fn_ajaxDataWithProductID;
    
    		return args;
    	} );
    }

    EDIT:

    Elliot has responded yet again and explained that there is a filter to modify the ajax data. The filter is undocumented. I wasn’t able to find it in the source code, but it does work. It must be added programmatically. The filter can be used as such:

    acf.add_filter( 'select2_ajax_data', function( data, settings, query ) {
        // note: I don't know what "settings" and "query" are actually called
    
        // "this" is the window object, not the field. I don't know how to get the field!
    
        data.my_new_field = 1;
        return data;
    });

    I’m not sure how to get the field that is being triggered. “this” is the window. No reference to the field is passed in any of the parameters. So unfortunately, this filter seems useless for my original purpose. I asked Elliot if there is a way. But I think the hack from the beginning of this comment is still the best way.

  • @ayama I actually needed to use this again today and it seems this solution doesn’t work at all in ACF Version 5.5.7.

    I’ve sent in a support ticket to hopefully get some more information, and hopefully a better implementation. The one I used before was quite a hack. It seems to be the only way, though.

  • I struggled to get John’s code to update the post date. It seems that if you are setting the post_status to draft or pending, then you also need another argument: “edit_date”.

    $args = array(
    	'post_status'   => 'pending',
    	'post_date'     => date( 'Y-m-d H:i:s', $date_timestamp ), // Eg: "2016-10-15 00:00:00"
    	'post_date_gmt' => date( 'Y-m-d H:i:s', $date_timestamp ), // You want this particularly when the post already exists, or the GMT date will be wrong
    	'edit_date'     => true // Must be true, prevents WordPress for "clearing" the post date for drafts and pending posts.
    );

    In addition, the pre_save_post hook MIGHT pass a post ID. To prevent the possibility of duplicate posts being added (especially if you hook in to this more than once), then you should support an existing ID. It’s easy:

    if ( $post_id ) {
    	// Update a post that was already inserted
    	$args['ID'] = $post_id;
    	wp_update_post( $args );
    }else{
    	// Insert a new post
    	$post_id = wp_insert_post( $args );
    }
    
    return $post_id;
  • Seems to come from: add_action( 'get_footer', 'wcd_add_acf_prerequisites_for_memberpress_form' );

    After changing tinymce to text area, and image field to a text field, the error goes away. For some reason – maybe related – none of the clone fields work in either situation. Everything works as an administrator, though.

    Still stumped. Now I have two serious issues. Clone fields are broken, and wyswig is broken.

    Here’s a screenshot of the form basics. See the phone field doesn’t have anything on the right? https://goo.gl/ddQTGb

    Any ideas? I’ve tried disabling other plugins to no avail. Unless it’s memberpress, but I need that for this system to work anyway.

  • No, unfortunately. I’ve tried a few things to get it to work but in the end I had given up.

  • I’ve created a PHP script for this purpose as I ran into the same issue. John’s instructions of step #4 doesn’t apply, as it expects the ACF field already exists – and just doesn’t have lat/lng.

    Here’s the link to the other forum thread:

    http://support.advancedcustomfields.com/forums/topic/how-to-update-google-map-latitudelongitude-after-importing-using-address/

  • Thanks for the reply @elliot.

    I would say it is safe to make them not case sensitive. The main reasoning is that file extensions in Windows are not case sensitive. That might be different on unix/mac.

    I think the more important question to ask is, is there any reason why someone would upload one file, and another one with the same extension except the opposite case, and intend the file types to be different. I’ve never encountered such a scenario.

    I think the main reasoning behind it is much simpler:

    1. iPhone cameras save photos using .JPG
    2. My Android’s camera saves photos using .jpg

    Both are still camera photos, and so I think they should NOT be case sensitive.

    Would it cause problems for people currently using the feature?

    Maaaaaaybe, but I think it is far more likely that this would fix more problems than it causes.

  • (EDIT: This solution stopped working for me, but I found a new one with Elliot’s help. See my new comment.)

    PROBLEM SOLVED!!

    I found a solution.

    It’s not very pretty, but it certainly works. None of the filters I found in the source code offered a way to extend the arguments sent in a select2 ajax request.

    However, there is a filter to modify the select2 arguments. The annoying part is that the select2 arguments are actually a callback to an ACF function. So the magic here is that we replace that function with a “wrapper” function. This new function still calls the old function, then it adds the “Make” to the results. This data is then sent via ajax, and our filter can now show the correctly models!

    Here is the JavaScript, hard-coded by field ID for the MAKE:

    // Update the ajax arguments for select2 objects to include the Make value
    // This is done by replacing the default ajax.data function with a wrapper, which calls the old function and then appends "vehicle_make" to the results.
    acf.add_filter(
        'select2_args',
        function( args ) {
    
            if ( typeof args.ajax.data == 'function' ) {
                var old_data_func = args.ajax.data; // We'll keep this for maximum compatibility, and extend it.
    
                args.ajax.data = function(term, page) {
                    var default_response = old_data_func( term, page ); // Call the old, default function.
    
                    default_response.vehicle_make = function() {
                        // Add the vehicle make to the ajax function. This happens for all select 2 objects, even if it's blank.
                        return jQuery('#acf-field_55890984e822f').val();
                    };
    
                    // Return the default args with our vehicle_make function.
                    return default_response;
                }
            }
    
            return args;
        }
    );

    Here is the PHP Filter which limits the MODEL by term parent:

    function oss_filter_model_dropdown_admin( $args, $field, $post_id ) {
        // Look for the vehicle make in the AJAX request.
        $make = isset($_REQUEST['vehicle_make']) ? (int) $_REQUEST['vehicle_make'] : false;
    
        // If not found, use the previous vehicle's value.
        if ( $make === false ) $make = get_field( 'make_term', $post_id );
    
        // If no make has been selected, do not show any terms (-1 will never give results)
        // Otherwise, use the make as the parent term. Models are always a child of a make.
        if ( !$make ) $args['parent'] = -1;
        else $args['parent'] = (int) $make;
    
        return $args;
    }
    add_filter( 'acf/fields/taxonomy/query/name=model_term', 'oss_filter_model_dropdown_admin', 20, 3 );

    Here is a video demonstrating the end result, showing that the “Model” field’s options are directly tied to the “Make”.

    http://gfycat.com/RevolvingSleepyBarasingha

  • Thanks for the attempt John. I’ve already got the javascript file included properly, though I did not mention this.

    The problem with the second piece of code is that it does fire, but it fires after you select an option.

    Here is a demonstration: http://gfycat.com/IcyBaggyDore

    In that recording, I expect the console to log the event when the ajax data is prepared (as the filter name describes). This would allow me to say “hey ajax call, why don’t you take the value of MAKE with you!”.

    The problem though, is that it doesn’t fire immediately. It fires after you select an option.

    The reason this is a problem is because I want to filter what shows up in the dropdown, to do this I need to send that value when you click on the dropdown – when it is loading the results – so that I can access that value in my PHP filter (acf/fields/taxonomy/query/name=model_term)

    Here’s what SHOULD happen

    1. User clicks on dropdown
    2. Value of “Make” is added to ajax request
    3. Ajax request is fired, return a list of options
    4. Dropdown is populated with the returned options
    5. User selects one of the “Models” displayed, which are direct descendents of the “Make” from step 2.

    And here is what is CURRENTLY happening:

    1. User clicks dropdown
    2. The make is absent from AJAX request
    3. Ajax request is fired, but we cannot filter by the make
    4. Dropdown is populated with either ALL terms, or terms from the PREVIOUSLY SAVED MAKE.
    5. User is confused because either the wrong models are appearing, or a tremendous list (1300 items) is loaded.

Viewing 18 posts - 1 through 18 (of 18 total)