When importing from Printify service to Woocommerse, the variations in attributes do not match color, size and price. I transferred attributes to global and variations are posted in a scatter. Here is the code that is available.
The code already handles colors and sizes correctly, but does not update prices for variations. To add support for Printify prices
add_action('rest_after_insert_product', function($product) {
$product_id = $product->get_id();
error_log("Processing product: $product_id");
convert_custom_to_global_attributes($product_id);
update_variation_prices($product_id);
}, 10, 1);
add_action('shutdown', function() {
global $wpdb;
$products = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'product' AND post_status = 'publish'");
foreach ($products as $product_id) {
convert_custom_to_global_attributes($product_id);
}
});
add_action('woocommerce_before_single_product', function() {
$product = wc_get_product(get_the_ID());
$attributes = $product->get_attributes();
error_log("Product attributes: " . print_r($attributes, true));
});
function convert_custom_to_global_attributes($product_id) {
$product = wc_get_product($product_id);
if (!$product) {
error_log("Product not found: $product_id");
return;
}
$attributes = $product->get_attributes();
$updated_attributes = []; // To store only global attributes
$attribute_mapping = [
'custom_sizes' => 'pa_sizes',
'custom_colors' => 'pa_colors',
];
foreach ($attributes as $key => $attr) {
if (!$attr->is_taxonomy()) { // Check if it's a custom attribute
$name = $attr->get_name();
$taxonomy = 'pa_' . sanitize_title($name);
// Create the global attribute if it doesn't exist
if (!taxonomy_exists($taxonomy)) {
$result = wc_create_attribute([
'name' => $name,
'slug' => sanitize_title($name),
'type' => 'select',
'order_by' => 'menu_order',
'has_archives' => false,
]);
if (is_wp_error($result)) {
error_log("Failed to create global attribute $name: " . $result->get_error_message());
continue;
}
register_taxonomy($taxonomy, 'product', [
'hierarchical' => true,
'show_ui' => false,
'query_var' => true,
'rewrite' => false,
]);
}
// Convert terms to global taxonomy terms
$options = $attr->get_options();
foreach ($options as $option) {
if (!term_exists($option, $taxonomy)) {
$term_result = wp_insert_term($option, $taxonomy);
if (is_wp_error($term_result)) {
error_log("Failed to create term '$option' in taxonomy '$taxonomy': " . $term_result->get_error_message());
} else {
error_log("Created term '$option' in taxonomy '$taxonomy'.");
error_log("Variation $variation_id original attributes: " . print_r($variation_attributes, true));
error_log("Updated attributes for variation $variation_id: " . print_r($updated_variation_attributes, true));
}
}
}
// Prepare the global attribute
$global_attribute = new WC_Product_Attribute();
$global_attribute->set_id(wc_attribute_taxonomy_id_by_name($name));
$global_attribute->set_name($taxonomy);
$global_attribute->set_options($options);
$global_attribute->set_visible($attr->get_visible());
$global_attribute->set_variation($attr->get_variation());
$updated_attributes[$taxonomy] = $global_attribute; // Add to updated attributes
$attribute_mapping[$name] = $taxonomy; // Map old attribute name to global taxonomy
$attribute_mapping = [
'custom_sizes' => 'pa_sizes',
'custom_colors' => 'pa_colors',
];
} else {
// Keep existing global attributes
$updated_attributes[$key] = $attr;
}
}
// Update the product with only the global attributes
$product->set_attributes($updated_attributes);
$product->save();
// Update variations to use global attributes
update_variation_attributes($product_id, $attribute_mapping);
}
function update_variation_attributes($product_id, $attribute_mapping) {
$product = wc_get_product($product_id);
if (!$product || !$product->is_type('variable')) {
error_log("Product $product_id is not variable or not found.");
return;
}
$variations = $product->get_children();
$used_sizes = [];
$used_colors = [];
foreach ($variations as $variation_index => $variation_id) {
$variation = wc_get_product($variation_id);
if (!$variation) {
error_log("Variation $variation_id not found for product $product_id.");
continue;
}
$updated_attributes = [];
$missing_attributes = [];
$current_attributes = $variation->get_attributes();
foreach ($attribute_mapping as $custom_name => $global_taxonomy) {
$custom_value = $variation->get_attribute($custom_name);
if ($custom_value) {
$term = get_term_by('name', $custom_value, $global_taxonomy);
if ($term) {
// Проверяем, нет ли уже атрибута в текущих значениях
if (!isset($current_attributes['attribute_' . $global_taxonomy]) || $current_attributes['attribute_' . $global_taxonomy] !== $term->slug) {
$updated_attributes['attribute_' . $global_taxonomy] = $term->slug;
error_log("Variation $variation_id: Mapped '$custom_name' to global term '{$term->slug}' in taxonomy '$global_taxonomy'.");
}
// Добавляем в списки использованных атрибутов
if ($global_taxonomy === 'pa_sizes') {
$used_sizes[] = $term->slug;
}
if ($global_taxonomy === 'pa_colors') {
$used_colors[] = $term->slug;
}
} else {
$missing_attributes[] = $global_taxonomy;
error_log("Variation $variation_id: Term '$custom_value' not found in taxonomy '$global_taxonomy'.");
}
} else {
// Распределение терминов, если значение отсутствует
$attribute_terms = get_terms([
'taxonomy' => $global_taxonomy,
'hide_empty' => false,
]);
if (!empty($attribute_terms)) {
$term_slug = $attribute_terms[$variation_index % count($attribute_terms)]->slug;
// Проверяем, чтобы термин не дублировался
if (
($global_taxonomy === 'pa_sizes' && !in_array($term_slug, $used_sizes)) ||
($global_taxonomy === 'pa_colors' && !in_array($term_slug, $used_colors))
) {
$updated_attributes['attribute_' . $global_taxonomy] = $term_slug;
error_log("Variation $variation_id: Assigned term '{$term_slug}' for '$global_taxonomy'.");
}
} else {
$missing_attributes[] = $global_taxonomy;
error_log("Variation $variation_id: No terms available for taxonomy '$global_taxonomy'.");
}
}
}
if (!empty($updated_attributes)) {
// Устанавливаем новые атрибуты и сохраняем вариацию
$variation->set_attributes(array_merge($current_attributes, $updated_attributes));
$variation->save();
} else {
error_log("No attributes updated for variation $variation_id of product $product_id. Missing attributes: " . implode(', ', $missing_attributes));
}
}
// Синхронизация продукта
WC_Product_Variable::sync($product_id);
wc_delete_product_transients($product_id);
}