'GET', 'callback' => array( $this, 'get_branches' ), 'permission_callback' => '__return_true', ) ); // GET /car-classes-all (all defined classes, no params needed) register_rest_route( self::NAMESPACE, '/car-classes-all', array( 'methods' => 'GET', 'callback' => array( $this, 'get_all_car_classes' ), 'permission_callback' => '__return_true', ) ); // GET /segments-branches-map (cached segment→branches mapping) register_rest_route( self::NAMESPACE, '/segments-branches-map', array( 'methods' => 'GET', 'callback' => array( $this, 'get_segments_branches_map' ), 'permission_callback' => '__return_true', ) ); // POST /car-classes register_rest_route( self::NAMESPACE, '/car-classes', array( 'methods' => 'POST', 'callback' => array( $this, 'get_car_classes' ), 'permission_callback' => array( $this, 'check_nonce' ), 'args' => array( 'dateFrom' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'dateTo' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'branchName' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), ), ) ); // POST /car-models register_rest_route( self::NAMESPACE, '/car-models', array( 'methods' => 'POST', 'callback' => array( $this, 'get_car_models' ), 'permission_callback' => array( $this, 'check_nonce' ), 'args' => array( 'dateFrom' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'dateTo' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'branchName' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'category' => array( 'required' => false, 'sanitize_callback' => 'sanitize_text_field', 'default' => '' ), ), ) ); // POST /pricelist register_rest_route( self::NAMESPACE, '/pricelist', array( 'methods' => 'POST', 'callback' => array( $this, 'get_pricelist' ), 'permission_callback' => array( $this, 'check_nonce' ), 'args' => array( 'category' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'dateFrom' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'dateTo' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'pickUpLocation' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), ), ) ); // POST /pricing-summary register_rest_route( self::NAMESPACE, '/pricing-summary', array( 'methods' => 'POST', 'callback' => array( $this, 'get_pricing_summary' ), 'permission_callback' => array( $this, 'check_nonce' ), ) ); // POST /customer register_rest_route( self::NAMESPACE, '/customer', array( 'methods' => 'POST', 'callback' => array( $this, 'add_customer' ), 'permission_callback' => array( $this, 'check_nonce' ), ) ); // POST /booking register_rest_route( self::NAMESPACE, '/booking', array( 'methods' => 'POST', 'callback' => array( $this, 'make_booking' ), 'permission_callback' => array( $this, 'check_nonce' ), ) ); // POST /booking/confirm register_rest_route( self::NAMESPACE, '/booking/confirm', array( 'methods' => 'POST', 'callback' => array( $this, 'confirm_booking' ), 'permission_callback' => array( $this, 'check_nonce' ), 'args' => array( 'reservationId' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), ), ) ); // POST /booking/cancel register_rest_route( self::NAMESPACE, '/booking/cancel', array( 'methods' => 'POST', 'callback' => array( $this, 'cancel_booking' ), 'permission_callback' => array( $this, 'check_nonce' ), 'args' => array( 'reservationId' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), 'reason' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ), ), ) ); // GET /agreements register_rest_route( self::NAMESPACE, '/agreements', array( 'methods' => 'GET', 'callback' => array( $this, 'get_agreements' ), 'permission_callback' => '__return_true', ) ); } /** * Verify WP REST nonce for POST requests. */ public function check_nonce( WP_REST_Request $request ) { $nonce = $request->get_header( 'X-WP-Nonce' ); if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wp_rest' ) ) { return new WP_Error( 'rest_forbidden', 'Invalid nonce.', array( 'status' => 403 ) ); } return true; } /** * Get API instance or return error. */ private function api() { $api = Carei_Softra_API::get_instance(); if ( null === $api ) { return new WP_Error( 'carei_not_configured', 'Softra API not configured.', array( 'status' => 500 ) ); } return $api; } /** * Wrap API response. */ private function respond( $result ) { if ( is_wp_error( $result ) ) { return $result; } return new WP_REST_Response( $result, 200 ); } // ─── Callbacks ──────────────────────────────────────────────── public function get_segments_branches_map( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->get_segments_branches_map() ); } public function get_all_car_classes( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->get_all_car_classes() ); } public function get_branches( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->get_branches() ); } public function get_car_classes( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->get_car_classes( $request->get_param( 'dateFrom' ), $request->get_param( 'dateTo' ), $request->get_param( 'branchName' ) ) ); } public function get_car_models( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->get_car_models( $request->get_param( 'dateFrom' ), $request->get_param( 'dateTo' ), $request->get_param( 'branchName' ), $request->get_param( 'category' ) ) ); } public function get_pricelist( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->get_pricelist( $request->get_param( 'category' ), $request->get_param( 'dateFrom' ), $request->get_param( 'dateTo' ), $request->get_param( 'pickUpLocation' ) ) ); } public function get_pricing_summary( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } $params = $request->get_json_params(); return $this->respond( $api->get_pricing_summary( $params ) ); } public function add_customer( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } $data = $request->get_json_params(); return $this->respond( $api->add_customer( $data ) ); } public function make_booking( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } $data = $request->get_json_params(); $result = $api->make_booking( $data ); // Save reservation to WP on success (fire-and-forget) if ( ! is_wp_error( $result ) && isset( $result['success'] ) && $result['success'] ) { Carei_Admin_Panel::save_reservation( $data, $result ); } return $this->respond( $result ); } public function confirm_booking( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->confirm_booking( $request->get_param( 'reservationId' ) ) ); } public function cancel_booking( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->cancel_booking( $request->get_param( 'reservationId' ), $request->get_param( 'reason' ) ) ); } public function get_agreements( WP_REST_Request $request ) { $api = $this->api(); if ( is_wp_error( $api ) ) { return $api; } return $this->respond( $api->get_agreements() ); } }