/**
  * Bundled cart items inherit the subscription schemes of their parent if:
  *  - parent is statically priced, or
  *  - parent has subscription schemes defined at product-level.
  *
  * @param  array  $schemes
  * @param  array  $cart_item
  * @param  string $scope
  * @return array
  */
 public static function get_bundled_item_schemes($schemes, $cart_item, $scope)
 {
     foreach (self::$container_key_names as $container_key_name) {
         if (!empty($cart_item[$container_key_name])) {
             $container_key = $cart_item[$container_key_name];
             if (isset(WC()->cart->cart_contents[$container_key])) {
                 $container_cart_item = WC()->cart->cart_contents[$container_key];
                 if (self::overrides_child_schemes($container_cart_item)) {
                     $schemes = WCS_ATT_Schemes::get_subscription_schemes($container_cart_item, $scope);
                 }
             }
         }
     }
     return $schemes;
 }
 /**
  * Add subscription price string info to products with attached subscription schemes.
  *
  * @param  string     $price
  * @param  WC_Product $product
  * @return string
  */
 public static function filter_price_html($price, $product)
 {
     if (self::$bypass_price_html_filter) {
         return $price;
     }
     $subscription_schemes = WCS_ATT_Schemes::get_product_subscription_schemes($product);
     $has_product_level_schemes = empty($subscription_schemes) ? false : true;
     if ($has_product_level_schemes) {
         $force_subscription = get_post_meta($product->id, '_wcsatt_force_subscription', true);
         if ($force_subscription === 'yes') {
             $subscription_scheme = current($subscription_schemes);
             $overridden_prices = WCS_ATT_Schemes::get_subscription_scheme_prices($product, $subscription_scheme);
             $suffix = '';
             $_cloned = clone $product;
             $_cloned->is_converted_to_sub = 'yes';
             $_cloned->subscription_period = $subscription_scheme['subscription_period'];
             $_cloned->subscription_period_interval = $subscription_scheme['subscription_period_interval'];
             $_cloned->subscription_length = $subscription_scheme['subscription_length'];
             if (!empty($overridden_prices)) {
                 $_cloned->regular_price = $overridden_prices['regular_price'];
                 $_cloned->price = $overridden_prices['price'];
                 $_cloned->sale_price = $overridden_prices['sale_price'];
                 $_cloned->subscription_price = $overridden_prices['price'];
             }
             self::$bypass_price_html_filter = true;
             $price = $_cloned->get_price_html();
             self::$bypass_price_html_filter = false;
             $price = WC_Subscriptions_Product::get_price_string($_cloned, array('price' => $price));
             if (count($subscription_schemes) > 1 && false === strpos($price, $_cloned->get_price_html_from_text())) {
                 $price = sprintf(_x('%1$s%2$s', 'Price range: from', WCS_ATT::TEXT_DOMAIN), $_cloned->get_price_html_from_text(), $price);
             }
         } else {
             $price_overrides_exist = WCS_ATT_Schemes::subscription_price_overrides_exist($subscription_schemes);
             $lowest_scheme_price = $product->price;
             $lowest_scheme_sale_price = $product->sale_price;
             $lowest_scheme_regular_price = $product->regular_price;
             $lowest_scheme_price_html = '';
             $from_price = '';
             if ($price_overrides_exist) {
                 foreach ($subscription_schemes as $subscription_scheme) {
                     $overridden_prices = WCS_ATT_Schemes::get_subscription_scheme_prices($product, $subscription_scheme);
                     if (!empty($overridden_prices)) {
                         if ($overridden_prices['price'] < $lowest_scheme_price) {
                             $lowest_scheme_price = $overridden_prices['price'];
                             $lowest_scheme_sale_price = $overridden_prices['sale_price'];
                             $lowest_scheme_regular_price = $overridden_prices['regular_price'];
                         }
                     }
                 }
                 if ($lowest_scheme_price < $product->price) {
                     $_cloned = clone $product;
                     $_cloned->is_converted_to_sub = 'yes';
                     $_cloned->subscription_period = $subscription_scheme['subscription_period'];
                     $_cloned->subscription_period_interval = $subscription_scheme['subscription_period_interval'];
                     $_cloned->subscription_length = $subscription_scheme['subscription_length'];
                     $_cloned->price = $lowest_scheme_price;
                     $_cloned->sale_price = $lowest_scheme_price;
                     $_cloned->regular_price = $lowest_scheme_regular_price;
                     self::$bypass_price_html_filter = true;
                     $lowest_scheme_price_html = $_cloned->get_price_html();
                     $lowest_scheme_price_html = WC_Subscriptions_Product::get_price_string($_cloned, array('price' => $lowest_scheme_price_html));
                     self::$bypass_price_html_filter = false;
                     if (count($subscription_schemes) > 1) {
                         $from_price = sprintf(_x('%1$s%2$s', 'Price range: from', WCS_ATT::TEXT_DOMAIN), _x('<span class="from">from </span>', 'min-price: 1 plan available', WCS_ATT::TEXT_DOMAIN), $lowest_scheme_price_html);
                     } else {
                         $from_price = sprintf(_x('%1$s%2$s', 'Price range: from', WCS_ATT::TEXT_DOMAIN), _x('<span class="for">for </span>', 'min-price: multiple plans available', WCS_ATT::TEXT_DOMAIN), $lowest_scheme_price_html);
                     }
                 }
             }
             if ($price_overrides_exist) {
                 $suffix = ' <small class="wcsatt-sub-options">' . sprintf(_n('&ndash; or subscribe %s', '&ndash; or subscribe %s', count($subscription_schemes), WCS_ATT::TEXT_DOMAIN), $from_price) . '</small>';
             } else {
                 $suffix = ' <small class="wcsatt-sub-options">' . sprintf(_n('&ndash; subscription plan available', '&ndash; subscription plans available', count($subscription_schemes), WCS_ATT::TEXT_DOMAIN), $from_price) . '</small>';
             }
             $price = sprintf(__('%1$s%2$s', 'price html sub options suffix', WCS_ATT::TEXT_DOMAIN), $price, $suffix);
         }
     }
     return $price;
 }
 /**
  * Cart items are converted to subscriptions here, then Subs code does all the magic.
  *
  * @param  WC_Cart $cart
  * @return void
  */
 public static function apply_convert_to_sub_session_data($cart)
 {
     $cart_level_schemes = WCS_ATT_Schemes::get_cart_subscription_schemes();
     foreach (WC()->cart->cart_contents as $cart_item_key => $cart_item) {
         if (isset($cart_item['wccsub_data'])) {
             // Initialize subscription scheme data
             $cart_item['wccsub_data']['active_subscription_scheme_id'] = WCS_ATT_Schemes::set_subscription_scheme_id($cart_item, $cart_level_schemes);
             // Convert the cart item to a subscription, if needed
             WC()->cart->cart_contents[$cart_item_key] = self::convert_to_sub($cart_item);
         }
     }
 }
 /**
  * Returns cart item pricing data based on the active subscription scheme settings of a cart item.
  *
  * @return string
  */
 public static function get_active_subscription_scheme_prices($cart_item, $active_subscription_scheme = array())
 {
     $prices = array();
     if (empty($active_subscription_scheme)) {
         $active_subscription_scheme = WCS_ATT_Schemes::get_active_subscription_scheme($cart_item);
     }
     if (!empty($active_subscription_scheme)) {
         $prices = self::get_subscription_scheme_prices(array('price' => $cart_item['data']->price, 'regular_price' => $cart_item['data']->regular_price, 'sale_price' => $cart_item['data']->sale_price), $active_subscription_scheme);
     }
     return $prices;
 }
 /**
  * Bundled cart items inherit the subscription schemes of their parent if:
  *  - parent is statically priced, or
  *  - parent has subscription schemes defined at product-level.
  *
  * @param  array  $schemes
  * @param  array  $cart_item
  * @param  string $scope
  * @return array
  */
 public static function get_bundled_item_schemes($schemes, $cart_item, $scope)
 {
     $container_key = self::has_bundle_type_container($cart_item);
     if (false !== $container_key) {
         if (isset(WC()->cart->cart_contents[$container_key])) {
             $container_cart_item = WC()->cart->cart_contents[$container_key];
             if (self::overrides_child_schemes($container_cart_item)) {
                 $schemes = WCS_ATT_Schemes::get_subscription_schemes($container_cart_item, $scope);
                 foreach ($schemes as $scheme) {
                     if (WCS_ATT_Scheme_Prices::has_subscription_price_override($scheme) && $scheme['subscription_pricing_method'] === 'override') {
                         $scheme['subscription_pricing_method'] = 'inherit';
                         $scheme['subscription_discount'] = '';
                     }
                 }
             }
         }
     }
     return $schemes;
 }
 /**
  * Adds subscription price string info to products with attached subscription schemes.
  *
  * @param  string     $price
  * @param  WC_Product $product
  * @return string
  */
 public static function filter_price_html($price, $product)
 {
     if (self::$bypass_price_html_filter) {
         return $price;
     }
     if ($product->get_price() === '') {
         return $price;
     }
     $product_level_schemes = WCS_ATT_Schemes::get_product_subscription_schemes($product);
     if (!empty($product_level_schemes)) {
         $has_variable_price = false;
         $subscription_scheme = current($product_level_schemes);
         if ($price_overrides_exist = WCS_ATT_Scheme_Prices::subscription_price_overrides_exist($product_level_schemes)) {
             $lowest_scheme_price_data = WCS_ATT_Scheme_Prices::get_lowest_price_subscription_scheme_data($product, $product_level_schemes);
             $subscription_scheme = $lowest_scheme_price_data['scheme'];
         }
         // Reinstantiate variable products to re-populate a filtered version of the 'prices_array' property. Otherwise, a clone should do... but re-instantiate just in case.
         $_product = wc_get_product($product->id);
         // ...and let this be filterable.
         $_product = apply_filters('wcsatt_overridden_subscription_prices_product', $_product, $subscription_scheme, $product);
         $_product->is_converted_to_sub = 'yes';
         $_product->subscription_period = isset($subscription_scheme['subscription_period']) ? $subscription_scheme['subscription_period'] : '';
         $_product->subscription_period_interval = isset($subscription_scheme['subscription_period_interval']) ? $subscription_scheme['subscription_period_interval'] : '';
         $_product->subscription_length = isset($subscription_scheme['subscription_length']) ? $subscription_scheme['subscription_length'] : '';
         // Add price method filters.
         WCS_ATT_Scheme_Prices::add_price_filters($_product, $subscription_scheme);
         if (count($product_level_schemes) > 1) {
             $has_variable_price = true;
         } else {
             if ('variable' === $product->product_type && $_product->get_variation_price('min') !== $_product->get_variation_price('max')) {
                 $has_variable_price = true;
                 // If all variations prices are overridden, they will be equal.
                 if (isset($subscription_scheme['subscription_pricing_method']) && $subscription_scheme['subscription_pricing_method'] === 'override') {
                     $has_variable_price = false;
                 }
             } elseif ('bundle' === $product->product_type && $product->get_bundle_price('min') !== $product->get_bundle_price('max')) {
                 $has_variable_price = true;
             } elseif ('composite' === $product->product_type && $product->get_composite_price('min') !== $product->get_composite_price('max')) {
                 $has_variable_price = true;
             }
         }
         $force_subscription = get_post_meta($product->id, '_wcsatt_force_subscription', true);
         if ($force_subscription === 'yes') {
             self::$bypass_price_html_filter = true;
             $price = $_product->get_price_html();
             self::$bypass_price_html_filter = false;
             $price = WC_Subscriptions_Product::get_price_string($_product, array('price' => $price));
             if ($has_variable_price && false === strpos($price, $_product->get_price_html_from_text())) {
                 $price = sprintf(_x('%1$s%2$s', 'Price range: from', WCS_ATT::TEXT_DOMAIN), $_product->get_price_html_from_text(), $price);
             }
         } else {
             $suffix_price_html = '';
             // Discount format vs Price format. Experimental use only.
             if (apply_filters('wcsatt_price_html_discount_format', false, $product) && WCS_ATT_Scheme_Prices::has_subscription_price_override($subscription_scheme) && $subscription_scheme['subscription_pricing_method'] === 'inherit') {
                 $discount = $subscription_scheme['subscription_discount'];
                 $discount_html = '</small> <span class="wcsatt-sub-discount">' . sprintf(__('%s&#37; off', WCS_ATT::TEXT_DOMAIN), $discount) . '</span><small>';
                 $suffix_price_html = sprintf(__('at%1$s%2$s', WCS_ATT::TEXT_DOMAIN), $has_variable_price ? __(' up to', WCS_ATT::TEXT_DOMAIN) : '', $discount_html);
             } else {
                 self::$bypass_price_html_filter = true;
                 $lowest_scheme_price_html = $_product->get_price_html();
                 self::$bypass_price_html_filter = false;
                 $lowest_scheme_price_data = isset($lowest_scheme_price_data) ? $lowest_scheme_price_data : array();
                 $lowest_scheme_price_html = WC_Subscriptions_Product::get_price_string($_product, apply_filters('wcsatt_get_single_product_lowest_price_string', array('price' => $lowest_scheme_price_html), $lowest_scheme_price_data));
                 if ($has_variable_price) {
                     $suffix_price_html = sprintf(_x('%1$s%2$s', 'Price range: from', WCS_ATT::TEXT_DOMAIN), _x('<span class="from">from </span>', 'subscribe from price', WCS_ATT::TEXT_DOMAIN), str_replace($_product->get_price_html_from_text(), '', $lowest_scheme_price_html));
                 } else {
                     $suffix_price_html = sprintf(_x('%1$s%2$s', 'Price range: from', WCS_ATT::TEXT_DOMAIN), _x('<span class="for">for </span>', 'subscribe for price', WCS_ATT::TEXT_DOMAIN), $lowest_scheme_price_html);
                 }
             }
             if ($price_overrides_exist) {
                 $suffix = ' <small class="wcsatt-sub-options">' . sprintf(_n('&ndash; or subscribe %s', '&ndash; subscription plans available %s', count($product_level_schemes), WCS_ATT::TEXT_DOMAIN), $suffix_price_html) . '</small>';
             } else {
                 $suffix = ' <small class="wcsatt-sub-options">' . sprintf(_n('&ndash; subscription available', '&ndash; subscription plans available', count($product_level_schemes), WCS_ATT::TEXT_DOMAIN), $suffix_price_html) . '</small>';
             }
             $price = sprintf(_x('%1$s%2$s', 'price html sub options suffix', WCS_ATT::TEXT_DOMAIN), $price, $suffix);
         }
         WCS_ATT_Scheme_Prices::remove_price_filters();
     }
     return $price;
 }
 /**
  * Add subscription price string info to products with attached subscription schemes.
  *
  * @param  string     $price
  * @param  WC_Product $product
  * @return string
  */
 public static function filter_price_html($price, $product)
 {
     $subscription_schemes = WCS_ATT_Schemes::get_product_subscription_schemes($product);
     $has_product_level_schemes = empty($subscription_schemes) ? false : true;
     if ($has_product_level_schemes) {
         $force_subscription = get_post_meta($product->id, '_wcsatt_force_subscription', true);
         if ($force_subscription === 'yes') {
             $subscription_scheme = current($subscription_schemes);
             $suffix = '';
             if (count($subscription_schemes) > 1) {
                 $suffix = ' <small class="wcsatt-sub-options">' . __('(additional subscription options available)', WCS_ATT::TEXT_DOMAIN) . '</small>';
             }
             $_cloned = clone $product;
             $_cloned->is_converted_to_sub = 'yes';
             $_cloned->subscription_period = $subscription_scheme['subscription_period'];
             $_cloned->subscription_period_interval = $subscription_scheme['subscription_period_interval'];
             $_cloned->subscription_length = $subscription_scheme['subscription_length'];
             $price = WC_Subscriptions_Product::get_price_string($_cloned, array('price' => $price));
             $price = sprintf(__('%1$s%2$s', 'price html sub options suffix', WCS_ATT::TEXT_DOMAIN), $price, $suffix);
         } else {
             $suffix = ' <small class="wcsatt-sub-options">' . __('(also available as subscription)', WCS_ATT::TEXT_DOMAIN) . '</small>';
             $price = sprintf(__('%1$s%2$s', 'price html sub options suffix', WCS_ATT::TEXT_DOMAIN), $price, $suffix);
         }
     }
     return $price;
 }