“I’ve created my first custom product with its ‘variants’, meant to have divisions based on dimensions and prices. Generally, everything works fine in the admin panel, but unfortunately, when I tried to add a product, for example with ID 47156 and its variant ID 6627db9886b28, I get the following message in the browser console:
Product ID: 47156
roleta-1/:340 Variant ID: 6627db9886b28
roleta-1/:341 Nonce: f02f367310
roleta-1/:353 AJAX Response: {success: false, data: {…}}”
This is the code that creates a custom product in woocommerce:
// Register custom product type
function register_custom_product_type() {
class WC_Product_Custom_Roll_Dimensions extends WC_Product {
public $product_type;
public function __construct( $product ) {
$this->product_type = 'custom_roll_dimensions';
parent::__construct( $product );
}
}
// Add the custom product type to WooCommerce
add_filter('product_type_selector', function( $types ){
$types['custom_roll_dimensions'] = 'Wymiary Rolet';
return $types;
});
}
add_action('init', 'register_custom_product_type');
// Custom Variants Manager Class
class CustomVariantsManager {
public function __construct() {
add_action('admin_enqueue_scripts', array($this, 'enqueueStyles'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_and_localize_scripts'));
add_action('add_meta_boxes', array($this, 'addCustomVariantsMetabox'));
add_action('save_post', array($this, 'saveCustomVariants'), 10, 2);
add_action('wp_ajax_custom_variants_pagination', array($this, 'customVariantsPagination'));
add_action('wp_ajax_nopriv_custom_variants_pagination', array($this, 'customVariantsPagination'));
add_action('wp_ajax_remove_custom_variant', array($this, 'removeCustomVariantCallback'));
add_action('wp_ajax_add_custom_variant', array($this, 'addCustomVariantCallback'));
// Include the kalkulator.php file
include_once(plugin_dir_path(__FILE__) . 'Kalkulator.php');
}
// Enqueue styles for the admin area
public function enqueueStyles() {
wp_enqueue_style('moj-wtyczka-styl', plugins_url('css/moj-wtyczka-styl.css', __FILE__));
}
// Enqueue and localize scripts for admin area
public function enqueue_and_localize_scripts(){
// Enqueue your JavaScript file
wp_enqueue_script('custom-variants-scripts', plugin_dir_url(__FILE__) . 'JS/custom-variants-scripts.js', array('jquery'), '1.0', true);
// Localize the script with necessary data
wp_localize_script('custom-variants-scripts', 'ajax_object', array(
'post_id' => get_the_ID(),
'ajax_url' => admin_url('admin-ajax.php'), // Make sure this points to admin-ajax.php
));
wp_localize_script('custom-variants-scripts', 'custom_script_vars', array(
'post_id' => get_the_ID(), // Notice the comma here
));
}
// Add the custom variants metabox
public function addCustomVariantsMetabox() {
add_meta_box(
'custom_variants_metabox_id', // Unique ID
'Warianty Produktu', // Box title
array($this, 'customVariantsMetaboxHtml'), // Content callback, must be of type callable
['product', 'custom_roll_dimensions'], // Support for new product type
'normal'
);
}
// Metabox HTML
public function customVariantsMetaboxHtml($post) {
wp_nonce_field(plugin_basename(__FILE__), 'custom_variants_nonce');
$variants = get_post_meta($post->ID, 'custom_variants', true);
if (!is_array($variants)) {
$variants = [];
}
$shipping_classes = get_terms('product_shipping_class', array('hide_empty' => false));
echo '<div id="custom_variants_containers">';
echo '<button id="add_variant" type="button">Dodaj Nowy Wariant</button>';
echo '<button id="remove_all_variants" type="button">Usuń Wszystkie Warianty</button>';
$totalVariants = count($variants);
echo '<div id="total_variants">Wszystkie: ' . $totalVariants . '</div>';
echo '<div id="custom_variants_container">';
if ($variants) {
foreach ($variants as $index => $variant) {
echo '<div class="variant">';
$dimensions = esc_attr($variant['width']) . 'x' . esc_attr($variant['height']);
echo '<div id="variant_dimensionsss">';
echo '<div id="variant_dimensionss" style="display: flex; align-items: center;">';
echo '<span>ID wariantu: ' . esc_html($variant['id']) . '</span>';
echo '<div id="variant_dimensions_' . $index . '" style="display: flex; align-items: center; margin-left:10px">';
echo '<label for="variant_dimensions_' . $index . '">Wymiary:</label>';
echo '<span id="variant_dimensions_' . $index . '">' . $dimensions . '</span>';
echo '</div>';
echo '</div>';
echo '<div>';
echo '<button class="remove_variant" type="button" data-index="' . $index . '">Usuń Wariant</button>';
echo '<button class="rozwin_variant" type="button" data-index="' . $index . '">Rozwiń</button>';
echo '</div>';
echo '</div>';
echo '<div id="custom_variants_containerx">';
echo '<div id="custom_variants_container1" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">';
echo '<div>';
echo '<label for="variant_width_' . $index . '">Szerokość</label>';
echo '<input type="text" id="variant_width_' . $index . '" name="variants[' . $index . '][width]" value="' . esc_attr($variant['width']) . '" />';
echo '</div>';
echo '<div>';
echo '<label for="variant_height_' . $index . '">Wysokość</label>';
echo '<input type="text" id="variant_height_' . $index . '" name="variants[' . $index . '][height]" value="' . esc_attr($variant['height']) . '" />';
echo '</div>';
echo '<div>';
echo '<label for="variant_sku_' . $index . '">SKU</label>';
echo '<input type="text" id="variant_sku_' . $index . '" name="variants[' . $index . '][sku]" value="' . esc_attr($variant['sku']) . '" />';
echo '</div>';
echo '</div>';
echo '<div id="custom_variants_container2" style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px;">';
echo '<div>';
echo '<label for="variant_regular_price_' . $index . '">Cena Regularna</label>';
echo '<input type="text" id="variant_regular_price_' . $index . '" name="variants[' . $index . '][regular_price]" value="' . esc_attr($variant['regular_price']) . '" size="50" />';
echo '</div>';
echo '<div>';
echo '<label for="variant_sale_price_' . $index . '">Cena Promocyjna</label>';
echo '<input type="text" id="variant_sale_price_' . $index . '" name="variants[' . $index . '][sale_price]" value="' . esc_attr($variant['sale_price']) . '" size="50" />';
echo '</div>';
echo '</div>';
echo '<div id="custom_variants_container3" style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 0px;">';
echo '<label for="variant_weight_' . $index . '">Waga</label>';
echo '<input type="text" id="variant_weight_' . $index . '" name="variants[' . $index . '][weight]" value="' . esc_attr($variant['weight']) . '" size="25" />';
echo '</div>';
echo '<div>';
echo '<label for="variant_stock_status_' . $index . '">Stan magazynowy:</label>';
echo '<select id="variant_stock_status_' . $index . '" name="variants[' . $index . '][stock_status]">';
echo '<option value="instock"' . (isset($variant['stock_status']) && $variant['stock_status'] === 'instock' ? ' selected' : '') . '>Na stanie</option>';
echo '<option value="outofstock"' . (isset($variant['stock_status']) && $variant['stock_status'] === 'outofstock' ? ' selected' : '') . '>Brak na stanie</option>';
echo '</select>';
echo '</div>';
echo '<div id="custom_variants_container4" style="display: grid; grid-template-columns: repeat(1, 1fr); gap: px;">';
echo '<label for="variant_shipping_class_' . $index . '">Klasa Wysyłkowa</label>';
echo '<select name="variants[' . $index . '][shipping_class]" id="variant_shipping_class_' . $index . '" class="postform">';
echo '<option value="-1"' . (!isset($variant['shipping_class']) || $variant['shipping_class'] == '-1' ? ' selected="selected"' : '') . '>Taka sama jak nadrzędny</option>';
foreach ($shipping_classes as $class) {
$selected = (isset($variant['shipping_class']) && $variant['shipping_class'] == $class->slug) ? ' selected="selected"' : '';
echo '<option value="' . esc_attr($class->slug) . '"' . $selected . '>' . esc_html($class->name) . '</option>';
}
echo '</select>';
echo '</div>';
echo '</div>';
echo '</div>';
}
}
echo '</div>';
echo '</div>';
}
// Save custom variants
public function saveCustomVariants($post_id, $post) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (!isset($_POST['custom_variants_nonce']) || !wp_verify_nonce($_POST['custom_variants_nonce'], plugin_basename(__FILE__))) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
if ($post->post_type != 'product' && $post->post_type != 'custom_roll_dimensions') {
return;
}
if (isset($_POST['variants']) && is_array($_POST['variants'])) {
update_post_meta($post_id, 'custom_variants', $_POST['variants']);
} else {
delete_post_meta($post_id, 'custom_variants');
}
}
// Pagination AJAX handler
public function customVariantsPagination() {
$page = isset($_POST['page']) ? intval($_POST['page']) : 1;
$per_page = isset($_POST['per_page']) ? intval($_POST['per_page']) : 10;
$post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
$variants = get_post_meta($post_id, 'custom_variants', true);
if (!is_array($variants)) {
$variants = [];
}
$total_variants = count($variants);
$total_pages = ceil($total_variants / $per_page);
$start = ($page - 1) * $per_page;
$end = $start + $per_page;
$paged_variants = array_slice($variants, $start, $per_page);
ob_start();
foreach ($paged_variants as $index => $variant) {
echo '<div class="variant">';
echo '<span>ID wariantu: ' . esc_html($variant['id']) . '</span>';
echo '<span>Wymiary: ' . esc_html($variant['width']) . 'x' . esc_html($variant['height']) . '</span>';
echo '<button class="remove_variant" type="button" data-index="' . $index . '">Usuń Wariant</button>';
echo '</div>';
}
$content = ob_get_clean();
wp_send_json_success(array(
'content' => $content,
'total_pages' => $total_pages,
));
}
// Remove custom variant AJAX handler
public function removeCustomVariantCallback() {
if (!isset($_POST['post_id']) || !isset($_POST['index'])) {
wp_send_json_error();
return;
}
$post_id = intval($_POST['post_id']);
$index = intval($_POST['index']);
$variants = get_post_meta($post_id, 'custom_variants', true);
if (!is_array($variants)) {
wp_send_json_error();
return;
}
if ($index < 0 || $index >= count($variants)) {
wp_send_json_error();
return;
}
array_splice($variants, $index, 1);
update_post_meta($post_id, 'custom_variants', $variants);
wp_send_json_success();
}
// Add custom variant AJAX handler
public function addCustomVariantCallback() {
if (!isset($_POST['post_id']) || !isset($_POST['variant'])) {
wp_send_json_error();
return;
}
$post_id = intval($_POST['post_id']);
$new_variant = $_POST['variant'];
$variants = get_post_meta($post_id, 'custom_variants', true);
if (!is_array($variants)) {
$variants = [];
}
$variants[] = $new_variant;
update_post_meta($post_id, 'custom_variants', $variants);
wp_send_json_success();
}
}
// Initialize the CustomVariantsManager class
new CustomVariantsManager();
I tried to add the code that will add a specific product from the created product and its variant, but unfortunately I keep getting an error
code for adding a specific product to the cart
function add_custom_variant_to_cart() {
// Check nonce for security
if (!check_ajax_referer('add_custom_variant_nonce', 'security', false)) {
error_log('Nonce verification failed.');
wp_send_json_error(array('message' => 'Nonce verification failed.'));
wp_die();
}
// Get the product ID and variant ID from the request
$product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;
$variant_id = isset($_POST['variant_id']) ? sanitize_text_field($_POST['variant_id']) : '';
error_log('Product ID: ' . $product_id);
error_log('Variant ID: ' . $variant_id);
// Check if the product ID and variant ID are valid
if ($product_id && $variant_id) {
$variants = get_post_meta($product_id, 'custom_variants', true);
error_log('Variants: ' . print_r($variants, true));
if (is_array($variants)) {
foreach ($variants as $variant) {
error_log('Checking variant: ' . print_r($variant, true));
if ($variant['id'] === $variant_id) {
// Add to cart
$cart_item_data = array(
'variant_id' => $variant_id,
'custom_variant_data' => $variant,
);
$added = WC()->cart->add_to_cart($product_id, 1, 0, array(), $cart_item_data);
error_log('Add to cart result: ' . print_r($added, true));
if ($added) {
wp_send_json_success(array('message' => 'Product added to cart'));
} else {
wp_send_json_error(array('message' => 'Failed to add product to cart'));
}
}
}
} else {
error_log('No valid variants found.');
}
} else {
error_log('Invalid product ID or variant ID.');
}
wp_send_json_error(array('message' => 'Unable to add product to cart'));
wp_die();
}
add_action('wp_ajax_add_custom_variant_to_cart', 'add_custom_variant_to_cart');
add_action('wp_ajax_nopriv_add_custom_variant_to_cart', 'add_custom_variant_to_cart');
// Example JavaScript to handle AJAX request
add_action('wp_footer', 'custom_add_to_cart_script');
function custom_add_to_cart_script() {
?>
<script type="text/javascript">
jQuery(document).ready(function($) {
$('#custom_add_to_cart_button').click(function(e) {
e.preventDefault();
var product_id = 47156;
var variant_id = '6627db9886b28';
var security = '<?php echo wp_create_nonce('add_custom_variant_nonce'); ?>';
console.log('Product ID:', product_id);
console.log('Variant ID:', variant_id);
console.log('Nonce:', security);
$.ajax({
url: '<?php echo admin_url('admin-ajax.php'); ?>',
type: 'POST',
data: {
action: 'add_custom_variant_to_cart',
product_id: product_id,
variant_id: variant_id,
security: security
},
success: function(response) {
console.log('AJAX Response:', response);
if (response.success) {
alert(response.data.message);
window.location.href = '<?php echo wc_get_cart_url(); ?>';
} else {
alert(response.data.message);
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('AJAX Error:', textStatus, errorThrown);
console.log('Response Text:', jqXHR.responseText);
}
});
});
});
</script>
<?php
}
// Filter to add custom data to cart item
function custom_add_cart_item_data($cart_item_data, $product_id, $variation_id) {
if (isset($_POST['custom_variant_data'])) {
$cart_item_data['custom_variant_data'] = sanitize_text_field($_POST['custom_variant_data']);
}
return $cart_item_data;
}
add_filter('woocommerce_add_cart_item_data', 'custom_add_cart_item_data', 10, 3);
// Display custom variant data in the cart
function custom_get_item_data($item_data, $cart_item) {
if (isset($cart_item['custom_variant_data'])) {
$item_data[] = array(
'name' => __('Variant Dimensions', 'textdomain'),
'value' => $cart_item['custom_variant_data']['width'] . 'x' . $cart_item['custom_variant_data']['height'],
);
}
return $item_data;
}
add_filter('woocommerce_get_item_data', 'custom_get_item_data', 10, 2);