/**
* Product Factory
*
* The WooCommerce product factory creating the right product object.
*
* @package WooCommerce/Classes
* @version 3.0.0
*/
/**
* Product factory class.
*/
class WC_Product_Factory {}
This class is used to find the targeted product class by the product type using product ID.
The get_product()
is the main method in this class which retrieves the right product class using the given product ID.
/**
* Get a product.
*
* @param mixed $product_id WC_Product|WP_Post|int|bool $product Product instance, post instance, numeric or false to use global $post.
* @param array $deprecated Previously used to pass arguments to the factory, e.g. to force a type.
* @return WC_Product|bool Product object or false if the product cannot be loaded.
*/
public function get_product( $product_id = false, $deprecated = array() ) {
$product_id = $this->get_product_id( $product_id );
if ( ! $product_id ) {
return false;
}
$product_type = $this->get_product_type( $product_id );
// Backwards compatibility.
if ( ! empty( $deprecated ) ) {
wc_deprecated_argument( 'args', '3.0', 'Passing args to the product factory is deprecated. If you need to force a type, construct the product class directly.' );
if ( isset( $deprecated['product_type'] ) ) {
$product_type = $this->get_classname_from_product_type( $deprecated['product_type'] );
}
}
$classname = $this->get_product_classname( $product_id, $product_type );
try {
return new $classname( $product_id, $deprecated );
} catch ( Exception $e ) {
return false;
}
}
/**
* Simple Product Class.
*
* The default product type kinda product.
*
* @package WooCommerce/Classes/Products
*/
/**
* Simple product class.
*/
class WC_Product_Simple extends WC_Product {}
This is the default product class which handles the data processing of the default product type by extending the WC_Product
class.
The main data processing tasks are maintained in the parent class. So, only the helper functions used in the product loop are maintained here.
/**
* Initialize simple product.
*
* @param WC_Product|int $product Product instance or ID.
*/
public function __construct( $product = 0 ) {
$this->supports[] = 'ajax_add_to_cart';
parent::__construct( $product );
}
/**
* WooCommerce product base class.
*
* @package WooCommerce/Abstracts
*/
/**
* Abstract Product Class
*
* The WooCommerce product class handles individual product data.
*
* @version 3.0.0
* @package WooCommerce/Abstracts
*/
class WC_Product extends WC_Abstract_Legacy_Product {}
This class handles individual product data
/**
* This is the name of this object type.
*
* @var string
*/
protected $object_type = 'product';
/**
* Post type.
*
* @var string
*/
protected $post_type = 'product';
/**
* Cache group.
*
* @var string
*/
protected $cache_group = 'products';
/**
* Stores product data.
*
* @var array
*/
protected $data = array(
'name' => '',
'slug' => '',
'date_created' => null,
'date_modified' => null,
'status' => false,
'featured' => false,
'catalog_visibility' => 'visible',
'description' => '',
'short_description' => '',
'sku' => '',
'price' => '',
'regular_price' => '',
'sale_price' => '',
'date_on_sale_from' => null,
'date_on_sale_to' => null,
'total_sales' => '0',
'tax_status' => 'taxable',
'tax_class' => '',
'manage_stock' => false,
'stock_quantity' => null,
'stock_status' => 'instock',
'backorders' => 'no',
'low_stock_amount' => '',
'sold_individually' => false,
'weight' => '',
'length' => '',
'width' => '',
'height' => '',
'upsell_ids' => array(),
'cross_sell_ids' => array(),
'parent_id' => 0,
'reviews_allowed' => true,
'purchase_note' => '',
'attributes' => array(),
'default_attributes' => array(),
'menu_order' => 0,
'post_password' => '',
'virtual' => false,
'downloadable' => false,
'category_ids' => array(),
'tag_ids' => array(),
'shipping_class_id' => 0,
'downloads' => array(),
'image_id' => '',
'gallery_image_ids' => array(),
'download_limit' => -1,
'download_expiry' => -1,
'rating_counts' => array(),
'average_rating' => 0,
'review_count' => 0,
);
/**
* Supported features such as 'ajax_add_to_cart'.
*
* @var array
*/
protected $supports = array();
/**
* Get the product if ID is passed, otherwise the product is new and empty.
* This class should NOT be instantiated, but the wc_get_product() function
* should be used. It is possible, but the wc_get_product() is preferred.
*
* @param int|WC_Product|object $product Product to init.
*/
public function __construct( $product = 0 ) {
parent::__construct( $product );
if ( is_numeric( $product ) && $product > 0 ) {
$this->set_id( $product );
} elseif ( $product instanceof self ) {
$this->set_id( absint( $product->get_id() ) );
} elseif ( ! empty( $product->ID ) ) {
$this->set_id( absint( $product->ID ) );
} else {
$this->set_object_read( true );
}
$this->data_store = WC_Data_Store::load( 'product-' . $this->get_type() );
if ( $this->get_id() > 0 ) {
$this->data_store->read( $this );
}
}
// Path: wp-content\plugins\woocommerce\includes\class-wc-shortcodes.php
/**
* Shortcodes
*
* @package WooCommerce/Classes
* @version 3.2.0
*/
/**
* WooCommerce Shortcodes class.
*/
class WC_Shortcodes {}
/**
* Init shortcodes.
*/
public static function init() {
$shortcodes = array(
'product' => __CLASS__ . '::product',
'product_page' => __CLASS__ . '::product_page',
'product_category' => __CLASS__ . '::product_category',
'product_categories' => __CLASS__ . '::product_categories',
'add_to_cart' => __CLASS__ . '::product_add_to_cart',
'add_to_cart_url' => __CLASS__ . '::product_add_to_cart_url',
'products' => __CLASS__ . '::products',
'recent_products' => __CLASS__ . '::recent_products',
'sale_products' => __CLASS__ . '::sale_products',
'best_selling_products' => __CLASS__ . '::best_selling_products',
'top_rated_products' => __CLASS__ . '::top_rated_products',
'featured_products' => __CLASS__ . '::featured_products',
'product_attribute' => __CLASS__ . '::product_attribute',
'related_products' => __CLASS__ . '::related_products',
'shop_messages' => __CLASS__ . '::shop_messages',
'woocommerce_order_tracking' => __CLASS__ . '::order_tracking',
'woocommerce_cart' => __CLASS__ . '::cart',
'woocommerce_checkout' => __CLASS__ . '::checkout',
'woocommerce_my_account' => __CLASS__ . '::my_account',
);
foreach ( $shortcodes as $shortcode => $function ) {
add_shortcode( apply_filters( "{$shortcode}_shortcode_tag", $shortcode ), $function );
}
// Alias for pre 2.1 compatibility.
add_shortcode( 'woocommerce_messages', __CLASS__ . '::shop_messages' );
}
/**
* List multiple products shortcode.
*
* @param array $atts Attributes.
* @return string
*/
public static function products( $atts ) {
$atts = (array) $atts;
$type = 'products';
// Allow list product based on specific cases.
if ( isset( $atts['on_sale'] ) && wc_string_to_bool( $atts['on_sale'] ) ) {
$type = 'sale_products';
} elseif ( isset( $atts['best_selling'] ) && wc_string_to_bool( $atts['best_selling'] ) ) {
$type = 'best_selling_products';
} elseif ( isset( $atts['top_rated'] ) && wc_string_to_bool( $atts['top_rated'] ) ) {
$type = 'top_rated_products';
}
$shortcode = new WC_Shortcode_Products( $atts, $type );
return $shortcode->get_content();
}
// Path:
/**
* Products shortcode
*
* @package WooCommerce/Shortcodes
* @version 3.2.4
*/
/**
* Products shortcode class.
*/
class WC_Shortcode_Products {}
/**
* Initialize shortcode.
*
* @since 3.2.0
* @param array $attributes Shortcode attributes.
* @param string $type Shortcode type.
*/
public function __construct( $attributes = array(), $type = 'products' ) {
$this->type = $type;
$this->attributes = $this->parse_attributes( $attributes );
$this->query_args = $this->parse_query_args();
}
/**
* Get shortcode content.
*
* @since 3.2.0
* @return string
*/
public function get_content() {
return $this->product_loop();
}
/**
* Loop over found products.
*
* @since 3.2.0
* @return string
*/
protected function product_loop() {
$columns = absint( $this->attributes['columns'] );
$classes = $this->get_wrapper_classes( $columns );
$products = $this->get_query_results();
ob_start();
if ( $products && $products->ids ) {
// Prime caches to reduce future queries.
if ( is_callable( '_prime_post_caches' ) ) {
_prime_post_caches( $products->ids );
}
// Setup the loop.
wc_setup_loop(
array(
'columns' => $columns,
'name' => $this->type,
'is_shortcode' => true,
'is_search' => false,
'is_paginated' => wc_string_to_bool( $this->attributes['paginate'] ),
'total' => $products->total,
'total_pages' => $products->total_pages,
'per_page' => $products->per_page,
'current_page' => $products->current_page,
)
);
$original_post = $GLOBALS['post'];
do_action( "woocommerce_shortcode_before_{$this->type}_loop", $this->attributes );
// Fire standard shop loop hooks when paginating results so we can show result counts and so on.
if ( wc_string_to_bool( $this->attributes['paginate'] ) ) {
do_action( 'woocommerce_before_shop_loop' );
}
woocommerce_product_loop_start();
if ( wc_get_loop_prop( 'total' ) ) {
foreach ( $products->ids as $product_id ) {
$GLOBALS['post'] = get_post( $product_id ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
setup_postdata( $GLOBALS['post'] );
// Set custom product visibility when quering hidden products.
add_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
// Render product template.
wc_get_template_part( 'content', 'product' );
// Restore product visibility.
remove_action( 'woocommerce_product_is_visible', array( $this, 'set_product_as_visible' ) );
}
}
$GLOBALS['post'] = $original_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
woocommerce_product_loop_end();
// Fire standard shop loop hooks when paginating results so we can show result counts and so on.
if ( wc_string_to_bool( $this->attributes['paginate'] ) ) {
do_action( 'woocommerce_after_shop_loop' );
}
do_action( "woocommerce_shortcode_after_{$this->type}_loop", $this->attributes );
wp_reset_postdata();
wc_reset_loop();
} else {
do_action( "woocommerce_shortcode_{$this->type}_loop_no_results", $this->attributes );
}
return '<div class="' . esc_attr( implode( ' ', $classes ) ) . '">' . ob_get_clean() . '</div>';
}
$products = $this->get_query_results();
// Prime caches to reduce future queries.
if ( is_callable( '_prime_post_caches' ) ) {
_prime_post_caches( $products->ids );
}
// Render product template.
wc_get_template_part( 'content', 'product' );
/**
* Run the query and return an array of data, including queried ids and pagination information.
*
* @since 3.3.0
* @return object Object with the following props; ids, per_page, found_posts, max_num_pages, current_page
*/
protected function get_query_results() {
$transient_name = $this->get_transient_name();
$transient_version = WC_Cache_Helper::get_transient_version( 'product_query' );
$cache = wc_string_to_bool( $this->attributes['cache'] ) === true;
$transient_value = $cache ? get_transient( $transient_name ) : false;
if ( isset( $transient_value['value'], $transient_value['version'] ) && $transient_value['version'] === $transient_version ) {
$results = $transient_value['value'];
} else {
$query = new WP_Query( $this->query_args );
$paginated = ! $query->get( 'no_found_rows' );
$results = (object) array(
'ids' => wp_parse_id_list( $query->posts ),
'total' => $paginated ? (int) $query->found_posts : count( $query->posts ),
'total_pages' => $paginated ? (int) $query->max_num_pages : 1,
'per_page' => (int) $query->get( 'posts_per_page' ),
'current_page' => $paginated ? (int) max( 1, $query->get( 'paged', 1 ) ) : 1,
);
if ( $cache ) {
$transient_value = array(
'version' => $transient_version,
'value' => $results,
);
set_transient( $transient_name, $transient_value, DAY_IN_SECONDS * 30 );
}
}
// Remove ordering query arguments which may have been added by get_catalog_ordering_args.
WC()->query->remove_ordering_args();
/**
* Filter shortcode products query results.
*
* @since 4.0.0
* @param stdClass $results Query results.
* @param WC_Shortcode_Products $this WC_Shortcode_Products instance.
*/
return apply_filters( 'woocommerce_shortcode_products_query_results', $results, $this );
}
// Path: wp-content\plugins\woocommerce\templates\archive-product.php
woocommerce_product_loop_start();
if ( wc_get_loop_prop( 'total' ) ) {
while ( have_posts() ) {
the_post();
/**
* Hook: woocommerce_shop_loop.
*/
do_action( 'woocommerce_shop_loop' );
wc_get_template_part( 'content', 'product' );
}
}
woocommerce_product_loop_end();
// Path: wp-content\plugins\woocommerce\templates\content-product.php
global $product;
// Ensure visibility.
if ( empty( $product ) || ! $product->is_visible() ) {
return;
}
?>
<li <?php wc_product_class( '', $product ); ?>>
<?php
/**
* Hook: woocommerce_before_shop_loop_item.
*
* @hooked woocommerce_template_loop_product_link_open - 10
*/
do_action( 'woocommerce_before_shop_loop_item' );
/**
* Hook: woocommerce_before_shop_loop_item_title.
*
* @hooked woocommerce_show_product_loop_sale_flash - 10
* @hooked woocommerce_template_loop_product_thumbnail - 10
*/
do_action( 'woocommerce_before_shop_loop_item_title' );
/**
* Hook: woocommerce_shop_loop_item_title.
*
* @hooked woocommerce_template_loop_product_title - 10
*/
do_action( 'woocommerce_shop_loop_item_title' );
/**
* Hook: woocommerce_after_shop_loop_item_title.
*
* @hooked woocommerce_template_loop_rating - 5
* @hooked woocommerce_template_loop_price - 10
*/
do_action( 'woocommerce_after_shop_loop_item_title' );
/**
* Hook: woocommerce_after_shop_loop_item.
*
* @hooked woocommerce_template_loop_product_link_close - 5
* @hooked woocommerce_template_loop_add_to_cart - 10
*/
do_action( 'woocommerce_after_shop_loop_item' );
?>
</li>
// Path: wp-content\plugins\woocommerce\includes\wc-template-functions.php
/**
* When the_post is called, put product data into a global.
*
* @param mixed $post Post Object.
* @return WC_Product
*/
function wc_setup_product_data( $post ) {
unset( $GLOBALS['product'] );
if ( is_int( $post ) ) {
$post = get_post( $post );
}
if ( empty( $post->post_type ) || ! in_array( $post->post_type, array( 'product', 'product_variation' ), true ) ) {
return;
}
$GLOBALS['product'] = wc_get_product( $post );
return $GLOBALS['product'];
}
add_action( 'the_post', 'wc_setup_product_data' );
// Path: wp-content\plugins\woocommerce\includes\wc-product-functions.php
/**
* Main function for returning products, uses the WC_Product_Factory class.
*
* This function should only be called after 'init' action is finished, as there might be taxonomies that are getting
* registered during the init action.
*
* @since 2.2.0
*
* @param mixed $the_product Post object or post ID of the product.
* @param array $deprecated Previously used to pass arguments to the factory, e.g. to force a type.
* @return WC_Product|null|false
*/
function wc_get_product( $the_product = false, $deprecated = array() ) {
if ( ! did_action( 'woocommerce_init' ) || ! did_action( 'woocommerce_after_register_taxonomy' ) || ! did_action( 'woocommerce_after_register_post_type' ) ) {
/* translators: 1: wc_get_product 2: woocommerce_init 3: woocommerce_after_register_taxonomy 4: woocommerce_after_register_post_type */
wc_doing_it_wrong( __FUNCTION__, sprintf( __( '%1$s should not be called before the %2$s, %3$s and %4$s actions have finished.', 'woocommerce' ), 'wc_get_product', 'woocommerce_init', 'woocommerce_after_register_taxonomy', 'woocommerce_after_register_post_type' ), '3.9' );
return false;
}
if ( ! empty( $deprecated ) ) {
wc_deprecated_argument( 'args', '3.0', 'Passing args to wc_get_product is deprecated. If you need to force a type, construct the product class directly.' );
}
// new WC_Product_Factory()
return WC()->product_factory->get_product( $the_product, $deprecated );
}
// Path: wp-content\plugins\woocommerce\includes\class-wc-product-factory.php
/**
* Product Factory
*
* The WooCommerce product factory creating the right product object.
*
* @package WooCommerce/Classes
* @version 3.0.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Product factory class.
*/
class WC_Product_Factory {
/**
* Get a product.
*
* @param mixed $product_id WC_Product|WP_Post|int|bool $product Product instance, post instance, numeric or false to use global $post.
* @param array $deprecated Previously used to pass arguments to the factory, e.g. to force a type.
* @return WC_Product|bool Product object or false if the product cannot be loaded.
*/
public function get_product( $product_id = false, $deprecated = array() ) {
$product_id = $this->get_product_id( $product_id );
if ( ! $product_id ) {
return false;
}
$product_type = $this->get_product_type( $product_id );
// Backwards compatibility.
if ( ! empty( $deprecated ) ) {
wc_deprecated_argument( 'args', '3.0', 'Passing args to the product factory is deprecated. If you need to force a type, construct the product class directly.' );
if ( isset( $deprecated['product_type'] ) ) {
$product_type = $this->get_classname_from_product_type( $deprecated['product_type'] );
}
}
$classname = $this->get_product_classname( $product_id, $product_type );
try {
// new WC_Product_Simple()
return new $classname( $product_id, $deprecated );
} catch ( Exception $e ) {
return false;
}
}
}
// Path: wp-content\plugins\woocommerce\includes\class-wc-product-simple.php
/**
* Simple Product Class.
*
* The default product type kinda product.
*
* @package WooCommerce/Classes/Products
*/
defined( 'ABSPATH' ) || exit;
/**
* Simple product class.
*/
class WC_Product_Simple extends WC_Product {
/**
* Initialize simple product.
*
* @param WC_Product|int $product Product instance or ID.
*/
public function __construct( $product = 0 ) {
$this->supports[] = 'ajax_add_to_cart';
parent::__construct( $product );
}
}
// Path: wp-content\plugins\woocommerce\includes\abstracts\abstract-wc-product.php
/**
* WooCommerce product base class.
*
* @package WooCommerce/Abstracts
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Legacy product contains all deprecated methods for this class and can be
* removed in the future.
*/
require_once WC_ABSPATH . 'includes/legacy/abstract-wc-legacy-product.php';
/**
* Abstract Product Class
*
* The WooCommerce product class handles individual product data.
*
* @version 3.0.0
* @package WooCommerce/Abstracts
*/
class WC_Product extends WC_Abstract_Legacy_Product {
/**
* This is the name of this object type.
*
* @var string
*/
protected $object_type = 'product';
/**
* Post type.
*
* @var string
*/
protected $post_type = 'product';
/**
* Cache group.
*
* @var string
*/
protected $cache_group = 'products';
/**
* Stores product data.
*
* @var array
*/
protected $data = array(
'name' => '',
'slug' => '',
'date_created' => null,
'date_modified' => null,
'status' => false,
'featured' => false,
'catalog_visibility' => 'visible',
'description' => '',
'short_description' => '',
'sku' => '',
'price' => '',
'regular_price' => '',
'sale_price' => '',
'date_on_sale_from' => null,
'date_on_sale_to' => null,
'total_sales' => '0',
'tax_status' => 'taxable',
'tax_class' => '',
'manage_stock' => false,
'stock_quantity' => null,
'stock_status' => 'instock',
'backorders' => 'no',
'low_stock_amount' => '',
'sold_individually' => false,
'weight' => '',
'length' => '',
'width' => '',
'height' => '',
'upsell_ids' => array(),
'cross_sell_ids' => array(),
'parent_id' => 0,
'reviews_allowed' => true,
'purchase_note' => '',
'attributes' => array(),
'default_attributes' => array(),
'menu_order' => 0,
'post_password' => '',
'virtual' => false,
'downloadable' => false,
'category_ids' => array(),
'tag_ids' => array(),
'shipping_class_id' => 0,
'downloads' => array(),
'image_id' => '',
'gallery_image_ids' => array(),
'download_limit' => -1,
'download_expiry' => -1,
'rating_counts' => array(),
'average_rating' => 0,
'review_count' => 0,
);
/**
* Supported features such as 'ajax_add_to_cart'.
*
* @var array
*/
protected $supports = array();
/**
* Get the product if ID is passed, otherwise the product is new and empty.
* This class should NOT be instantiated, but the wc_get_product() function
* should be used. It is possible, but the wc_get_product() is preferred.
*
* @param int|WC_Product|object $product Product to init.
*/
public function __construct( $product = 0 ) {
parent::__construct( $product );
if ( is_numeric( $product ) && $product > 0 ) {
$this->set_id( $product );
} elseif ( $product instanceof self ) {
$this->set_id( absint( $product->get_id() ) );
} elseif ( ! empty( $product->ID ) ) {
$this->set_id( absint( $product->ID ) );
} else {
$this->set_object_read( true );
}
$this->data_store = WC_Data_Store::load( 'product-' . $this->get_type() );
if ( $this->get_id() > 0 ) {
$this->data_store->read( $this );
}
}
}
// Path: wp-content\plugins\woocommerce\includes\class-wc-data-store.php
/**
* WC Data Store.
*
* @package WooCommerce\Classes
* @since 3.0.0
* @version 3.0.0
*/
defined( 'ABSPATH' ) || exit;
/**
* Data store class.
*/
class WC_Data_Store {
/**
* Contains an instance of the data store class that we are working with.
*
* @var WC_Data_Store
*/
private $instance = null;
/**
* Contains an array of default WC supported data stores.
* Format of object name => class name.
* Example: 'product' => 'WC_Product_Data_Store_CPT'
* You can also pass something like product_<type> for product stores and
* that type will be used first when available, if a store is requested like
* this and doesn't exist, then the store would fall back to 'product'.
* Ran through `woocommerce_data_stores`.
*
* @var array
*/
private $stores = array(
'coupon' => 'WC_Coupon_Data_Store_CPT',
'customer' => 'WC_Customer_Data_Store',
'customer-download' => 'WC_Customer_Download_Data_Store',
'customer-download-log' => 'WC_Customer_Download_Log_Data_Store',
'customer-session' => 'WC_Customer_Data_Store_Session',
'order' => 'WC_Order_Data_Store_CPT',
'order-refund' => 'WC_Order_Refund_Data_Store_CPT',
'order-item' => 'WC_Order_Item_Data_Store',
'order-item-coupon' => 'WC_Order_Item_Coupon_Data_Store',
'order-item-fee' => 'WC_Order_Item_Fee_Data_Store',
'order-item-product' => 'WC_Order_Item_Product_Data_Store',
'order-item-shipping' => 'WC_Order_Item_Shipping_Data_Store',
'order-item-tax' => 'WC_Order_Item_Tax_Data_Store',
'payment-token' => 'WC_Payment_Token_Data_Store',
'product' => 'WC_Product_Data_Store_CPT',
'product-grouped' => 'WC_Product_Grouped_Data_Store_CPT',
'product-variable' => 'WC_Product_Variable_Data_Store_CPT',
'product-variation' => 'WC_Product_Variation_Data_Store_CPT',
'shipping-zone' => 'WC_Shipping_Zone_Data_Store',
'webhook' => 'WC_Webhook_Data_Store',
);
/**
* Contains the name of the current data store's class name.
*
* @var string
*/
private $current_class_name = '';
/**
* The object type this store works with.
*
* @var string
*/
private $object_type = '';
/**
* Tells WC_Data_Store which object (coupon, product, order, etc)
* store we want to work with.
*
* @throws Exception When validation fails.
* @param string $object_type Name of object.
*/
public function __construct( $object_type ) {
$this->object_type = $object_type;
$this->stores = apply_filters( 'woocommerce_data_stores', $this->stores );
// If this object type can't be found, check to see if we can load one
// level up (so if product-type isn't found, we try product).
if ( ! array_key_exists( $object_type, $this->stores ) ) {
$pieces = explode( '-', $object_type );
$object_type = $pieces[0];
}
if ( array_key_exists( $object_type, $this->stores ) ) {
$store = apply_filters( 'woocommerce_' . $object_type . '_data_store', $this->stores[ $object_type ] );
if ( is_object( $store ) ) {
if ( ! $store instanceof WC_Object_Data_Store_Interface ) {
throw new Exception( __( 'Invalid data store.', 'woocommerce' ) );
}
$this->current_class_name = get_class( $store );
$this->instance = $store;
} else {
if ( ! class_exists( $store ) ) {
throw new Exception( __( 'Invalid data store.', 'woocommerce' ) );
}
$this->current_class_name = $store;
$this->instance = new $store();
}
} else {
throw new Exception( __( 'Invalid data store.', 'woocommerce' ) );
}
}
/**
* Reads an object from the data store.
*
* @since 3.0.0
* @param WC_Data $data WooCommerce data instance.
*/
public function read( &$data ) {
$this->instance->read( $data );
}
}
// Path: wp-content\plugins\woocommerce\includes\data-stores\class-wc-product-data-store-cpt.php
/**
* WC_Product_Data_Store_CPT class file.
*
* @package WooCommerce/Classes
*/
use Automattic\Jetpack\Constants;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* WC Product Data Store: Stored in CPT.
*
* @version 3.0.0
*/
class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Data_Store_Interface, WC_Product_Data_Store_Interface {
/**
* Data stored in meta keys, but not considered "meta".
*
* @since 3.0.0
* @var array
*/
protected $internal_meta_keys = array(
'_visibility',
'_sku',
'_price',
'_regular_price',
'_sale_price',
'_sale_price_dates_from',
'_sale_price_dates_to',
'total_sales',
'_tax_status',
'_tax_class',
'_manage_stock',
'_stock',
'_stock_status',
'_backorders',
'_low_stock_amount',
'_sold_individually',
'_weight',
'_length',
'_width',
'_height',
'_upsell_ids',
'_crosssell_ids',
'_purchase_note',
'_default_attributes',
'_product_attributes',
'_virtual',
'_downloadable',
'_download_limit',
'_download_expiry',
'_featured',
'_downloadable_files',
'_wc_rating_count',
'_wc_average_rating',
'_wc_review_count',
'_variation_description',
'_thumbnail_id',
'_file_paths',
'_product_image_gallery',
'_product_version',
'_wp_old_slug',
'_edit_last',
'_edit_lock',
);
/**
* Meta data which should exist in the DB, even if empty.
*
* @since 3.6.0
*
* @var array
*/
protected $must_exist_meta_keys = array(
'_tax_class',
);
/**
* If we have already saved our extra data, don't do automatic / default handling.
*
* @var bool
*/
protected $extra_data_saved = false;
/**
* Stores updated props.
*
* @var array
*/
protected $updated_props = array();
/*
|--------------------------------------------------------------------------
| CRUD Methods
|--------------------------------------------------------------------------
*/
/**
* Method to read a product from the database.
*
* @param WC_Product $product Product object.
* @throws Exception If invalid product.
*/
public function read( &$product ) {
$product->set_defaults();
$post_object = get_post( $product->get_id() );
if ( ! $product->get_id() || ! $post_object || 'product' !== $post_object->post_type ) {
throw new Exception( __( 'Invalid product.', 'woocommerce' ) );
}
$product->set_props(
array(
'name' => $post_object->post_title,
'slug' => $post_object->post_name,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
'status' => $post_object->post_status,
'description' => $post_object->post_content,
'short_description' => $post_object->post_excerpt,
'parent_id' => $post_object->post_parent,
'menu_order' => $post_object->menu_order,
'post_password' => $post_object->post_password,
'reviews_allowed' => 'open' === $post_object->comment_status,
)
);
$this->read_attributes( $product );
$this->read_downloads( $product );
$this->read_visibility( $product );
$this->read_product_data( $product );
$this->read_extra_data( $product );
$product->set_object_read( true );
do_action( 'woocommerce_product_read', $product->get_id() );
}
}
// Path: wp-content\plugins\woocommerce\includes\data-stores\class-wc-data-store-wp.php
/**
* Shared logic for WP based data.
* Contains functions like meta handling for all default data stores.
* Your own data store doesn't need to use WC_Data_Store_WP -- you can write
* your own meta handling functions.
*
* @version 3.0.0
* @package WooCommerce/Classes
*/
defined( 'ABSPATH' ) || exit;
/**
* WC_Data_Store_WP class.
*/
class WC_Data_Store_WP {
/**
* Meta type. This should match up with
* the types available at https://developer.wordpress.org/reference/functions/add_metadata/.
* WP defines 'post', 'user', 'comment', and 'term'.
*
* @var string
*/
protected $meta_type = 'post';
/**
* This only needs set if you are using a custom metadata type (for example payment tokens.
* This should be the name of the field your table uses for associating meta with objects.
* For example, in payment_tokenmeta, this would be payment_token_id.
*
* @var string
*/
protected $object_id_field_for_meta = '';
/**
* Data stored in meta keys, but not considered "meta" for an object.
*
* @since 3.0.0
*
* @var array
*/
protected $internal_meta_keys = array();
/**
* Meta data which should exist in the DB, even if empty.
*
* @since 3.6.0
*
* @var array
*/
protected $must_exist_meta_keys = array();
}
// Path: wp-content\plugins\woocommerce\includes\abstracts\abstract-wc-data.php
/**
* Abstract Data.
*
* Handles generic data interaction which is implemented by
* the different data store classes.
*
* @class WC_Data
* @version 3.0.0
* @package WooCommerce/Classes
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Abstract WC Data Class
*
* Implemented by classes using the same CRUD(s) pattern.
*
* @version 2.6.0
* @package WooCommerce/Abstracts
*/
abstract class WC_Data {
/**
* ID for this object.
*
* @since 3.0.0
* @var int
*/
protected $id = 0;
/**
* Core data for this object. Name value pairs (name + default value).
*
* @since 3.0.0
* @var array
*/
protected $data = array();
/**
* Core data changes for this object.
*
* @since 3.0.0
* @var array
*/
protected $changes = array();
/**
* This is false until the object is read from the DB.
*
* @since 3.0.0
* @var bool
*/
protected $object_read = false;
/**
* This is the name of this object type.
*
* @since 3.0.0
* @var string
*/
protected $object_type = 'data';
/**
* Extra data for this object. Name value pairs (name + default value).
* Used as a standard way for sub classes (like product types) to add
* additional information to an inherited class.
*
* @since 3.0.0
* @var array
*/
protected $extra_data = array();
/**
* Set to _data on construct so we can track and reset data if needed.
*
* @since 3.0.0
* @var array
*/
protected $default_data = array();
/**
* Contains a reference to the data store for this class.
*
* @since 3.0.0
* @var object
*/
protected $data_store;
/**
* Stores meta in cache for future reads.
* A group must be set to to enable caching.
*
* @since 3.0.0
* @var string
*/
protected $cache_group = '';
/**
* Stores additional meta data.
*
* @since 3.0.0
* @var array
*/
protected $meta_data = null;
/**
* Default constructor.
*
* @param int|object|array $read ID to load from the DB (optional) or already queried data.
*/
public function __construct( $read = 0 ) {
$this->data = array_merge( $this->data, $this->extra_data );
$this->default_data = $this->data;
}
/**
* Set object read property.
*
* @since 3.0.0
* @param boolean $read Should read?.
*/
public function set_object_read( $read = true ) {
$this->object_read = (bool) $read;
}
}