/**
 * get_option( 'woocommerce_price_num_decimals' ) cache.
 *
 * @return string
 */
function wc_cp_price_num_decimals()
{
    $wc_price_num_decimals = WC_CP()->api->cache_get('wc_price_num_decimals');
    if (null === $wc_price_num_decimals) {
        $wc_price_num_decimals = absint(get_option('woocommerce_price_num_decimals'));
        WC_CP()->api->cache_set('wc_price_num_decimals', $wc_price_num_decimals);
    }
    return $wc_price_num_decimals;
}
 /**
  * Load scripts for use by QV on non-product pages.
  *
  * @return  void
  */
 public static function load_scripts()
 {
     if (!is_product()) {
         WC_CP()->display->wc_cp_frontend_scripts();
         // Enqueue script.
         wp_enqueue_script('wc-add-to-cart-composite');
         // Enqueue styles.
         wp_enqueue_style('wc-composite-single-css');
     }
 }
 /**
  * Remove filters that modify bundled product prices when parent product is composited and has a discount.
  *
  * @param  string $cart_item_data
  * @return void
  */
 public static function bundled_cart_item_after_price_modification($cart_item_data)
 {
     if (isset($cart_item_data['bundled_by'])) {
         $bundle_key = $cart_item_data['bundled_by'];
         if (isset(WC()->cart->cart_contents[$bundle_key])) {
             $bundle_cart_data = WC()->cart->cart_contents[$bundle_key];
             if (isset($bundle_cart_data['composite_parent'])) {
                 $composite_key = $bundle_cart_data['composite_parent'];
                 if (isset(WC()->cart->cart_contents[$composite_key])) {
                     WC_CP()->api->remove_composited_product_filters();
                 }
             }
         }
     }
     return $cart_item_data;
 }
 /**
  * OPC Single-product bundle-type add-to-cart template
  *
  * @param  int  $opc_post_id
  * @return void
  */
 public static function opc_single_add_to_cart_composite($opc_post_id)
 {
     global $product;
     // Enqueue scripts
     wp_enqueue_script('wc-add-to-cart-composite');
     // Enqueue styles
     wp_enqueue_style('wc-composite-single-css');
     // Load NYP scripts
     if (function_exists('WC_Name_Your_Price')) {
         WC_Name_Your_Price()->display->nyp_scripts();
     }
     // Enqueue Bundle styles
     if (class_exists('WC_Bundles')) {
         wp_enqueue_style('wc-bundle-css');
     }
     $navigation_style = $product->get_composite_layout_style();
     $components = $product->get_composite_data();
     ob_start();
     if (!empty($components)) {
         wc_get_template('single-product/add-to-cart/composite.php', array('navigation_style' => $navigation_style, 'components' => $components, 'product' => $product), '', WC_CP()->plugin_path() . '/templates/');
     }
     echo str_replace(array('<form method="post" enctype="multipart/form-data"', '</form>'), array('<div', '</div>'), ob_get_clean());
 }
 /**
  * Get component thumbnail.
  *
  * @param  string $component_id
  * @return array
  */
 public function get_component_image($component_id)
 {
     $component_data = $this->get_component_data($component_id);
     if (!$component_data) {
         return '';
     }
     $image_src = '';
     if (!empty($component_data['thumbnail_id'])) {
         $image_src_data = wp_get_attachment_image_src($component_data['thumbnail_id'], apply_filters('woocommerce_composite_component_image_size', 'shop_catalog'));
         $image_src = $image_src_data ? current($image_src_data) : false;
     }
     if (!$image_src) {
         $image_src = WC_CP()->plugin_url() . '/assets/images/placeholder.png';
     }
     $image = sprintf('<img class="summary_element_content" alt="%s" src="%s"/>', __('Component image', 'woocommerce-composite-products'), $image_src);
     // Add class="norefresh" to prevent summary image updates and keep the original image static.
     // Return '' to hide all images from the summary section.
     return apply_filters('woocommerce_composite_component_image', $image, $image_src, $component_id, $this);
 }
/**
 * Composited single variation template.
 *
 * @param  WC_Product_Variable  $product
 * @param  string               $component_id
 * @param  WC_Product_Composite $composite
 * @return void
 */
function wc_cp_composited_single_variation($product, $component_id, $composite)
{
    $component_data = $composite->get_component_data($component_id);
    $quantity_min = $component_data['quantity_min'];
    $quantity_max = $component_data['quantity_max'];
    if ($product->sold_individually === 'yes') {
        $quantity_max = 1;
        $quantity_min = min($quantity_min, 1);
    }
    wc_get_template('composited-product/variation.php', array('quantity_min' => $quantity_min, 'quantity_max' => $quantity_max, 'component_id' => $component_id, 'product' => $product, 'composite_product' => $composite), '', WC_CP()->plugin_path() . '/templates/');
}
?>
" data-item_id="<?php 
echo $component_id;
?>
" style="display:none;">

	<div class="component_title_wrapper"><?php 
$title = apply_filters('woocommerce_composite_component_title', esc_html($component_data['title']), $component_id, $product->id);
wc_get_template('single-product/component-title.php', array('title' => apply_filters('woocommerce_composite_component_step_title', sprintf(__('<span class="step_index">%d</span> <span class="step_title">%s</span>', 'woocommerce-composite-products'), $step, $title), $title, $step, $steps, $product), 'toggled' => false), '', WC_CP()->plugin_path() . '/templates/');
?>
</div>

	<div class="component_inner">
		<div class="component_description_wrapper"><?php 
if ($component_data['description'] !== '') {
    wc_get_template('single-product/component-description.php', array('description' => apply_filters('woocommerce_composite_component_description', wpautop(do_shortcode(wp_kses_post($component_data['description']))), $component_id, $product->id)), '', WC_CP()->plugin_path() . '/templates/');
}
?>
</div>
		<div class="component_selections"><?php 
/**
 * woocommerce_composite_component_selections_paged hook (multi-page)
 *
 * @hooked wc_cp_add_sorting                      - 15
 * @hooked wc_cp_add_filtering                    - 20
 * @hooked wc_cp_add_component_options            - 25
 * @hooked wc_cp_add_component_options_pagination - 26
 * @hooked wc_cp_add_current_selection_details    - 30
 */
do_action('woocommerce_composite_component_selections_paged', $component_id, $product);
?>
 /**
  * Get bundled item regular price after discount.
  *
  * @param  string  $min_or_max
  * @param  boolean $display
  * @return double
  */
 public function get_regular_price($min_or_max = 'min', $display = false)
 {
     if (!$this->exists()) {
         return false;
     }
     $prop = $min_or_max . '_regular_price_product';
     $product = !empty($this->{$prop}) ? $this->{$prop} : $this->product;
     $price = $min_or_max === 'min' ? $this->min_regular_price : $this->max_regular_price;
     $price = apply_filters('woocommerce_get_regular_price', $price, $product);
     return apply_filters('woocommerce_composited_product_get_regular_price', $display ? WC_CP()->api->get_composited_product_price($product, $price) : $price, $min_or_max, $display, $this);
 }
 /**
  * Adds component title preambles to order-details template.
  *
  * @param  string 	$content
  * @param  array 	$order_item
  * @return string
  */
 public function wc_cp_order_table_component_title($content, $order_item)
 {
     if (!empty($order_item['composite_item'])) {
         $item_id = $order_item['composite_item'];
         $composite_data = maybe_unserialize($order_item['composite_data']);
         $composite_id = !empty($composite_data[$item_id]['composite_id']) ? $composite_data[$item_id]['composite_id'] : '';
         $item_title = apply_filters('woocommerce_composite_component_title', $composite_data[$item_id]['title'], $item_id, $composite_id);
         $item_quantity = apply_filters('woocommerce_composited_order_item_quantity_html', '<strong class="composited-product-quantity">' . sprintf(_x(' &times; %s', 'qty string', 'woocommerce-composite-products'), $order_item['qty']) . '</strong>', $order_item);
         if (did_action('woocommerce_view_order') || did_action('woocommerce_thankyou')) {
             $item_data = array('key' => $item_title, 'value' => $content . $item_quantity);
             $this->wc_cp_enqueue_composited_table_item_js();
             ob_start();
             wc_get_template('component-item.php', array('component_data' => $item_data), '', WC_CP()->plugin_path() . '/templates/');
             $content = ob_get_clean();
         } elseif (did_action('woocommerce_email_before_order_table') > did_action('woocommerce_email_after_order_table')) {
             $content = '<small><span style="display:block">' . wp_kses_post($item_title) . ':</span> ' . wp_kses_post($content) . '</small>';
         }
     }
     return $content;
 }
 /**
  * Ajax listener that fetches product markup when a new selection is made.
  *
  * @param  mixed    $product_id
  * @param  mixed    $item_id
  * @param  mixed    $container_id
  * @return string
  */
 public static function show_composited_product_ajax($product_id = '', $component_id = '', $composite_id = '')
 {
     global $product;
     if (isset($_POST['product_id']) && intval($_POST['product_id']) > 0 && isset($_POST['component_id']) && !empty($_POST['component_id']) && isset($_POST['composite_id']) && !empty($_POST['composite_id'])) {
         $product_id = intval($_POST['product_id']);
         $component_id = intval($_POST['component_id']);
         $composite_id = intval($_POST['composite_id']);
     } else {
         wp_send_json(array('result' => 'failure', 'reason' => 'required params missing', 'markup' => sprintf('<div class="component_data woocommerce-error" data-component_set="false" data-price="0" data-regular_price="0" data-product_type="invalid-data">%s</div>', __('Sorry, the selected item cannot be purchased at the moment.', 'woocommerce-composite-products'))));
     }
     $composite = wc_get_product($composite_id);
     $composited_product = $composite->get_composited_product($component_id, $product_id);
     $product = $composited_product->get_product();
     if (!$product || !$composited_product->is_purchasable()) {
         wp_send_json(array('result' => 'failure', 'reason' => 'product does not exist or is not purchasable', 'markup' => sprintf('<div class="component_data woocommerce-error" data-component_set="false" data-price="0" data-regular_price="0" data-product_type="invalid-product">%s</div>', __('Sorry, the selected item cannot be purchased at the moment.', 'woocommerce-composite-products'))));
     }
     $composite->sync_composite();
     ob_start();
     WC_CP()->api->apply_composited_product_filters($product, $component_id, $composite);
     do_action('woocommerce_composite_show_composited_product', $product, $component_id, $composite);
     WC_CP()->api->remove_composited_product_filters();
     $output = ob_get_clean();
     wp_send_json(array('result' => 'success', 'markup' => $output));
 }
 /**
  * Returns the following arrays:
  *
  * 1. $scenarios             - contains all scenario ids.
  * 2. $scenario_settings     - includes scenario actions and masked components in scenarios.
  * 3. $scenario_data         - maps every product/variation in a group to the scenarios where it is active.
  * 4. $defaults_in_scenarios - the scenarios where all default component selections coexist.
  *
  * @param  array $bto_scenario_meta     scenarios meta
  * @param  array $bto_data              component data - values may contain a 'current_component_options' key to generate scenarios for a subset of all component options
  * @return array
  */
 public static function build_scenarios($bto_scenario_meta, $bto_data)
 {
     $scenarios = empty($bto_scenario_meta) ? array() : array_map('strval', array_keys($bto_scenario_meta));
     $common_scenarios = $scenarios;
     $scenario_data = array();
     $scenario_settings = array();
     $compat_group_count = 0;
     // Store the 'actions' associated with every scenario.
     foreach ($scenarios as $scenario_id) {
         $scenario_settings['scenario_actions'][$scenario_id] = array();
         if (isset($bto_scenario_meta[$scenario_id]['scenario_actions'])) {
             $actions = array();
             foreach ($bto_scenario_meta[$scenario_id]['scenario_actions'] as $action_name => $action_data) {
                 if (isset($action_data['is_active']) && $action_data['is_active'] === 'yes') {
                     $actions[] = $action_name;
                     if ($action_name === 'compat_group') {
                         $compat_group_count++;
                     }
                 }
             }
             $scenario_settings['scenario_actions'][$scenario_id] = $actions;
         } else {
             $scenario_settings['scenario_actions'][$scenario_id] = array('compat_group');
             $compat_group_count++;
         }
     }
     $scenario_settings['scenario_actions']['0'] = array('compat_group');
     // Find which components in every scenario are 'non shaping components' (marked as unrelated).
     if (!empty($bto_scenario_meta)) {
         foreach ($bto_scenario_meta as $scenario_id => $scenario_single_meta) {
             $scenario_settings['masked_components'][$scenario_id] = array();
             foreach ($bto_data as $group_id => $group_data) {
                 if (isset($scenario_single_meta['modifier'][$group_id]) && $scenario_single_meta['modifier'][$group_id] === 'masked') {
                     $scenario_settings['masked_components'][$scenario_id][] = (string) $group_id;
                 }
             }
         }
     }
     $scenario_settings['masked_components']['0'] = array();
     // Include the '0' scenario for use when no 'compat_group' scenarios exist.
     if ($compat_group_count === 0) {
         $scenarios[] = '0';
     }
     // Map each product and variation to the scenarios that contain it.
     foreach ($bto_data as $group_id => $group_data) {
         $scenario_data[$group_id] = array();
         // 'None' option.
         if ($group_data['optional'] === 'yes') {
             $scenarios_for_product = self::get_scenarios_for_product($bto_scenario_meta, $group_id, -1, '', 'none');
             $scenario_data[$group_id][0] = $scenarios_for_product;
         }
         // Component options.
         // When indicated, build scenarios only based on a limited set of component options.
         if (isset($bto_data[$group_id]['current_component_options'])) {
             $component_options = $bto_data[$group_id]['current_component_options'];
             // Otherwise run a query to get all component options.
         } else {
             $component_options = WC_CP()->api->get_component_options($group_data);
         }
         foreach ($component_options as $product_id) {
             if (!is_numeric($product_id)) {
                 continue;
             }
             // Get product type.
             $terms = get_the_terms($product_id, 'product_type');
             $product_type = !empty($terms) && isset(current($terms)->name) ? sanitize_title(current($terms)->name) : 'simple';
             if ($product_type === 'variable') {
                 $variations = WC_CP_Helpers::get_product_variations($product_id);
                 if (!empty($variations)) {
                     $scenarios_for_product = array();
                     foreach ($variations as $variation_id) {
                         $scenarios_for_variation = self::get_scenarios_for_product($bto_scenario_meta, $group_id, $product_id, $variation_id, 'variation');
                         $scenarios_for_product = array_merge($scenarios_for_product, $scenarios_for_variation);
                         $scenario_data[$group_id][$variation_id] = $scenarios_for_variation;
                     }
                     $scenario_data[$group_id][$product_id] = array_values(array_unique($scenarios_for_product));
                 }
             } else {
                 $scenarios_for_product = self::get_scenarios_for_product($bto_scenario_meta, $group_id, $product_id, '', $product_type);
                 $scenario_data[$group_id][$product_id] = $scenarios_for_product;
             }
         }
         if (isset($group_data['default_id']) && $group_data['default_id'] !== '') {
             if (!empty($scenario_data[$group_id][$group_data['default_id']])) {
                 $common_scenarios = array_intersect($common_scenarios, $scenario_data[$group_id][$group_data['default_id']]);
             } else {
                 $common_scenarios = array();
             }
         }
     }
     return array('scenarios' => $scenarios, 'scenario_settings' => $scenario_settings, 'scenario_data' => $scenario_data, 'defaults_in_scenarios' => $common_scenarios);
 }
 /**
  * Support scanning for template overrides in extension.
  *
  * @param  array $paths
  * @return array
  */
 public function composite_template_scan_path($paths)
 {
     $paths['WooCommerce Composite Products'] = WC_CP()->plugin_path() . '/templates/';
     return $paths;
 }
Пример #13
0
}
?>
<form method="post" enctype="multipart/form-data" class="composite_form"><?php 
$loop = 0;
$steps = count($components);
/**
 * woocommerce_composite_before_components hook
 *
 * @hooked wc_cp_before_components - 10
 */
do_action('woocommerce_composite_before_components', $components, $product);
foreach ($components as $component_id => $component_data) {
    $loop++;
    if ($navigation_style == 'single') {
        wc_get_template('single-product/component-single-page.php', array('product' => $product, 'component_id' => $component_id, 'component_data' => $component_data, 'step' => $loop, 'steps' => $steps), '', WC_CP()->plugin_path() . '/templates/');
    } elseif ($navigation_style == 'progressive') {
        wc_get_template('single-product/component-single-page-progressive.php', array('product' => $product, 'component_id' => $component_id, 'component_data' => $component_data, 'step' => $loop, 'steps' => $steps), '', WC_CP()->plugin_path() . '/templates/');
    } else {
        wc_get_template('single-product/component-multi-page.php', array('product' => $product, 'component_id' => $component_id, 'component_data' => $component_data, 'step' => $loop, 'steps' => $steps), '', WC_CP()->plugin_path() . '/templates/');
    }
}
/**
 * woocommerce_composite_after_components hook
 *
 * @hooked wc_cp_after_components - 10
 * @hooked wc_cp_no_js_msg        - 15
 */
do_action('woocommerce_composite_after_components', $components, $product);
?>
</form>
    {
        delete_option('woocommerce_composite_products_version');
    }
    /**
     * Show row meta on the plugin screen.
     *
     * @param	mixed $links Plugin Row Meta
     * @param	mixed $file  Plugin Base file
     * @return	array
     */
    public function plugin_meta_links($links, $file)
    {
        if ($file == plugin_basename(__FILE__)) {
            $links[] = '<a href="http://docs.woothemes.com/document/composite-products/">' . __('Docs', 'woocommerce-composite-products') . '</a>';
            $links[] = '<a href="http://support.woothemes.com/">' . __('Support', 'woocommerce-composite-products') . '</a>';
        }
        return $links;
    }
}
/**
 * Returns the main instance of WC_Composite_Products to prevent the need to use globals.
 *
 * @since  3.2.3
 * @return WooCommerce Composite Products
 */
function WC_CP()
{
    return WC_Composite_Products::instance();
}
$GLOBALS['woocommerce_composite_products'] = WC_CP();
 public function tm_post_class($classes = "")
 {
     if (is_admin() || !$this->tm_related_products_output) {
         return $classes;
     }
     global $post;
     $post_id = get_the_ID();
     if ($post && ('product' == get_post_type($post_id) || $this->wc_vars['is_product'])) {
         $has_options = $this->get_product_tm_epos($post_id);
         if (is_array($has_options) && (!empty($has_options['global']) || !empty($has_options['local']))) {
             $classes[] = 'tm-has-options';
         } elseif ($this->tm_epo_enable_final_total_box_all == "yes") {
             $classes[] = 'tm-no-options-pxq';
         } else {
             $terms = get_the_terms($post_id, 'product_type');
             $product_type = !empty($terms) && isset(current($terms)->name) ? sanitize_title(current($terms)->name) : 'simple';
             if (($product_type == 'bto' || $product_type == 'composite') && !(is_array($has_options) && (!empty($has_options['global']) || !empty($has_options['local']))) && $this->tm_epo_enable_final_total_box_all != "yes") {
                 // search components for options
                 $product = wc_get_product($post_id);
                 $composite_data = $product->get_composite_data();
                 foreach ($composite_data as $component_id => $component_data) {
                     $component_options = array();
                     if (function_exists('WC_CP')) {
                         $component_options = WC_CP()->api->get_component_options($component_data);
                     } else {
                         global $woocommerce_composite_products;
                         if (is_object($woocommerce_composite_products) && function_exists('WC_CP')) {
                             $component_options = WC_CP()->api->get_component_options($component_data);
                         } else {
                             if (isset($component_data['assigned_ids']) && is_array($component_data['assigned_ids'])) {
                                 $component_options = $component_data['assigned_ids'];
                             }
                         }
                     }
                     foreach ($component_options as $key => $pid) {
                         $has_options = $this->get_product_tm_epos($pid);
                         if (is_array($has_options) && (!empty($has_options['global']) || !empty($has_options['local']))) {
                             $classes[] = 'tm-no-options-composite';
                             return $classes;
                         }
                     }
                 }
             }
             $classes[] = 'tm-no-options';
         }
     }
     return $classes;
 }
" data-product_type="simple" data-custom="<?php 
echo esc_attr(json_encode($custom_data));
?>
"><?php 
/**
 * woocommerce_composited_product_details hook.
 * @since 3.2.0
 *
 * @hooked wc_cp_composited_product_excerpt - 10
 */
do_action('woocommerce_composited_product_details', $product, $component_id, $composite_product);
?>
<div class="component_wrap"><?php 
/**
 * woocommerce_composited_product_add_to_cart hook.
 *
 * @hooked wc_cp_composited_product_price - 8
 */
do_action('woocommerce_composited_product_add_to_cart', $product, $component_id, $composite_product);
$availability = WC_CP()->api->get_composited_item_availability($product, $quantity_min);
$availability_html = empty($availability['availability']) ? '' : '<p class="stock ' . esc_attr($availability['class']) . '">' . esc_html($availability['availability']) . '</p>';
echo apply_filters('woocommerce_stock_html', $availability_html, $availability['availability'], $product);
?>
<div class="quantity_button"><?php 
wc_get_template('composited-product/quantity.php', array('quantity_min' => $quantity_min, 'quantity_max' => $quantity_max, 'component_id' => $component_id, 'product' => $product, 'composite_product' => $composite_product), '', WC_CP()->plugin_path() . '/templates/');
?>
</div>
	</div>
</div>

 /**
  * Validates that all composited items chosen can be added-to-cart before actually starting to add items.
  *
  * @param  bool 	$add
  * @param  int 		$product_id
  * @param  int 		$product_quantity
  * @return bool
  */
 public function wc_cp_validation($add, $product_id, $product_quantity, $variation_id = '', $variations = array(), $cart_item_data = array())
 {
     // Get product type
     $terms = get_the_terms($product_id, 'product_type');
     $product_type = !empty($terms) && isset(current($terms)->name) ? sanitize_title(current($terms)->name) : 'simple';
     // Ordering again?
     $order_again = isset($_GET['order_again']) && isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'woocommerce-order_again');
     // prevent composited items from getting validated - they will be added by the container item.
     if (isset($cart_item_data['is_composited']) && $order_again) {
         return false;
     }
     if ($product_type == 'composite') {
         // Get composite data
         $composite = wc_get_product($product_id);
         $composite_data = $composite->get_composite_data();
         $component_ids = array_keys($composite_data);
         // Check request and prepare validation data for stock and scenarios.
         $validate_scenarios = array();
         // If a stock-managed product / variation exists in the bundle multiple times, its stock will be checked only once for the sum of all bundled quantities.
         // The WC_CP_Stock_Manager class does exactly that
         $composited_stock = new WC_CP_Stock_Manager($composite);
         foreach ($component_ids as $component_id) {
             // Check that a product has been selected
             if (isset($_REQUEST['wccp_component_selection'][$component_id]) && $_REQUEST['wccp_component_selection'][$component_id] !== '') {
                 $composited_product_id = $_REQUEST['wccp_component_selection'][$component_id];
             } elseif (isset($cart_item_data['composite_data'][$component_id]['product_id']) && $order_again) {
                 $composited_product_id = $cart_item_data['composite_data'][$component_id]['product_id'];
             } else {
                 $_REQUEST['wccp_component_selection'][$component_id] = '';
                 // Save for later
                 $validate_scenarios[$component_id] = array();
                 $validate_scenarios[$component_id]['product_id'] = '0';
                 $validate_scenarios[$component_id]['product_type'] = 'none';
                 continue;
             }
             // Prevent people from f*****g around - only valid component options can be added to the cart.
             if (!in_array($composited_product_id, WC_CP()->api->get_component_options($composite_data[$component_id]))) {
                 return false;
             }
             $item_quantity_min = absint($composite_data[$component_id]['quantity_min']);
             $item_quantity_max = $composite_data[$component_id]['quantity_max'] !== '' ? absint($composite_data[$component_id]['quantity_max']) : '';
             // Check quantity
             if (isset($_REQUEST['wccp_component_quantity'][$component_id]) && is_numeric($_REQUEST['wccp_component_quantity'][$component_id])) {
                 $item_quantity = absint($_REQUEST['wccp_component_quantity'][$component_id]);
             } elseif (isset($cart_item_data['composite_data'][$component_id]['quantity']) && $order_again) {
                 $item_quantity = absint($cart_item_data['composite_data'][$component_id]['quantity']);
             } else {
                 $item_quantity = $item_quantity_min;
             }
             $quantity = $item_quantity * $product_quantity;
             $item_sold_individually = get_post_meta($composited_product_id, '_sold_individually', true);
             if ($item_sold_individually === 'yes' && $quantity > 1) {
                 $quantity = 1;
             }
             // Save for later.
             $validate_scenarios[$component_id] = array();
             $validate_scenarios[$component_id]['quantity'] = $item_quantity;
             $validate_scenarios[$component_id]['quantity_min'] = $item_quantity_min;
             $validate_scenarios[$component_id]['quantity_max'] = $item_quantity_max;
             $validate_scenarios[$component_id]['sold_individually'] = $item_sold_individually;
             // Get composited product type.
             $composited_product_wrapper = $composite->get_composited_product($component_id, $composited_product_id);
             if (!$composited_product_wrapper) {
                 wc_add_notice(sprintf(__('This &quot;%1$s&quot; configuration cannot be added to the cart. Please choose another &quot;%2$s&quot; option&hellip;', 'woocommerce-composite-products'), get_the_title($product_id), apply_filters('woocommerce_composite_component_title', $composite_data[$component_id]['title'], $component_id, $product_id)), 'error');
                 return false;
             }
             $composited_product = $composited_product_wrapper->get_product();
             $composited_product_type = $composited_product->product_type;
             // Save for later.
             $validate_scenarios[$component_id]['product_type'] = $composited_product_type;
             $validate_scenarios[$component_id]['product_id'] = $composited_product_id;
             // Validate attributes.
             if ($composited_product_type === 'variable') {
                 $variation_id = '';
                 if (isset($cart_item_data['composite_data'][$component_id]['variation_id']) && $order_again) {
                     $variation_id = $cart_item_data['composite_data'][$component_id]['variation_id'];
                 } elseif (isset($_REQUEST['wccp_variation_id'][$component_id])) {
                     $variation_id = $_REQUEST['wccp_variation_id'][$component_id];
                 }
                 if ($variation_id && is_numeric($variation_id) && $variation_id > 1) {
                     // Add item for validation.
                     $composited_stock->add_item($composited_product_id, $variation_id, $quantity);
                     // Save for later.
                     $validate_scenarios[$component_id]['variation_id'] = $variation_id;
                 }
                 // Verify all attributes for the variable product were set.
                 $composited_variation = wc_get_product($variation_id);
                 $attributes = $composited_product->get_attributes();
                 $variation_data = array();
                 $missing_attributes = array();
                 $all_set = true;
                 if ($composited_variation) {
                     $variation_data = $composited_variation->variation_data;
                 }
                 foreach ($attributes as $attribute) {
                     if (!$attribute['is_variation']) {
                         continue;
                     }
                     $taxonomy = 'attribute_' . sanitize_title($attribute['name']);
                     if (isset($_REQUEST['wccp_' . $taxonomy][$component_id])) {
                         if (WC_CP_Core_Compatibility::is_wc_version_gte_2_4()) {
                             // Get value from post data.
                             if ($attribute['is_taxonomy']) {
                                 $value = sanitize_title(stripslashes($_REQUEST['wccp_' . $taxonomy][$component_id]));
                             } else {
                                 $value = wc_clean(stripslashes($_REQUEST['wccp_' . $taxonomy][$component_id]));
                             }
                         } else {
                             // Get value from post data.
                             $value = sanitize_title(trim(stripslashes($_REQUEST['wccp_' . $taxonomy][$component_id])));
                         }
                         // Get valid value from variation.
                         $valid_value = $variation_data[$taxonomy];
                         // Allow if valid.
                         if ($valid_value === '' || $valid_value === $value) {
                             continue;
                         }
                     } elseif (isset($cart_item_data['composite_data'][$component_id]['attributes'][$taxonomy]) && isset($cart_item_data['composite_data'][$component_id]['variation_id']) && $order_again) {
                         if (WC_CP_Core_Compatibility::is_wc_version_gte_2_4()) {
                             // Get value from post data.
                             if ($attribute['is_taxonomy']) {
                                 $value = sanitize_title(stripslashes($cart_item_data['composite_data'][$component_id]['attributes'][$taxonomy]));
                             } else {
                                 $value = wc_clean(stripslashes($cart_item_data['composite_data'][$component_id]['attributes'][$taxonomy]));
                             }
                         } else {
                             // Get value from post data.
                             $value = sanitize_title(trim(stripslashes($cart_item_data['composite_data'][$component_id]['attributes'][$taxonomy])));
                         }
                         $valid_value = $variation_data[$taxonomy];
                         if ($valid_value === '' || $valid_value === $value) {
                             continue;
                         }
                     } else {
                         $missing_attributes[] = wc_attribute_label($attribute['name']);
                     }
                     $all_set = false;
                 }
                 if (!$all_set) {
                     if ($missing_attributes && WC_CP_Core_Compatibility::is_wc_version_gte_2_3()) {
                         $required_fields_notice = sprintf(_n('%1$s is a required &quot;%2$s&quot; field', '%1$s are required &quot;%2$s&quot; fields', sizeof($missing_attributes), 'woocommerce-composite-products'), wc_format_list_of_items($missing_attributes), apply_filters('woocommerce_composite_component_title', $composite_data[$component_id]['title'], $component_id, $product_id));
                         wc_add_notice(sprintf(__('This &quot;%1$s&quot; configuration cannot be added to the cart. %2$s.', 'woocommerce-composite-products'), get_the_title($product_id), $required_fields_notice), 'error');
                         return false;
                     } else {
                         wc_add_notice(sprintf(__('This &quot;%1$s&quot; configuration cannot be added to the cart. Please choose &quot;%2$s&quot; options&hellip;', 'woocommerce-composite-products'), get_the_title($product_id), apply_filters('woocommerce_composite_component_title', $composite_data[$component_id]['title'], $component_id, $product_id)), 'error');
                         return false;
                     }
                 }
             } elseif ($composited_product_type === 'simple') {
                 // Add item for validation.
                 $composited_stock->add_item($composited_product_id, false, $quantity);
             } else {
                 // Add item for validation.
                 $composited_stock->add_item($composited_product_id, false, $quantity);
             }
             if (!apply_filters('woocommerce_composite_component_add_to_cart_validation', true, $product_id, $component_id, $composited_product_id, $quantity, $cart_item_data)) {
                 return false;
             }
             // Allow composited products to add extra items to the stock manager.
             $composited_stock->add_stock(apply_filters('woocommerce_composite_component_associated_stock', '', $product_id, $component_id, $composited_product_id, $quantity));
         }
         /*
          * Stock Validation.
          */
         if (false === $composited_stock->validate_stock()) {
             return false;
         }
         /*
          * Scenarios Validation.
          */
         $scenario_data = get_post_meta($product_id, '_bto_scenario_data', true);
         $scenario_data = apply_filters('woocommerce_composite_scenario_meta', $scenario_data, $composite);
         $posted_scenarios = !empty($_POST['wccp_active_scenarios']) ? array_map('wc_clean', explode(',', $_POST['wccp_active_scenarios'])) : array();
         if (!empty($posted_scenarios)) {
             $scenario_data = array_intersect_key($scenario_data, array_flip($posted_scenarios));
         }
         // Build scenarios for the selected combination of options
         foreach ($composite_data as $component_id => &$modified_component_data) {
             if (isset($validate_scenarios[$component_id]) && $validate_scenarios[$component_id]['product_type'] !== 'none') {
                 $modified_component_data['current_component_options'] = array($validate_scenarios[$component_id]['product_id']);
             } else {
                 $modified_component_data['current_component_options'] = array('');
             }
         }
         $scenarios_for_products = apply_filters('woocommerce_composite_validation_scenario_data', WC_CP_Scenarios::build_scenarios($scenario_data, $composite_data), $composite_data, $scenario_data, $product_id);
         $common_scenarios = array_values($scenarios_for_products['scenarios']);
         $common_compat_group_scenarios = WC_CP_Scenarios::filter_scenarios_by_type($common_scenarios, 'compat_group', $scenarios_for_products);
         // Validate Selections.
         foreach ($composite_data as $component_id => $component_data) {
             if (isset($validate_scenarios[$component_id])) {
                 $validate_product_id = isset($validate_scenarios[$component_id]['variation_id']) ? $validate_scenarios[$component_id]['variation_id'] : $validate_scenarios[$component_id]['product_id'];
                 $scenarios_for_product = array();
                 $mandatory_override_check = false;
                 if ($validate_product_id === '0' && $component_data['optional'] === 'no') {
                     $mandatory_override_check = true;
                 }
                 if (!empty($scenarios_for_products['scenario_data'][$component_id][$validate_product_id])) {
                     $scenarios_for_product = $scenarios_for_products['scenario_data'][$component_id][$validate_product_id];
                     $compat_group_scenarios_for_product = WC_CP_Scenarios::filter_scenarios_by_type($scenarios_for_product, 'compat_group', $scenarios_for_products);
                 }
                 if (empty($compat_group_scenarios_for_product) || $mandatory_override_check) {
                     if ($validate_product_id === '0') {
                         // Allow 3rd parties to override notices for empty selections in non-optional components conditionally through scenarios.
                         if (apply_filters('woocommerce_composite_validation_component_is_mandatory', true, $component_id, $validate_scenarios[$component_id], $common_scenarios, $scenarios_for_products, $product_id)) {
                             wc_add_notice(sprintf(__('Please select a &quot;%s&quot; option.', 'woocommerce-composite-products'), apply_filters('woocommerce_composite_component_title', $component_data['title'], $component_id, $product_id)), 'error');
                             return false;
                         }
                     } else {
                         wc_add_notice(sprintf(__('Please select a different &quot;%s&quot; option &mdash; the selected product cannot be purchased at the moment.', 'woocommerce-composite-products'), apply_filters('woocommerce_composite_component_title', $component_data['title'], $component_id, $product_id)), 'error');
                         return false;
                     }
                 } else {
                     $common_scenarios = array_intersect($common_scenarios, $scenarios_for_product);
                     $common_compat_group_scenarios = array_intersect($common_compat_group_scenarios, $compat_group_scenarios_for_product);
                 }
             }
         }
         if (empty($common_compat_group_scenarios)) {
             wc_add_notice(__('The selected options cannot be purchased together. Please select a different configuration and try again.', 'woocommerce-composite-products'), 'error');
             return false;
         }
         // Validate Quantities.
         foreach ($composite_data as $component_id => $component_data) {
             if (!isset($validate_scenarios[$component_id]) || $validate_scenarios[$component_id]['product_type'] === 'none') {
                 continue;
             }
             $qty = $validate_scenarios[$component_id]['quantity'];
             // Allow 3rd parties to modify the min/max qty settings of a component conditionally through scenarios.
             $qty_min = absint(apply_filters('woocommerce_composite_validation_component_quantity_min', $component_data['quantity_min'], $component_id, $validate_scenarios[$component_id], $common_scenarios, $scenarios_for_products, $product_id));
             $qty_max = absint(apply_filters('woocommerce_composite_validation_component_quantity_max', $component_data['quantity_max'], $component_id, $validate_scenarios[$component_id], $common_scenarios, $scenarios_for_products, $product_id));
             $sold_individually = $validate_scenarios[$component_id]['sold_individually'];
             if ($qty < $qty_min && $sold_individually !== 'yes') {
                 wc_add_notice(sprintf(__('This &quot;%1$s&quot; configuration cannot be added to the cart. The quantity of &quot;%2$s&quot; cannot be lower than %3$d.', 'woocommerce-composite-products'), get_the_title($product_id), apply_filters('woocommerce_composite_component_title', $composite_data[$component_id]['title'], $component_id, $product_id), $qty_min), 'error');
                 return false;
             } elseif ($qty_max && $qty > $qty_max) {
                 wc_add_notice(sprintf(__('This &quot;%1$s&quot; configuration cannot be added to the cart. The quantity of &quot;%2$s&quot; cannot be higher than %3$d.', 'woocommerce-composite-products'), get_the_title($product_id), apply_filters('woocommerce_composite_component_title', $composite_data[$component_id]['title'], $component_id, $product_id), $qty_max), 'error');
                 return false;
             }
         }
         $add = apply_filters('woocommerce_add_to_cart_composite_validation', $add, $product_id, $composited_stock);
     }
     return $add;
 }
echo $is_static ? 'display:none;' : '';
?>
">

	<div class="component_options_inner cp_clearfix">

		<p class="component_section_title">
			<label class="select_label">
				<?php 
echo $selection_mode === 'thumbnails' ? __('Available options:', 'woocommerce-composite-products') : __('Select an option&hellip;', 'woocommerce-composite-products');
?>
			</label>
		</p><?php 
// Thumbnails template
if ($selection_mode === 'thumbnails') {
    wc_get_template('single-product/component-option-thumbnails.php', array('product' => $product, 'component_id' => $component_id, 'quantity_min' => $quantity_min, 'quantity_max' => $quantity_max, 'component_options' => $component_options, 'selected_option' => $selected_option), '', WC_CP()->plugin_path() . '/templates/');
}
?>
<div class="component_options_select_wrapper" style="<?php 
echo $selection_mode === 'thumbnails' ? 'display:none;' : '';
?>
">
			<select id="component_options_<?php 
echo $component_id;
?>
" class="component_options_select" name="wccp_component_selection[<?php 
echo $component_id;
?>
]"><?php 
if (!$is_static) {
    ?>