This lightweight solution worked for me:
function my_acf_render_field( $field ) {
if ( did_action('acf/render_field/key=field_508a263b40457') % 2 === 0 ) {
return;
}
echo '<p>Some extra HTML for the post object field</p>';
}
add_action( 'acf/render_field/key=field_508a263b40457', 'my_acf_render_field' );
Using the modulus division operator, the function will bail early every 2nd execution.
Unfortunately, a call is made each time.
Looking at acf_field_oembed::wp_oembed_get()
, the field type relies primarily on WordPress’ wp_oembed_get()
. That function does not support caching.
If wp_oembed_get()
fails, then the field type will try with WP_Embed::shortcode()
which does support caching (internally uses wp_oembed_get()
:p ).
I’ve come up with two solutions.
1. Skip format value
$url = get_field('oembed', false, false);
$embed = $wp_embed->shortcode([ 'width' => 640, 'height' => 390 ], $url);
2. Via ACF Filters
The solution I implemented:
/** Disables acf_field_oembed::format_value() */
add_action( 'acf/init', function () {
$field_type = acf_get_field_type('oembed');
remove_filter( 'acf/format_value/type=oembed', [ $field_type, 'format_value' ] );
}, 1 );
/** Fetch the cached oEmbed HTML; Replaces the original method */
add_filter( 'acf/format_value/type=oembed', function ( $value, $post_id, $field ) {
if ( ! empty( $value ) ) {
$value = acf_oembed_get( $value, $post_id, $field );
}
return $value;
}, 10, 3 );
/** Cache the oEmbed HTML */
add_filter( 'acf/update_value/type=oembed', function ( $value, $post_id, $field ) {
if ( ! empty( $value ) ) {
// Warm the cache
acf_oembed_get( $value, $post_id, $field );
}
return $value;
}, 10, 3 );
/**
* Attempts to fetch the embed HTML for a provided URL using oEmbed.
*
* Checks for a cached result (stored as custom post or in the post meta).
*
* @see \WP_Embed::shortcode()
*
* @param mixed $value The URL to cache.
* @param integer $post_id The post ID to save against.
* @param array $field The field structure.
* @return string|null The embed HTML on success, otherwise the original URL.
*/
function acf_oembed_get( $value, $post_id, $field )
{
if ( empty( $value ) ) {
return $value;
}
global $wp_embed;
$attr = [
'width' => $field['width'],
'height' => $field['height'],
];
remove_filter('embed_oembed_html', 'Roots\\Soil\\CleanUp\\embed_wrap');
$html = $wp_embed->shortcode($attr, $value);
add_filter('embed_oembed_html', 'Roots\\Soil\\CleanUp\\embed_wrap');
if ( $html ) {
return $html;
}
return $value;
}
This is how I added support to limit the number of selectable checkboxes:
acf.add_action('ready', function( $el ){
var limit = 4,
selector = '.acf-field-573408b96dcd4 :checkbox',
$boxes = $(selector),
limiter = function () {
if ($boxes.filter(':checked').length >= limit) {
// this.checked = false;
$boxes.not(':checked').attr('disabled', true).prop('disabled', true);
} else {
$boxes.filter(':disabled').removeAttr('disabled').prop('disabled', false);
}
};
if ($boxes.length) {
limiter();
}
$(document).on('change.aqcpe.acf.careers', selector, limiter);
});
Hi,
@elliot I stumbled upon this forum thread in search of a Composer or Git version of ACF Pro. Currently, I’m managing a private manually synced Git repository of ACF Pro that I use as a Git submodule.
For my next project, I’m leaning on using a Composer package-defined repository, as per this Gist.
I was wondering if its possible to be added to this private repository. I like to use edge-versions of WordPress and plugins while a site is in development and due for launch after said packages are golden.
My GitHub username is “mcaskill”.
Thanks
Hi,
I don’t know if we are sharing the same issue (and for me, the issue stretches further back than 5.2.5) but I’ve figured out mine.
The Context:
The project I’m currently working on uses Polylang for translations. Custom fields aren’t set to be translated, their data is synced manually.
I have a post object setup to retrieve posts from two custom post types: partner
and sponsor
. These post types aren’t configured to be multilingual.
The Issue:
In acf_field_post_object::render_field()
, if there’s a saved value, ACF will retrieve all posts matching the saved value (in order to pre-populate the rendered field).
$posts = acf_get_posts(array(
'post__in' => $field['value']
));
Unfortunately, this returns an empty array because acf_get_posts()
will default to loading from all available post types. In my case, acf_get_post_types()
returns: post
, page
, attachment
, partner
, and sponsor
.
And this is the key problem: post
and page
are configured to be multilingual. This triggers Polylang to add a condition to fetch posts in the current language which the non-multilingual post types can’t fulfill.
First Solution:
Require ACF to pass along the filtered list of post types:
$posts = acf_get_posts(array(
'post__in' => $field['value'],
'post_type' => $field['post_type']
));
The one downside of this is if the list of filtered post types changes (e.g., a post type is removed), it will affect any currently saved value assigned to that now-removed post type.
Second Solution:
Intercept Polylang before it adds that language condition to the WP_query
. I accomplish this using a backtrace to figure out if the WP_query
was called by acf_get_posts()
by way of acf_field->render_field()
.
**Updated 2015-05-21T17:22-05:00**
add_action( 'pre_get_posts', function ( &$wp_query ) {
$is_acf_get_posts = (
( $e = new Exception )
&& ( $trace = $e->getTraceAsString() )
&& false !== strpos( $trace, 'acf_get_posts(Array)' )
&& (
( is_admin() && false !== strpos( $trace, '->render_field(Array)' ) )
|| ( ! is_admin() && false !== strpos( $trace, '->format_value(' ) )
)
);
if ( $is_acf_get_posts && pll_is_not_translated_post_type( $wp_query->get('post_type') ) ) {
pll_remove_language_query_var( $wp_query );
}
}, 9 );
function pll_is_not_translated_post_type( $post_type ) {
global $polylang;
if ( isset( $polylang ) ) {
$pll_post_types = $polylang->model->get_translated_post_types( false );
return ( is_array( $post_type ) && array_diff( $post_type, $pll_post_types ) || in_array( $post_type, $pll_post_types ) );
}
return false;
}
function pll_remove_language_query_var( &$query ) {
$qv = &$query->query_vars;
unset( $qv['lang'] );
if ( ! empty( $qv['tax_query'] ) ) {
foreach ( $qv['tax_query'] as $i => $tax_query ) {
if ( isset( $tax_query['taxonomy'] ) && 'language' === $tax_query['taxonomy'] ) {
unset( $qv['tax_query'][ $i ] );
}
}
}
}
I made this filter very verbose just to make sure the idea is understand. I’m using a much more compact version in my project. This function can also be easily translated to your multilingual-plugin flavour (e.g., WPML).
Cheers,
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.