@pkhunter I wanted to created a read only “relationship” field that gets updated bidirectionally from a linked post. This is the solution I am using:
// render readonly field on relationship settings
add_action('acf/render_field_settings/type=relationship', function($field) {
acf_render_field_setting( $field, array(
'label' => __('Read Only?','acf'),
'instructions' => '',
'type' => 'true_false',
'name' => 'readonly',
'ui' => 1,
'class' => 'acf-field-object-true-false-ui'
));
});
// render relationships as links to the edit pages.
add_filter('acf/prepare_field/type=relationship', function($field) {
// check to see if this is a read only relationship field
if (isset($field['readonly']) && $field['readonly']) {
// the value is an array of post_ids
$post_ids = $field['value'];
// render them as a list
echo "<ul style='margin-left:5px;'>";
foreach($post_ids as $post_id) {
$post = get_post($post_id);
$edit_link = get_edit_post_link($post_id);
echo "<li><a href='$edit_link'>" . $post->post_title . "</a></li>";
}
echo "</ul>";
// return false to stop default rendering
return false;
}
return $field;
});
The problem is that in $GLOBALS['my_query_filters']
you need to pass it the key
and then the name
, but you are passing the name in twice. Because of this it isn’t able to call get_field_object()
correctly, thus can’t determine the field type
, thus the error.
The repeater field stores the values as a serialized array in the database so I don’t think it will be easy to get an exact count outside of the repeater loop. If you need discreet access to this data I would use the acf/update_value
and acf/delete_value
filters to maintain the counts in different meta fields.
$field_key = 'your field key'; // or use name, type, etc and the proper filters
// Run on field value update
add_filter( 'acf/update_value/key={$field_key}', function($values, $post_id, $field){
if ( $field['type'] == 'repeater' ){
// you might need to delete "old" value sums in the db that aren't on the current values
$sums = array();
foreach( $values as $value ){
if ( !isset( $sums[$value] ) ){
$sums[$value] = 1;
} else {
$sums[$value]++;
}
}
foreach( $sums as $value => $sum ){
// save the sum for each value in a different field
}
}
}, 20, 3 );
// Run when a value is deleted
add_filter( 'acf/delete_value/key={$field_key}', function($value, $post_id, $field){
// probably do the exact same thing as when a value is updated... recalculate the sum of each value
}, 20, 3 );
You need to check to see if the lat
and lng
indexes are set on the field array. You do this using the isset()
PHP method. If they aren’t shown you can display an error (or nothing) and if they are then proceed with the rest of your code.
$location = get_field('map');
if ( isset( $location['lat'] ) && isset( $location['lng'] ) ){
$lat = $location['lat'];
$lng = $location['lng'];
$coords = $lat.".".$lng;
// ... the rest of your code
} else {
// ... the lat/lng location is not set
}
Hi Pawel – it’s definitely possible but I think you’ll have to do some custom programming. On your blog page you can use the Map field to create the initial map that will hold all your markers, but then you will need to add the markers programmatically using the location value from the field on each of your posts.
If you don’t want to use my plugin, just hook your logic into one of the following validate filters – acf/validate_value
, acf/validate_value/type={$field['type']}
, acf/validate_value/name={$field['name']}
, or acf/validate_value/key={$field['key']}
. These filters take the arguments $valid, $value, $field, $input
and return true
for success or a string
if there was an error.
Also let me know if you would like to try out the new version of my validation plugin – it might contain a few bugs still but has a lot of new features.
Shameless plug – you can use my Validated Field plugin to check ACF field submissions. I am currently working on an upgrade (done with 5.x, working through the 4.x code now) but you can check it out in the WordPress repo here: https://wordpress.org/plugins/validated-field-for-acf/
The logic above would still be used as part of the PHP validation, and if there is an error you would just return "this is the error message";
otherwise you can return true;
to have it pass (or just do nothing, pass is the default).
@tararotten In that case the code I posted should work for the front end basic uploader, and the admin media gallery. If you upload using the basic uploader, you will get the filename (not numeric) but if you use the media gallery you will get the attachment id (numeric). By checking to see if the $value
is numeric you can determine how to get the mime type so you can validate it.
You can do this using the PHP acf/admin/input_head
action to write JavaScript that uses the google_maps_args
ACF JavaScript filter.
add_action( 'acf/input/admin_head', function(){
?>
<script type="text/javascript">
(function($){
acf.add_filter( 'google_map_args', function( options, $field ){
return $.extend({scrollwheel: false}, options);
} )
})(jQuery);
</script>
<?php
});
I recently noticed this too – I think it’s related to using the basic uploader vs wp media gallery rather than frontend/backend. Before I go further, you can also control the allowed file types in the Field Group Editor for your image field, you don’t have to use a custom filter.
The value that is passed to the filter from the basic uploader is “C:\fakepath\image.jpg” (I have a Mac, so it’s really a fake path. Going through the Media Gallery it has already uploaded the file, then passes the attachment ID to the filter, so for example 123
.
If you do want to use your custom filter you would just need to check to see if the value is numeric or not, and if it is fetch the attachment (which should already have the file type).
if ( !empty( $value ) && is_numeric( $value ) ){
// https://codex.wordpress.org/Function_Reference/get_post_mime_type
$mime_type = get_post_mime_type( $value );
} else {
// use the filename
$fileinfo = wp_check_filetype( $value );
$mime_type = $fileinfo['type'];
}
if( !in_array( str_replace( 'image/', '', $mime_type ), array( 'jpeg', 'gif', 'png', 'bmp', 'tiff', 'jpg' ) ) ){
$valid = "Please upload a valid image file!";
}
@bokis I needed to be able to search these values as well for my plugin Validated Field so that I could check for unique values (the plugin supports different types of uniqueness per field). It actually needed to work for any field that can support multiple values (select, checkbox, relationship, posts, users, etc), plus I’ve previously been asked to support WPML so that’s in there too.
My solution was to use the acf/update_value
and acf/delete_value
hooks to process the array values into discrete meta field entries suffixed by type: “__p” for post IDs, “__t” for taxonomy IDs, “__u” for User IDs, and “__x” for everything else. Additionally I am sorting the array values and saving that for comparison as well.
This means for a set of Post Ids 3, 1, 2 caled “related_posts” it would save:
#original value (out of order IDs) related_posts = array( 3, 1, 2 ) # sorted value related_posts__ps = array( 1, 2, 3 ) # discrete ID values related_posts__p = 1 related_posts__p = 2 related_posts__p = 3
I will be releasing the 2.0 version of the plugin in a few days so you could take advantage of the metadata that it creates, since these are standard meta fields they should be searchable by most search plugins. Or if you just want to peek at the code: https://github.com/doublesharp/validated-field-for-acf/blob/master/common/acf_vf_validated_field.php#L191
@jonathan That sounds reasonable. Unless it was seriously faster to use JSON, just having a PHP array makes things much easier, plus I can use the same config for ACF4 (with register_field_group()
) as well as ACf 5, since ACF4 wouldn’t support the json config. To your last point, it also lets me filter them so I can configure the form on the fly.
Thanks for confirming I don’t need to refactor anything 🙂
I am doing this on some of my sites with the following code. YMMV performance wise having this inline, in an enqueued file, etc depending on the specific implementation:
add_action( "admin_footer", "acf_link_to_tab" );
function acf_link_to_tab(){ ?>
<script>
(function($){
acf.add_action('ready', function(){
if (location.hash.length>1){
var hash = location.hash.substring(1);
$('.acf-tab-wrap .acf-tab-button').each(function(i, button){
if (hash==$(button).text().toLowerCase().replace(' ', '-')){
$(button).trigger('click');
return false;
}
});
}
});
})(jQuery);
</script><?php
}
I’m planning on adding this functionality to my Validated Field add-on (or a pro version of it) in the near future.
Thanks!
Justin
I dont think my plugin is obsolete 🙂
Its primary function is to handle validation, but it also does the exact same thing as your code internally, and also includes the workaround for the front-end forms. Definitely something you can do in your functions.php or elsewhere; I was responding to this post as this code in the Validated Field plugin to enable different advanced functionality.
Timo,
That’s the solution I described, however it doesn’t work on the front-end form, only in the WP Admin. The “hacky” workaround is for inserting the post ID into the front-end form that is generated from acf_form()
.
Justin
Thanks Robby, but I am not using WPML. From my research it looks like it is saving “all” as the taxonomy when none are selected but nothing is returned since it isn’t a real taxonomy.
I do have some special cases in my setup – specifically I’m using a wrapper field type on some ACF fields – but for me I was able to get around the problem by adding a filter on load_field
.
if ( $field['taxonomy'][0] == 'all' ){
unset( $field['taxonomy']);
}
I am still having what seems to be a related issue. If I select a custom post type and no taxonomy, it saves an array with a single element of “all” in the settings. When it then tries to load the related posts, it filters them based on a taxonomy of “all” which doesn’t exist and nothing is displayed.
I’m seeing this error with version 5.1.3 and a User select field. Trying to select a value just results in “loading…” and the above Javascript error.
@sheikadv – thanks, but I think we should cut Elliot some slack too, I’m sure he is pretty busy and this is somewhat of an edge case.
That said, it affects a lot of the fields I use (given that I am using Regex and PHP code a lot) and I ended up having to make even more changes for my Validated Field plugin. The changes are still in “beta” while I do more testing – but I could really use some help if you have time. The links to the beta version can be found here and should correct for importing and saving fields with a backslash. The extra fixes were to allow for Repeater fields, and escaping both single and double quotes in values.
Definitely backup your database first, but any feedback you can give me would be great – even if you don’t use the Validated Field part, it should still fix the backslash issue for all fields.
@busybrian I was having issues with backslashes in any field, it was breaking the serialized data saved to the post_content and then it was unable to load the field at all. I wrote it up in another post and included some code that fixed it for me – I wrote the sample as a standalone class but am including it in my Validated Field plugin (however currently only in the beta version), which should also be forwards compatible if it is fixed in ACF.
Unfortunately if you have already performed the database upgrade for ACF5 then any fields containing backslashes will have already been corrupted…
I added a more complete report here, sample code to fix the upgrade and save. Not sure what the proper way to address this in ACF is, however it is pretty serious as it loses the configuration for any field with a backslash anywhere in its serialized data….
@ucheng for ACF 5 you need to use the acf-validate_value
filter. I wrote a plugin called Validated Field that wraps other field types to provide server side validation, uniqueness queries, etc.
It has just been updated to support ACF 5, could use some help testing it if you want to give the latest beta version a try: https://wordpress.org/support/topic/validated-field-34-beta
Edit: ACF 5 Support and many new features available from https://wordpress.org/plugins/validated-field-for-acf/
I was also able to correct this using a filter to avoid changing the ACF code directly, the preg_match()
will only do the replace if there is a single \
in the content, not a double \\
:
add_filter( 'content_save_pre', function( $content ){
global $post;
if ( get_post_type() == 'acf-field-group' ){
if ( preg_match( '~(?<!\\\\)\\\\(?!\\\\)~', $content ) ){
$content = str_replace('\\', '\\\\', $content);
}
}
return $content;
});
I’m including this filter in my Validated Field plugin since backslashes are pretty common in regular expressions which is one of the validations types I am supporting.
I was able to fix this by changing api/api_field.php
on line 789 from:
$data = maybe_serialize( $data );
Once single slashes are replaced with double slashes (which then get escaped back to a single slash in the database post_content) it saves the proper serialized data and can be loaded correctly.
$data = maybe_serialize( $data );
$data = str_replace('\\', '\\\\', $data);
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.