From d42d7c13b6d472454084e19d7e3d7085453b6e8f Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Fri, 13 May 2016 19:06:16 +0100 Subject: [PATCH] Prevent variations being created/returned without parents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nasty bug discovered by @RiaanKnoetze where it would get a variation without parent, and due to the return, it wouldn’t be ‘seen’ as a variation, therefore creating fatal errors when props are called. To prevent this, lets allow product constructors to throw exceptions. If they do, the factory class will catch them and return false instead of an invalid product object. @claudiosmweb Thoughts on this one before merge? --- includes/class-wc-product-factory.php | 35 ++++++++++++++----------- includes/class-wc-product-variation.php | 4 +-- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/includes/class-wc-product-factory.php b/includes/class-wc-product-factory.php index 79b316af799..582fefd8e4e 100644 --- a/includes/class-wc-product-factory.php +++ b/includes/class-wc-product-factory.php @@ -18,30 +18,35 @@ if ( ! defined( 'ABSPATH' ) ) { class WC_Product_Factory { /** - * Get product. + * Get a product. * * @param bool $the_product (default: false) * @param array $args (default: array()) * @return WC_Product|bool false if the product cannot be loaded */ public function get_product( $the_product = false, $args = array() ) { - $the_product = $this->get_product_object( $the_product ); + try { + $the_product = $this->get_product_object( $the_product ); - if ( ! $the_product ) { + if ( ! $the_product ) { + throw new Exception( 'Product object does not exist', 422 ); + } + + $classname = $this->get_product_class( $the_product, $args ); + + if ( ! $classname ) { + throw new Exception( 'Missing classname', 422 ); + } + + if ( ! class_exists( $classname ) ) { + $classname = 'WC_Product_Simple'; + } + + return new $classname( $the_product, $args ); + + } catch ( Exception $e ) { return false; } - - $classname = $this->get_product_class( $the_product, $args ); - - if ( ! $classname ) { - return false; - } - - if ( ! class_exists( $classname ) ) { - $classname = 'WC_Product_Simple'; - } - - return new $classname( $the_product, $args ); } /** diff --git a/includes/class-wc-product-variation.php b/includes/class-wc-product-variation.php index 658d662096d..8ef88acb39d 100644 --- a/includes/class-wc-product-variation.php +++ b/includes/class-wc-product-variation.php @@ -80,9 +80,9 @@ class WC_Product_Variation extends WC_Product { /* Get main product data from parent (args) */ $this->id = ! empty( $args['parent_id'] ) ? intval( $args['parent_id'] ) : wp_get_post_parent_id( $this->variation_id ); - // The post doesn't have a parent id, therefore its invalid. + // The post doesn't have a parent id, therefore its invalid and we should prevent this being created. if ( empty( $this->id ) ) { - return; + throw new Exception( sprintf( 'No parent product set for variation #%d', $this->variation_id ), 422 ); } $this->product_type = 'variation';