PageRenderTime 32ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/woocommerce/includes/api/v2/class-wc-api-customers.php

https://gitlab.com/webkod3r/tripolis
PHP | 844 lines | 466 code | 141 blank | 237 comment | 62 complexity | 8c71f1910976f73a4c3f0d92fc9468ff MD5 | raw file
  1. <?php
  2. /**
  3. * WooCommerce API Customers Class
  4. *
  5. * Handles requests to the /customers endpoint
  6. *
  7. * @author WooThemes
  8. * @category API
  9. * @package WooCommerce/API
  10. * @since 2.2
  11. */
  12. if ( ! defined( 'ABSPATH' ) ) {
  13. exit; // Exit if accessed directly
  14. }
  15. class WC_API_Customers extends WC_API_Resource {
  16. /** @var string $base the route base */
  17. protected $base = '/customers';
  18. /** @var string $created_at_min for date filtering */
  19. private $created_at_min = null;
  20. /** @var string $created_at_max for date filtering */
  21. private $created_at_max = null;
  22. /**
  23. * Setup class, overridden to provide customer data to order response
  24. *
  25. * @since 2.1
  26. * @param WC_API_Server $server
  27. * @return WC_API_Customers
  28. */
  29. public function __construct( WC_API_Server $server ) {
  30. parent::__construct( $server );
  31. // add customer data to order responses
  32. add_filter( 'woocommerce_api_order_response', array( $this, 'add_customer_data' ), 10, 2 );
  33. // modify WP_User_Query to support created_at date filtering
  34. add_action( 'pre_user_query', array( $this, 'modify_user_query' ) );
  35. }
  36. /**
  37. * Register the routes for this class
  38. *
  39. * GET /customers
  40. * GET /customers/count
  41. * GET /customers/<id>
  42. * GET /customers/<id>/orders
  43. *
  44. * @since 2.2
  45. * @param array $routes
  46. * @return array
  47. */
  48. public function register_routes( $routes ) {
  49. # GET/POST /customers
  50. $routes[ $this->base ] = array(
  51. array( array( $this, 'get_customers' ), WC_API_SERVER::READABLE ),
  52. array( array( $this, 'create_customer' ), WC_API_SERVER::CREATABLE | WC_API_Server::ACCEPT_DATA ),
  53. );
  54. # GET /customers/count
  55. $routes[ $this->base . '/count'] = array(
  56. array( array( $this, 'get_customers_count' ), WC_API_SERVER::READABLE ),
  57. );
  58. # GET/PUT/DELETE /customers/<id>
  59. $routes[ $this->base . '/(?P<id>\d+)' ] = array(
  60. array( array( $this, 'get_customer' ), WC_API_SERVER::READABLE ),
  61. array( array( $this, 'edit_customer' ), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA ),
  62. array( array( $this, 'delete_customer' ), WC_API_SERVER::DELETABLE ),
  63. );
  64. # GET /customers/email/<email>
  65. $routes[ $this->base . '/email/(?P<email>.+)' ] = array(
  66. array( array( $this, 'get_customer_by_email' ), WC_API_SERVER::READABLE ),
  67. );
  68. # GET /customers/<id>/orders
  69. $routes[ $this->base . '/(?P<id>\d+)/orders' ] = array(
  70. array( array( $this, 'get_customer_orders' ), WC_API_SERVER::READABLE ),
  71. );
  72. # GET /customers/<id>/downloads
  73. $routes[ $this->base . '/(?P<id>\d+)/downloads' ] = array(
  74. array( array( $this, 'get_customer_downloads' ), WC_API_SERVER::READABLE ),
  75. );
  76. # POST|PUT /customers/bulk
  77. $routes[ $this->base . '/bulk' ] = array(
  78. array( array( $this, 'bulk' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
  79. );
  80. return $routes;
  81. }
  82. /**
  83. * Get all customers
  84. *
  85. * @since 2.1
  86. * @param array $fields
  87. * @param array $filter
  88. * @param int $page
  89. * @return array
  90. */
  91. public function get_customers( $fields = null, $filter = array(), $page = 1 ) {
  92. $filter['page'] = $page;
  93. $query = $this->query_customers( $filter );
  94. $customers = array();
  95. foreach ( $query->get_results() as $user_id ) {
  96. if ( ! $this->is_readable( $user_id ) ) {
  97. continue;
  98. }
  99. $customers[] = current( $this->get_customer( $user_id, $fields ) );
  100. }
  101. $this->server->add_pagination_headers( $query );
  102. return array( 'customers' => $customers );
  103. }
  104. /**
  105. * Get the customer for the given ID
  106. *
  107. * @since 2.1
  108. * @param int $id the customer ID
  109. * @param array $fields
  110. * @return array
  111. */
  112. public function get_customer( $id, $fields = null ) {
  113. global $wpdb;
  114. $id = $this->validate_request( $id, 'customer', 'read' );
  115. if ( is_wp_error( $id ) ) {
  116. return $id;
  117. }
  118. $customer = new WP_User( $id );
  119. // Get info about user's last order
  120. $last_order = $wpdb->get_row( "SELECT id, post_date_gmt
  121. FROM $wpdb->posts AS posts
  122. LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
  123. WHERE meta.meta_key = '_customer_user'
  124. AND meta.meta_value = {$customer->ID}
  125. AND posts.post_type = 'shop_order'
  126. AND posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
  127. ORDER BY posts.ID DESC
  128. " );
  129. $customer_data = array(
  130. 'id' => $customer->ID,
  131. 'created_at' => $this->server->format_datetime( $customer->user_registered ),
  132. 'email' => $customer->user_email,
  133. 'first_name' => $customer->first_name,
  134. 'last_name' => $customer->last_name,
  135. 'username' => $customer->user_login,
  136. 'role' => $customer->roles[0],
  137. 'last_order_id' => is_object( $last_order ) ? $last_order->id : null,
  138. 'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->post_date_gmt ) : null,
  139. 'orders_count' => wc_get_customer_order_count( $customer->ID ),
  140. 'total_spent' => wc_format_decimal( wc_get_customer_total_spent( $customer->ID ), 2 ),
  141. 'avatar_url' => $this->get_avatar_url( $customer->customer_email ),
  142. 'billing_address' => array(
  143. 'first_name' => $customer->billing_first_name,
  144. 'last_name' => $customer->billing_last_name,
  145. 'company' => $customer->billing_company,
  146. 'address_1' => $customer->billing_address_1,
  147. 'address_2' => $customer->billing_address_2,
  148. 'city' => $customer->billing_city,
  149. 'state' => $customer->billing_state,
  150. 'postcode' => $customer->billing_postcode,
  151. 'country' => $customer->billing_country,
  152. 'email' => $customer->billing_email,
  153. 'phone' => $customer->billing_phone,
  154. ),
  155. 'shipping_address' => array(
  156. 'first_name' => $customer->shipping_first_name,
  157. 'last_name' => $customer->shipping_last_name,
  158. 'company' => $customer->shipping_company,
  159. 'address_1' => $customer->shipping_address_1,
  160. 'address_2' => $customer->shipping_address_2,
  161. 'city' => $customer->shipping_city,
  162. 'state' => $customer->shipping_state,
  163. 'postcode' => $customer->shipping_postcode,
  164. 'country' => $customer->shipping_country,
  165. ),
  166. );
  167. return array( 'customer' => apply_filters( 'woocommerce_api_customer_response', $customer_data, $customer, $fields, $this->server ) );
  168. }
  169. /**
  170. * Get the customer for the given email
  171. *
  172. * @since 2.1
  173. * @param string $email the customer email
  174. * @param array $fields
  175. * @return array
  176. */
  177. public function get_customer_by_email( $email, $fields = null ) {
  178. try {
  179. if ( is_email( $email ) ) {
  180. $customer = get_user_by( 'email', $email );
  181. if ( ! is_object( $customer ) ) {
  182. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 );
  183. }
  184. } else {
  185. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 );
  186. }
  187. return $this->get_customer( $customer->ID, $fields );
  188. } catch ( WC_API_Exception $e ) {
  189. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  190. }
  191. }
  192. /**
  193. * Get the total number of customers
  194. *
  195. * @since 2.1
  196. * @param array $filter
  197. * @return array
  198. */
  199. public function get_customers_count( $filter = array() ) {
  200. try {
  201. if ( ! current_user_can( 'list_users' ) ) {
  202. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_customers_count', __( 'You do not have permission to read the customers count', 'woocommerce' ), 401 );
  203. }
  204. $query = $this->query_customers( $filter );
  205. return array( 'count' => $query->get_total() );
  206. } catch ( WC_API_Exception $e ) {
  207. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  208. }
  209. }
  210. /**
  211. * Get customer billing address fields.
  212. *
  213. * @since 2.2
  214. * @return array
  215. */
  216. protected function get_customer_billing_address() {
  217. $billing_address = apply_filters( 'woocommerce_api_customer_billing_address', array(
  218. 'first_name',
  219. 'last_name',
  220. 'company',
  221. 'address_1',
  222. 'address_2',
  223. 'city',
  224. 'state',
  225. 'postcode',
  226. 'country',
  227. 'email',
  228. 'phone',
  229. ) );
  230. return $billing_address;
  231. }
  232. /**
  233. * Get customer shipping address fields.
  234. *
  235. * @since 2.2
  236. * @return array
  237. */
  238. protected function get_customer_shipping_address() {
  239. $shipping_address = apply_filters( 'woocommerce_api_customer_shipping_address', array(
  240. 'first_name',
  241. 'last_name',
  242. 'company',
  243. 'address_1',
  244. 'address_2',
  245. 'city',
  246. 'state',
  247. 'postcode',
  248. 'country',
  249. ) );
  250. return $shipping_address;
  251. }
  252. /**
  253. * Add/Update customer data.
  254. *
  255. * @since 2.2
  256. * @param int $id the customer ID
  257. * @param array $data
  258. */
  259. protected function update_customer_data( $id, $data ) {
  260. // Customer first name.
  261. if ( isset( $data['first_name'] ) ) {
  262. update_user_meta( $id, 'first_name', wc_clean( $data['first_name'] ) );
  263. }
  264. // Customer last name.
  265. if ( isset( $data['last_name'] ) ) {
  266. update_user_meta( $id, 'last_name', wc_clean( $data['last_name'] ) );
  267. }
  268. // Customer billing address.
  269. if ( isset( $data['billing_address'] ) ) {
  270. foreach ( $this->get_customer_billing_address() as $address ) {
  271. if ( isset( $data['billing_address'][ $address ] ) ) {
  272. update_user_meta( $id, 'billing_' . $address, wc_clean( $data['billing_address'][ $address ] ) );
  273. }
  274. }
  275. }
  276. // Customer shipping address.
  277. if ( isset( $data['shipping_address'] ) ) {
  278. foreach ( $this->get_customer_shipping_address() as $address ) {
  279. if ( isset( $data['shipping_address'][ $address ] ) ) {
  280. update_user_meta( $id, 'shipping_' . $address, wc_clean( $data['shipping_address'][ $address ] ) );
  281. }
  282. }
  283. }
  284. do_action( 'woocommerce_api_update_customer_data', $id, $data );
  285. }
  286. /**
  287. * Create a customer
  288. *
  289. * @since 2.2
  290. * @param array $data
  291. * @return array
  292. */
  293. public function create_customer( $data ) {
  294. try {
  295. if ( ! isset( $data['customer'] ) ) {
  296. throw new WC_API_Exception( 'woocommerce_api_missing_customer_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'customer' ), 400 );
  297. }
  298. $data = $data['customer'];
  299. // Checks with can create new users.
  300. if ( ! current_user_can( 'create_users' ) ) {
  301. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_customer', __( 'You do not have permission to create this customer', 'woocommerce' ), 401 );
  302. }
  303. $data = apply_filters( 'woocommerce_api_create_customer_data', $data, $this );
  304. // Checks with the email is missing.
  305. if ( ! isset( $data['email'] ) ) {
  306. throw new WC_API_Exception( 'woocommerce_api_missing_customer_email', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'email' ), 400 );
  307. }
  308. // Sets the username.
  309. $data['username'] = ! empty( $data['username'] ) ? $data['username'] : '';
  310. // Sets the password.
  311. $data['password'] = ! empty( $data['password'] ) ? $data['password'] : '';
  312. // Attempts to create the new customer
  313. $id = wc_create_new_customer( $data['email'], $data['username'], $data['password'] );
  314. // Checks for an error in the customer creation.
  315. if ( is_wp_error( $id ) ) {
  316. throw new WC_API_Exception( $id->get_error_code(), $id->get_error_message(), 400 );
  317. }
  318. // Added customer data.
  319. $this->update_customer_data( $id, $data );
  320. do_action( 'woocommerce_api_create_customer', $id, $data );
  321. $this->server->send_status( 201 );
  322. return $this->get_customer( $id );
  323. } catch ( WC_API_Exception $e ) {
  324. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  325. }
  326. }
  327. /**
  328. * Edit a customer
  329. *
  330. * @since 2.2
  331. * @param int $id the customer ID
  332. * @param array $data
  333. * @return array
  334. */
  335. public function edit_customer( $id, $data ) {
  336. try {
  337. if ( ! isset( $data['customer'] ) ) {
  338. throw new WC_API_Exception( 'woocommerce_api_missing_customer_data', sprintf( __( 'No %1$s data specified to edit %1$s', 'woocommerce' ), 'customer' ), 400 );
  339. }
  340. $data = $data['customer'];
  341. // Validate the customer ID.
  342. $id = $this->validate_request( $id, 'customer', 'edit' );
  343. // Return the validate error.
  344. if ( is_wp_error( $id ) ) {
  345. throw new WC_API_Exception( $id->get_error_code(), $id->get_error_message(), 400 );
  346. }
  347. $data = apply_filters( 'woocommerce_api_edit_customer_data', $data, $this );
  348. // Customer email.
  349. if ( isset( $data['email'] ) ) {
  350. wp_update_user( array( 'ID' => $id, 'user_email' => sanitize_email( $data['email'] ) ) );
  351. }
  352. // Customer password.
  353. if ( isset( $data['password'] ) ) {
  354. wp_update_user( array( 'ID' => $id, 'user_pass' => wc_clean( $data['password'] ) ) );
  355. }
  356. // Update customer data.
  357. $this->update_customer_data( $id, $data );
  358. do_action( 'woocommerce_api_edit_customer', $id, $data );
  359. return $this->get_customer( $id );
  360. } catch ( WC_API_Exception $e ) {
  361. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  362. }
  363. }
  364. /**
  365. * Delete a customer
  366. *
  367. * @since 2.2
  368. * @param int $id the customer ID
  369. * @return array
  370. */
  371. public function delete_customer( $id ) {
  372. // Validate the customer ID.
  373. $id = $this->validate_request( $id, 'customer', 'delete' );
  374. // Return the validate error.
  375. if ( is_wp_error( $id ) ) {
  376. return $id;
  377. }
  378. do_action( 'woocommerce_api_delete_customer', $id, $this );
  379. return $this->delete( $id, 'customer' );
  380. }
  381. /**
  382. * Get the orders for a customer
  383. *
  384. * @since 2.1
  385. * @param int $id the customer ID
  386. * @param string $fields fields to include in response
  387. * @return array
  388. */
  389. public function get_customer_orders( $id, $fields = null ) {
  390. global $wpdb;
  391. $id = $this->validate_request( $id, 'customer', 'read' );
  392. if ( is_wp_error( $id ) ) {
  393. return $id;
  394. }
  395. $order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id
  396. FROM $wpdb->posts AS posts
  397. LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
  398. WHERE meta.meta_key = '_customer_user'
  399. AND meta.meta_value = '%s'
  400. AND posts.post_type = 'shop_order'
  401. AND posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
  402. ", $id ) );
  403. if ( empty( $order_ids ) ) {
  404. return array( 'orders' => array() );
  405. }
  406. $orders = array();
  407. foreach ( $order_ids as $order_id ) {
  408. $orders[] = current( WC()->api->WC_API_Orders->get_order( $order_id, $fields ) );
  409. }
  410. return array( 'orders' => apply_filters( 'woocommerce_api_customer_orders_response', $orders, $id, $fields, $order_ids, $this->server ) );
  411. }
  412. /**
  413. * Get the available downloads for a customer
  414. *
  415. * @since 2.2
  416. * @param int $id the customer ID
  417. * @param string $fields fields to include in response
  418. * @return array
  419. */
  420. public function get_customer_downloads( $id, $fields = null ) {
  421. $id = $this->validate_request( $id, 'customer', 'read' );
  422. if ( is_wp_error( $id ) ) {
  423. return $id;
  424. }
  425. $downloads = array();
  426. $_downloads = wc_get_customer_available_downloads( $id );
  427. foreach ( $_downloads as $key => $download ) {
  428. $downloads[ $key ] = $download;
  429. $downloads[ $key ]['access_expires'] = $this->server->format_datetime( $downloads[ $key ]['access_expires'] );
  430. }
  431. return array( 'downloads' => apply_filters( 'woocommerce_api_customer_downloads_response', $downloads, $id, $fields, $this->server ) );
  432. }
  433. /**
  434. * Helper method to get customer user objects
  435. *
  436. * Note that WP_User_Query does not have built-in pagination so limit & offset are used to provide limited
  437. * pagination support
  438. *
  439. * The filter for role can only be a single role in a string.
  440. *
  441. * @since 2.3
  442. * @param array $args request arguments for filtering query
  443. * @return WP_User_Query
  444. */
  445. private function query_customers( $args = array() ) {
  446. // default users per page
  447. $users_per_page = get_option( 'posts_per_page' );
  448. // Set base query arguments
  449. $query_args = array(
  450. 'fields' => 'ID',
  451. 'role' => 'customer',
  452. 'orderby' => 'registered',
  453. 'number' => $users_per_page,
  454. );
  455. // Custom Role
  456. if ( ! empty( $args['role'] ) ) {
  457. $query_args['role'] = $args['role'];
  458. }
  459. // Search
  460. if ( ! empty( $args['q'] ) ) {
  461. $query_args['search'] = $args['q'];
  462. }
  463. // Limit number of users returned
  464. if ( ! empty( $args['limit'] ) ) {
  465. if ( $args['limit'] == -1 ) {
  466. unset( $query_args['number'] );
  467. } else {
  468. $query_args['number'] = absint( $args['limit'] );
  469. $users_per_page = absint( $args['limit'] );
  470. }
  471. } else {
  472. $args['limit'] = $query_args['number'];
  473. }
  474. // Page
  475. $page = ( isset( $args['page'] ) ) ? absint( $args['page'] ) : 1;
  476. // Offset
  477. if ( ! empty( $args['offset'] ) ) {
  478. $query_args['offset'] = absint( $args['offset'] );
  479. } else {
  480. $query_args['offset'] = $users_per_page * ( $page - 1 );
  481. }
  482. // Created date
  483. if ( ! empty( $args['created_at_min'] ) ) {
  484. $this->created_at_min = $this->server->parse_datetime( $args['created_at_min'] );
  485. }
  486. if ( ! empty( $args['created_at_max'] ) ) {
  487. $this->created_at_max = $this->server->parse_datetime( $args['created_at_max'] );
  488. }
  489. // Order (ASC or DESC, ASC by default)
  490. if ( ! empty( $args['order'] ) ) {
  491. $query_args['order'] = $args['order'];
  492. }
  493. // Orderby
  494. if ( ! empty( $args['orderby'] ) ) {
  495. $query_args['orderby'] = $args['orderby'];
  496. // Allow sorting by meta value
  497. if ( ! empty( $args['orderby_meta_key'] ) ) {
  498. $query_args['meta_key'] = $args['orderby_meta_key'];
  499. }
  500. }
  501. $query = new WP_User_Query( $query_args );
  502. // Helper members for pagination headers
  503. $query->total_pages = ( $args['limit'] == -1 ) ? 1 : ceil( $query->get_total() / $users_per_page );
  504. $query->page = $page;
  505. return $query;
  506. }
  507. /**
  508. * Add customer data to orders
  509. *
  510. * @since 2.1
  511. * @param $order_data
  512. * @param $order
  513. * @return array
  514. */
  515. public function add_customer_data( $order_data, $order ) {
  516. if ( 0 == $order->customer_user ) {
  517. // add customer data from order
  518. $order_data['customer'] = array(
  519. 'id' => 0,
  520. 'email' => $order->billing_email,
  521. 'first_name' => $order->billing_first_name,
  522. 'last_name' => $order->billing_last_name,
  523. 'billing_address' => array(
  524. 'first_name' => $order->billing_first_name,
  525. 'last_name' => $order->billing_last_name,
  526. 'company' => $order->billing_company,
  527. 'address_1' => $order->billing_address_1,
  528. 'address_2' => $order->billing_address_2,
  529. 'city' => $order->billing_city,
  530. 'state' => $order->billing_state,
  531. 'postcode' => $order->billing_postcode,
  532. 'country' => $order->billing_country,
  533. 'email' => $order->billing_email,
  534. 'phone' => $order->billing_phone,
  535. ),
  536. 'shipping_address' => array(
  537. 'first_name' => $order->shipping_first_name,
  538. 'last_name' => $order->shipping_last_name,
  539. 'company' => $order->shipping_company,
  540. 'address_1' => $order->shipping_address_1,
  541. 'address_2' => $order->shipping_address_2,
  542. 'city' => $order->shipping_city,
  543. 'state' => $order->shipping_state,
  544. 'postcode' => $order->shipping_postcode,
  545. 'country' => $order->shipping_country,
  546. ),
  547. );
  548. } else {
  549. $order_data['customer'] = current( $this->get_customer( $order->customer_user ) );
  550. }
  551. return $order_data;
  552. }
  553. /**
  554. * Modify the WP_User_Query to support filtering on the date the customer was created
  555. *
  556. * @since 2.1
  557. * @param WP_User_Query $query
  558. */
  559. public function modify_user_query( $query ) {
  560. if ( $this->created_at_min ) {
  561. $query->query_where .= sprintf( " AND user_registered >= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%H:%%i:%%s' )", esc_sql( $this->created_at_min ) );
  562. }
  563. if ( $this->created_at_max ) {
  564. $query->query_where .= sprintf( " AND user_registered <= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%H:%%i:%%s' )", esc_sql( $this->created_at_max ) );
  565. }
  566. }
  567. /**
  568. * Wrapper for @see get_avatar() which doesn't simply return
  569. * the URL so we need to pluck it from the HTML img tag
  570. *
  571. * Kudos to https://github.com/WP-API/WP-API for offering a better solution
  572. *
  573. * @since 2.1
  574. * @param string $email the customer's email
  575. * @return string the URL to the customer's avatar
  576. */
  577. private function get_avatar_url( $email ) {
  578. $avatar_html = get_avatar( $email );
  579. // Get the URL of the avatar from the provided HTML
  580. preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches );
  581. if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) {
  582. return esc_url_raw( $matches[1] );
  583. }
  584. return null;
  585. }
  586. /**
  587. * Validate the request by checking:
  588. *
  589. * 1) the ID is a valid integer
  590. * 2) the ID returns a valid WP_User
  591. * 3) the current user has the proper permissions
  592. *
  593. * @since 2.1
  594. * @see WC_API_Resource::validate_request()
  595. * @param integer $id the customer ID
  596. * @param string $type the request type, unused because this method overrides the parent class
  597. * @param string $context the context of the request, either `read`, `edit` or `delete`
  598. * @return int|WP_Error valid user ID or WP_Error if any of the checks fails
  599. */
  600. protected function validate_request( $id, $type, $context ) {
  601. try {
  602. $id = absint( $id );
  603. // validate ID
  604. if ( empty( $id ) ) {
  605. throw new WC_API_Exception( 'woocommerce_api_invalid_customer_id', __( 'Invalid customer ID', 'woocommerce' ), 404 );
  606. }
  607. // non-existent IDs return a valid WP_User object with the user ID = 0
  608. $customer = new WP_User( $id );
  609. if ( 0 === $customer->ID ) {
  610. throw new WC_API_Exception( 'woocommerce_api_invalid_customer', __( 'Invalid customer', 'woocommerce' ), 404 );
  611. }
  612. // validate permissions
  613. switch ( $context ) {
  614. case 'read':
  615. if ( ! current_user_can( 'list_users' ) ) {
  616. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_customer', __( 'You do not have permission to read this customer', 'woocommerce' ), 401 );
  617. }
  618. break;
  619. case 'edit':
  620. if ( ! current_user_can( 'edit_users' ) ) {
  621. throw new WC_API_Exception( 'woocommerce_api_user_cannot_edit_customer', __( 'You do not have permission to edit this customer', 'woocommerce' ), 401 );
  622. }
  623. break;
  624. case 'delete':
  625. if ( ! current_user_can( 'delete_users' ) ) {
  626. throw new WC_API_Exception( 'woocommerce_api_user_cannot_delete_customer', __( 'You do not have permission to delete this customer', 'woocommerce' ), 401 );
  627. }
  628. break;
  629. }
  630. return $id;
  631. } catch ( WC_API_Exception $e ) {
  632. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  633. }
  634. }
  635. /**
  636. * Check if the current user can read users
  637. *
  638. * @since 2.1
  639. * @see WC_API_Resource::is_readable()
  640. * @param int|WP_Post $post unused
  641. * @return bool true if the current user can read users, false otherwise
  642. */
  643. protected function is_readable( $post ) {
  644. return current_user_can( 'list_users' );
  645. }
  646. /**
  647. * Bulk update or insert customers
  648. * Accepts an array with customers in the formats supported by
  649. * WC_API_Customers->create_customer() and WC_API_Customers->edit_customer()
  650. *
  651. * @since 2.4.0
  652. * @param array $data
  653. * @return array
  654. */
  655. public function bulk( $data ) {
  656. try {
  657. if ( ! isset( $data['customers'] ) ) {
  658. throw new WC_API_Exception( 'woocommerce_api_missing_customers_data', sprintf( __( 'No %1$s data specified to create/edit %1$s', 'woocommerce' ), 'customers' ), 400 );
  659. }
  660. $data = $data['customers'];
  661. $limit = apply_filters( 'woocommerce_api_bulk_limit', 100, 'customers' );
  662. // Limit bulk operation
  663. if ( count( $data ) > $limit ) {
  664. throw new WC_API_Exception( 'woocommerce_api_customers_request_entity_too_large', sprintf( __( 'Unable to accept more than %s items for this request', 'woocommerce' ), $limit ), 413 );
  665. }
  666. $customers = array();
  667. foreach ( $data as $_customer ) {
  668. $customer_id = 0;
  669. // Try to get the customer ID
  670. if ( isset( $_customer['id'] ) ) {
  671. $customer_id = intval( $_customer['id'] );
  672. }
  673. // Customer exists / edit customer
  674. if ( $customer_id ) {
  675. $edit = $this->edit_customer( $customer_id, array( 'customer' => $_customer ) );
  676. if ( is_wp_error( $edit ) ) {
  677. $customers[] = array(
  678. 'id' => $customer_id,
  679. 'error' => array( 'code' => $edit->get_error_code(), 'message' => $edit->get_error_message() )
  680. );
  681. } else {
  682. $customers[] = $edit['customer'];
  683. }
  684. }
  685. // Customer don't exists / create customer
  686. else {
  687. $new = $this->create_customer( array( 'customer' => $_customer ) );
  688. if ( is_wp_error( $new ) ) {
  689. $customers[] = array(
  690. 'id' => $customer_id,
  691. 'error' => array( 'code' => $new->get_error_code(), 'message' => $new->get_error_message() )
  692. );
  693. } else {
  694. $customers[] = $new['customer'];
  695. }
  696. }
  697. }
  698. return array( 'customers' => apply_filters( 'woocommerce_api_customers_bulk_response', $customers, $this ) );
  699. } catch ( WC_API_Exception $e ) {
  700. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
  701. }
  702. }
  703. }