In WooCommerce, I would like:
This is the code that I have:
add_action('save_post_product', 'auto_link_cross_sells', 20, 2);
function auto_link_cross_sells($post_id, $post) {
// Prevent infinite loop using a transient
if (get_transient('auto_cross_sell_processing')) {
return;
}
// Get the current product's cross-sell IDs
$cross_sell_ids = get_post_meta($post_id, '_crosssell_ids', true);
// If there are no cross-sell IDs, exit the function
if (empty($cross_sell_ids) || !is_array($cross_sell_ids)) {
return;
}
// Set a transient to prevent an infinite loop
set_transient('auto_cross_sell_processing', true, 10);
// Loop through each cross-sell product ID
foreach ($cross_sell_ids as $cross_sell_id) {
// Check if the cross-sell product ID is valid
if (!get_post($cross_sell_id)) {
continue;
}
// Get the existing cross-sell IDs for the cross-sell product
$existing_cross_sells = get_post_meta($cross_sell_id, '_crosssell_ids', true);
if (!is_array($existing_cross_sells)) {
$existing_cross_sells = [];
}
// If the current product is not already a cross-sell of the cross-sell product, add it
if (!in_array($post_id, $existing_cross_sells)) {
$existing_cross_sells[] = $post_id;
update_post_meta($cross_sell_id, '_crosssell_ids', $existing_cross_sells);
}
}
// Remove the transient to allow the function to run again later
delete_transient('auto_cross_sell_processing');
}
But it still doesn't do the job.
There are some missing things in your code, as what you are trying to do is more complicated than you thought.
Also, since WooCommerce 3, you should better use WC_Product
available methods than WordPress Post Meta functions, as WooCommerce uses custom database tables.
Here we need to use a custom field to keep track of previous history, allowing to process removed Cross-Sell IDS.
Try the following code instead, that should process and interlink cross-sells between products:
add_action( 'woocommerce_process_product_meta', 'process_interlinked_product_cross_sells', 100 );
function process_interlinked_product_cross_sells( $post_id ) {
// Get current WC_Product object
$product = wc_get_product( $post_id );
// Get the current product cross-sell IDs
$cross_sell_ids = (array) $product->get_cross_sell_ids();
// Get current product cross-sell IDs previous history track
$previous_cs_ids = (array) $product->get_meta('_previous_cs_ids');
// Check differences related to history
$differences_add = array_diff($cross_sell_ids, $previous_cs_ids);
$differences_remove = array_diff($previous_cs_ids, $cross_sell_ids);
// Added IDS case
if ( count($differences_add) > 0 ) {
// Loop through product cross-sell IDs (added)
foreach ( $differences_add as $cross_sell_id ) {
// get the WC_Product object from current cross sell ID
$_product = wc_get_product( $cross_sell_id );
if ( ! $_product ) continue;
// Get cross-sell IDs for the cross-sell product
$_cross_sell_ids = (array) $_product->get_cross_sell_ids();
if ( ! in_array( $post_id, $_cross_sell_ids ) ) {
$_cross_sell_ids[] = $post_id; // Add the initial current product Id to the array
$_product->set_cross_sell_ids( $_cross_sell_ids ); // Set updated cross-sells Ids
$_product->update_meta_data( '_previous_cs_ids', $_cross_sell_ids ?: '' ); // Update history
$_product->save(); // Sync and save
}
}
}
// Removed IDS case
if ( count($differences_remove) > 0 ) {
// Loop through product cross-sell IDs (removed)
foreach ( $differences_remove as $key => $cross_sell_id ) {
// get the WC_Product object from current cross sell ID
$_product = wc_get_product( $cross_sell_id );
if ( ! $_product ) continue;
// Get cross-sell IDs for the cross-sell product
$_cross_sell_ids = (array) $_product->get_cross_sell_ids();
if ( in_array( $post_id, $_cross_sell_ids ) ) {
// Remove the initial current product Id from the array
unset($_cross_sell_ids[$key]);
$_product->set_cross_sell_ids( $_cross_sell_ids ); // Set updated cross-sells Ids
$_product->update_meta_data( '_previous_cs_ids', $_cross_sell_ids ?: '' ); // Update history track
$_product->save(); // Sync and save
}
}
}
// Update current product history track
if ( count($differences_add) > 0 || count($differences_remove) > 0 ) {
$product->update_meta_data( '_previous_cs_ids', $cross_sell_ids ?: '' ); // Update history track
$product->save();// Sync and save
}
}
Tested and works.