Before update post to save value using save_post hook? - wordpress

Add new product to update product then set sku number permalinks before post title to set in permalinks. Product import then set sku number in permalinks before update product.
I tried the below code:
add_action('save_post', 'change_title');
function change_title($post_id) {
// unhook this function so it doesn't loop infinitely
remove_action('save_post', 'change_title');
$_sku = get_post_meta( $post_id, '_sku', true);
$args = array('ID'=>$post_id,'post_name'=>$_sku,);
// update the post, which calls save_post again
wp_update_post( $args );
// re-hook this function
add_action('save_post', 'change_title');
}

Try :
function change_title( $post_id ){
$_sku = get_post_meta( $post_id, '_sku', true);
global $wpdb;
$wpdb->update( $wpdb->posts, array( 'post_title' => $_sku ), array( 'ID' => $post_id ) );
}
add_action( 'save_post', 'change_title');

Try this
function update_product_link( $post_id, $post, $update ) {
if( $post->post_type != "product" ) {
return;
}
$_sku = get_post_meta( $post_id, '_sku', true);
//This will update post name to SKU
$post->post_name = $_sku;
}
add_action( 'save_post', 'update_product_link', 1, 3 );
Also set your product permalink base structure to /product/%postname%/

Related

Wordpress: saving a taxonomy based on the value of a different taxonomy

We're building a clothing store. The products that will be uploaded could have label sizes from various countries, and as such we have two size taxonomies: product_size and product_size_uk.
I'm trying to set the uk size based upon the international size at the point the product is saved/updated, and running a switch to set a variable to the id of the uk size taxonomy and using
wp_set_object_terms. But this isn't working:
add_action( 'save_post', 'save_uk_size' );
function save_uk_size( $post_id ) {
if ( $post->post_type == 'product' ) {
$post = get_post($post_id);
$terms = wp_get_post_terms( $post->ID, 'product_size', array( 'fields' => 'all' ) );
if ( $terms ) {
$prod_size_int = $terms[0]->slug;
}
switch ($prod_size_int) {
...
case "FR-36":
$prod_size_uk = 805;
break;
case "FR-38":
$prod_size_uk = 806;
break;
...
}
wp_set_object_terms($post_id, $prod_size_uk, 'product_size_uk');
}
}
Can anyone steer me in the right direction? Thanks!
First you need to install Advanced Custom Fields plugin
Then for taxonomy product_size we create Taxonomy field (product_size_uk).
Now in the pages of taxonomy product_size in admin panel there is a field where we can choose which product_size_uk corresponds to this taxonomy.
3.Then we have to choose product_size_uk matching for all sizes.
And then this code
add_action( 'save_post_product', 'product_save_new_term' );
function product_save_new_term($post_id) {
remove_action( 'save_post_product', 'product_save_new_term' );
$terms = wp_get_object_terms( $post_id, 'product_size' );
$term_id = $terms[0]->term_id;
if($term_id != "") {
$key_for_field = 'product_size_' . $term_id;
$product_size_uk_value = get_field( 'product_size_uk', $key_for_field );
wp_set_object_terms($post_id, $product_size_uk_value, 'product_size_uk');
clean_post_cache( $post_id );
} else {
wp_delete_object_term_relationships( $post_id, 'product_size_uk' );
}
add_action( 'save_post_product', 'product_save_new_term' );
}
Or, if you don't want to have controls for size matching in the admin panel and it's easier for you to write everything in the code.
add_action( 'save_post_product', 'product_save_new_term' );
function product_save_new_term($post_id) {
$data_array = array(
"product_size_term_id" => "product_size_uk_term_id",
"product_size_term_id2" => "product_size_uk_term_id2",
"product_size_term_id3" => "product_size_uk_term_id3",
);
remove_action( 'save_post_product', 'product_save_new_term' );
$terms = wp_get_object_terms( $post_id, 'product_size' );
$term_id = $terms[0]->term_id;
if($term_id != "") {
$product_size_uk_value = $data_array[$term_id];
if($product_size_uk_value !="") {
wp_set_object_terms($post_id, $product_size_uk_value, 'product_size_uk');
}
clean_post_cache( $post_id );
} else {
wp_delete_object_term_relationships( $post_id, 'product_size_uk' );
}
add_action( 'save_post_product', 'product_save_new_term' );
}

Woocommerce - Calculate Exta Fee Based on Amount of People

I've added in a function for a custom field on the product general options:
// Add Custom Field to Product under General
function create_extra_fee_field() {
$args = array(
'id' => 'park_fee',
'label' => __( 'Natl Park Entrance Fee', 'tranq-lsx-child' ),
'class' => 'tranq-custom-field',
'desc_tip' => true,
'description' => __( 'This sets the Fee that will be added to the car.', 'tranq-lsx-child' ),
);
woocommerce_wp_text_input( $args );
}
add_action( 'woocommerce_product_options_general_product_data', 'create_extra_fee_field' );
// Save Custom Field Data
function save_extra_fee_field( $post_id ) {
$product = wc_get_product( $post_id );
$title = isset( $_POST['park_fee'] ) ? $_POST['park_fee'] : '';
$product->update_meta_data( 'park_fee', sanitize_text_field( $title ) );
$product->save();
}
add_action( 'woocommerce_process_product_meta', 'save_extra_fee_field' );
I would like to add this as an extra fee to the Cart Totals which multiplied based on the amount of Person/People that were selected from the Woocommerce Bookings.
Something like this:
// Calculate Extra Fee Based on Amount of People.
add_action('woocommerce_cart_calculate_fees' , 'add_custom_fees');
function add_custom_fees( WC_Cart $cart ){
$park_fee = get_post_meta($item['product_id'] , 'park_fee', true);
foreach( $cart->get_cart() as $item ){
$fees += $item[ 'park_fee' ] * 14706;
}
if( $fees != 0 ){
$cart->add_fee( 'Park Fee', $fees);
}
}
How do I go about in achieving this? Any Links to a walkthrough would be greatly appreciated.
I've added this and it seems to work:
// Add Custom Field to Cart Totals
function woo_add_cart_fee() {
global $woocommerce;
foreach( WC()->cart->get_cart() as $cart_item ){
// Get the WC_Product object (instance)
$product = $cart_item['data'];
$product_id = $product->get_id(); // get the product ID
$custom_field_value = get_post_meta( $product->get_id(), 'park_fee', true );
$person = array_sum( $cart_item['booking']['_persons'] );
}
$additional_fee_name = "Natl Park Entrance Fee";
$extra_fee = $custom_field_value * $person;
$addedFee = false;
// first check to make sure it isn’t already there
foreach ( $woocommerce->cart->get_fees() as $_fee )
{
if ($_fee->id == sanitize_title($additional_fee_name) )
{
$_fee->amount = (float) esc_attr( $extra_fee );
}
}
if (!$addedFee)
{
$woocommerce->cart->add_fee( __($additional_fee_name, "woocommerce"),
$extra_fee, $additional_fee_taxable );
}
}
add_action( "woocommerce_before_calculate_totals", "woo_add_cart_fee" );

How to set a WordPress custom post type visibility to private after editing?

I created a custom post type with a plugin. A registered user can insert a new post from front-end and it is saved as draft. When I edit it in back-end I need it is saved with private visibility.
I found this snippet to set visibility by default:
public function force_dpa_request_private( $data , $postarr ) {
if( empty( $data['post_name'] ) && 'my-cpt' == $postarr['post_type'] )
$data[ 'post_status' ] = 'private';
return $data;
}
but it works only on first insert, when I edit it the visibility change to public...
You can hook to the save_post which is called after the post is created or updated.
<?php
add_action( 'save_post', 'callback_save_post', 10, 3);
function callback_save_post( $post_ID, $post, $update ){
if ( 'my-cpt' === get_post_type( $post_ID) && ! wp_is_post_revision( $post_ID ) ) {
// unhook this function so it doesn't loop infinitely
remove_action('save_post', 'callback_save_post', 10 );
// Make the post private if it is edited else make it draft.
if ( $update ) {
$postarr = array(
'ID' => $post_ID,
'post_status' => 'private'
);
} else {
$postarr = array(
'ID' => $post_ID,
'post_status' => 'draft'
);
}
// Update the post.
wp_update_post( $postarr );
// re-hook this function.
add_action( 'save_post', 'callback_save_post', 10, 3);
}
}
Reference:
https://developer.wordpress.org/reference/hooks/save_post/
https://codex.wordpress.org/Function_Reference/wp_update_post
Slight variation from your question, but you can still edit the post on creation, if you make all your post type private. Thus this works.
function force_type_private($post)
{
if ($post['post_type'] == 'Your Post Type')
$post['post_status'] = 'private';
return $post;
}
add_filter('wp_insert_post_data', 'force_type_private');

WordPress custom post type permalink as post ID (multiple CPTs)

I'm working on a site for a sports team with multiple age ranges. I've created two custom post types (teams and players) and want to link to each type of CPT via the post_id, rather than the post name informing the permalink.
I found some code online to adapt the permalink to the post_id, but despite passing the post_type to the function, which I thought would only adapt that cpt, it's adapting every cpt - so despite choosing to only change the team permalink, it's changing both the team and player permalinks to 'team/post_id'.
// Rewrite permalink structure
function teams_rewrite() {
global $wp_rewrite;
$queryarg = 'post_type=teams&p=';
$wp_rewrite->add_rewrite_tag( '%cpt_id%', '([^/]+)', $queryarg );
$wp_rewrite->add_permastruct( 'teams', '/teams/%cpt_id%/', false );
}
add_action( 'init', 'teams_rewrite' );
function teams_permalink( $post_link, $id = 0, $leavename ) {
global $wp_rewrite;
$post = &get_post( $id );
if ( is_wp_error( $post ) )
return $post;
$newlink = $wp_rewrite->get_extra_permastruct( 'teams' );
$newlink = str_replace( '%cpt_id%', $post->ID, $newlink );
$newlink = home_url( user_trailingslashit( $newlink ) );
return $newlink;
}
add_filter('post_type_link', 'teams_permalink', 1, 3);
Both CPTs have their own $arg in their setup:
'rewrite'=> array( 'with_front' => false, 'slug' => 'players' )
'rewrite'=> array( 'with_front' => false, 'slug' => 'teams' )
UPDATE
In addition, I've just discovered that this breaks all the permalinks, except the teams CPT that is listed.
function teams_permalink( $post_link, $id = 0, $leavename ) {
global $wp_rewrite;
$post = &get_post( $id );
if ( is_wp_error( $post ) || get_post_type($post) != 'teams')
return $post_link;
$newlink = $wp_rewrite->get_extra_permastruct( 'teams' );
$newlink = str_replace( '%cpt_id%', $post->ID, $newlink );
$newlink = home_url( user_trailingslashit( $newlink ) );
return $newlink;
}
add_filter('post_type_link', 'teams_permalink', 1, 3);
Can you try this? So here I added an extra check to make sure that the newlink is only updated for teams post_type.
Also you where returning $post which might cause some issues since functions which are using this filter will be expecting a string therefore we are now returning $post_link

Updating GEO my WP fields using frontend Advanced custom fields form - WordPress

I’ve created a frontend form using the advanced custom fields (ACF) plugin. Within this form I’ve added some location fields such as postcode and city.
Below is the function used to update the post
global $post_id;
add_filter('acf/pre_save_post' , 'tsm_do_pre_save_post' );
function tsm_do_pre_save_post( $post_id ) {
// Bail if not logged in or not able to post
if ( ! ( is_user_logged_in() ) ) {
return;
}
// check if this is to be a new post
if( $post_id != 'new_job' ) {
return $post_id;
}
$profile_id = um_profile_id();
$userID = 'user_'.$profile_id;
$user_id = get_current_user_id();
// Create a new post
$post = array(
'ID'=> $post_id,
'post_type' => 'members',
'post_status' => 'publish',
'post_title' => $userID,
'post_author' => $user_id,
'category' => $_POST['acf']['field_594d0ffc2a66d'],
);
// insert the post
$post_id = wp_insert_post( $post );
// Save the fields to the post
do_action( 'acf/save_post' , $post_id );
return $post_id;
exit;
}
Once this form has been submitted, the custom post type is updated with no issues.
How can I add the submitted location data (postcode, city etc) into the GEO MY WP information for the post?
I’ve tried to follow the information in the docs secetion (http://docs.geomywp.com/gmw_pt_update_location/) but not having much luck.
GEO my WP function fron docs below:
function gmw_update_post_type_post_location( $post_id ) {
// Return if it's a post revision
if ( false !== wp_is_post_revision( $post_id ) )
return;
// check autosave //
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
//check if user can edit post
if ( !current_user_can( 'edit_post', $post_id ) )
return;
//get the address from the custom field "address"
$address = get_post_meta( $post_id, 'address', true );
//varify that address exists. Otherwise abort the function.
if ( empty( $address ) )
return;
//include the update location file file
include_once( GMW_PT_PATH .'/includes/gmw-pt-update-location.php' );
//make sure the file included and the function exists
if ( !function_exists( 'gmw_pt_update_location' ) )
return;
//Create the array that will pass to the function
$args = array(
'post_id' => $post_id, //Post Id of the post
'address' => $address // the address we pull from the custom field above
);
//run the udpate location function
gmw_pt_update_location( $args );
}
//execute the function whenever post type is being updated
add_action( 'save_post_post', 'gmw_update_post_type_post_location' );
I believe I need to somehow combine the two functions so when the ACF form is updated, it also needs to update the GEO my wp meta data also.
I've tried combining the two functions but not having much luck.
If someone can point me in the right direction it will be very much appreciated
Thanks
Updated code.....
I've tried to add the gmw_update_post_type_post_location() function within the ACF function (code below) but still not having much luck...
global $post_id;
add_filter('acf/pre_save_post' , 'tsm_do_pre_save_post' );
function tsm_do_pre_save_post( $post_id ) {
// Bail if not logged in or not able to post
if ( ! ( is_user_logged_in() ) ) {
return;
}
// check if this is to be a new post
if( $post_id != 'new_job' ) {
return $post_id;
}
$profile_id = um_profile_id();
$userID = 'user_'.$profile_id;
$user_id = get_current_user_id();
$profilePostcode = get_post_meta( $post_id, 'location_postcode', true );
// Create a new post
$post = array(
'ID'=> $post_id,
'post_type' => 'members', // Your post type ( post, page, custom post type )
'post_status' => 'publish', // You can use -> publish, draft, private, etc.
'post_title' => $userID, // Post Title ACF field key
'post_author' => $user_id,
'category' => $_POST['acf']['field_594d0ffc2a66d'], // Post Content ACF field key
);
// insert the post
$post_id = wp_insert_post( $post );
// Save the fields to the post
do_action( 'acf/save_post' , $post_id );
gmw_update_post_type_members_location($post_id);
return $post_id;
exit;
}
function gmw_update_post_type_members_location( $post_id ) {
$profilePostcode = get_post_meta( $post_id, 'profile_location_postcode', true );
if ( empty( $profilePostcode ) )
return;
$address = array(
//'street' => $_POST['location_address'],
//'city' => $_POST['location_town'],
//'state' => $_POST['location_state'],
'zipcode' => $profilePostcode,
//'country' => $_POST['location_country']
);
include_once( GMW_PT_PATH .'/includes/gmw-pt-update-location.php' );
if ( !function_exists( 'gmw_pt_update_location' ) )
return;
$profile_id = um_profile_id();
$userID = 'user_'.$profile_id;
$user_id = get_current_user_id();
$args = array(
'post_id' => $post_id, //Post Id of the post
'post_title' => $userID, // Post Title ACF field key
'post_author' => $user_id,
'post_type' => 'members',
'address' => $address
);
//run the udpate location function
gmw_pt_update_location( $args );
}

Resources