skip to Main Content

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


  1. Chosen as BEST ANSWER

    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


  2. 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:

    
    function assign_dimension_attribute_to_variant($post_id) {
        $product = wc_get_product($post_id);
        if (!$product || !$product->is_type('variable')) return;
    
        $attribute_name = 'pa_dimensions'; // The attribute taxonomy name
        $attribute_values = array(); // An array to store attribute values
    
        $variants = $product->get_children(); // Get the IDs of the product variants
        foreach ($variants as $variant_id) {
            $variant = wc_get_product($variant_id);
            $width = $variant->get_width();
            $height = $variant->get_height();
    
            if ($width && $height) {
                $dimension_value = $width . 'x' . $height;
                $attribute_values[] = $dimension_value;
    
                // Update the variant with the attribute value
                update_post_meta($variant_id, 'attribute_' . $attribute_name, $dimension_value);
            }
        }
    
        // Ensure that the attribute exists and is a product attribute
        if (!taxonomy_exists($attribute_name)) {
            register_taxonomy(
                $attribute_name,
                'product',
                array('hierarchical' => true, 'label' => 'Dimensions')
            );
        }
    
        // Update the product with the attribute and its values
        wp_set_object_terms($post_id, $attribute_values, $attribute_name);
        $product_attributes = $product->get_attributes();
        $product_attributes[$attribute_name] = array(
            'name' => $attribute_name,
            'value' => '',
            'is_visible' => '1',
            'is_variation' => '1',
            'is_taxonomy' => '1'
        );
        update_post_meta($post_id, '_product_attributes', $product_attributes);
    
        // Save the product
        $product->save();
    }
    add_action('save_post_product', 'assign_dimension_attribute_to_variant', 10, 1);
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search