/includes/data-stores/class-wc-customer-data-store.php

  1. <?php 
  2. if ( ! defined( 'ABSPATH' ) ) { 
  3. exit; 
  4.  
  5. /** 
  6. * WC Customer Data Store. 
  7. * 
  8. * @version 3.0.0 
  9. * @category Class 
  10. * @author WooThemes 
  11. */ 
  12. class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Data_Store_Interface, WC_Object_Data_Store_Interface { 
  13.  
  14. /** 
  15. * Data stored in meta keys, but not considered "meta". 
  16. * 
  17. * @since 3.0.0 
  18. * @var array 
  19. */ 
  20. protected $internal_meta_keys = array( 
  21. 'locale',  
  22. 'billing_postcode',  
  23. 'billing_city',  
  24. 'billing_address_1',  
  25. 'billing_address_2',  
  26. 'billing_state',  
  27. 'billing_country',  
  28. 'shipping_postcode',  
  29. 'shipping_city',  
  30. 'shipping_address_1',  
  31. 'shipping_address_2',  
  32. 'shipping_state',  
  33. 'shipping_country',  
  34. 'paying_customer',  
  35. 'last_update',  
  36. 'first_name',  
  37. 'last_name',  
  38. 'show_admin_bar_front',  
  39. 'use_ssl',  
  40. 'admin_color',  
  41. 'rich_editing',  
  42. 'comment_shortcuts',  
  43. 'dismissed_wp_pointers',  
  44. 'show_welcome_panel',  
  45. '_woocommerce_persistent_cart',  
  46. 'session_tokens',  
  47. 'nickname',  
  48. 'description',  
  49. 'billing_first_name',  
  50. 'billing_last_name',  
  51. 'billing_company',  
  52. 'billing_phone',  
  53. 'billing_email',  
  54. 'shipping_first_name',  
  55. 'shipping_last_name',  
  56. 'shipping_company',  
  57. 'wptests_capabilities',  
  58. 'wptests_user_level',  
  59. '_order_count',  
  60. '_money_spent',  
  61. ); 
  62.  
  63. /** 
  64. * Internal meta type used to store user data. 
  65. * 
  66. * @var string 
  67. */ 
  68. protected $meta_type = 'user'; 
  69.  
  70. /** 
  71. * Callback to remove unwanted meta data. 
  72. * 
  73. * @param object $meta 
  74. * @return bool 
  75. */ 
  76. protected function exclude_internal_meta_keys( $meta ) { 
  77. global $wpdb; 
  78.  
  79. $table_prefix = $wpdb->prefix ? $wpdb->prefix : 'wp_'; 
  80.  
  81. return ! in_array( $meta->meta_key, $this->internal_meta_keys ) 
  82. && 0 !== strpos( $meta->meta_key, 'closedpostboxes_' ) 
  83. && 0 !== strpos( $meta->meta_key, 'metaboxhidden_' ) 
  84. && 0 !== strpos( $meta->meta_key, 'manageedit-' ) 
  85. && ! strstr( $meta->meta_key, $table_prefix ) 
  86. && 0 !== stripos( $meta->meta_key, 'wp_' ); 
  87.  
  88. /** 
  89. * Method to create a new customer in the database. 
  90. * 
  91. * @since 3.0.0 
  92. * @param WC_Customer 
  93. */ 
  94. public function create( &$customer ) { 
  95. $id = wc_create_new_customer( $customer->get_email(), $customer->get_username(), $customer->get_password() ); 
  96.  
  97. if ( is_wp_error( $id ) ) { 
  98. throw new WC_Data_Exception( $id->get_error_code(), $id->get_error_message() ); 
  99.  
  100. $customer->set_id( $id ); 
  101. $this->update_user_meta( $customer ); 
  102.  
  103. // Prevent wp_update_user calls in the same request and customer trigger the 'Notice of Password Changed' email 
  104. $customer->set_password( '' ); 
  105.  
  106. wp_update_user( apply_filters( 'woocommerce_update_customer_args', array( 
  107. 'ID' => $customer->get_id(),  
  108. 'role' => $customer->get_role(),  
  109. 'display_name' => $customer->get_first_name() . ' ' . $customer->get_last_name(),  
  110. ), $customer ) ); 
  111. $wp_user = new WP_User( $customer->get_id() ); 
  112. $customer->set_date_created( $wp_user->user_registered ); 
  113. $customer->set_date_modified( get_user_meta( $customer->get_id(), 'last_update', true ) ); 
  114. $customer->save_meta_data(); 
  115. $customer->apply_changes(); 
  116. do_action( 'woocommerce_new_customer', $customer->get_id() ); 
  117.  
  118. /** 
  119. * Method to read a customer object. 
  120. * 
  121. * @since 3.0.0 
  122. * @param WC_Customer 
  123. * @throws Exception 
  124. */ 
  125. public function read( &$customer ) { 
  126. global $wpdb; 
  127.  
  128. // User object is required. 
  129. if ( ! $customer->get_id() || ! ( $user_object = get_user_by( 'id', $customer->get_id() ) ) || empty( $user_object->ID ) ) { 
  130. throw new Exception( __( 'Invalid customer.', 'woocommerce' ) ); 
  131.  
  132. // Only users on this site should be read. 
  133. if ( is_multisite() && ! is_user_member_of_blog( $customer->get_id() ) ) { 
  134. throw new Exception( __( 'Invalid customer.', 'woocommerce' ) ); 
  135.  
  136. $customer_id = $customer->get_id(); 
  137. // Load meta but exclude deprecated props. 
  138. $user_meta = array_diff_key( array_map( 'wc_flatten_meta_callback', get_user_meta( $customer_id ) ), array_flip( array( 'country', 'state', 'postcode', 'city', 'address', 'address_2', 'default', 'location' ) ) ); 
  139. $customer->set_props( $user_meta ); 
  140. $customer->set_props( array( 
  141. 'is_paying_customer' => get_user_meta( $customer_id, 'paying_customer', true ),  
  142. 'email' => $user_object->user_email,  
  143. 'username' => $user_object->user_login,  
  144. 'date_created' => $user_object->user_registered, // Mysql string in local format. 
  145. 'date_modified' => get_user_meta( $customer_id, 'last_update', true ),  
  146. 'role' => ! empty( $user_object->roles[0] ) ? $user_object->roles[0] : 'customer',  
  147. ) ); 
  148. $customer->read_meta_data(); 
  149. $customer->set_object_read( true ); 
  150. do_action( 'woocommerce_customer_loaded', $customer ); 
  151.  
  152. /** 
  153. * Updates a customer in the database. 
  154. * 
  155. * @since 3.0.0 
  156. * @param WC_Customer 
  157. */ 
  158. public function update( &$customer ) { 
  159. wp_update_user( apply_filters( 'woocommerce_update_customer_args', array( 
  160. 'ID' => $customer->get_id(),  
  161. 'user_email' => $customer->get_email(),  
  162. 'display_name' => $customer->get_first_name() . ' ' . $customer->get_last_name(),  
  163. ), $customer ) ); 
  164. // Only update password if a new one was set with set_password. 
  165. if ( $customer->get_password() ) { 
  166. wp_update_user( array( 'ID' => $customer->get_id(), 'user_pass' => $customer->get_password() ) ); 
  167. $customer->set_password( '' ); 
  168. $this->update_user_meta( $customer ); 
  169. $customer->set_date_modified( get_user_meta( $customer->get_id(), 'last_update', true ) ); 
  170. $customer->save_meta_data(); 
  171. $customer->apply_changes(); 
  172. do_action( 'woocommerce_update_customer', $customer->get_id() ); 
  173.  
  174. /** 
  175. * Deletes a customer from the database. 
  176. * 
  177. * @since 3.0.0 
  178. * @param WC_Customer 
  179. * @param array $args Array of args to pass to the delete method. 
  180. */ 
  181. public function delete( &$customer, $args = array() ) { 
  182. if ( ! $customer->get_id() ) { 
  183. return; 
  184. $args = wp_parse_args( $args, array( 
  185. 'reassign' => 0,  
  186. ) ); 
  187.  
  188. $id = $customer->get_id(); 
  189. wp_delete_user( $id, $args['reassign'] ); 
  190.  
  191. do_action( 'woocommerce_delete_customer', $id ); 
  192.  
  193. /** 
  194. * Helper method that updates all the meta for a customer. Used for update & create. 
  195. * @since 3.0.0 
  196. * @param WC_Customer 
  197. */ 
  198. private function update_user_meta( $customer ) { 
  199. $updated_props = array(); 
  200. $changed_props = $customer->get_changes(); 
  201.  
  202. $meta_key_to_props = array( 
  203. 'paying_customer' => 'is_paying_customer',  
  204. 'first_name' => 'first_name',  
  205. 'last_name' => 'last_name',  
  206. ); 
  207.  
  208. foreach ( $meta_key_to_props as $meta_key => $prop ) { 
  209. if ( ! array_key_exists( $prop, $changed_props ) ) { 
  210. continue; 
  211.  
  212. if ( update_user_meta( $customer->get_id(), $meta_key, $customer->{"get_$prop"}( 'edit' ) ) ) { 
  213. $updated_props[] = $prop; 
  214.  
  215. $billing_address_props = array( 
  216. 'billing_first_name' => 'billing_first_name',  
  217. 'billing_last_name' => 'billing_last_name',  
  218. 'billing_company' => 'billing_company',  
  219. 'billing_address_1' => 'billing_address_1',  
  220. 'billing_address_2' => 'billing_address_2',  
  221. 'billing_city' => 'billing_city',  
  222. 'billing_state' => 'billing_state',  
  223. 'billing_postcode' => 'billing_postcode',  
  224. 'billing_country' => 'billing_country',  
  225. 'billing_email' => 'billing_email',  
  226. 'billing_phone' => 'billing_phone',  
  227. ); 
  228.  
  229. foreach ( $billing_address_props as $meta_key => $prop ) { 
  230. $prop_key = substr( $prop, 8 ); 
  231. if ( ! isset( $changed_props['billing'] ) || ! array_key_exists( $prop_key, $changed_props['billing'] ) ) { 
  232. continue; 
  233. if ( update_user_meta( $customer->get_id(), $meta_key, $customer->{"get_$prop"}( 'edit' ) ) ) { 
  234. $updated_props[] = $prop; 
  235.  
  236. $shipping_address_props = array( 
  237. 'shipping_first_name' => 'shipping_first_name',  
  238. 'shipping_last_name' => 'shipping_last_name',  
  239. 'shipping_company' => 'shipping_company',  
  240. 'shipping_address_1' => 'shipping_address_1',  
  241. 'shipping_address_2' => 'shipping_address_2',  
  242. 'shipping_city' => 'shipping_city',  
  243. 'shipping_state' => 'shipping_state',  
  244. 'shipping_postcode' => 'shipping_postcode',  
  245. 'shipping_country' => 'shipping_country',  
  246. ); 
  247.  
  248. foreach ( $shipping_address_props as $meta_key => $prop ) { 
  249. $prop_key = substr( $prop, 9 ); 
  250. if ( ! isset( $changed_props['shipping'] ) || ! array_key_exists( $prop_key, $changed_props['shipping'] ) ) { 
  251. continue; 
  252. if ( update_user_meta( $customer->get_id(), $meta_key, $customer->{"get_$prop"}( 'edit' ) ) ) { 
  253. $updated_props[] = $prop; 
  254.  
  255. do_action( 'woocommerce_customer_object_updated_props', $customer, $updated_props ); 
  256.  
  257. /** 
  258. * Gets the customers last order. 
  259. * 
  260. * @since 3.0.0 
  261. * @param WC_Customer 
  262. * @return WC_Order|false 
  263. */ 
  264. public function get_last_order( &$customer ) { 
  265. global $wpdb; 
  266.  
  267. $last_order = $wpdb->get_var( "SELECT posts.ID 
  268. FROM $wpdb->posts AS posts 
  269. LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id 
  270. WHERE meta.meta_key = '_customer_user' 
  271. AND meta.meta_value = '" . esc_sql( $customer->get_id() ) . "' 
  272. AND posts.post_type = 'shop_order' 
  273. AND posts.post_status IN ( '" . implode( "', '", array_map( 'esc_sql', array_keys( wc_get_order_statuses() ) ) ) . "' ) 
  274. ORDER BY posts.ID DESC 
  275. " ); 
  276.  
  277. if ( $last_order ) { 
  278. return wc_get_order( absint( $last_order ) ); 
  279. } else { 
  280. return false; 
  281.  
  282. /** 
  283. * Return the number of orders this customer has. 
  284. * 
  285. * @since 3.0.0 
  286. * @param WC_Customer 
  287. * @return integer 
  288. */ 
  289. public function get_order_count( &$customer ) { 
  290. $count = get_user_meta( $customer->get_id(), '_order_count', true ); 
  291.  
  292. if ( '' === $count ) { 
  293. global $wpdb; 
  294.  
  295. $count = $wpdb->get_var( "SELECT COUNT(*) 
  296. FROM $wpdb->posts as posts 
  297. LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id 
  298. WHERE meta.meta_key = '_customer_user' 
  299. AND posts.post_type = 'shop_order' 
  300. AND posts.post_status IN ( '" . implode( "', '", array_map( 'esc_sql', array_keys( wc_get_order_statuses() ) ) ) . "' ) 
  301. AND meta_value = '" . esc_sql( $customer->get_id() ) . "' 
  302. " ); 
  303. update_user_meta( $customer->get_id(), '_order_count', $count ); 
  304.  
  305. return absint( $count ); 
  306.  
  307. /** 
  308. * Return how much money this customer has spent. 
  309. * 
  310. * @since 3.0.0 
  311. * @param WC_Customer 
  312. * @return float 
  313. */ 
  314. public function get_total_spent( &$customer ) { 
  315. $spent = get_user_meta( $customer->get_id(), '_money_spent', true ); 
  316.  
  317. if ( '' === $spent ) { 
  318. global $wpdb; 
  319.  
  320. $statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() ); 
  321. $spent = $wpdb->get_var( "SELECT SUM(meta2.meta_value) 
  322. FROM $wpdb->posts as posts 
  323. LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id 
  324. LEFT JOIN {$wpdb->postmeta} AS meta2 ON posts.ID = meta2.post_id 
  325. WHERE meta.meta_key = '_customer_user' 
  326. AND meta.meta_value = '" . esc_sql( $customer->get_id() ) . "' 
  327. AND posts.post_type = 'shop_order' 
  328. AND posts.post_status IN ( 'wc-" . implode( "', 'wc-", $statuses ) . "' ) 
  329. AND meta2.meta_key = '_order_total' 
  330. " ); 
  331.  
  332. if ( ! $spent ) { 
  333. $spent = 0; 
  334. update_user_meta( $customer->get_id(), '_money_spent', $spent ); 
  335.  
  336. return wc_format_decimal( $spent, 2 ); 
  337.  
  338. /** 
  339. * Search customers and return customer IDs. 
  340. * 
  341. * @param string $term 
  342. * @return array 
  343. */ 
  344. public function search_customers( $term ) { 
  345. $query = new WP_User_Query( array( 
  346. 'search' => '*' . esc_attr( $term ) . '*',  
  347. 'search_columns' => array( 'user_login', 'user_url', 'user_email', 'user_nicename', 'display_name' ),  
  348. 'fields' => 'ID',  
  349. ) ); 
  350.  
  351. $query2 = new WP_User_Query( array( 
  352. 'fields' => 'ID',  
  353. 'meta_query' => array( 
  354. 'relation' => 'OR',  
  355. array( 
  356. 'key' => 'first_name',  
  357. 'value' => $term,  
  358. 'compare' => 'LIKE',  
  359. ),  
  360. array( 
  361. 'key' => 'last_name',  
  362. 'value' => $term,  
  363. 'compare' => 'LIKE',  
  364. ),  
  365. ),  
  366. ) ); 
  367. return wp_parse_id_list( array_merge( $query->get_results(), $query2->get_results() ) ); 
.