# booktics/1.0.2/core/customer/controllers/customer-controller.php

Booktics – Appointment Booking Calendar for Service Businesses, version 1.0.2. 483 lines.

- Page: https://pluginprobe.com/plugins/booktics/1.0.2/code/core/customer/controllers/customer-controller.php
- Raw: https://pluginprobe.com/plugins/booktics/1.0.2/raw/core/customer/controllers/customer-controller.php
- Modified: 2025-07-10T05:36:58+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/booktics/1.0.2/code/core/customer/controllers/customer-controller.php#L10-L20`.

```php
<?php

namespace Booktics\Customer\Controllers;

use Booktics\Abstracts\Base_Rest_Controller;
use Booktics\Abstracts\Booktics_Database;
use Booktics\Abstracts\User_Model;
use Booktics\Customer\Handlers\Customer_Event_Handler;
use Booktics\Models\Appointment_Model;
use Booktics\Models\Customer_Model;
use Booktics\Models\Order_Model;
use Booktics\Models\Payment_Model;
use WP_Error;
use WP_HTTP_Response;
use WP_REST_Response;
use WP_REST_Server;

/**
 * Customer controller
 *
 * @package Booktics/Customer
 */
class Customer_Controller extends Base_Rest_Controller {

    /**
     * Store namespace of api
     *
     * @var string
     */
    protected $namespace = 'booktics/v1';

    /**
     * Store base url
     *
     * @var string
     */
    protected $base = 'customers';

    /**
     *
     *
     * @return void
     */
    public function register_routes(): void {
        register_rest_route(
            $this->namespace, $this->base, array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_item' ),
					'permission_callback' => array(
						$this,
						'create_customer_permission',
					),
				),
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_items' ),
					'permission_callback' => array(
						$this,
						'get_customer_permission',
					),
				),
				array(
					'methods'             => WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_items' ),
					'permission_callback' => array(
						$this,
						'delete_customer_permission',
					),
				),
            )
        );

        register_rest_route(
            $this->namespace, '/' . $this->base . '/(?P<id>[\d]+)', array(
				array(
					'methods'             => WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'update_item' ),
					'permission_callback' => array(
						$this,
						'update_customer_permission',
					),
					'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
				),
				array(
					'methods'             => WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_item' ),
					'permission_callback' => array(
						$this,
						'delete_customer_permission',
					),
				),
				array(
					'method'              => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_item' ),
					'permission_callback' => array(
						$this,
						'get_customer_permission',
					),
				),
            )
        );
    }

    /**
     * Check if a given request has access to create items.
     *
     * @param $request Full data about the request.
     */
    public function create_customer_permission( $request ) {
        return true;
    }

    /**
     * Prepare and validate customer data
     *
     * @param $request
     *
     * @return array|bool|WP_Error
     */
    protected function prepare_customer_data( $request ) {
        $input_data = json_decode( $request->get_body(), true );

        $validate = booktics_validate(
            $input_data, array(
				'first_name' => array(
					'required',
				),
				'email'      => array(
					'required',
					'unique:wp_users,email',
				),
            )
        );

        if ( is_wp_error( $validate ) ) {
            return $validate;
        }

        return array(
            'first_name' => $input_data['first_name'],
            'last_name'  => $input_data['last_name'],
            'user_email' => $input_data['email'],
            'user_login' => User_Model::generate_username( $input_data['email'] ),
            'phone'      => $input_data['phone'],
            'email'      => $input_data['email'],
            'status'     => 'pending',
        );
    }

    /**
     * Store new customer data
     *
     * @param $request
     *
     * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
     */
    public function create_item( $request ) {
        $prepared_data = $this->prepare_customer_data( $request );
        if ( is_wp_error( $prepared_data ) ) {
            return $this->error(
                $prepared_data->get_error_message(),
                422,
                'Validation',
                $prepared_data->errors
            );
        }

        $customer = new Customer_Model();
        $created  = $customer->save( $prepared_data );

        $image_url = $request->get_param( 'image' );
        if ( $image_url ) {
            $customer->update( array( 'image' => esc_url_raw( $image_url ) ) );
        }

        if ( ! $created ) {
            return $this->error( __( 'Customer create error', 'booktics' ), 500 );
        }

        do_action( 'booktics_customer_created', $customer, $request );

        ( new Customer_Event_Handler() )->on_customer_create( $created );
        $customer = $customer->find( $created );

        return $this->response( $customer, __( 'Successfully created customer', 'booktics' ), 201 );
    }

    /**
     * Check if a given request has access to get all customer
     *
     * @param $request
     *
     * @return bool
     */
    public function get_customer_permission( $request ) {
        return true;
    }

    /**
     * Get paginated list items for customer
     *
     * @param $request
     *
     * @return WP_Error|WP_HTTP_Response|WP_REST_Response
     */
    public function get_items( $request ) {
        $per_page   = ! empty( $request['per_page'] ) ? intval( $request['per_page'] ) : 20;
        $paged      = ! empty( $request['paged'] ) ? intval( $request['paged'] ) : 1;
        $first_name = ! empty( $request['first_name'] ) ? trim( $request['first_name'] ) : '';
        $last_name  = ! empty( $request['last_name'] ) ? trim( $request['last_name'] ) : '';
        $email      = ! empty( $request['email'] ) ? trim( $request['email'] ) : '';
        $phone      = ! empty( $request['phone'] ) ? trim( $request['phone'] ) : '';
        $user_name  = ! empty( $request['user_name'] ) ? trim( $request['user_name'] ) : '';
        $search     = ! empty( $request['search'] ) ? trim( $request['search'] ) : '';

        $customers = ( new Customer_Model() )
            ->when(
                $first_name, function ( $q, $v ) {
					$q->where( 'first_name', $v, 'LIKE' );
				}
            )
            ->when(
                $last_name, function ( $q, $v ) {
					$q->where( 'last_name', $v, 'LIKE' );
				}
            )
            ->when(
                $email, function ( $q, $v ) {
					$q->where( 'user_email', $v, 'LIKE' );
				}
            )
            ->when(
                $phone, function ( $q, $v ) {
					$q->where( 'phone', $v, 'LIKE' );
				}
            )
            ->when(
                $user_name, function ( $q, $v ) {
					$q->where( 'user_login', 'LIKE', $v, 'LIKE' );
				}
            )
            ->when(
                $search, function ( $q, $v ) {
					$q->where( 'first_name', $v, 'LIKE' )
                    ->or_where( 'last_name', $v, 'LIKE' )
                    ->or_where( 'phone', $v, 'LIKE' );
				}
            )->all(
                array(
					'paged' => $paged,
					'number' => $per_page,
				)
            );

        return $this->response( $customers, __( 'Successfully fetched customer', 'booktics' ) );
    }

    /**
     * Checks if a given request has access to delete a team member.
     *
     * @param $request
     *
     * @return bool
     */
    public function delete_customer_permission( $request ) {
        return true;
    }

    /**
     * Delete a customer
     *
     * @param $request
     *
     * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
     */
    public function delete_item( $request ) {
        $id = intval( $request['id'] );

        $db         = new Booktics_Database();
        $order_model = new Order_Model( $db );
        $orders     = $order_model->get( array( 'customer_id' => $id ) );
        foreach ( $orders['items'] as $order ) {
            $appointment_model = new Appointment_Model();
            $appointments     = $appointment_model->where( 'order_id', $order->id );
            foreach ( $appointments as $appointment ) {
                $appointment->delete();
            }
            $payment_model = new Payment_Model( $db );
            $payments     = $payment_model->get( array( 'order_id' => $order->id ) );
            foreach ( $payments['items'] as $payment ) {
                ( new Payment_Model( $db ) )->delete( $payment->id );
            }
            $order_model->delete( $order->id );
        }

        $customer = new Customer_Model( $id );
        $previous = $customer->find( $id );
        $deleted  = $customer->delete();

        if ( ! $deleted ) {
            return $this->error( __( 'Customer delete error', 'booktics' ), 500 );
        }

        do_action( 'booktics_customers_deleted', $request );

        return $this->response( $previous, __( 'Successfully deleted customer', 'booktics' ) );
    }

    /**
     * Delete multiple customer
     *
     * @param $request
     *
     * @return array|WP_Error|WP_HTTP_Response
     */
    public function delete_items( $request ) {
        $ids = ! empty( $request['ids'] ) ? $request['ids'] : array();

        if ( ! $ids ) {
            return $this->error( __( 'Customer ids cannot be empty', 'booktics' ), 500 );
        }
        $count = 0;
        $db    = new Booktics_Database();
        foreach ( $ids as $id ) {
            // Delete all orders (and their related appointments and payments) for this customer
            $order_model = new Order_Model( $db );
            $orders     = $order_model->get( array( 'customer_id' => $id ) );
            foreach ( $orders['items'] as $order ) {
                // Delete related appointments
                $appointment_model = new Appointment_Model();
                $appointments     = $appointment_model->where( 'order_id', $order->id );
                foreach ( $appointments as $appointment ) {
                    $appointment->delete();
                }
                // Delete related payments
                $payment_model = new Payment_Model( $db );
                $payments     = $payment_model->get( array( 'order_id' => $order->id ) );
                foreach ( $payments['items'] as $payment ) {
                    ( new Payment_Model( $db ) )->delete( $payment->id );
                }
                // Delete the order
                $order_model->delete( $order->id );
            }
            $customer = new Customer_Model( $id );
            if ( $customer->delete() ) {
                ++$count;
            }
        }
        if ( $count == 0 ) {
            return $this->error( __( 'Customer delete error', 'booktics' ), 500 );
        }

        do_action( 'booktics_customers_deleted', $request );

        return $this->response( array(), __( 'Successfully deleted customer', 'booktics' ) );
    }

    /**
     * Get single customer
     *
     * @param $request
     *
     * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
     */
    public function get_item( $request ) {
        $id       = intval( $request['id'] );
        $customer = new Customer_Model( $id );
        $customer = $customer->find( $id );
        if ( ! $customer ) {
            return $this->error( __( 'Customer not found', 'booktics' ), 404 );
        }

        $db                      = new Booktics_Database();
        $orders                  = ( new Order_Model( $db ) )->get( array( 'customer_id' => $id ) );
        $customer_data           = $customer->to_array();
        $customer_data['orders'] = array_map(
            function ( $order ) {
                $booking_count = ( new Appointment_Model() )
                ->get_appointments_count_by_order_id( $order->id );

                return array(
					'date'          => $order->created_at ? gmdate( 'j F, Y', strtotime( $order->created_at ) ) : '',
					'total_booking' => $booking_count,
					'total_amount'  => $order->total,
                );
            }, $orders['items']
        );

        return $this->response( $customer_data, __( 'Customer found successfully', 'booktics' ) );
    }

    /**
     * Checks if a given request has access to update a customer.
     *
     * @param $request
     *
     * @return bool True if the request has access to update the item, WP_Error object otherwise.
     */
    public function update_customer_permission( $request ) {
        return true;
    }

    /**
     * Prepare data for customer update
     *
     * @param $request
     *
     * @return array|bool|WP_Error
     */
    public function prepare_customer_update( $request ) {
        $input_data              = json_decode( $request->get_body(), true );
        $validation_rules        = array(
            'first_name' => array(
                'required',
            ),
            'email'      => array(
                'required',
                'unique:wp_users,email,' . $request['id'],
            ),
        );
        $update_validation_rules = array();
        $validated_data          = array();

        if ( ! is_array( $input_data ) ) {
            return new WP_Error(
                'invalid_input_data',
                'Invalid data'
            );
        }

        foreach ( $input_data as $key => $value ) {
            if ( $key == 'email' ) {
                $update_validation_rules[ $key ] = $validation_rules[ $key ];
                $validated_data['user_email']    = sanitize_email( $value );
                continue;
            }
            $validated_data[ $key ] = $value;
        }

        $validate = booktics_validate( $input_data, $update_validation_rules );

        if ( is_wp_error( $validate ) ) {
            return $validate;
        }
        $validated_data['status'] = 'active';

        return $validated_data;
    }

    /**
     * @param $request
     *
     * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response
     */
    public function update_item( $request ) {
        if ( ! isset( $request['id'] ) ) {
            return $this->error( 'Invalid team member id', 400 );
        }
        $prepared_data = $this->prepare_customer_update( $request );

        if ( is_wp_error( $prepared_data ) ) {
            return $this->error( __( 'Customer validation error', 'booktics' ), 422, 'Validation', $prepared_data->errors );
        }

        $customer  = new Customer_Model( $request['id'] );
        $updated   = $customer->update( $prepared_data );
        $image_url = $request->get_param( 'image' );
        if ( $image_url ) {
            $customer->update( array( 'image' => esc_url_raw( $image_url ) ) );
        }

        if ( ! $updated ) {
            return $this->error( __( 'Customer update error', 'booktics' ), 500 );
        }

        do_action( 'booktics_customer_updated', $customer, $request );
        $customer = $customer->find( $request['id'] );

        return $this->response( $customer, __( 'Successfully updated customer', 'booktics' ) );
    }
}

```
