I have created code that allows you to save a CSV file from which product variants are created on the WooCommerce product editor page, and then publish the product also attribute and taxonomy, but I don’t know how to assign each product variant the appropriate taxonomy and attribute?
//nowy
// Funkcja do usuwania przestarzałych plików CSV
function remove_old_csv_files() {
$args = array(
'post_type' => 'product',
'posts_per_page' => -1,
'post_status' => 'any',
'meta_query' => array(
array(
'key' => 'product_csv_file_url',
'value' => '',
'compare' => '!='
)
)
);
$products = new WP_Query($args);
if ($products->have_posts()) {
while ($products->have_posts()) {
$products->the_post();
$product_id = get_the_ID();
$csv_file_url = get_post_meta($product_id, 'product_csv_file_url', true);
$upload_date = get_post_meta($product_id, 'product_csv_file_upload_date', true);
if (!empty($csv_file_url) && !empty($upload_date)) {
$current_time = current_time('timestamp');
$upload_time = strtotime($upload_date);
if (($current_time - $upload_time) > DAY_IN_SECONDS) {
$file_path = str_replace(wp_get_upload_dir()['baseurl'], wp_get_upload_dir()['basedir'], $csv_file_url);
if (file_exists($file_path)) {
unlink($file_path);
}
delete_post_meta($product_id, 'product_csv_file_url');
delete_post_meta($product_id, 'product_csv_file_name');
delete_post_meta($product_id, 'product_csv_file_upload_date');
}
}
}
wp_reset_postdata();
}
}
// Harmonogram codziennego usuwania plików CSV
if (!wp_next_scheduled('daily_csv_cleanup')) {
wp_schedule_event(time(), 'daily', 'daily_csv_cleanup');
}
add_action('daily_csv_cleanup', 'remove_old_csv_files');
// Dodanie meta boxa do produktów WooCommerce dla uploadu pliku CSV.
function add_product_csv_upload_meta_box() {
add_meta_box(
'product_csv_upload_meta_box',
'Upload Product CSV',
'product_csv_upload_meta_box_html',
'product'
);
}
add_action('add_meta_boxes', 'add_product_csv_upload_meta_box');
// HTML dla meta boxa uploadu pliku CSV.
function product_csv_upload_meta_box_html($post) {
wp_nonce_field('product_csv_upload_meta_box', 'product_csv_upload_meta_box_nonce');
$csv_file_url = get_post_meta($post->ID, 'product_csv_file_url', true);
$csv_file_name = get_post_meta($post->ID, 'product_csv_file_name', true);
if (!empty($csv_file_url)) {
echo '<p>Current Product CSV File: <a href="' . esc_url($csv_file_url) . '">' . esc_html($csv_file_name) . '</a></p>';
echo '<label for="delete_product_csv">Delete File:</label> ';
echo '<input type="checkbox" name="delete_product_csv" id="delete_product_csv"><br><br>';
}
echo '<input type="file" name="product_csv_file" id="product_csv_file" accept=".csv">';
echo '<input type="submit" name="save_product_csv" value="Zapisz CSV">';
}
// Zapisywanie danych meta boxa do produktu i przetwarzanie pliku CSV.
function save_product_csv_meta_box_data($post_id) {
if (!isset($_POST['product_csv_upload_meta_box_nonce']) ||
!wp_verify_nonce($_POST['product_csv_upload_meta_box_nonce'], 'product_csv_upload_meta_box') ||
defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ||
!current_user_can('edit_post', $post_id)) {
return;
}
if (!empty($_POST['delete_product_csv'])) {
delete_post_meta($post_id, 'product_csv_file_url');
delete_post_meta($post_id, 'product_csv_file_name');
return;
}
if (isset($_FILES['product_csv_file']) && !empty($_FILES['product_csv_file']['name'])) {
$uploaded_file = wp_handle_upload($_FILES['product_csv_file'], array('test_form' => false));
if (isset($uploaded_file['file'])) {
update_post_meta($post_id, 'product_csv_file_url', $uploaded_file['url']);
update_post_meta($post_id, 'product_csv_file_name', $_FILES['product_csv_file']['name']);
process_product_csv_file($post_id, $uploaded_file['file']);
}
}
}
add_action('save_post', 'save_product_csv_meta_box_data');
// Aktualizacja formularza edycji produktu, aby umożliwić upload plików.
function update_product_edit_form() {
echo ' enctype="multipart/form-data"';
}
add_action('post_edit_form_tag', 'update_product_edit_form');
// Zmiana w funkcji process_product_csv_file
function process_product_csv_file($post_id, $csv_file_path) {
$csv_data = array_map('str_getcsv', file($csv_file_path));
array_shift($csv_data); // Usuń nagłówek CSV, jeśli istnieje
foreach ($csv_data as $row) {
if (count($row) >= 3) {
$width = $row[0];
$height = $row[1];
$price = $row[2];
create_or_update_product_variant($post_id, $width, $height, $price);
}
}
}
// Funkcja do tworzenia wariantu produktu.
function create_product_variant($product_id, $width, $height, $price) {
$variant = new WC_Product_Variation();
$variant->set_parent_id($product_id);
$variant->set_regular_price($price);
$variant->save(); // Zapisanie wariantu
}
// Funkcja do tworzenia lub aktualizacji wariantu produktu.
function create_or_update_product_variant($product_id, $width, $height, $price) {
$existing_variants = wc_get_products(array(
'status' => 'publish',
'type' => 'variation',
'parent' => $product_id,
'limit' => -1,
));
$variant_id = null;
// Sprawdzenie, czy wariant już istnieje
foreach ($existing_variants as $variant) {
$variant_dimensions = $variant->get_dimensions(false);
if ($variant_dimensions['width'] == $width && $variant_dimensions['height'] == $height) {
$variant_id = $variant->get_id();
break;
}
}
if ($variant_id) {
$variant = new WC_Product_Variation($variant_id);
} else {
$variant = new WC_Product_Variation();
$variant->set_parent_id($product_id);
}
$variant->set_regular_price($price);
$variant->set_props(array(
'length' => '0', // Ustawienie długości na 0, jeśli nie jest dostarczana
'width' => $width,
'height' => $height
));
$variant->save(); // Zapisanie wariantu
// Zapisanie ID wariantu w metadanych produktu
$variant_ids = get_post_meta($product_id, 'variant_ids', true) ?: array();
if (!in_array($variant->get_id(), $variant_ids)) {
$variant_ids[] = $variant->get_id();
update_post_meta($product_id, 'variant_ids', $variant_ids);
}
}
function create_attribute_on_product_publish($post_id) {
// Make sure this is a genuine product save action and not a revision
if (get_post_type($post_id) === 'product' && !wp_is_post_revision($post_id)) {
create_custom_attribute($post_id);
}
}
function create_custom_attribute($post_id) {
// Get the current product name using the post ID
$product_name = get_the_title($post_id);
$attribute_name = sanitize_title($product_name); // Use the product name as the attribute name
$attribute_taxonomy_name = wc_attribute_taxonomy_name($attribute_name);
// Check if attribute already exists
if (!attribute_exists($attribute_name)) {
// Add new attribute
$args = array(
'name' => $attribute_name,
'type' => 'select',
'order_by' => 'menu_order',
'has_archives' => false,
);
wc_create_attribute($args);
}
// Check if taxonomy for the attribute already exists
if (!taxonomy_exists($attribute_taxonomy_name)) {
// Register taxonomy for the attribute
register_taxonomy(
$attribute_taxonomy_name,
'product',
array(
'label' => $attribute_name,
'hierarchical' => false,
'show_in_nav_menus' => false,
'show_ui' => false,
)
);
}
// Get the product object using the post ID
$product = wc_get_product($post_id);
if (!$product) return;
// Check if the product is a variable product
if ($product->is_type('variable')) {
// Get metadata from product variants and create attribute values
$variants = $product->get_available_variations();
foreach ($variants as $variant) {
$variant_obj = new WC_Product_Variation($variant['variation_id']);
$width = $variant_obj->get_width();
$height = $variant_obj->get_height();
// Check if both width and height are available
if ($width && $height) {
$dimension_value = $width . 'x' . $height; // Combine width and height
if (!term_exists($dimension_value, $attribute_taxonomy_name)) {
wp_insert_term($dimension_value, $attribute_taxonomy_name);
}
}
}
}
}
add_action('save_post', 'create_attribute_on_product_publish');
function attribute_exists($attribute_name) {
global $wpdb;
$attribute_name = wc_sanitize_taxonomy_name($attribute_name);
$sql = "SELECT attribute_id FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies WHERE attribute_name = %s";
return $wpdb->get_var($wpdb->prepare($sql, $attribute_name)) ? true : false;
}
I tried to do something like this, but it’s not quite the way to go, unfortunately.
function assign_dimension_attribute_to_variant($post_id) {
// Pobieranie produktu
$product = wc_get_product($post_id);
if (!$product || !$product->is_type('variable')) return;
$attribute_name = 'pa_dimensions'; // Nazwa atrybutu
// Sprawdź, czy atrybut istnieje, jeśli nie - zakończ funkcję
if (!taxonomy_exists($attribute_name)) {
error_log('Atrybut wymiarów nie istnieje: ' . $attribute_name);
return;
}
$variants = $product->get_children(); // Pobierz ID wariantów produktu
foreach ($variants as $variant_id) {
$variant = wc_get_product($variant_id);
if (!$variant) continue;
// Pobierz wymiary wariantu
$width = $variant->get_width();
$height = $variant->get_height();
// Jeśli wymiary są dostępne, zaktualizuj atrybut w wariancie
if ($width && $height) {
$dimension_value = $width . 'x' . $height;
// Zaktualizuj atrybut w wariancie
wp_set_object_terms($variant_id, $dimension_value, $attribute_name);
}
}
// Aktualizacja atrybutów w produkcie głównym
$product_attributes = $product->get_attributes();
$product_attributes[$attribute_name] = array(
'name' => $attribute_name,
'value' => '',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1'
);
$product->set_attributes($product_attributes);
// Zapisz produkt
$product->save();
}
add_action('save_post_product', 'assign_dimension_attribute_to_variant', 10, 1);
2
Answers
thanks for the answer, but unfortunately the code still doesn't work. Product variants still have empty fields without the taxonomy attribute.
enter image description here
The code you’ve written is on the right track, but there are a few issues that need to be addressed.
Firstly, you’re creating a new attribute for each variant, which is not necessary. You should have one attribute (for example, "Dimensions") and each variant should have a different term of this attribute (for example, "10×20", "20×30", etc.).
Secondly, you’re trying to assign the attribute to the variant directly. However, in WooCommerce, attributes are assigned to the parent product, not to the variants. Variants have attribute values, not attributes themselves.
Here’s a revised version of your
assign_dimension_attribute_to_variant
function that should work:This function will create a "Dimensions" attribute (if it doesn’t exist already), assign it to the product, and assign the appropriate dimension value to each variant.