namespace, $this->base, array( array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'create_item' ), 'permission_callback' => array( $this, 'create_team_member_permission', ), ), array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_items' ), 'permission_callback' => array( $this, 'get_team_member_permission', ), ), array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array( $this, 'delete_items' ), 'permission_callback' => array( $this, 'delete_team_member_permission', ), ), ) ); register_rest_route( $this->namespace, $this->base.'/profile', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_profile' ), 'permission_callback' => array( $this, 'get_team_member_profile_permission', ), ), ) ); register_rest_route( $this->namespace, '/' . $this->base . '/(?P[\d]+)', array( array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_item' ), 'permission_callback' => array( $this, 'update_team_member_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_team_member_permission', ), ), array( 'method' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_item' ), 'permission_callback' => array( $this, 'get_team_member_permission', ), ), ) ); register_rest_route( $this->namespace, '/' . $this->base . '/(?P[\d]+)/reinvites', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'reinvite' ), 'permission_callback' => array( $this, 'create_team_member_permission', ), ), ) ); } /** * Check if a given request has access to create items. * * @param $request * * @return mixed */ public function create_team_member_permission( $request ) { return current_user_can( 'manage_options' ); } /** * Prepare and validate team member data * * @param $request * * @return array|bool|WP_Error */ protected function prepare_team_member_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', 'enable_custom_holiday' => $input_data['enable_custom_holiday'] ?? false, 'enable_custom_schedule' => $input_data['enable_custom_schedule'] ?? false, 'enable_custom_availability' => $input_data['enable_custom_availability'] ?? false, ); } /** * Store new team member data * * @param $request * * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response */ public function create_item( $request ) { $prepared_data = $this->prepare_team_member_data( $request ); if ( is_wp_error( $prepared_data ) ) { return $this->error( $prepared_data->get_error_message(), 422, 'Validation', $prepared_data->errors ); } $all_team_members = ( new Team_Member_Model() )->all( array() ); if ( ! is_booktics_pro() && isset( $all_team_members['total'] ) && $all_team_members['total'] >= 3 ) { return $this->error( 'Team member limit reached for free plan.', 422, 'Validation' ); } $team_member = new Team_Member_Model(); $created = $team_member->save( $prepared_data ); $image_url = $request->get_param( 'image' ); if ( $image_url ) { $team_member->update( array( 'image' => esc_url_raw( $image_url ) ) ); } if ( ! $created ) { return $this->error( __( 'Team member create error', 'booktics' ), 500 ); } do_action( 'booktics_team_member_created', $team_member, $request ); ( new Team_Member_Event_Handler() )->on_team_member_create( $created ); return $this->response( $team_member->find( $created )->to_array(), __( 'Successfully created team member', 'booktics' ), 201 ); } /** * Check if a given request has access to get all team member * * @param $request * * @return bool */ public function get_team_member_permission( $request ) { return true; } /** * Get paginated list items for team member * * @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'] ) : ''; $status = ! empty( $request['status'] ) ? trim( $request['status'] ) : ''; $service_id = ! empty( $request['service_id'] ) ? trim( $request['service_id'] ) : ''; $search = ! empty( $request['search'] ) ? trim( $request['search'] ) : ''; $team_members = ( new Team_Member_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', $v, 'LIKE' ); } ) ->when( $service_id, function ( $q, $v ) { $q->where( 'services', $v, 'LIKE' ); } ) ->when( $status, function ( $q, $v ) { $q->where( 'status', $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( $team_members ); } /** * Checks if a given request has access to update a team member. * * @param $request * * @return bool */ public function update_team_member_permission( $request ) { return current_user_can( 'manage_options' ); } /** * Updates a single team member. * * @param $request * * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response * @throws Exception */ public function update_item( $request ) { if ( ! isset( $request['id'] ) ) { return $this->error( __( 'Invalid team member id', 'booktics' ), 400 ); } $team_member = ( new Team_Member_Model( $request['id'] ) ); if ( isset( $request['password'] ) ) { $current_password = sanitize_text_field( $request['current_password'] ?? '' ); $new_password = sanitize_text_field( $request['password'] ?? '' ); $confirm_password = sanitize_text_field( $request['confirm_password'] ?? '' ); $validate = booktics_validate( array( 'current_password' => $current_password, 'password' => $new_password, 'confirm_password' => $confirm_password, ), array( 'current_password' => array( 'required' ), 'password' => array( 'required' ), 'confirm_password' => array( 'required' ), ) ); if ( is_wp_error( $validate ) ) { return $validate; } $user = wp_get_current_user(); if ( ! wp_check_password( $current_password, $user->user_pass, $user->ID ) ) { return $this->error( __( 'Current password is incorrect.', 'booktics' ), 401 ); } wp_set_password( $new_password, $user->ID ); return $this->response( $team_member->find( $request['id'] )->to_array(), __( 'Successfully updated team member', 'booktics' ) ); } $prepared_data = $this->prepare_team_member_update( $request ); if ( is_wp_error( $prepared_data ) ) { return $this->error( $prepared_data->get_error_message(), 422, 'Validation', $prepared_data->errors ); } $updated = $team_member->update( $prepared_data ); // First handle adding team member to new services foreach ( $prepared_data['services'] as $service ) { $service_model = Service_Model::find( $service ); $service_team_member = $service_model->team_member == '' ? array() : $service_model->team_member; if ( ! in_array( (int) $team_member->id, $service_team_member ) ) { $service_team_member[] = (int) $request['id']; if ( $service_model ) { $service_model->update( array( 'team_member' => $service_team_member ) ); } } } // Then remove team member from services they're no longer assigned to $services = Service_Model::query() ->where( 'team_member', $request['id'], 'LIKE' ) ->where_not_ids( $prepared_data['services'] ) ->get(); foreach ( $services as $service ) { if ( $service->team_member ) { $service_team_members = array_diff( $service->team_member, array( (int) $request['id'] ) ); Service_Model::find( $service->id )->update( array( 'team_member' => $service_team_members ) ); } } $image_url = $request->get_param( 'image' ); if ( $image_url ) { $team_member->update( array( 'image' => esc_url_raw( $image_url ) ) ); } if ( ! $updated ) { return $this->error( __( 'Team member update error', 'booktics' ), 500 ); } if ( isset( $request['schedule'] ) || isset( $request['custom'] ) || isset( $request['holiday'] ) ) { $input_data = json_decode( $request->get_body(), true ); $team_member_schedule = Schedule_Manager::make( $input_data ); $team_member_schedule->with_team_member_id( $request['id'] ); $team_member_schedule->save(); } do_action( 'booktics_team_member_updated', $team_member, $request ); $team_member = $team_member->find( $request['id'] )->to_array(); $schedule_record = ( new Schedule_Record() )->get_schedules( $request['id'] ); $team_member['schedule'] = empty( $schedule_record['schedule'] ) ? (object) array() : $schedule_record['schedule']; $team_member['custom'] = $schedule_record['custom']; $team_member['holiday'] = $schedule_record['holiday']; return $this->response( $team_member, __( 'Successfully updated team member', 'booktics' ) ); } /** * Prepare data for team member update * * @param $request * * @return array|bool|WP_Error */ public function prepare_team_member_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(); foreach ( $input_data as $key => $value ) { $validated_data[ $key ] = $value; if ( ! isset( $validation_rules[ $key ] ) ) { continue; } $update_validation_rules[ $key ] = $validation_rules[ $key ]; if ( $key == 'email' ) { $update_validation_rules[ $key ] = $validation_rules[ $key ]; $validated_data['user_email'] = sanitize_email( $value ); } } $validate = booktics_validate( $input_data, $update_validation_rules ); if ( is_wp_error( $validate ) ) { return $validate; } $validated_data['services'] = ! empty( $input_data['services'] ) ? $input_data['services'] : array(); //$validated_data['status'] = 'active'; return $validated_data; } /** * Checks if a given request has access to delete a team member. * * @param $request * * @return bool */ public function delete_team_member_permission( $request ) { return current_user_can( 'manage_options' ); } /** * Delete a team member * * @param $request * * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response */ public function delete_item( $request ) { $id = intval( $request['id'] ); $team_member = new Team_Member_Model( $id ); $previous = $team_member->find( $id ); // Remove team member from assigned services $services = Service_Model::query()->where( 'team_member', $id, 'LIKE' )->get(); foreach ( $services as $service ) { if ( $service->team_member ) { $service_team_members = array_diff( $service->team_member, array( $id ) ); Service_Model::find( $service->id )->update( array( 'team_member' => $service_team_members ) ); } } $deleted = $team_member->delete(); if ( ! $deleted ) { return $this->error( __( 'Team member delete error', 'booktics' ), 500 ); } do_action( 'booktics_team_members_deleted', $request ); return $this->response( $previous, __( 'Successfully deleted team member', 'booktics' ) ); } /** * Delete multiple team member * * @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( __( 'Team member ids cannot be empty', 'booktics' ), 500 ); } $count = 0; foreach ( $ids as $id ) { $team_member = new Team_Member_Model( $id ); if ( $team_member->delete() ) { ++$count; } } if ( $count == 0 ) { return $this->error( __( 'Team member delete error', 'booktics' ), 500 ); } do_action( 'booktics_team_members_deleted', $request ); return $this->response( array(), __( 'Successfully deleted team member', 'booktics' ) ); } /** * Get single team member * * @param $request * * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response */ public function get_item( $request ) { $id = intval( $request['id'] ); $team_member = new Team_Member_Model( $id ); $team_member = $team_member->find( $id ); if ( ! $team_member ) { return $this->error( __( 'Team member not found', 'booktics' ), 404 ); } $team_member = $team_member->to_array(); $schedule_record = ( new Schedule_Record() )->get_schedules( $request['id'] ); $team_member['schedule'] = ! empty( $schedule_record['schedule'] ) ? $schedule_record['schedule'] : $team_member['schedule']; $team_member['custom'] = ! empty( $schedule_record['custom'] ) ? $schedule_record['custom'] : $team_member['custom']; $team_member['holiday'] = ! empty( $schedule_record['holiday'] ) ? $schedule_record['holiday'] : $team_member['holiday']; // Add filter to allow modifying team member data $team_member = apply_filters( 'booktics_team_member_data', $team_member, $id ); return $this->response( $team_member, __( 'Team member successfully fetched', 'booktics' ) ); } /** * Check if a given request has access to create items. * * @param $request * * @return mixed */ public function create_team_member_schedule_permission( $request ) { return current_user_can( 'manage_options' ); } /** * Team member reinvite * * @param $request * * @return array|WP_HTTP_Response */ public function reinvite( $request ) { $id = intval( $request['id'] ); $invite = ( new Team_Member_Event_Handler() )->on_team_member_create( $id ); if ( ! $invite ) { return $this->error( __( 'Team member reinvite error', 'booktics' ) ); } return $this->response( array(), __( 'Team member reinvited successfully', 'booktics' ) ); } /** * Check if a given request has access to get team member profile. * * @return bool */ public function get_team_member_profile_permission() { return current_user_can( 'manage_options' ); } /** * Get team member profile * * @param $request * * @return array|WP_Error|WP_HTTP_Response|WP_REST_Response */ public function get_profile( $request ) { $id = get_current_user_id(); $team_member = new Team_Member_Model( $id ); $team_member = $team_member->find( $id ); if ( ! $team_member ) { return $this->error( __( 'Team member not found', 'booktics' ), 404 ); } $team_member = $team_member->to_array(); $schedule_record = ( new Schedule_Record() )->get_schedules( $id ); $team_member['schedule'] = ! empty( $schedule_record['schedule'] ) ? $schedule_record['schedule'] : $team_member['schedule']; $team_member['custom'] = ! empty( $schedule_record['custom'] ) ? $schedule_record['custom'] : $team_member['custom']; $team_member['holiday'] = ! empty( $schedule_record['holiday'] ) ? $schedule_record['holiday'] : $team_member['holiday']; // Add filter to allow modifying team member data $team_member = apply_filters( 'booktics_team_member_data', $team_member, $id ); return $this->response( $team_member, __( 'Team member successfully fetched', 'booktics' ) ); } }