Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save JiveDig/7abe617b34c5f0ba659269834b9f00c4 to your computer and use it in GitHub Desktop.
Save JiveDig/7abe617b34c5f0ba659269834b9f00c4 to your computer and use it in GitHub Desktop.
WooCommerce Product Taxonomy Import/Export. Makes it easy to add custom taxonomies to built in WooCommerce import/export feature.

WooCommerce Product Taxonomy Import/Export

Add your registered custom product taxonomies to the importer/exporter with the code below.

/**
 * Setup export/import for custom taxonomies.
 *
 * @return void
 */
add_action( 'woocommerce_init', function() {
	// Bail if class does not exist.
	if ( ! class_exists( 'Mai_WooCommerce_Product_Taxonomy_Import_Export' ) ) {
		return;
	}

	// Taxonomies to import/export.
	$taxonomies = [
		'my_taxonomy',
		'another_taxonomy',
	];

	// Setup import/export for each taxonomy.
	foreach ( $taxonomies as $taxonomy ) {
		new Mai_WooCommerce_Product_Taxonomy_Import_Export( $taxonomy );
	}
});
<?php
// Prevent direct file access.
defined( 'ABSPATH' ) || die;
/**
* The main plugin class.
*
* @version 0.1.0
*
* @link https://gist.github.com/JiveDig/7abe617b34c5f0ba659269834b9f00c4
* @link https://gist.github.com/helgatheviking/114c8df50cabb7119b3c895b1d854533/
*/
class Mai_WooCommerce_Product_Taxonomy_Import_Export {
protected $taxonomy;
protected $key;
/**
* Construct the class.
*/
function __construct( $taxonomy ) {
$this->taxonomy = $taxonomy;
$this->key = 'custom_taxonomy_' . $this->taxonomy;
$this->hooks();
}
/**
* Add hooks.
*
* @since 0.1.0
*
* @return void
*/
function hooks() {
add_filter( 'woocommerce_product_export_column_names', [ $this, 'add_column' ] );
add_filter( 'woocommerce_product_export_product_default_columns', [ $this, 'add_column' ] );
add_filter( "woocommerce_product_export_product_column_$this->key", [ $this, 'export_taxonomy' ], 10, 2 );
add_filter( 'woocommerce_csv_product_import_mapping_options', [ $this, 'add_column' ] );
add_filter( 'woocommerce_csv_product_import_mapping_default_columns', [ $this, 'add_mapping_column' ] );
add_filter( 'woocommerce_product_importer_parsed_data', [ $this, 'parse_json' ], 10, 2 );
add_filter( 'woocommerce_product_import_inserted_product_object', [ $this, 'set_taxonomy' ], 10, 2 );
}
/**
* Add CSV columns for exporting extra data.
*
* @since 0.1.0
*
* @param array $columns
*
* @return array
*/
function add_column( $columns ) {
$taxonomy_obj = $this->get_taxonomy( $this->taxonomy );
// Bail if no taxonomy.
if ( ! $taxonomy_obj ) {
return $columns;
}
$columns[ $this->key ] = $taxonomy_obj->labels->name;
return $columns;
}
/**
* Adds contents data column content.
*
* @since 0.1.0
*
* @param mixed $value
* @param WC_Product $product
*
* @return mixed
*/
function export_taxonomy( $value, $product ) {
// Get the terms for the product.
$terms = get_terms(
[
'object_ids' => $product->get_ID(),
'taxonomy' => $this->taxonomy,
]
);
// If we have terms, encode them.
if ( $terms && ! is_wp_error( $terms ) ) {
$data = [];
// Loop through terms and add the name.
foreach ( (array) $terms as $term ) {
$data[] = $term->slug;
}
$value = implode( ',', $data );
}
return $value;
}
/**
* Add automatic mapping support for custom columns.
*
* @since 0.1.0
*
* @param array $columns
*
* @return array
*/
function add_mapping_column( $columns ) {
$taxonomy_obj = $this->get_taxonomy( $this->taxonomy );
// Bail if no taxonomy.
if ( ! $taxonomy_obj ) {
return $columns;
}
$columns[ $taxonomy_obj->labels->name ] = $this->key;
return $columns;
}
/**
* Decode data items and parse JSON IDs.
*
* @since 0.1.0
*
* @param array $parsed_data
* @param WC_Product_CSV_Importer $importer
*
* @return array
*/
function parse_json( $parsed_data, $importer ) {
// Bail if no data.
if ( ! isset( $parsed_data[ $this->taxonomy ] ) || empty( $parsed_data[ $this->taxonomy ] ) ) {
return $parsed_data;
}
// Decode the data.
$data = json_decode( $parsed_data[ $this->taxonomy ], true );
// Unset the original data.
unset( $parsed_data[ $this->taxonomy ] );
// If we have data, add it back to the parsed data.
if ( $data && is_array( $data ) ) {
$parsed_data[ $this->taxonomy ] = [];
foreach ( $data as $term_name ) {
$parsed_data[ $this->taxonomy ][] = $term_name;
}
}
return $parsed_data;
}
/**
* Set taxonomy.
*
* @since 0.1.0
*
* @param array $product
*
* @return array
*/
function set_taxonomy( $product, $data ) {
if ( ! $product instanceof WC_Product ) {
return $product;
}
// Bail if no data.
if ( ! isset( $data[ $this->key ] ) || empty( $data[ $this->key ] ) ) {
return $product;
}
// Get terms.
$slugs = explode( ',', $data[ $this->key ] );
// Bail if no terms.
if ( ! $slugs ) {
return $product;
}
// Set the terms.
wp_set_object_terms( $product->get_id(), $slugs, $this->taxonomy );
return $product;
}
/**
* Get taxonomy object.
*
* @since 0.1.0
*
* @param string $taxonomy
*
* @return WP_Taxonomy
*/
function get_taxonomy( $taxonomy ) {
static $cache = null;
if ( ! is_null( $cache ) ) {
return $cache;
}
$cache = get_taxonomy( $taxonomy );
return $cache;
}
}
@carloslato
Copy link

carloslato commented Oct 4, 2024

static cache variable is returning just the first taxonomy name, here my fixed version:

add_action( 'woocommerce_init', function() {
	// Bail if class does not exist.
	if ( ! class_exists( 'Mai_WooCommerce_Product_Taxonomy_Import_Export' ) ) {
		return;
	}

	// Taxonomies to import/export.
	$taxonomies = [
		'taxonomy_one',
		'taxonomy_two',
		'taxonomy_three',
		'taxonomy_four',
		
	];

	// Setup import/export for each taxonomy.
	foreach ( $taxonomies as $taxonomy ) {
		new Mai_WooCommerce_Product_Taxonomy_Import_Export( $taxonomy );
	}
});



class Mai_WooCommerce_Product_Taxonomy_Import_Export {
	protected $taxonomy;
	protected $key;

	/**
	 * Construct the class.
	 */
	function __construct( $taxonomy ) {
		$this->taxonomy = $taxonomy;
		$this->key      = 'custom_taxonomy_' . $this->taxonomy;

		$this->hooks();
	}

	/**
	 * Add hooks.
	 *
	 * @since 0.1.0
	 *
	 * @return void
	 */
	function hooks() {
		add_filter( 'woocommerce_product_export_column_names',                [ $this, 'add_column' ] );
		add_filter( 'woocommerce_product_export_product_default_columns',     [ $this, 'add_column' ] );
		add_filter( "woocommerce_product_export_product_column_$this->key",   [ $this, 'export_taxonomy' ], 10, 2 );
		add_filter( 'woocommerce_csv_product_import_mapping_options',         [ $this, 'add_column' ] );
		add_filter( 'woocommerce_csv_product_import_mapping_default_columns', [ $this, 'add_mapping_column' ] );
		add_filter( 'woocommerce_product_importer_parsed_data',               [ $this, 'parse_json' ], 10, 2 );
		add_filter( 'woocommerce_product_import_inserted_product_object',     [ $this, 'set_taxonomy' ], 10, 2 );
	}

	/**
	 * Add CSV columns for exporting extra data.
	 *
	 * @since 0.1.0
	 *
	 * @param array $columns
	 *
	 * @return array
	 */
	function add_column( $columns ) {
		$taxonomy_obj = $this->get_taxonomy( $this->taxonomy );

		// Bail if no taxonomy.
		if ( ! $taxonomy_obj ) {
			return $columns;
		}

		$columns[ $this->key ] = $taxonomy_obj->labels->name;

		return $columns;
	}

	/**
	 * Adds contents data column content.
	 *
	 * @since 0.1.0
	 *
	 * @param mixed      $value
	 * @param WC_Product $product
	 *
	 * @return mixed
	 */
	function export_taxonomy( $value, $product ) {
		// Get the terms for the product.
		$terms = get_terms(
			[
				'object_ids' => $product->get_ID(),
				'taxonomy'   => $this->taxonomy,
			]
		);

		// If we have terms, encode them.
		if ( $terms && ! is_wp_error( $terms ) ) {
			$data = [];

			// Loop through terms and add the name.
			foreach ( (array) $terms as $term ) {
				$data[] = $term->slug;
			}

			$value = implode( ',', $data );
		}

		return $value;
	}

	/**
	 * Add automatic mapping support for custom columns.
	 *
	 * @since 0.1.0
	 *
	 * @param array $columns
	 *
	 * @return array
	 */
	function add_mapping_column( $columns ) {
		$taxonomy_obj = $this->get_taxonomy( $this->taxonomy );

		// Bail if no taxonomy.
		if ( ! $taxonomy_obj ) {
			return $columns;
		}

		$columns[ $taxonomy_obj->labels->name ] = $this->key;

		return $columns;
	}

	/**
	 * Decode data items and parse JSON IDs.
	 *
	 * @since 0.1.0
	 *
	 * @param array                   $parsed_data
	 * @param WC_Product_CSV_Importer $importer
	 *
	 * @return array
	 */
	function parse_json( $parsed_data, $importer ) {
		// Bail if no data.
		if ( ! isset( $parsed_data[ $this->taxonomy ] ) || empty( $parsed_data[ $this->taxonomy ] ) ) {
			return $parsed_data;
		}

		// Decode the data.
		$data = json_decode( $parsed_data[ $this->taxonomy ], true );

		// Unset the original data.
		unset( $parsed_data[ $this->taxonomy ] );

		// If we have data, add it back to the parsed data.
		if ( $data && is_array( $data ) ) {
			$parsed_data[ $this->taxonomy ] = [];

			foreach ( $data as $term_name ) {
				$parsed_data[ $this->taxonomy ][] = $term_name;
			}
		}

		return $parsed_data;
	}

	/**
	 * Set taxonomy.
	 *
	 * @since 0.1.0
	 *
	 * @param array $product
	 *
	 * @return array
	 */
	function set_taxonomy( $product, $data ) {
		if ( ! $product instanceof WC_Product ) {
			return $product;
		}

		// Bail if no data.
		if ( ! isset( $data[ $this->key ] ) || empty( $data[ $this->key ] ) ) {
			return $product;
		}

		// Get terms.
		$slugs = explode( ',', $data[ $this->key ] );

		// Bail if no terms.
		if ( ! $slugs ) {
			return $product;
		}

		// Set the terms.
		wp_set_object_terms( $product->get_id(), $slugs, $this->taxonomy );

		return $product;
	}

	/**
	 * Get taxonomy object.
	 *
	 * @since 0.1.0
	 *
	 * @param string $taxonomy
	 *
	 * @return WP_Taxonomy
	 */
	 
	 /*
	function get_taxonomy( $taxonomy ) {
		static $cache = null;

		if ( ! is_null( $cache ) ) {
			return $cache;
		}

		$cache = get_taxonomy( $taxonomy );

		return $cache;
	}
	*/
	function get_taxonomy( $taxonomy ) {
        static $cache = [];
    
        if ( isset( $cache[ $taxonomy ] ) ) {
            return $cache[ $taxonomy ];
        }
    
        $cache[ $taxonomy ] = get_taxonomy( $taxonomy );
    
        return $cache[ $taxonomy ];
    }
}

@JiveDig
Copy link
Author

JiveDig commented Oct 5, 2024

@carloslato good catch! I'll update the gist when I'm back at my desk. Thanks 🙏

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