function __construct($bundled_item_id, $parent) { $this->item_id = $bundled_item_id; $this->product_id = $parent->bundle_data[$bundled_item_id]['product_id']; $this->bundle_id = $parent->id; $this->item_data = $parent->bundle_data[$bundled_item_id]; // Do not process bundled item stock data in the back end, in order to speed things up just a bit $this->is_front_end = !is_admin() || defined('DOING_AJAX') && true == DOING_AJAX; do_action('woocommerce_before_init_bundled_item', $this); $bundled_product = WC_PB_Core_Compatibility::wc_get_product($this->product_id); // if not present, item cannot be purchased if ($bundled_product) { $this->product = $bundled_product; $this->title = !empty($this->item_data['override_title']) && $this->item_data['override_title'] === 'yes' ? $this->item_data['product_title'] : $bundled_product->get_title(); $this->description = !empty($this->item_data['override_description']) && $this->item_data['override_description'] === 'yes' ? $this->item_data['product_description'] : $bundled_product->post->post_excerpt; $this->visibility = !empty($this->item_data['visibility']) && in_array($this->item_data['visibility'], array('hidden', 'secret')) ? $this->item_data['visibility'] : 'visible'; $this->optional = !empty($this->item_data['optional']) && $this->item_data['optional'] === 'yes' ? 'yes' : 'no'; $this->hide_thumbnail = !empty($this->item_data['hide_thumbnail']) && $this->item_data['hide_thumbnail'] === 'yes' ? 'yes' : 'no'; $this->quantity = isset($this->item_data['bundle_quantity']) ? absint($this->item_data['bundle_quantity']) : 1; $this->discount = !empty($this->item_data['bundle_discount']) ? (double) $this->item_data['bundle_discount'] : 0.0; $this->sign_up_discount = !empty($this->item_data['bundle_sign_up_discount']) ? (double) $this->item_data['bundle_sign_up_discount'] : 0.0; $this->selection_overrides = !empty($this->item_data['override_defaults']) && $this->item_data['override_defaults'] === 'yes' ? $this->item_data['bundle_defaults'] : ''; $this->allowed_variations = !empty($this->item_data['filter_variations']) && $this->item_data['filter_variations'] === 'yes' ? $this->item_data['allowed_variations'] : ''; $this->per_product_pricing = $parent->is_priced_per_product(); $this->sold_individually = false; $this->on_sale = false; $this->nyp = false; $this->purchasable = false; if ($bundled_product->is_purchasable()) { $this->purchasable = true; $this->init(); } } do_action('woocommerce_after_init_bundled_item', $this); }
/** * Return a formatted product title based on variation id. * * @param int $item_id * @return string */ public function get_product_variation_title($variation_id) { $variation = WC_PB_Core_Compatibility::wc_get_product($variation_id); if (!$variation) { return false; } $description = wc_get_formatted_variation($variation->get_variation_attributes(), true); $title = $variation->get_title(); $sku = $variation->get_sku(); if ($sku) { $sku = sprintf(__('(SKU: %s)', 'woocommerce-product-bundles'), $sku); } return $this->format_product_title($title, $sku, $description); }
/** * Add a bundled product to the cart. Must be done without updating session data, recalculating totals or calling 'woocommerce_add_to_cart' recursively. * For the recursion issue, see: https://core.trac.wordpress.org/ticket/17817. * * @param int $bundle_id * @param int $product_id * @param int $quantity * @param int $variation_id * @param array $variation * @param array $cart_item_data * @return bool */ public function bundled_add_to_cart($bundle_id, $product_id, $quantity = 1, $variation_id = '', $variation = '', $cart_item_data) { global $woocommerce_bundles; if ($quantity <= 0) { return false; } // Load cart item data when adding to cart $cart_item_data = (array) apply_filters('woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id); // Generate a ID based on product ID, variation ID, variation data, and other cart item data $cart_id = WC()->cart->generate_cart_id($product_id, $variation_id, $variation, $cart_item_data); // See if this product and its options is already in the cart $cart_item_key = WC()->cart->find_product_in_cart($cart_id); // Ensure we don't add a variation to the cart directly by variation ID if ('product_variation' == get_post_type($product_id)) { $variation_id = $product_id; $product_id = wp_get_post_parent_id($variation_id); } // Get the product $product_data = WC_PB_Core_Compatibility::wc_get_product($variation_id ? $variation_id : $product_id); // If cart_item_key is set, the item is already in the cart and its quantity will be handled by woo_bundles_update_quantity_in_cart. if (!$cart_item_key) { $cart_item_key = $cart_id; // Add item after merging with $cart_item_data - allow plugins and woo_bundles_add_cart_item_filter to modify cart item WC()->cart->cart_contents[$cart_item_key] = apply_filters('woocommerce_add_cart_item', array_merge($cart_item_data, array('product_id' => $product_id, 'variation_id' => $variation_id, 'variation' => $variation, 'quantity' => $quantity, 'data' => $product_data)), $cart_item_key); } return $cart_item_key; }
/** * Validate that all managed items in the collection are in stock. * * @param int $bundle_id * @return boolean */ public function validate_stock($bundle_id) { $managed_items = $this->get_managed_items(); if (empty($managed_items)) { return true; } // Stock Validation foreach ($managed_items as $managed_item_id => $managed_item) { $quantity = $managed_item['quantity']; // Get the product $product_data = WC_PB_Core_Compatibility::wc_get_product($managed_item_id); if (!$product_data) { return false; } // is_sold_individually if ($product_data->sold_individually === 'yes' && $quantity > 1) { wc_add_notice(sprintf(__('"%1$s" cannot be added to the cart — only 1 "%2$s" may be purchased.', 'woocommerce-product-bundles'), get_the_title($bundle_id), $product_data->get_title()), 'error'); return false; } // Stock check - only check if we're managing stock and backorders are not allowed if (!$product_data->is_in_stock()) { if ($product_data->product_type === 'variable') { wc_add_notice(sprintf(__('"%1$s" cannot be added to the cart because your "%2$s" selection is out of stock.', 'woocommerce-product-bundles'), get_the_title($bundle_id), $product_data->get_title()), 'error'); } else { wc_add_notice(sprintf(__('"%1$s" cannot be added to the cart because "%2$s" is out of stock.', 'woocommerce-product-bundles'), get_the_title($bundle_id), $product_data->get_title()), 'error'); } return false; } elseif (!$product_data->has_enough_stock($quantity)) { if ($product_data->product_type === 'variable') { wc_add_notice(sprintf(__('"%1$s" cannot be added to the cart because your "%2$s" selection does not have enough stock (%3$s remaining).', 'woocommerce-product-bundles'), get_the_title($bundle_id), $product_data->get_title(), $product_data->get_stock_quantity()), 'error'); } else { wc_add_notice(sprintf(__('"%1$s" cannot be added to the cart because there is not enough stock of "%2$s" (%3$s remaining).', 'woocommerce-product-bundles'), get_the_title($bundle_id), $product_data->get_title(), $product_data->get_stock_quantity()), 'error'); } return false; } // Stock check - this time accounting for whats already in-cart $product_qty_in_cart = WC()->cart->get_cart_item_quantities(); if ($product_data->managing_stock()) { // Variations if ($managed_item['is_variation'] && $product_data->variation_has_stock) { if (isset($product_qty_in_cart[$managed_item_id]) && !$product_data->has_enough_stock($product_qty_in_cart[$managed_item_id] + $quantity)) { wc_add_notice(sprintf('<a href="%s" class="button wc-forward">%s</a> %s', WC()->cart->get_cart_url(), __('View Cart', 'woocommerce'), sprintf(__('"%1$s" cannot be added to the cart because the option selected for "%2$s" does not have enough stock — we have %3$s in stock and you already have %4$s in your cart.', 'woocommerce-product-bundles'), get_the_title($bundle_id), $product_data->get_title(), $product_data->get_stock_quantity(), $product_qty_in_cart[$managed_item_id])), 'error'); return false; } // Products } else { if (isset($product_qty_in_cart[$managed_item_id]) && !$product_data->has_enough_stock($product_qty_in_cart[$managed_item_id] + $quantity)) { wc_add_notice(sprintf('<a href="%s" class="button wc-forward">%s</a> %s', WC()->cart->get_cart_url(), __('View Cart', 'woocommerce'), sprintf(__('"%1$s" cannot be added to the cart because there is not enough stock of "%2$s" — we have %3$s in stock and you already have %4$s in your cart.', 'woocommerce-product-bundles'), get_the_title($bundle_id), $product_data->get_title(), $product_data->get_stock_quantity(), $product_qty_in_cart[$managed_item_id])), 'error'); return false; } } } } return true; }
/** * Handles adding bundled products via ajax. * * @return void */ function ajax_add_bundled_product() { global $woocommerce_bundles; check_ajax_referer('wc_bundles_add_bundled_product', 'security'); $loop = intval($_POST['id']); $post_id = intval($_POST['post_id']); $product_id = intval($_POST['product_id']); $title = $woocommerce_bundles->helpers->get_product_title($product_id); $product = WC_PB_Core_Compatibility::wc_get_product($product_id); $response = array(); $response['markup'] = ''; $response['message'] = ''; if ($title && $product) { if (in_array($product->product_type, array('simple', 'variable', 'subscription'))) { ob_start(); include 'html-bundled-product-admin.php'; $response['markup'] = ob_get_clean(); } else { $response['message'] = __('The selected product cannot be bundled. Please select a simple product, a variable product, or a simple subscription.', 'woocommerce-product-bundles'); } } else { $response['message'] = __('The selected product is invalid.', 'woocommerce-product-bundles'); } header('Content-Type: application/json; charset=utf-8'); echo json_encode($response); die; }
/** * Inserts bundle contents after main wishlist bundle item is displayed. * * @param array $item Wishlist item * @param array $wishlist Wishlist * @return void */ function woo_bundles_wishlist_after_list_item_name($item, $wishlist) { if ($item['data']->is_type('bundle') && !empty($item['stamp'])) { echo '<dl>'; foreach ($item['stamp'] as $bundled_item_id => $bundled_item_data) { echo '<dt class="bundled_title_meta wishlist_bundled_title_meta">' . get_the_title($bundled_item_data['product_id']) . ' <strong class="bundled_quantity_meta wishlist_bundled_quantity_meta product-quantity">× ' . $bundled_item_data['quantity'] . '</strong></dt>'; if (!empty($bundled_item_data['attributes'])) { $attributes = ''; foreach ($bundled_item_data['attributes'] as $attribute_name => $attribute_value) { $taxonomy = wc_attribute_taxonomy_name(str_replace('attribute_pa_', '', urldecode($attribute_name))); // If this is a term slug, get the term's nice name if (taxonomy_exists($taxonomy)) { $term = get_term_by('slug', $attribute_value, $taxonomy); if (!is_wp_error($term) && $term && $term->name) { $attribute_value = $term->name; } $label = wc_attribute_label($taxonomy); // If this is a custom option slug, get the options name } else { $attribute_value = apply_filters('woocommerce_variation_option_name', $attribute_value); $bundled_product = WC_PB_Core_Compatibility::wc_get_product($bundled_item_data['product_id']); $product_attributes = $bundled_product->get_attributes(); if (isset($product_attributes[str_replace('attribute_', '', $attribute_name)])) { $label = wc_attribute_label($product_attributes[str_replace('attribute_', '', $attribute_name)]['name']); } else { $label = $attribute_name; } } $attributes = $attributes . $label . ': ' . $attribute_value . ', '; } echo '<dd class="bundled_attribute_meta wishlist_bundled_attribute_meta">' . rtrim($attributes, ', ') . '</dd>'; } } echo '</dl>'; echo '<p class="bundled_notice wishlist_component_notice">' . __('*', 'woocommerce-product-bundles') . ' <em>' . __('For accurate pricing details, please add the product in your cart.', 'woocommerce-product-bundles') . '</em></p>'; } }