I've several custom image fields (ACF) from an old configuration, and would like to move those images in the Product Gallery (Woocommerce), now I've converted all the datas into a Product post type.
I tried to set this function (found in a similar post), but nothing happens, and no errors returned neither :
function upload_all_images_to_product($product_id, $image_id_array) {
//define the array with custom fields images
$image_1 = get_field('images'); // should returns image IDs
$image_2 = get_field('images-2');
$image_3 = get_field('images-3');
$image_4 = get_field('images-4');
$image_5 = get_field('images-5');
$image_6 = get_field('images-6');
$image_id_array = array($image_1, $image_2, $image_3, $image_4, $image_5, $image_6);
//take the first image in the array and set that as the featured image
set_post_thumbnail($product_id, $image_id_array[0]);
//if there is more than 1 image - add the rest to product gallery
if(sizeof($image_id_array) > 1) {
array_shift($image_id_array); //removes first item of the array (because it's been set as the featured image already)
update_post_meta($product_id, '_product_image_gallery', implode(',',$image_id_array)); //set the images id's left over after the array shift as the gallery images
}
}
Could someone help or explain me what's wrong ?
Depending on where you run this function, you should define the $product_id argument in ACF get_field() function.
Questions to clarify: How do you run this function? are you using a hook?
Update: Hooked the function in woocommerce_process_product_meta, so when a product is created or updated, it will trigger the code.
Also your code can be simplified, optimized and compacted as follow:
add_action( 'woocommerce_process_product_meta', 'save_my_custom_settings' );
function upload_all_images_to_product( $product_id, $image_ids = array(); ) {
// Loop from 1 to 6
for ( $i = 1; $i <= 6; $i++ ) {
$field_key = 'images'.( $i == 1 ? '' : '-'.$i );
// Check that the custom field exists
if( $field_value = get_field( $field_key, $product_id ) )
$image_ids[] = $field_value; // Set each ACF field value in the array
}
if( ! empty($image_ids) ) {
// Take the first image (removing it from the array) and set it as the featured image
set_post_thumbnail( $product_id, array_shift($image_ids) );
}
if( ! empty($image_ids) ) {
// Set the remaining array images ids as a coma separated string for gallery images
update_post_meta( $product_id, '_product_image_gallery', implode(',', $image_ids) );
}
}
Code goes in functions.php file of your active child theme (or active theme). untested it could work.
Related
I edited my theme to allow me saving some extra data on wp_options table, to my tags using this code:
add_action ( 'edit_term', 'save_termmeta_tag');
// save extra category extra fields callback function
function save_termmeta_tag( $term_id ) {
if ( isset( $_POST['Tag_meta'] ) ) {
$t_id = $term_id;
$tag_meta = get_option( "tag_$t_id");
$tag_keys = array_keys($_POST['Tag_meta']);
foreach ($tag_keys as $key){
if (isset($_POST['Tag_meta'][$key])){
$tag_meta[$key] = $_POST['Tag_meta'][$key];
}
}
//save the option array
update_option( "tag_$t_id", $tag_meta );
}
}
Each group of these options is saved under the option name tag_(tag ID here)
Now I need to get all the tags with the option $tag_meta['what_is_this'] »» (product).
How can I query with this?
I would like to populate WPGRIDBUILDER grid from ACF Gallery field.
Support told me:
Grids only work with WOrdPress content type: (custom) post types, (custom) taxonomy terms and WordPress users.
So, what you are looking for requires to use custom PHP code in order to populate a grid from ACF field.
And the field must hold image IDs uploaded in WordPress media library.
Here are two snippets which I assume can be the answer. I'm totally newbie in PHP.
https://docs.wpgridbuilder.com/resources/filter-grid-query-args/
function prefix_query_args( $query_args, $grid_id ) {
if ( 1 === $grid_id ) {
$query_args['post__not_in'] = [ 1, 2, 3, 4 ];
}
return $query_args;
}
add_filter( 'wp_grid_builder/grid/query_args', 'prefix_query_args', 10, 2 );
https://support.advancedcustomfields.com/forums/topic/gallery-field-return-images-ids/
$images = get_field('gallery_field'); //gallery field
foreach( $images as $img ):
$img_srcset = wp_get_attachment_image_srcset($img['ID']); // return Image ID for each in gallery
Here is my take on it:
function prefix_query_args( $query_args, $grid_id ) {
if ( 2 === $grid_id ) { //mygrid id
$query_args['post_type'] = [ 'realizacje-cpt' ];//my cpt
$images = get_field('gallery-cf'); //gallery field
foreach( $images as $img )
$img_srcset = wp_get_attachment_image_srcset($img['ID']);
}
return $query_args,$images;
}
add_filter( 'wp_grid_builder/grid/query_args', 'prefix_query_args', 10, 2 );
Em I even going in right direction?
So, here is the woocommerce setting that I have.
I have a few categores, let’s call them A, B, C, D, E… and so on.
From the backend, I gave category images to each categories.
Now, let’s say I post a product in the category A without selecting any images.
The product just shows the woocommerce default image (the one with the grey background).
Is there a way to use the category images as the default product image when there is no image selected?
I have tried a few codes, this is the last one I have:
add_action( 'init', 'custom_fix_thumbnail');
function custom_fix_thumbnail(){
add_filter('wc_placeholder_img_src', 'custom_woocommerce_placeholder_img_src');
function custom_woocommerce_placeholder_img_src( $src ) {
if (is_shop() || is_singular('product') || is_archive() || is_checkout() || is_cart()) {
global $post;
$array = get_the_terms($post->ID, 'product_cat');
reset($array);
$first_key = key($array);
$thumbnail_id = get_woocommerce_term_meta($first_key, 'thumbnail_id', true);
// get the image URL for parent category
$image = wp_get_attachment_url($thumbnail_id);
// print the IMG HTML for parent category
if ($image)
$src = $image;
}
return $src;
}
}
Try changing hook to woocommerce_placeholder_img_src. wc_placeholder_img_src seems to be deprecated.
For the purpose of a product image flipper, I want to display the second image from the variation images for each product.
I'm using the WooCommerce Additional Variation Images plugin and I don't know how to get that image.
I tried this
$product->wp_get_attachment_image_src( $id )
but it returns the following : Call to undefined method WC_Product_Variation::wp_get_attachment_image_src() in...
Anyone who is familiar with this plugin could help me ? If you need more information let me know.
Thanks !
You can get the additional variation images IDs and use these IDs to get the image src like this:
$attachment_ids = get_post_meta( key($values), '_wc_additional_variation_images', true );
$variation_images_src = array();
if ( $attachment_ids ) {
foreach ( $attachment_ids as $attachment_id ) {
$variation_images_src[] = wp_get_attachment_image_src($attachment_id)
}
}
You can get all images for all product variations by this code:
$variations = $product->get_available_variations();
foreach ( $variations as $variation ) {
echo $variation['image_src'];
}
Basically I have a custom post type setup called "Parts" with over 5,000 posts currently in it. There are a number of custom fields associated with each part, including a "part number". Currently, the URL for each part is:
http://site.com/parts/name-of-part/
What I would rather have is:
http://site.com/parts/XXXX-608-AB/ (That's a part number, stored as a custom field "partno".)
I believe I need to do two things:
1) Make a script to bulk edit all the slugs for each existing part, based on the custom field "partno".
2) Hook into a Wordpress function to trigger it to always create the slug for new parts based on the custom field "partno".
Does anyone have any knowledge on how to accomplish one or both of these aspects?
UPDATE: Below is the code I ended up using for changing existing posts
// Set max posts per query
$max = 500;
$total = 5000;
for($i=0;$i<=$total;$i+=$max) {
$parts = get_posts(array('post_type' => 'parts', 'numberposts' => $max, 'offset' => $i));
// loop through every part
foreach ( $parts as $part ) {
// get part number
$partno = get_post_meta( $part->ID, 'partno', true );
$updated_post = array();
$updated_post['ID'] = $part->ID;
$updated_post['post_name'] = $partno;
wp_update_post( $updated_post ); // update existing posts
echo $part->ID;
}
}
UPDATE: Below is the code I used in functions.php to change ongoing posts
(thanks in part to https://wordpress.stackexchange.com/questions/51363/how-to-avoid-infinite-loop-in-save-post-callback)
add_action('save_post', 'my_custom_slug');
function my_custom_slug($post_id) {
//Check it's not an auto save routine
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
return;
//Perform permission checks! For example:
if ( !current_user_can('edit_post', $post_id) )
return;
//If calling wp_update_post, unhook this function so it doesn't loop infinitely
remove_action('save_post', 'my_custom_slug');
//call wp_update_post update, which calls save_post again. E.g:
if($partno != '')
wp_update_post(array('ID' => $post_id, 'post_name' =>get_post_meta($post_id,'partno',true)));
// re-hook this function
add_action('save_post', 'my_custom_slug');
}
1) Create a new page and assign a new page template to it, lets say site.com/update and update.php. Inside of update.php write you bulk mechanism:
<?php // grab all your posts
$parts = get_posts(array('post_type' => 'parts', 'numberposts' => -1,))
// loop through every part
foreach ( $parts as $part ) {
// get part number
$partno = get_post_meta( $part->ID, 'parto', true );
$updated_post = array();
$updated_post['ID'] = $part->ID;
$updated_post['post_name'] = $partno;
wp_update_post( $updated_post ); // update existing posts
} ?>
You could place this anywhere in your theme but I like to create a page for that so I can easily run a cron job with it.
Next the function to change the slug of every newly created post:
<?php function change_default_slug($id) {
// get part number
$partno = get_post_meta( $id, 'parto', true );
$post_to_update = get_post( $id );
// prevent empty slug, running at every post_type and infinite loop
if ( $partno == '' || $post_to_update['post_type'] != 'parts' || $post_to_update['post_name'] == $partno )
return;
$updated_post = array();
$updated_post['ID'] = $id;
$updated_post['post_name'] = $partno;
wp_update_post( $updated_post ); // update newly created post
}
add_action('save_post', 'change_default_slug'); ?>
The code above runs every time a post gets saved (e.g. when published for the first time) and sets a new post_name to the part no.