getInputs(); $service_id = $inputs['service_id'] ?? '?'; $changes = []; if ( ! empty( $inputs['title'] ) ) { $changes[] = "name to \"{$inputs['title']}\""; } if ( ! empty( $inputs['status'] ) ) { $changes[] = "status to \"{$inputs['status']}\""; } if ( isset( $inputs['price'] ) && '' !== $inputs['price'] ) { $changes[] = 'price to ' . $inputs['price']; } if ( ! empty( $inputs['duration_minutes'] ) ) { $changes[] = "duration to {$inputs['duration_minutes']} min"; } if ( isset( $inputs['team_member_ids'] ) ) { $changes[] = 'assigned team members'; } $summary = "Update service #{$service_id}"; if ( ! empty( $changes ) ) { $summary .= ': ' . implode( ', ', $changes ); } return $summary; } /** * Human-readable inputs shown in the approval card table. * * @return array */ public function get_approval_inputs(): array { return $this->getInputs(); } /** * Execute the tool after human approval. * * @param int $service_id Service ID to update. * @param string|null $title New title. * @param string|null $description New description. * @param int|null $duration_minutes New duration in minutes. * @param float|null $price New charge amount. * @param string|null $status active|deactive. * @param int|null $before_buffer_time New buffer before, minutes. * @param int|null $after_buffer_time New buffer after, minutes. * @param array|null $team_member_ids Replacement team-member IDs. * @param array|null $category_ids Replacement category term IDs. * @return array */ public function __invoke( int $service_id, ?string $title = null, ?string $description = null, ?int $duration_minutes = null, ?float $price = null, ?string $status = null, ?int $before_buffer_time = null, ?int $after_buffer_time = null, ?array $team_member_ids = null, ?array $category_ids = null ): array { $check = $this->guard_admin(); if ( $check ) { return $check; } if ( $service_id <= 0 ) { return [ 'error' => 'service_id must be a positive integer.' ]; } if ( null !== $status && ! in_array( $status, self::ALLOWED_STATUSES, true ) ) { return [ 'error' => "Invalid status '{$status}'. Accepted values: " . implode( ', ', self::ALLOWED_STATUSES ) . '.' ]; } try { // find() yields a hollow instance for a valid post ID of another type, // so confirm the loaded record's own ID matches before merging. $service = \Booktics\Models\Service_Model::find( $service_id ); if ( ! $service || (int) $service->id !== $service_id ) { return [ 'error' => "Service #{$service_id} was not found." ]; } $current = $service->to_array(); // Booktics' update endpoint resets omitted fields to defaults, so we // rebuild the full record from current values and merge changes on top. $body = [ 'title' => $current['title'] ?? '', 'description' => $current['description'] ?? '', 'content' => $current['content'] ?? '', 'link' => $current['link'] ?? '', 'image' => $current['image'] ?? '', 'image_id' => $current['image_id'] ?? '', 'status' => $current['status'] ?? 'deactive', 'interval_time' => $current['interval_time'] ?? 0, 'before_buffer_time' => $current['before_buffer_time'] ?? 0, 'after_buffer_time' => $current['after_buffer_time'] ?? 0, 'show_end_time' => $current['show_end_time'] ?? false, 'team_member' => $current['team_member'] ?? [], 'categories' => $current['categories'] ?? [], 'additional_durations' => $current['additional_durations'] ?? [], 'enable_custom_holiday' => $current['enable_custom_holiday'] ?? false, 'enable_custom_schedule' => $current['enable_custom_schedule'] ?? false, 'enable_additional_service_duration' => $current['enable_additional_service_duration'] ?? false, ]; $changed = []; if ( null !== $title ) { if ( '' === trim( $title ) ) { return [ 'error' => 'title cannot be empty.' ]; } $body['title'] = sanitize_text_field( $title ); $changed[] = 'title'; } if ( null !== $description ) { $body['description'] = sanitize_text_field( $description ); $changed[] = 'description'; } if ( null !== $status ) { $body['status'] = $status; $changed[] = 'status'; } if ( null !== $before_buffer_time ) { $body['before_buffer_time'] = max( 0, $before_buffer_time ); $changed[] = 'before_buffer_time'; } if ( null !== $after_buffer_time ) { $body['after_buffer_time'] = max( 0, $after_buffer_time ); $changed[] = 'after_buffer_time'; } if ( null !== $team_member_ids ) { $body['team_member'] = array_values( array_unique( array_map( 'intval', $team_member_ids ) ) ); $changed[] = 'team_member'; } if ( null !== $category_ids ) { $body['categories'] = array_values( array_unique( array_map( 'intval', $category_ids ) ) ); $changed[] = 'categories'; } if ( null !== $duration_minutes || null !== $price ) { $durations = ! empty( $body['additional_durations'] ) ? $body['additional_durations'] : [ $this->default_duration_row() ]; if ( null !== $duration_minutes ) { $durations[0]['duration_time'] = max( 1, $duration_minutes ); $durations[0]['duration_unit'] = $durations[0]['duration_unit'] ?? 'min'; $changed[] = 'duration'; } if ( null !== $price ) { $durations[0]['charge_amount'] = max( 0.0, $price ); $changed[] = 'price'; } $body['additional_durations'] = $durations; } if ( empty( $changed ) ) { return [ 'error' => 'No fields provided to update.' ]; } $request = $this->build_json_request( 'PUT', '/booktics/v1/services/' . $service_id, $body, $service_id ); if ( is_array( $request ) ) { return $request; } $controller = new \Booktics\Service\Controllers\Service_Controller(); $data = $this->extract_response( $controller->update_item( $request ), 'Failed to update service.' ); if ( isset( $data['error'] ) ) { return $data; } return [ 'success' => true, 'service_id' => $service_id, 'updated_fields' => array_values( array_unique( $changed ) ), 'message' => "Service #{$service_id} updated successfully.", ]; } catch ( \Throwable $e ) { Log::error( 'Booktics_Update_Service_Tool error', [ 'error' => $e->getMessage() ] ); return [ 'error' => 'Failed to update service: ' . $e->getMessage() ]; } } }