diff --git a/includes/rules_shipping_framework_woocommerce.php b/includes/rules_shipping_framework_woocommerce.php index 726601e0b841957addde3a0525063e2778f404ae..cd676f921c067f8100a1f5d1d1b47e144e57af28 100644 --- a/includes/rules_shipping_framework_woocommerce.php +++ b/includes/rules_shipping_framework_woocommerce.php @@ -14,11 +14,12 @@ require_once( plugin_dir_path( __FILE__ ) . '/../library/rules_shipping_framewor class RulesShippingFrameworkWooCommerce extends RulesShippingFramework { protected static $_method_ordering = 'woocommerce_shipping_rules_ordering'; - function _construct() { - parent::_construct(); + function __construct() { + parent::__construct(); load_plugin_textdomain('woocommerce-shipping-by-rules', false, basename( dirname( __FILE__ ) ) . '/languages' ); $this->registerScopings(array( "categories" => 'categories', + "subcategories" => 'subcategories', "products" => 'products', "skus" => 'products', )); @@ -291,10 +292,36 @@ class RulesShippingFrameworkWooCommerce extends RulesShippingFramework { */ public function filterProducts($products, $filter_conditions) { $result = array(); + + // For the subcategories scoping we need all subcategories of the conditions: + $subcategories = array(); + if (isset($filter_conditions['subcategories']) && !empty($filter_conditions['subcategories'])) { + foreach ($filter_conditions['subcategories'] as $catslug) { + // Get the term itself (we have only the slug!) + $cat = get_term_by('slug', $catslug, 'product_cat'); + if (empty($cat)) + continue; + $subcategories[] = $cat->slug; + // Get the list of all subcategories of the given categories + $args=array('child_of' => $cat->term_id, 'hierarchical' => 1); + foreach (get_terms( 'product_cat', $args) as $subcat) { + $subcategories[] = $subcat->slug; + } + } + $subcategories = array_unique($subcategories); + } + + // Now filter out all products that do not match the conditions foreach ($products as $p) { + $prodcategories = array(); + foreach (wc_get_product_terms( $p['data']->id, 'product_cat') as $cat) { + $prodcategories[] = $cat->slug; + } if (!empty($filter_conditions['products']) && !in_array($p['data']->get_sku(), $filter_conditions['products'])) continue; - if (!empty($filter_conditions['categories']) && count(array_intersect($filter_conditions['categories'], $p['data']->get_categories())==0)) + if (!empty($filter_conditions['categories']) && count(array_intersect($filter_conditions['categories'], $prodcategories))==0) + continue; + if (!empty($filter_conditions['subcategories']) && count(array_intersect($subcategories, $prodcategories))==0) continue; $result[] = $p; } diff --git a/includes/rules_shipping_framework_woocommerce_advanced.php b/includes/rules_shipping_framework_woocommerce_advanced.php index a120ad77ed60bccfb209d4b461ea49d9e99a5156..d0f467708ddbb8735b4140e25c82a16a0857aa7b 100644 --- a/includes/rules_shipping_framework_woocommerce_advanced.php +++ b/includes/rules_shipping_framework_woocommerce_advanced.php @@ -21,8 +21,8 @@ class RulesShippingFrameworkWooCommerceAdvanced extends RulesShippingFrameworkWo } return $helper; } - function _construct() { - parent::_construct(); + function __construct() { + parent::__construct(); } function isAdvanced() { return true; diff --git a/library/rules_shipping_framework.php b/library/rules_shipping_framework.php index aef007cabfe4be25354bbcd215f08bfa78354ef0..b34c48bb98a0d7c8a587a25a875b6c30f87b35fa 100644 --- a/library/rules_shipping_framework.php +++ b/library/rules_shipping_framework.php @@ -90,6 +90,14 @@ class RulesShippingFramework { $this->available_scopings = $scopings; } + /** + * Get the list of all scopings the framework implementation claims to have + * implemented. + */ + public function getScopings() { + return $this->available_scopings; + } + public function readableString($string) { switch ($string) { case "OTSHIPMENT_RULES_CUSTOMFUNCTIONS_ALREADY_DEFINED": @@ -777,27 +785,30 @@ class ShippingRule { } } + protected function normalizeScoping($scoping) { + $scopings = $this->framework->getScopings(); +// $this->framework->warning("<pre>normalizing Scoping $scoping. Registered scopings are: ".print_r($scopings,1)."</pre>"); + if (isset($scopings[$scoping])) { + return $scopings[$scoping]; + } else { + return false; + } + } + /** Evaluate the given expression $expr only for the products that match the filter given by the scoping * function and the corresponding conditions */ protected function evaluateScoping($expr, $scoping, $conditionvals, $vals, $products, $cartvals_callback) { if (count($conditionvals)<1) return $this->evaluateTerm($expr, $vals, $products, $cartvals_callback); - - // TODO: Make this more general! - $filterkeys = array( - "categories" => 'categories', - "products" => 'products', - "skus" => 'products', - "vendors" => 'vendors', - "manufacturers" => 'manufacturers', - ); - $conditions = array(); - if (isset($filterkeys[$scoping])) { - $conditions[$filterkeys[$scoping]] = $conditionvals; - } else { - $this->framworks->warning('OTSHIPMENT_RULES_SCOPING_UNKNOWN', $scoping, $this->rulestring); +// $this->framework->warning("<pre>evaluating scoping $scoping of expression ".print_r($expr,1)." with conditions ".print_r($conditionvals,1)."</pre>"); + // Normalize aliases (e.g. 'skus' and 'products' usually indicate the same scoping + $normalizedScoping = $this->normalizeScoping($scoping); + if (!$normalizedScoping) { + $this->framework->warning('OTSHIPMENT_RULES_SCOPING_UNKNOWN', $scoping, $this->rulestring); return false; + } else { + $conditions = array($normalizedScoping => $conditionvals); } // Pass the conditions to the parent plugin class to filter the current list of products: @@ -907,7 +918,7 @@ class ShippingRule { // The scoping functions need to be handled differently, because they first need to adjust the cart variables to the filtered product list // before evaluating its first argument. So even though parsing the rules handles scoping functions like any other function, their // evaluation is fundamentally different and is special-cased here: - $is_scoping = is_array($expr) && ($expr[0]=="FUNCTION") && (count($expr)>1) && (substr($expr[1], 0, 13)==="evaluate_for_")); + $is_scoping = is_array($expr) && ($expr[0]=="FUNCTION") && (count($expr)>1) && (substr($expr[1], 0, 13)==="evaluate_for_"); if (is_null($expr)) { return $expr; diff --git a/releases/opentools-woocommerce-advanced-shipping-by-rules_v1.1.zip b/releases/opentools-woocommerce-advanced-shipping-by-rules_v1.1.zip index bb5caa12ccf4f9ab3edf07da27b2a87a3334aa82..9de621dcc2c182bdc1063f8b72394e3aabb57961 100644 Binary files a/releases/opentools-woocommerce-advanced-shipping-by-rules_v1.1.zip and b/releases/opentools-woocommerce-advanced-shipping-by-rules_v1.1.zip differ diff --git a/releases/opentools-woocommerce-shipping-by-rules_v1.1.zip b/releases/opentools-woocommerce-shipping-by-rules_v1.1.zip index 0b906f423d082006d5668bc9ebe8e0b375af70ec..e58e29a4b3c434bad9aeb8435407e4a137376086 100644 Binary files a/releases/opentools-woocommerce-shipping-by-rules_v1.1.zip and b/releases/opentools-woocommerce-shipping-by-rules_v1.1.zip differ