I’ve read the ACF ‘acf/save_post’ documentation here: https://www.advancedcustomfields.com/resources/acf-save_post/, which states this action enables one to add additional functionally before or after saving/updating a post. I want to test when this action is triggered.
I created a custom post type and a collection of ACF custom fields that are linked to this custom post type. This includes some ACF custom field types that I created using the ACF Starter Kit, and they are used for some of the ACF custom fields. When I edit a custom post and then click the ‘Update’ button in the Gutenberg editor, I expect the ‘acf/save_post’ action to fire, but it does not seem to do so. Perhaps I am missing something. Here is the relevant code from my theme’s ‘function.php’ file.
function my_acf_save_post($post_id) {
console_log("Testing...");
}
add_action('acf/save_post', 'my_acf_save_post', 20);
function console_log($output, $with_script_tags = true) {
$js_code = 'console.log(' . json_encode($output, JSON_HEX_TAG) . ')';
if($with_script_tags) {
$js_code = '<script>' . $js_code . '</script>';
}
echo $js_code;
}
Citation for the ‘console_log’ function: Kim Sia (see: https://stackify.com/how-to-log-to-console-in-php/).
I have my web browser’s inspector window opened for my custom post type post’s editor. After modifying the post and clicking ‘Update’, nothing displays in the inspector’s console pane. I posted about this in the ACF forum but have received no response.
Your feedback is appreciated. Thank you.
Hi there,
I want to update the $_POST[‘acf’]-Array with specific values for some field_keys. I use ACF with another plugin called “Event Organiser” which register the custom-post-type “event”. I have several ACF-Fields
When the user creates or edits an event my function should update the field for the thumbnails referring to the chosen district. Also it should update the fields for deleted and postponed.
I’ve two custom functions to get the choices of the select field “districts” and to get the field_keys for the thumbnail-fields for the different districts and the fields for deleted and postponed.
Here my code:
function update_image_fields( $post_id ){
$post_type = get_post_type( $post_id );
if (isset ($_POST['acf']['field_5ecf8ef280a84'])){
$new_district = strtolower($_POST['acf']['field_5ecf8ef280a84']);
} else {
$new_district = "bayreuth";
}
$image_urls = array (
'bamberg' => wp_get_attachment_image_url(244),
'bayreuth' => wp_get_attachment_image_url(244),
'coburg' => wp_get_attachment_image_url(244),
'forchheim' => wp_get_attachment_image_url(244),
'hof' => wp_get_attachment_image_url(244),
'kronach' => wp_get_attachment_image_url(244),
'kulmbach' => wp_get_attachment_image_url(244),
'lichtenfels' => wp_get_attachment_image_url(244),
'wunsiedel' => wp_get_attachment_image_url(244),
'postponed' => wp_get_attachment_image_url(476),
'deleted' => wp_get_attachment_image_url(481),
);
$acf_thumbs = get_district_choices ( );
array_push ($acf_thumbs, "deleted", "postponed");
if ('event' == $post_type){
//update all thumbnail_fields
$test_meta_key = "_thumbnail_" . $new_district;
$test = acf_get_all_field_key ( $test_meta_key, $post_id );
foreach ($acf_thumbs as $acf_thumb) {
$meta_key = "_thumbnail_" . $acf_thumb;
// if there is a new event
if (false === $test) {
$args = array (
'numberposts' => 1,
'post_type' => 'event',
'post_status' => 'publish',
'fields' => 'ids',
);
$new_post_id = get_posts($args)[0];
$field_keys[$acf_thumb] = acf_get_all_field_key ( $meta_key, $post_id = $new_post_id );
}
// for an update of an event
else {
$field_keys[$acf_thumb] = acf_get_all_field_key ( $meta_key, $post_id );
}
}
foreach ($field_keys as $field_key => $field_value) {
switch ($field_key) {
case "deleted" :
$fk_deleted = $field_keys['deleted'];
$_POST['acf']["$fk_deleted"] = $image_urls['deleted'];
break;
case "postponed" :
$fk_postponed = $field_keys['postponed'];
$_POST['acf']["$fk_postponed"] = $image_urls['postponed'];
break;
case $new_district :
$fk_new_district = $field_keys["$new_district"];
$_POST['acf']["$fk_new_district"] = $image_urls["$new_district"];
break;
default :
$fk_others = $field_keys["$field_key"];
$_POST['acf']["$fk_others"] = "";
break;
}
}
}
}
add_action( 'acf/save_post', 'update_image_fields', 5);
For updating an event, it do what it should. But when I am creating a new event nothing is updating. I think it’s overwritten by any build-in-function or by ACF when WordPress creates a new post. Can you please give me hint what I’m doing incorrect or what I can do otherwise? Is “acf/save_post” the correct action to hook for a new post/ event?
Thank you and all the best!
Hello,
I have a relationship field with a group and several post types, all of which share this same field. By using the below example, I was able to add bidirectional relations to saving the post.
https://www.advancedcustomfields.com/resources/bidirectional-relationships/
However, a large portion of the posts will be imported, and thought the import plugin creates the relation between Post A and Post B, to create the association between Post B and Post A, I would have to go to either and “save” the post.
To avoid this task, I would like to create a custom bulk action that will use the same ACF example but in a bulk manner.
Bellow is the skeleton code. Can you please advise if this is possible? All my attempts in doing so have failed. The update_field always returns true, but no update occurs.
add_filter( 'bulk_actions-edit-people', 'custom_rel_update_bulk_action' );
function custom_rel_update_bulk_action( $bulk_array ) {
$bulk_array['bulk_update_rels'] = 'Update Relationships';
return $bulk_array;
}
add_filter( 'handle_bulk_actions-edit-people', 'custom_rel_update_bulk_action_handler', 10, 3 );
function custom_rel_update_bulk_action_handler( $redirect, $doaction, $object_ids ) {
// let's remove query args first
$redirect = remove_query_arg( array( 'bulk_update_rels_done' ), $redirect );
// do something for "Make Draft" bulk action
if ( $doaction == 'bulk_update_rels' ) {
foreach ( $object_ids as $post_id ) {
//https://www.advancedcustomfields.com/resources/bidirectional-relationships/
}
// do not forget to add query args to URL because we will show notices later
$redirect = add_query_arg(
'bulk_update_rels_done', // just a parameter for URL (we will use $_GET['bulk_update_rels_done'] )
count( $object_ids ), // parameter value - how much posts have been affected
$redirect );
}
return $redirect;
}
add_action( 'admin_notices', 'bulk_update_rels_notices' );
function bulk_update_rels_notices() {
// first of all we have to make a message,
// of course it could be just "Posts updated." like this:
if ( ! empty( $_REQUEST['bulk_update_rels_done'] ) ) {
echo '<div id="message" class="updated notice is-dismissible">
<p>Posts updated.</p>
</div>';
}
}
Advanced Custom Fields PRO 5.9.1
Thank you very much
Hello,
I created a front-end form that allows a user to enter data to create a new flight log entry. I’m using AJAX to create the post. While the post is created and shows the title and content, I can’t get the data to save to the Advanced Custom Fields. I’ve registered the field groups and I’m using the field keys with update_field(). I’m not certain what I’m overlooking. Any help would be greatly appreciated.
createLogEntry(e){
var departure_field = $(“.new-flight-departure”).val();
var arrival_field = $(“.new-flight-arrival”).val();
var title = (date + ‘ ‘ + departure_field + ‘ ‘ + arrival_field);
var content = $(“.new-flight-text”).val();
$.ajax({
beforeSend: (xhr) => {
xhr.setRequestHeader(‘X-WP-NONCE’, flightData.nonce);
},
url: flightData.root_url + ‘/wp-json/wp/v2/flight/’,
type: ‘POST’,
data: {
action: ‘submit_log_entry’,
title: title,
departure_field: departure_field, //Advanced Custom Field
arrival_field: arrival_field, //Advanced Custom Field
content: content
},
success: (response) => {
console.log(“Congrats”);
console.log(response);
alert(‘Post has been saved.’);
},
error: (response) => {
console.log(“Sorry”);
console.log(response);
}
});
}
function submit_log_entry() {
$title = $_POST[‘title’];
$content = $_POST[‘content’];
$departure = $_POST[‘departure_field’];
$arrival = $_POST[‘arrival-field’];
$post_data = array(
‘post_title’ => $title,
‘post_content’ => $content,
‘post_type’ => ‘post’,
‘post_status’ => ‘publish’
);
$post_id = wp_insert_post($post_data);
//Update departure field
$field_key = ‘field_5ecb28b30812a’;
update_field($field_key, $departure ,$post_id);
//Update arrival field
$field_key = ‘field_5ecc33eb92cf4’;
update_field($field_key, $arrival ,$post_id);
die();
}
add_action( ‘wp_ajax_nopriv_submit_log_entry’, ‘submit_log_entry’ );
add_action( ‘wp_ajax_submit_log_entry’,’submit_log_entry’ );
I have been trying to Googling around and I can’t really find any answers for this.
I am creating a simple LMS project. The idea is that there will be many users. Each user has their own user ID which is generated from the WP.
Each user will have one or many courses displayed on the website, and on the website, the user can click on the checkboxes to mark which of the course lecture they have finished.
The problem is that right now the checkboxes are “global state”. That means every user can mark the checkbox and it’s not private anymore, or rather marked specifically for the user who attended the course lecture.
I have managed to create my own WP Customized REST API, but I have a problem with how to use the update_sub_field() in context to update for a specific user ID.
I am using the repeater Field type with checkboxes.
Here is my code:
add_action('rest_api_init', 's68_course_api');
function s68_course_api() {
register_rest_route('s68/v1', 'course/(?P<id>\d+)', [
[
'methods' => WP_REST_Server::EDITABLE,
'callback' => 's68_update_course'
]
]);
}
function s68_update_course($data) {
$subfield_whitelist = ['academy_course_progress_button'];
$post_id = sanitize_text_field( $data['id' ] );
if( $data['course_content'] ) {
$row_index = intval( $data['course_content']['row_index'] );
$sub_field = sanitize_text_field( $data['course_content']['sub_field'] );
$new_value = $data['course_content']['value'];
// If intval() returned 0, then $data['course_content']['row_index'] was not a number.
// It's alright to check this way because ACF row indexes start at 1 instead of 0 - so 0 is
// never a valid row number.
if( $row_index === 0 ) {
return [
'success' => false,
'message' => 'Invalid row number'
];
}
// Don't let malicious users change subfields they're not allowed to
if( !in_array( $sub_field, $subfield_whitelist ) ) {
return [
'success' => false,
'message' => 'Invalid sub field'
];
}
$success = update_sub_field(
[ 'academy_course_content', $row_index, $sub_field ],
$new_value,
$post_id,
);
update_user_meta('user_' . 1, '', $success);
return [
'success' => $success
];
}
return [
'success' => false,
'message' => 'Unknown update request'
];
}
I am not sure what I am missing here.
How do I achieve this?
Much appreciate if someone could please help me out
I’m trying to migrate some custom WYSIWYG fields from the Custom Field Suite plugin into ACF. I’ve generated some new WYSIWYG ACF fields with the same name as the CFS fields.
All of information seems to appear in both CFS and ACF fields ok, but when I view the ACF content on the front of the site, the content is not rendered with any html, and the shortcodes don’t work.
I’ve managed to get the shortcodes to work using
echo do_shortcode($extra_product);
…but the text content is just displaying as unstyled content (no html).
If I open and resave any of the pages, then the problem is solved, but I really don’t want to go through hundreds of pages resaving them – does anyone know of a way to somehow refresh this field content, and resave multiple pages all in one go?
Any ideas much appreciated.
Many thanks
Can someone explain to me what might be happening? Or maybe I’m just misunderstanding the documentation for the Taxonomy field. I’m seeing two issues, one with the “Save Terms” option and the other with “Load Terms”. For context, I have a repeater field with one of the subfields as a taxonomy field set to use the default post tags taxonomy.
When I set the “Save Terms” to true with the intention to make it so whatever tag they set here is also assigned to the post in the sidebar, making it dummy-proof for my editors in case they forget to also assign the tag to the post. But doing so while editing a post wipes out all other tags upon saving and makes it so that the tag assigned in this ACF subfield is the _only_ tag assigned to the post. Obviously this is not what I want, and I just set it to false and hope that my editors remember to assign the same tag they selected in ACF to the actual post.
As an alternative to the first issue, my second issue is when I set “Load Terms” to true with the idea that _only_ the tags assigned to the post will appear in the drop down, so it forces the editors to assign it first and then use the ACF. However, all tags appear in the drop-down, regardless if any tags are assigned to the post. Even worse, if I have two tags assigned to my post and I use field to point to the second one, after saving, it forcefully points to the first tag. Once again, I set this ACF configuration to false so it at least behaves normally but now I can’t really dummy-proof it for my editors in any capacity.
Is this the intended behavior of “Save Terms” and “Load Terms” or is something going on? Thanks in advance!
The issue I am having is straightforward an, hopefully, I am just overlooking something here. I have a custom field called, “XYZ”. The location rules are set to show the custom field grouping if the page template is equal to “ABC template” or “DEF template” or GHI template” or “TESTPAGE_A” page. Note: the last criteria here is a page, not a page template.
When I go to the edit screen for “TESTPAGE_A”, I can see the grouping for the custom field, “XYZ” an can edit, make changes and save. However, when I open the page after saving changes (using Incognito mode in Chrome to avoid caching) the custom field does not display. NOTE: The custom field will display if I go back to edit the TESTPAGE_A page, select one of the aforementioned page templates (ABC, DEF, GHI) for the page and save it.
I am using version 5.8.13 of ACF, PHP 7.3
Hello,
I have two content blocks (A and B) on my front page which I want to fill with post teasers. Each block has 6 positions, A1-A6 and B1-B6.
I created custom select field containing options with the values A1-B6 and an option with „X0 – not on front page“ which is the standard value.
Then I created two WP_Queries, one for each Block:
$args_a = array(
'numberposts' => 6,
'post_type' => 'post',
'meta_key' => 'position',
'meta_value' => '^A',
'meta_compare' => 'REGEXP',
'order_by' => 'meta_key',
'order' => 'ASC'
);
$args_b = array(
'numberposts' => 6,
'post_type' => 'post',
'meta_key' => 'position',
'meta_value' => '^B',
'meta_compare' => 'REGEXP',
'order_by' => 'meta_key',
'order' => 'ASC'
);
And put them in two different loops, like it’s shown in the documentation. So far, everything works fine, when I change the position from A to B, the teaser appears in the other box.
Then I decided to try if the position changes could be automated somehow. I created another custom select field with the same options and named it „position_new“ and one datetime field named it „switchtime“. The switchtime is in the future and when it is reached, the field position should be updated with the value from position_new and after that the values of the fields switchtime and position_new have to be deleted.
First I created another WP_Query which gets all posts that are scheduled:
// Get Scheduled Posts
$scheduled = array(
'numberposts' => -1,
'post_type' => 'post',
'order' => 'ASC',
'order_by' => 'meta_value',
'meta_key' => 'switchtime',
'meta_type' => 'DATETIME'
);
Here is the first problem, there are all posts inside the loop, including the posts, where the field switchtime is empty. Deleting meta_key and meta_type from the args does not have an effect.
And then I wrote inside the loop (the first part of the if statement is there to get rid of empty values):
if ( ( get_field("switchtime") != "" ) && ( current_time('Y-m-d H:i:s') > get_field("switchtime") ) ) {
$postid = get_the_ID();
$newpos = get_field("position_new");
update_field('position', $newpos, $postid);
delete_field('switchtime');
delete_field('position_new');
// wp_insert_post( array('ID' => $postid) );
}
At first sight, it seems to work, the field position is updated and the other two fields are deleted on switchtime, but my teaser which I moved from A to B still appears in content block A. I displayed the field value in the frontend and it clearly says B, but the WP_Query from A fetches it anyway. I have to edit the post in the backend simply by saving it without changing anything and after that the teaser appears in B.
Therefore I wondered if that last line in the if statement which should save the post would solve the problem, but no.
Do you know what to do?
Cheers,
Pierre