cart_manager = new Cart_Manager(); } /** * Register REST API routes for cart functionality * * @return void */ public function register_routes(): void { register_rest_route( $this->namespace, $this->base, array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'add_to_cart' ), 'permission_callback' => '__return_true', ) ); register_rest_route( $this->namespace, $this->base . '/(?P[a-zA-Z0-9-]+)', array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_from_cart' ), 'permission_callback' => '__return_true', ) ); register_rest_route( $this->namespace, $this->base, array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'sync_cart' ), 'permission_callback' => array( $this, 'is_user_logged_in' ), ) ); register_rest_route( $this->namespace, $this->base . '/(?P[a-zA-Z0-9-]+)', array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'edit_cart_item' ), 'permission_callback' => '__return_true', ) ); register_rest_route( $this->namespace, $this->base, array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_cart_items' ), 'permission_callback' => '__return_true', ) ); } /** * Prepare and validate cart item data * * @param array $data * * @return []|array|bool|WP_Error */ private function prepare_item_to_save( array $data ) { $validated = booktics_validate( $data, array( 'date' => array( 'required' ), 'start_time' => array( 'required' ), 'service_id' => array( 'required' ), 'team_member_id' => array( 'required' ), ) ); if ( is_wp_error( $validated ) ) { return $validated; } $item_validation = $this->validate_cart_item( $data ); if ( is_wp_error( $item_validation ) ) { return $item_validation; } return $item_validation; } /** * Add an item to the cart * * @param $request * * @return array|\WP_HTTP_Response */ public function add_to_cart( $request ) { $params = json_decode( $request->get_body(), true ); $validated = $this->prepare_item_to_save( $params ); if ( is_wp_error( $validated ) ) { return $this->error( __( 'Cart validation error', 'booktics' ), 422, 'Validation', $validated->errors ); } $response = $this->cart_manager->add_to_cart( $validated ); $response['service'] = $this->get_service( $response['service_id'] ); $response['team'] = $this->get_team_member( $response['team_member_id'] ); return $this->response( $response, __( 'Item added to cart', 'booktics' ), 201 ); } /** * Delete an item from the user's cart * * @param $request * * @return array|\WP_HTTP_Response */ public function delete_from_cart( $request ) { $uuid = $request->get_param( 'uuid' ); if ( empty( $uuid ) ) { return $this->error( __( 'UUID is required', 'booktics' ), 422, 'Validation' ); } $this->cart_manager->remove_cart_item( $uuid ); return $this->response( array(), __( 'Successfully deleted item from cart.', 'booktics' ) ); } /** * Synchronize cart session data to database for logged-in user * * @param $request * * @return array|\WP_HTTP_Response */ public function sync_cart( $request ) { $user_id = get_current_user_id(); $this->cart_manager->sync_session_to_db( $user_id ); $response = $this->cart_manager->get_cart(); return $this->response( $response, __( 'Successfully synced cart.', 'booktics' ) ); } /** * Get all items from the cart * * @return array|\WP_HTTP_Response */ public function get_cart_items() { $response = $this->cart_manager->get_cart(); $response['items'] = isset( $response['items'] ) ? array_map( function ( $item ) { if ( ! is_array( $item ) ) { $item = (array) $item; } $item['service'] = $this->get_service( $item['service_id'] ); $item['team'] = $this->get_team_member( $item['team_member_id'] ); return $item; }, $response['items'] ) : array(); return $this->response( $response, __( 'Cart items fetched successfully', 'booktics' ) ); } /** * Check if the current user is logged in * * @return bool True if user is logged in, false otherwise */ public function is_user_logged_in() { return is_user_logged_in(); } /** * Validate service, team member and price * * @param array $data Cart item data * * @return array|WP_Error Returns true if valid, WP_Error otherwise */ private function validate_cart_item( array $data ) { $error = new WP_Error(); $service = ( new Service_Model() )->find( $data['service_id'] ); if ( ! $service ) { $error->add( 'invalid_service', __( 'Invalid service selected', 'booktics' ) ); } $team_member = ( new Team_Member_Model() )->find( $data['team_member_id'] ); if ( empty( $team_member ) ) { $error->add( 'invalid_team_member', __( 'Invalid team member selected', 'booktics' ) ); } $service_price = 0; $addition_durations = $service->additional_durations; if ( ! empty( $addition_durations ) && isset( $data['additional_duration_id'] ) ) { $addition_durations = array_filter( $addition_durations, function ( $duration ) use ( $data ) { return $duration['id'] === $data['additional_duration_id']; } ); $addition_duration = reset( $addition_durations ); $service_price = $addition_duration['charge_amount'] ?? 0; } $data['price'] = $service_price; return $error->has_errors() ? $error : $data; } /** * Edit a cart item * * @param $request * * @return array|\WP_HTTP_Response */ public function edit_cart_item( $request ) { $uuid = $request->get_param( 'uuid' ); $params = json_decode( $request->get_body(), true ); if ( empty( $uuid ) ) { return $this->error( __( 'UUID is required', 'booktics' ), 422, 'Validation' ); } $validated = $this->prepare_item_to_save( $params ); if ( is_wp_error( $validated ) ) { return $this->error( __( 'Cart validation error', 'booktics' ), 422, 'Validation', $validated->errors ); } // Add UUID to validated data $validated['uuid'] = $uuid; // Update the cart item $updated_item = $this->cart_manager->edit_cart_item( $uuid, $validated ); if ( empty( $updated_item ) ) { return $this->error( __( 'Cart item not found', 'booktics' ), 404, 'NotFound' ); } return $this->response( $updated_item, __( 'Successfully updated cart item', 'booktics' ) ); } /** * @param $service_id * * @return array */ public function get_service( $service_id ): array { $service = Service_Model::find( $service_id ); if ( empty( $service ) ) { return array(); } return array( 'id' => $service->id, 'title' => $service->title, ); } /** * @param $team_member_id * * @return array */ public function get_team_member( $team_member_id ): array { $team_member = ( new Team_Member_Model() )->find( $team_member_id ); if ( empty( $team_member ) ) { return array(); } $team_member = $team_member->to_array(); return array( 'id' => $team_member['id'], 'display_name' => $team_member['display_name'] ?? '', 'image' => $team_member['image'] ?? '', ); } }