class-wc-data-store.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <?php
  2. /**
  3. * WC Data Store.
  4. *
  5. * @package WooCommerce\Classes
  6. * @since 3.0.0
  7. * @version 3.0.0
  8. */
  9. defined( 'ABSPATH' ) || exit;
  10. /**
  11. * Data store class.
  12. */
  13. class WC_Data_Store {
  14. /**
  15. * Contains an instance of the data store class that we are working with.
  16. *
  17. * @var WC_Data_Store
  18. */
  19. private $instance = null;
  20. /**
  21. * Contains an array of default WC supported data stores.
  22. * Format of object name => class name.
  23. * Example: 'product' => 'WC_Product_Data_Store_CPT'
  24. * You can also pass something like product_<type> for product stores and
  25. * that type will be used first when available, if a store is requested like
  26. * this and doesn't exist, then the store would fall back to 'product'.
  27. * Ran through `woocommerce_data_stores`.
  28. *
  29. * @var array
  30. */
  31. private $stores = array(
  32. 'coupon' => 'WC_Coupon_Data_Store_CPT',
  33. 'customer' => 'WC_Customer_Data_Store',
  34. 'customer-download' => 'WC_Customer_Download_Data_Store',
  35. 'customer-download-log' => 'WC_Customer_Download_Log_Data_Store',
  36. 'customer-session' => 'WC_Customer_Data_Store_Session',
  37. 'order' => 'WC_Order_Data_Store_CPT',
  38. 'order-refund' => 'WC_Order_Refund_Data_Store_CPT',
  39. 'order-item' => 'WC_Order_Item_Data_Store',
  40. 'order-item-coupon' => 'WC_Order_Item_Coupon_Data_Store',
  41. 'order-item-fee' => 'WC_Order_Item_Fee_Data_Store',
  42. 'order-item-product' => 'WC_Order_Item_Product_Data_Store',
  43. 'order-item-shipping' => 'WC_Order_Item_Shipping_Data_Store',
  44. 'order-item-tax' => 'WC_Order_Item_Tax_Data_Store',
  45. 'payment-token' => 'WC_Payment_Token_Data_Store',
  46. 'product' => 'WC_Product_Data_Store_CPT',
  47. 'product-grouped' => 'WC_Product_Grouped_Data_Store_CPT',
  48. 'product-variable' => 'WC_Product_Variable_Data_Store_CPT',
  49. 'product-variation' => 'WC_Product_Variation_Data_Store_CPT',
  50. 'shipping-zone' => 'WC_Shipping_Zone_Data_Store',
  51. 'webhook' => 'WC_Webhook_Data_Store',
  52. );
  53. /**
  54. * Contains the name of the current data store's class name.
  55. *
  56. * @var string
  57. */
  58. private $current_class_name = '';
  59. /**
  60. * The object type this store works with.
  61. *
  62. * @var string
  63. */
  64. private $object_type = '';
  65. /**
  66. * Tells WC_Data_Store which object (coupon, product, order, etc)
  67. * store we want to work with.
  68. *
  69. * @throws Exception When validation fails.
  70. * @param string $object_type Name of object.
  71. */
  72. public function __construct( $object_type ) {
  73. $this->object_type = $object_type;
  74. $this->stores = apply_filters( 'woocommerce_data_stores', $this->stores );
  75. // If this object type can't be found, check to see if we can load one
  76. // level up (so if product-type isn't found, we try product).
  77. if ( ! array_key_exists( $object_type, $this->stores ) ) {
  78. $pieces = explode( '-', $object_type );
  79. $object_type = $pieces[0];
  80. }
  81. if ( array_key_exists( $object_type, $this->stores ) ) {
  82. $store = apply_filters( 'woocommerce_' . $object_type . '_data_store', $this->stores[ $object_type ] );
  83. if ( is_object( $store ) ) {
  84. if ( ! $store instanceof WC_Object_Data_Store_Interface ) {
  85. throw new Exception( __( 'Invalid data store.', 'woocommerce' ) );
  86. }
  87. $this->current_class_name = get_class( $store );
  88. $this->instance = $store;
  89. } else {
  90. if ( ! class_exists( $store ) ) {
  91. throw new Exception( __( 'Invalid data store.', 'woocommerce' ) );
  92. }
  93. $this->current_class_name = $store;
  94. $this->instance = new $store();
  95. }
  96. } else {
  97. throw new Exception( __( 'Invalid data store.', 'woocommerce' ) );
  98. }
  99. }
  100. /**
  101. * Only store the object type to avoid serializing the data store instance.
  102. *
  103. * @return array
  104. */
  105. public function __sleep() {
  106. return array( 'object_type' );
  107. }
  108. /**
  109. * Re-run the constructor with the object type.
  110. */
  111. public function __wakeup() {
  112. $this->__construct( $this->object_type );
  113. }
  114. /**
  115. * Loads a data store.
  116. *
  117. * @param string $object_type Name of object.
  118. *
  119. * @since 3.0.0
  120. * @return WC_Data_Store
  121. */
  122. public static function load( $object_type ) {
  123. return new WC_Data_Store( $object_type );
  124. }
  125. /**
  126. * Returns the class name of the current data store.
  127. *
  128. * @since 3.0.0
  129. * @return string
  130. */
  131. public function get_current_class_name() {
  132. return $this->current_class_name;
  133. }
  134. /**
  135. * Reads an object from the data store.
  136. *
  137. * @since 3.0.0
  138. * @param WC_Data $data WooCommerce data instance.
  139. */
  140. public function read( &$data ) {
  141. $this->instance->read( $data );
  142. }
  143. /**
  144. * Create an object in the data store.
  145. *
  146. * @since 3.0.0
  147. * @param WC_Data $data WooCommerce data instance.
  148. */
  149. public function create( &$data ) {
  150. $this->instance->create( $data );
  151. }
  152. /**
  153. * Update an object in the data store.
  154. *
  155. * @since 3.0.0
  156. * @param WC_Data $data WooCommerce data instance.
  157. */
  158. public function update( &$data ) {
  159. $this->instance->update( $data );
  160. }
  161. /**
  162. * Delete an object from the data store.
  163. *
  164. * @since 3.0.0
  165. * @param WC_Data $data WooCommerce data instance.
  166. * @param array $args Array of args to pass to the delete method.
  167. */
  168. public function delete( &$data, $args = array() ) {
  169. $this->instance->delete( $data, $args );
  170. }
  171. /**
  172. * Data stores can define additional functions (for example, coupons have
  173. * some helper methods for increasing or decreasing usage). This passes
  174. * through to the instance if that function exists.
  175. *
  176. * @since 3.0.0
  177. * @param string $method Method.
  178. * @param mixed $parameters Parameters.
  179. * @return mixed
  180. */
  181. public function __call( $method, $parameters ) {
  182. if ( is_callable( array( $this->instance, $method ) ) ) {
  183. $object = array_shift( $parameters );
  184. return call_user_func_array( array( $this->instance, $method ), array_merge( array( &$object ), $parameters ) );
  185. }
  186. }
  187. }