<?php
if (!defined('ABSPATH')) {
exit;
}
class WC_API_Customers extends WC_API_Resource
{
protected $base = '/customers';
private $created_at_min = null;
private $created_at_max = null;
public function __construct(WC_API_Server $server)
{
parent::__construct($server);
add_filter('woocommerce_api_order_response', array($this, 'add_customer_data'), 10, 2);
add_action('pre_user_query', array($this, 'modify_user_query'));
}
public function register_routes($routes)
{
$routes[$this->base] = array(array(array($this, 'get_customers'), WC_API_SERVER::READABLE), array(array($this, 'create_customer'), WC_API_SERVER::CREATABLE | WC_API_Server::ACCEPT_DATA));
$routes[$this->base . '/count'] = array(array(array($this, 'get_customers_count'), WC_API_SERVER::READABLE));
$routes[$this->base . '/(?P<id>\\d+)'] = array(array(array($this, 'get_customer'), WC_API_SERVER::READABLE), array(array($this, 'edit_customer'), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA), array(array($this, 'delete_customer'), WC_API_SERVER::DELETABLE));
$routes[$this->base . '/email/(?P<email>.+)'] = array(array(array($this, 'get_customer_by_email'), WC_API_SERVER::READABLE));
$routes[$this->base . '/(?P<id>\\d+)/orders'] = array(array(array($this, 'get_customer_orders'), WC_API_SERVER::READABLE));
$routes[$this->base . '/(?P<id>\\d+)/downloads'] = array(array(array($this, 'get_customer_downloads'), WC_API_SERVER::READABLE));
$routes[$this->base . '/bulk'] = array(array(array($this, 'bulk'), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA));
return $routes;
}
public function get_customers($fields = null, $filter = array(), $page = 1)
{
$filter['page'] = $page;
$query = $this->query_customers($filter);
$customers = array();
foreach ($query->get_results() as $user_id) {
if (!$this->is_readable($user_id)) {
continue;
}
$customers[] = current($this->get_customer($user_id, $fields));
}
$this->server->add_pagination_headers($query);
return array('customers' => $customers);
}
public function get_customer($id, $fields = null)
{
global $wpdb;
$id = $this->validate_request($id, 'customer', 'read');
if (is_wp_error($id)) {
return $id;
}
$customer = new WC_Customer($id);
$last_order = $customer->get_last_order();
$customer_data = array('id' => $customer->get_id(), 'created_at' => $this->server->format_datetime($customer->get_date_created() ? $customer->get_date_created()->getTimestamp() : 0), 'last_update' => $this->server->format_datetime($customer->get_date_modified() ? $customer->get_date_modified()->getTimestamp() : 0), 'email' => $customer->get_email(), 'first_name' => $customer->get_first_name(), 'last_name' => $customer->get_last_name(), 'username' => $customer->get_username(), 'role' => $customer->get_role(), 'last_order_id' => is_object($last_order) ? $last_order->get_id() : null, 'last_order_date' => is_object($last_order) ? $this->server->format_datetime($last_order->get_date_created() ? $last_order->get_date_created()->getTimestamp() : 0) : null, 'orders_count' => $customer->get_order_count(), 'total_spent' => wc_format_decimal($customer->get_total_spent(), 2), 'avatar_url' => $customer->get_avatar_url(), 'billing_address' => array('first_name' => $customer->get_billing_first_name(), 'last_name' => $customer->get_billing_last_name(), 'company' => $customer->get_billing_company(), 'address_1' => $customer->get_billing_address_1(), 'address_2' => $customer->get_billing_address_2(), 'city' => $customer->get_billing_city(), 'state' => $customer->get_billing_state(), 'postcode' => $customer->get_billing_postcode(), 'country' => $customer->get_billing_country(), 'email' => $customer->get_billing_email(), 'phone' => $customer->get_billing_phone()), 'shipping_address' => array('first_name' => $customer->get_shipping_first_name(), 'last_name' => $customer->get_shipping_last_name(), 'company' => $customer->get_shipping_company(), 'address_1' => $customer->get_shipping_address_1(), 'address_2' => $customer->get_shipping_address_2(), 'city' => $customer->get_shipping_city(), 'state' => $customer->get_shipping_state(), 'postcode' => $customer->get_shipping_postcode(), 'country' => $customer->get_shipping_country()));
return array('customer' => apply_filters('woocommerce_api_customer_response', $customer_data, $customer, $fields, $this->server));
}
public function get_customer_by_email($email, $fields = null)
{
try {
if (is_email($email)) {
$customer = get_user_by('email', $email);
if (!is_object($customer)) {
throw new WC_API_Exception('woocommerce_api_invalid_customer_email', __('Invalid customer email', 'woocommerce'), 404);
}
} else {
throw new WC_API_Exception('woocommerce_api_invalid_customer_email', __('Invalid customer email', 'woocommerce'), 404);
}
return $this->get_customer($customer->ID, $fields);
} catch (WC_API_Exception $e) {
return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
}
}
public function get_customers_count($filter = array())
{
try {
if (!current_user_can('list_users')) {
throw new WC_API_Exception('woocommerce_api_user_cannot_read_customers_count', __('You do not have permission to read the customers count', 'woocommerce'), 401);
}
$query = $this->query_customers($filter);
return array('count' => $query->get_total());
} catch (WC_API_Exception $e) {
return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
}
}
protected function get_customer_billing_address()
{
$billing_address = apply_filters('woocommerce_api_customer_billing_address', array('first_name', 'last_name', 'company', 'address_1', 'address_2', 'city', 'state', 'postcode', 'country', 'email', 'phone'));
return $billing_address;
}
protected function get_customer_shipping_address()
{
$shipping_address = apply_filters('woocommerce_api_customer_shipping_address', array('first_name', 'last_name', 'company', 'address_1', 'address_2', 'city', 'state', 'postcode', 'country'));
return $shipping_address;
}
protected function update_customer_data($id, $data, $customer)
{
if (isset($data['first_name'])) {
$customer->set_first_name(wc_clean($data['first_name']));
}
if (isset($data['last_name'])) {
$customer->set_last_name(wc_clean($data['last_name']));
}
if (isset($data['billing_address'])) {
foreach ($this->get_customer_billing_address() as $field) {
if (isset($data['billing_address'][$field])) {
if (is_callable(array($customer, "set_billing_{$field}"))) {
$customer->{"set_billing_{$field}"}($data['billing_address'][$field]);
} else {
$customer->update_meta_data('billing_' . $field, wc_clean($data['billing_address'][$field]));
}
}
}
}
if (isset($data['shipping_address'])) {
foreach ($this->get_customer_shipping_address() as $field) {
if (isset($data['shipping_address'][$field])) {
if (is_callable(array($customer, "set_shipping_{$field}"))) {
$customer->{"set_shipping_{$field}"}($data['shipping_address'][$field]);
} else {
$customer->update_meta_data('shipping_' . $field, wc_clean($data['shipping_address'][$field]));
}
}
}
}
do_action('woocommerce_api_update_customer_data', $id, $data, $customer);
}
public function create_customer($data)
{
try {
if (!isset($data['customer'])) {
throw new WC_API_Exception('woocommerce_api_missing_customer_data', sprintf(__('No %1$s data specified to create %1$s', 'woocommerce'), 'customer'), 400);
}
$data = $data['customer'];
if (!current_user_can('create_users')) {
throw new WC_API_Exception('woocommerce_api_user_cannot_create_customer', __('You do not have permission to create this customer', 'woocommerce'), 401);
}
$data = apply_filters('woocommerce_api_create_customer_data', $data, $this);
if (!isset($data['email'])) {
throw new WC_API_Exception('woocommerce_api_missing_customer_email', sprintf(__('Missing parameter %s', 'woocommerce'), 'email'), 400);
}
$customer = new WC_Customer();
$customer->set_username(!empty($data['username']) ? $data['username'] : '');
$customer->set_password(!empty($data['password']) ? $data['password'] : '');
$customer->set_email($data['email']);
$customer->save();
if (!$customer->get_id()) {
throw new WC_API_Exception('woocommerce_api_user_cannot_create_customer', __('This resource cannot be created.', 'woocommerce'), 400);
}
$this->update_customer_data($customer->get_id(), $data, $customer);
$customer->save();
do_action('woocommerce_api_create_customer', $customer->get_id(), $data);
$this->server->send_status(201);
return $this->get_customer($customer->get_id());
} catch (Exception $e) {
return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
}
}
public function edit_customer($id, $data)
{
try {
if (!isset($data['customer'])) {
throw new WC_API_Exception('woocommerce_api_missing_customer_data', sprintf(__('No %1$s data specified to edit %1$s', 'woocommerce'), 'customer'), 400);
}
$data = $data['customer'];
$id = $this->validate_request($id, 'customer', 'edit');
if (is_wp_error($id)) {
throw new WC_API_Exception($id->get_error_code(), $id->get_error_message(), 400);
}
$data = apply_filters('woocommerce_api_edit_customer_data', $data, $this);
$customer = new WC_Customer($id);
if (isset($data['email'])) {
$customer->set_email($data['email']);
}
if (isset($data['password'])) {
$customer->set_password($data['password']);
}
$this->update_customer_data($customer->get_id(), $data, $customer);
$customer->save();
do_action('woocommerce_api_edit_customer', $customer->get_id(), $data);
return $this->get_customer($customer->get_id());
} catch (Exception $e) {
return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
}
}
public function delete_customer($id)
{
$id = $this->validate_request($id, 'customer', 'delete');
if (is_wp_error($id)) {
return $id;
}
do_action('woocommerce_api_delete_customer', $id, $this);
return $this->delete($id, 'customer');
}
public function get_customer_orders($id, $fields = null, $filter = array())
{
$id = $this->validate_request($id, 'customer', 'read');
if (is_wp_error($id)) {
return $id;
}
$filter['customer_id'] = $id;
$orders = WC()->api->WC_API_Orders->get_orders($fields, $filter, null, -1);
return $orders;
}
public function get_customer_downloads($id, $fields = null)
{
$id = $this->validate_request($id, 'customer', 'read');
if (is_wp_error($id)) {
return $id;
}
$downloads = array();
$_downloads = wc_get_customer_available_downloads($id);
foreach ($_downloads as $key => $download) {
$downloads[] = array('download_url' => $download['download_url'], 'download_id' => $download['download_id'], 'product_id' => $download['product_id'], 'download_name' => $download['download_name'], 'order_id' => $download['order_id'], 'order_key' => $download['order_key'], 'downloads_remaining' => $download['downloads_remaining'], 'access_expires' => $download['access_expires'] ? $this->server->format_datetime($download['access_expires']) : null, 'file' => $download['file']);
}
return array('downloads' => apply_filters('woocommerce_api_customer_downloads_response', $downloads, $id, $fields, $this->server));
}
private function query_customers($args = array())
{
$users_per_page = get_option('posts_per_page');
$query_args = array('fields' => 'ID', 'role' => 'customer', 'orderby' => 'registered', 'number' => $users_per_page);
if (!empty($args['role'])) {
$query_args['role'] = $args['role'];
if ('all' === $query_args['role']) {
unset($query_args['role']);
}
}
if (!empty($args['q'])) {
$query_args['search'] = $args['q'];
}
if (!empty($args['limit'])) {
if (-1 == $args['limit']) {
unset($query_args['number']);
} else {
$query_args['number'] = absint($args['limit']);
$users_per_page = absint($args['limit']);
}
} else {
$args['limit'] = $query_args['number'];
}
$page = isset($args['page']) ? absint($args['page']) : 1;
if (!empty($args['offset'])) {
$query_args['offset'] = absint($args['offset']);
} else {
$query_args['offset'] = $users_per_page * ($page - 1);
}
if (!empty($args['created_at_min'])) {
$this->created_at_min = $this->server->parse_datetime($args['created_at_min']);
}
if (!empty($args['created_at_max'])) {
$this->created_at_max = $this->server->parse_datetime($args['created_at_max']);
}
if (!empty($args['order'])) {
$query_args['order'] = $args['order'];
}
if (!empty($args['orderby'])) {
$query_args['orderby'] = $args['orderby'];
if (!empty($args['orderby_meta_key'])) {
$query_args['meta_key'] = $args['orderby_meta_key'];
}
}
$query = new WP_User_Query($query_args);
$query->total_pages = -1 == $args['limit'] ? 1 : ceil($query->get_total() / $users_per_page);
$query->page = $page;
return $query;
}
public function add_customer_data($order_data, $order)
{
if (0 == $order->get_user_id()) {
$order_data['customer'] = array('id' => 0, 'email' => $order->get_billing_email(), 'first_name' => $order->get_billing_first_name(), 'last_name' => $order->get_billing_last_name(), 'billing_address' => array('first_name' => $order->get_billing_first_name(), 'last_name' => $order->get_billing_last_name(), 'company' => $order->get_billing_company(), 'address_1' => $order->get_billing_address_1(), 'address_2' => $order->get_billing_address_2(), 'city' => $order->get_billing_city(), 'state' => $order->get_billing_state(), 'postcode' => $order->get_billing_postcode(), 'country' => $order->get_billing_country(), 'email' => $order->get_billing_email(), 'phone' => $order->get_billing_phone()), 'shipping_address' => array('first_name' => $order->get_shipping_first_name(), 'last_name' => $order->get_shipping_last_name(), 'company' => $order->get_shipping_company(), 'address_1' => $order->get_shipping_address_1(), 'address_2' => $order->get_shipping_address_2(), 'city' => $order->get_shipping_city(), 'state' => $order->get_shipping_state(), 'postcode' => $order->get_shipping_postcode(), 'country' => $order->get_shipping_country()));
} else {
$order_data['customer'] = current($this->get_customer($order->get_user_id()));
}
return $order_data;
}
public function modify_user_query($query)
{
if ($this->created_at_min) {
$query->query_where .= sprintf(" AND user_registered >= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%H:%%i:%%s' )", esc_sql($this->created_at_min));
}
if ($this->created_at_max) {
$query->query_where .= sprintf(" AND user_registered <= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%H:%%i:%%s' )", esc_sql($this->created_at_max));
}
}
protected function validate_request($id, $type, $context)
{
try {
$id = absint($id);
if (empty($id)) {
throw new WC_API_Exception('woocommerce_api_invalid_customer_id', __('Invalid customer ID', 'woocommerce'), 404);
}
$customer = new WP_User($id);
if (0 === $customer->ID) {
throw new WC_API_Exception('woocommerce_api_invalid_customer', __('Invalid customer', 'woocommerce'), 404);
}
switch ($context) {
case 'read':
if (!current_user_can('list_users')) {
throw new WC_API_Exception('woocommerce_api_user_cannot_read_customer', __('You do not have permission to read this customer', 'woocommerce'), 401);
}
break;
case 'edit':
if (!wc_rest_check_user_permissions('edit', $customer->ID)) {
throw new WC_API_Exception('woocommerce_api_user_cannot_edit_customer', __('You do not have permission to edit this customer', 'woocommerce'), 401);
}
break;
case 'delete':
if (!wc_rest_check_user_permissions('delete', $customer->ID)) {
throw new WC_API_Exception('woocommerce_api_user_cannot_delete_customer', __('You do not have permission to delete this customer', 'woocommerce'), 401);
}
break;
}
return $id;
} catch (WC_API_Exception $e) {
return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
}
}
protected function is_readable($post)
{
return current_user_can('list_users');
}
public function bulk($data)
{
try {
if (!isset($data['customers'])) {
throw new WC_API_Exception('woocommerce_api_missing_customers_data', sprintf(__('No %1$s data specified to create/edit %1$s', 'woocommerce'), 'customers'), 400);
}
$data = $data['customers'];
$limit = apply_filters('woocommerce_api_bulk_limit', 100, 'customers');
if (count($data) > $limit) {
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);
}
$customers = array();
foreach ($data as $_customer) {
$customer_id = 0;
if (isset($_customer['id'])) {
$customer_id = intval($_customer['id']);
}
if ($customer_id) {
$edit = $this->edit_customer($customer_id, array('customer' => $_customer));
if (is_wp_error($edit)) {
$customers[] = array('id' => $customer_id, 'error' => array('code' => $edit->get_error_code(), 'message' => $edit->get_error_message()));
} else {
$customers[] = $edit['customer'];
}
} else {
$new = $this->create_customer(array('customer' => $_customer));
if (is_wp_error($new)) {
$customers[] = array('id' => $customer_id, 'error' => array('code' => $new->get_error_code(), 'message' => $new->get_error_message()));
} else {
$customers[] = $new['customer'];
}
}
}
return array('customers' => apply_filters('woocommerce_api_customers_bulk_response', $customers, $this));
} catch (WC_API_Exception $e) {
return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode()));
}
}
}