You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
2.7 KiB
85 lines
2.7 KiB
<?php |
|
|
|
namespace App\Http\Controllers\Api\V1; |
|
|
|
use App\Http\Controllers\Api\Concerns\RespondsWithJson; |
|
use App\Http\Controllers\Controller; |
|
use App\Services\AuditLogService; |
|
use App\Services\ProjectSearchService; |
|
use App\Support\ApiActor; |
|
use Illuminate\Http\JsonResponse; |
|
use Illuminate\Http\Request; |
|
use InvalidArgumentException; |
|
use RuntimeException; |
|
use Throwable; |
|
|
|
class ProjectSearchController extends Controller |
|
{ |
|
use RespondsWithJson; |
|
|
|
public function __construct( |
|
private readonly ProjectSearchService $projectSearch, |
|
private readonly AuditLogService $auditLog |
|
) { |
|
} |
|
|
|
public function sources(): JsonResponse |
|
{ |
|
return $this->ok($this->projectSearch->listSources()); |
|
} |
|
|
|
public function indexStatus(): JsonResponse |
|
{ |
|
if (! $this->projectSearch->isAvailable()) { |
|
return $this->fail('Indeks project_search belum tersedia.', 'service_unavailable', 503); |
|
} |
|
|
|
return $this->ok($this->projectSearch->indexStatus()); |
|
} |
|
|
|
public function ask(Request $request): JsonResponse |
|
{ |
|
$validated = $request->validate([ |
|
'query' => ['required', 'string', 'min:3', 'max:500'], |
|
'sources' => ['sometimes', 'array'], |
|
'sources.*' => ['string', 'max:64'], |
|
'limit' => ['sometimes', 'integer', 'min:1', 'max:50'], |
|
]); |
|
|
|
try { |
|
$result = $this->projectSearch->ask( |
|
$validated['query'], |
|
$validated['sources'] ?? [], |
|
(int) ($validated['limit'] ?? config('project_search.default_limit', 20)) |
|
); |
|
|
|
$actor = $request->attributes->get('api_actor'); |
|
$username = $actor instanceof ApiActor ? $actor->identifier : null; |
|
$client = $actor instanceof ApiActor ? $actor->type : null; |
|
|
|
$this->auditLog->log( |
|
'project_search.ask', |
|
'api', |
|
$username, |
|
$client, |
|
'project_search', |
|
$request, |
|
200, |
|
[ |
|
'query' => $validated['query'], |
|
'result_count' => $result['meta']['result_count'] ?? 0, |
|
'sources' => $result['meta']['sources'] ?? [], |
|
] |
|
); |
|
|
|
return $this->ok([ |
|
'answer' => $result['answer'], |
|
'results' => $result['results'], |
|
], $result['meta']); |
|
} catch (InvalidArgumentException|RuntimeException $e) { |
|
return $this->fail($e->getMessage(), 'validation_error', 422); |
|
} catch (Throwable) { |
|
return $this->fail('Gagal memproses pencarian proyek.', 'server_error', 500); |
|
} |
|
} |
|
}
|
|
|