Skip to content

Instantly share code, notes, and snippets.

@birgire
Last active March 4, 2024 10:09
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save birgire/0ed300ae4436fcaf508c to your computer and use it in GitHub Desktop.
Save birgire/0ed300ae4436fcaf508c to your computer and use it in GitHub Desktop.
WordPress: WooCommerce Product Attributes - Bulk Modifier ( from custom meta attributes to taxonomy attributes)
<?php
/**
* Plugin Name: WooPAM: Woo Product Attributes Modifier
* Description: Bulk update 'custom meta product attributes' to 'taxonomy product attributes' in WooCommerce. Supports the GET variables, like: woopam_mode=run&woopam_from_attribute_meta=colour&woopam_to_attribute_tax=pa_colour&woopam_keep_attribute_meta&woopam_posts_per_page=10&woopam_paged=0&woopam_post_type=product&woopam_post_status=any. WARNING: Backup DB first!!!
* Plugin Author: birgire
* Author URI: https://github.com/birgire
* Plugin URI: https://gist.github.com/birgire/0ed300ae4436fcaf508c
* Version: 1.0.0
* License: GPL2+
* Text Domain: woopam
* Requires PHP: 5.4
*/
/*
*---------
* Support:
*---------
* If this helped your project and saved you some time, you can support the developement here:
*
* https://www.buymeacoffee.com/birgire
*
* Thanks.
*
*---------------
* Usage Example:
*---------------
*
* To change all custom product meta attributes "color" to "pa_color" products taxonomy (where pa_ is a WooCommerce auto-added prefix), we can run:
*
* https://example.com/?woopam_mode=run&woopam_from_attribute_meta=color&woopam_to_attribute_tax=pa_color&woopam_keep_attribute_meta=1&woopam_posts_per_page=100&woopam_paged=0&woopam_post_type=product&woopam_post_status=any
*
* REMEMBER: Create the product taxonomy beforehand here (without pa_ prefixing it yourself):
*
* https://example.com/wp-admin/edit.php?post_type=product&page=product_attributes
*
* WARNING: Remember to backup your database first!!!
*
*-----------
* CHANGELOG:
*-----------
*
* 2021-12-13 v1.0.0 Overhaul (Work: 5 hours)
*
*------
* TODO:
*------
*
* - Split into more smaller functions.
* - Add tests.
* - Add more documentation.
* - Look into UI.
*/
add_action( 'template_redirect', function() {
// Activate product attribute modification (only available for admins).
if ( ! current_user_can( 'manage_options' ) || 'run' !== filter_input( INPUT_GET, 'woopam_mode' ) ) {
return;
}
// User input.
$keep_attribute_meta = filter_input( INPUT_GET, 'woopam_keep_attribute_meta', FILTER_VALIDATE_BOOLEAN );
$from_attribute_meta = filter_input( INPUT_GET, 'woopam_from_attribute_meta', FILTER_SANITIZE_STRING );
$to_attribute_tax = filter_input( INPUT_GET, 'woopam_to_attribute_tax', FILTER_SANITIZE_STRING );
$post_type = filter_input( INPUT_GET, 'woopam_post_type', FILTER_SANITIZE_STRING );
$post_status = filter_input( INPUT_GET, 'woopam_post_status', FILTER_SANITIZE_STRING );
$posts_per_page = filter_input( INPUT_GET, 'woopam_posts_per_page', FILTER_SANITIZE_NUMBER_INT );
$paged = filter_input( INPUT_GET, 'woopam_paged', FILTER_SANITIZE_NUMBER_INT );
// Default values.
if ( empty( $posts_per_page ) ) {
$posts_per_page = 10;
}
if ( empty( $paged ) ) {
$paged = 1;
}
if ( empty( $post_type ) ) {
$post_type = 'product';
}
if ( empty( $keep_attribute_meta ) ) {
$keep_attribute_meta = false;
}
if ( empty( $post_status ) ) {
$post_status = 'any';
}
if ( empty( $from_attribute_meta ) || empty( $to_attribute_tax ) ) {
wp_die( esc_html__( 'Oh, rembember that the "from_attribute_meta" and "to_attribute_tax" variable must be set!', 'woopam' ) );
}
$meta_key = '_product_attributes';
// Fetch products with product attributes:
$args = array(
'post_type' => sanitize_key( $post_type ),
'fields' => 'ids',
'posts_per_page' => (int) $posts_per_page,
'paged' => absint ( $paged ),
'meta_key' => $meta_key,
'post_status' => sanitize_key( $post_status ),
);
$post_ids = get_posts( $args );
$total = 0;
$total_modified = 0;
$msg = esc_html__( "Bulk update 'custom meta product attributes' to 'taxonomy product attributes'", 'woopam' );
printf(
'<h1>%s</h1>%s<ul>',
$msg,
esc_html__( 'START', 'woopam' )
);
foreach ( (array) $post_ids as $post_id ) {
$total++;
$meta = get_post_meta( $post_id, $meta_key, true );
$product_needs_update = false;
foreach ( (array) $meta as $key => $terms ) {
// Locate our meta attribute.
if ( $from_attribute_meta === $terms['name'] ) {
$product_needs_update = true;
$tmp = explode( '|', $terms['value'] );
$product_terms = array();
foreach ( (array) $tmp as $term ) {
$product_terms[] = $term;
}
// Remove the product meta attribute:
if ( ! $keep_attribute_meta ) {
unset( $meta[$key] );
}
// Add it again as product taxonomy attribute:
$meta["{$to_attribute_tax}"] = array(
'name' => "{$to_attribute_tax}",
'value' => '',
'position' => $terms['position'],
'is_visible' => $terms['is_visible'],
'is_variation' => $terms['is_variation'],
'is_taxonomy' => 1,
);
} // end if
} // end foreach
echo '<li>';
if ( $product_needs_update ) {
// Assign terms to the post (create them if they don't exists).
$term_taxonomy_ids = wp_set_object_terms( $post_id, $product_terms, $to_attribute_tax, false );
if ( is_wp_error( $term_taxonomy_ids ) ) {
$msg = sprintf(
esc_html__( 'Error! Terms couldn\'t be set for product id: %d and WP error description: "%s" and product taxonomy slug: "%s"', 'woopam' ),
(int) $post_id,
esc_html( $term_taxonomy_ids->get_error_code() ),
esc_html( $to_attribute_tax )
);
printf( '<strong>%s</strong><br/>', $msg );
} else {
update_post_meta( $post_id, $meta_key, $meta );
$total_modified++;
$msg = sprintf(
esc_html__( 'Success! The taxonomy post attributes were set for product id: %d', 'woopam' ),
(int) $post_id
);
printf( '<strong>%s</strong><br/>', $msg );
}
} else {
$msg = sprintf(
esc_html__( 'Nothing to do here! No product attributes were set for product id: %d', 'woopam' ),
$post_id
);
printf( '%s<br/>', $msg );
}
echo '</li>';
} // end foreach post.
echo '</ul><br/>';
printf(
esc_html__( 'Total products checked: %d', 'woopam' ),
(int) $total
);
echo '<br/>';
printf(
esc_html__( 'Total modified products: %d', 'woopam' ),
(int) $total_modified
);
echo '<br/>';
echo '<br/>';
die( esc_html__( 'END', 'woopam' ) );
} );
@birgire
Copy link
Author

birgire commented Jan 5, 2024

Awesome, thank you for sharing @emmelemme

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment