class-wc-data-store.php 5.31 KB
Newer Older
imac's avatar
imac committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * WC Data Store.
 *
 * @since    3.0.0
 * @version  3.0.0
 * @category Class
 * @author   WooThemes
 */
class WC_Data_Store {

	/**
	 * Contains an instance of the data store class that we are working with.
	 */
	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 avaiable, if a store is requested like
	 * this and doesn't exist, then the store would fall back to 'product'.
	 * Ran through `woocommerce_data_stores`.
	 */
	private $stores = array(
		'coupon'              => 'WC_Coupon_Data_Store_CPT',
		'customer'            => 'WC_Customer_Data_Store',
		'customer-download'   => 'WC_Customer_Download_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',
	);

	/**
	 * Contains the name of the current data store's class name.
	 */
	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.
	 *
	 * @param string $object_type Name of object.
	 *
	 * @throws Exception
	 */
	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' ) );
		}
	}

	/**
	 * Only store the object type to avoid serializing the data store instance.
	 *
	 * @return array
	 */
	public function __sleep() {
		return array( 'object_type' );
	}

	/**
	 * Re-run the constructor with the object type.
	 */
	public function __wakeup() {
		$this->__construct( $this->object_type );
	}

	/**
	 * Loads a data store.
	 *
	 * @param string $object_type Name of object.
	 *
	 * @since 3.0.0
	 * @return WC_Data_Store
	 */
	public static function load( $object_type ) {
		return new WC_Data_Store( $object_type );
	}

	/**
	 * Returns the class name of the current data store.
	 *
	 * @since 3.0.0
	 * @return string
	 */
	public function get_current_class_name() {
		return $this->current_class_name;
	}

	/**
	 * Reads an object from the data store.
	 *
	 * @since 3.0.0
	 * @param WC_Data
	 */
	public function read( &$data ) {
		$this->instance->read( $data );
	}

	/**
	 * Create an object in the data store.
	 *
	 * @since 3.0.0
	 * @param WC_Data
	 */
	public function create( &$data ) {
		$this->instance->create( $data );
	}

	/**
	 * Update an object in the data store.
	 *
	 * @since 3.0.0
	 * @param WC_Data
	 */
	public function update( &$data ) {
		$this->instance->update( $data );
	}

	/**
	 * Delete an object from the data store.
	 *
	 * @since 3.0.0
	 * @param WC_Data
	 * @param array $args Array of args to pass to the delete method.
	 */
	public function delete( &$data, $args = array() ) {
		$this->instance->delete( $data, $args );
	}

	/**
	 * Data stores can define additional functions (for example, coupons have
	 * some helper methods for increasing or decreasing usage). This passes
	 * through to the instance if that function exists.
	 *
	 * @since 3.0.0
	 *
	 * @param $method
	 * @param $parameters
	 *
	 * @return mixed
	 */
	public function __call( $method, $parameters ) {
		if ( is_callable( array( $this->instance, $method ) ) ) {
			$object = array_shift( $parameters );
			return call_user_func_array( array( $this->instance, $method ), array_merge( array( &$object ), $parameters ) );
		}
	}

}