Backup #2052
| ID | 2052 |
| Dateipfad | /var/www/dev.campus.systemische-tools.de/src/Controller/Api/TaskController.php |
| Version | 29 |
| Typ |
modified |
| Größe | 12.6 KB |
| Hash | 44a01f7df5c6d09a9c9e6659b42c339b5be569336a3c6b53ce070bdc9d9e1a50 |
| Datum | 2025-12-28 23:27:55 |
| Geändert von | claude-code-hook |
| Grund | Claude Code Pre-Hook Backup vor Edit-Operation |
| Datei existiert |
Ja
|
Dateiinhalt
<?php
declare(strict_types=1);
namespace Controller\Api;
// @responsibility: REST-API für Task-Management (CRUD, Assignments, AI-Execution)
use Domain\Repository\TaskRepositoryInterface;
use Domain\Repository\TaskResultRepositoryInterface;
use Framework\Controller;
use UseCases\Task\AssignTaskUseCase;
use UseCases\Task\CreateTaskUseCase;
use UseCases\Task\DeleteTaskUseCase;
use UseCases\Task\ExecuteAITaskUseCase;
use UseCases\Task\GetTasksUseCase;
use UseCases\Task\SaveTaskResultUseCase;
use UseCases\Task\UpdateTaskStatusUseCase;
class TaskController extends Controller
{
private GetTasksUseCase $getTasksUseCase;
private CreateTaskUseCase $createTaskUseCase;
private DeleteTaskUseCase $deleteTaskUseCase;
private AssignTaskUseCase $assignTaskUseCase;
private UpdateTaskStatusUseCase $updateStatusUseCase;
private SaveTaskResultUseCase $saveResultUseCase;
private ExecuteAITaskUseCase $executeAIUseCase;
private TaskRepositoryInterface $taskRepository;
private TaskResultRepositoryInterface $resultRepository;
public function __construct(
GetTasksUseCase $getTasksUseCase,
CreateTaskUseCase $createTaskUseCase,
DeleteTaskUseCase $deleteTaskUseCase,
AssignTaskUseCase $assignTaskUseCase,
UpdateTaskStatusUseCase $updateStatusUseCase,
SaveTaskResultUseCase $saveResultUseCase,
ExecuteAITaskUseCase $executeAIUseCase,
TaskRepositoryInterface $taskRepository,
TaskResultRepositoryInterface $resultRepository
) {
$this->getTasksUseCase = $getTasksUseCase;
$this->createTaskUseCase = $createTaskUseCase;
$this->deleteTaskUseCase = $deleteTaskUseCase;
$this->assignTaskUseCase = $assignTaskUseCase;
$this->updateStatusUseCase = $updateStatusUseCase;
$this->saveResultUseCase = $saveResultUseCase;
$this->executeAIUseCase = $executeAIUseCase;
$this->taskRepository = $taskRepository;
$this->resultRepository = $resultRepository;
}
public function index(): void
{
try {
$filters = [];
$status = $this->getString('status');
if ($status !== '') {
$filters['status'] = $status;
}
$type = $this->getString('type');
if ($type !== '') {
$filters['type'] = $type;
}
$search = $this->getString('search');
if ($search !== '') {
$filters['search'] = $search;
}
$limit = $this->getInt('limit', 50);
$offset = $this->getInt('offset');
$tasks = $this->getTasksUseCase->execute($filters, $limit, $offset);
$total = $this->getTasksUseCase->count($filters);
$this->json([
'success' => true,
'data' => array_map(fn ($t) => $t->toArray(), $tasks),
'meta' => [
'total' => $total,
'limit' => $limit,
'offset' => $offset,
],
]);
} catch (\Exception $e) {
error_log(sprintf('[API.Task.index] %s: %s', get_class($e), $e->getMessage()));
$this->jsonError($e->getMessage());
}
}
public function show(string $id): void
{
try {
$details = $this->getTasksUseCase->getTaskWithDetails((int) $id);
if ($details === null) {
$this->json(['success' => false, 'error' => 'Task not found'], 404);
return;
}
$this->json([
'success' => true,
'data' => $details,
]);
} catch (\Exception $e) {
error_log(sprintf('[API.Task.show] %s: %s', get_class($e), $e->getMessage()));
$this->jsonError($e->getMessage());
}
}
public function store(): void
{
$this->requireCsrf();
try {
$input = $this->getJsonInput();
if (empty($input)) {
$input = $_POST;
}
$task = $this->createTaskUseCase->execute($input);
// HTMX: Redirect to new task
if ($this->isHtmxRequest()) {
$this->htmxRedirect('/tasks/' . $task->getId());
return;
}
$this->json([
'success' => true,
'data' => $task->toArray(),
], 201);
} catch (\InvalidArgumentException $e) {
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->json(['success' => false, 'error' => $e->getMessage()], 400);
} catch (\Exception $e) {
error_log(sprintf('[API.Task.store] %s: %s', get_class($e), $e->getMessage()));
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->jsonError($e->getMessage());
}
}
public function update(string $id): void
{
$this->requireCsrf();
try {
$input = $this->getJsonInput();
if (empty($input)) {
$input = $_POST;
}
$task = $this->getTasksUseCase->findById((int) $id);
if ($task === null) {
if ($this->isHtmxRequest()) {
$this->htmxError('Task nicht gefunden');
return;
}
$this->json(['success' => false, 'error' => 'Task not found'], 404);
return;
}
if (isset($input['title']) || isset($input['description'])) {
$task->updateDetails(
$input['title'] ?? $task->getTitle(),
$input['description'] ?? $task->getDescription()
);
}
if (isset($input['type'])) {
$task->changeType(\Domain\ValueObject\TaskType::from($input['type']));
}
if (isset($input['due_date'])) {
$task->setDueDate(new \DateTimeImmutable($input['due_date']));
}
$this->taskRepository->update($task);
// HTMX: Redirect to task page
if ($this->isHtmxRequest()) {
$this->htmxRedirect('/tasks/' . $id);
return;
}
$this->json([
'success' => true,
'data' => $task->toArray(),
]);
} catch (\InvalidArgumentException $e) {
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->json(['success' => false, 'error' => $e->getMessage()], 400);
} catch (\Exception $e) {
error_log(sprintf('[API.Task.update] %s: %s', get_class($e), $e->getMessage()));
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->jsonError($e->getMessage());
}
}
public function destroy(string $id): void
{
try {
$this->deleteTaskUseCase->execute((int) $id);
$this->json([
'success' => true,
'message' => 'Task deleted',
]);
} catch (\InvalidArgumentException $e) {
$this->json(['success' => false, 'error' => $e->getMessage()], 404);
} catch (\Exception $e) {
error_log(sprintf('[API.Task.destroy] %s: %s', get_class($e), $e->getMessage()));
$this->jsonError($e->getMessage());
}
}
public function assign(string $id): void
{
try {
$input = $this->getJsonInput();
$assignment = $this->assignTaskUseCase->execute((int) $id, $input);
$this->json([
'success' => true,
'data' => $assignment->toArray(),
], 201);
} catch (\InvalidArgumentException $e) {
$this->json(['success' => false, 'error' => $e->getMessage()], 400);
} catch (\Exception $e) {
error_log(sprintf('[API.Task.assign] %s: %s', get_class($e), $e->getMessage()));
$this->jsonError($e->getMessage());
}
}
public function updateStatus(string $id): void
{
$this->requireCsrf();
try {
// Accept both JSON and form data
$input = $this->getJsonInput();
$status = $input['status'] ?? $_POST['status'] ?? null;
if ($status === null || $status === '') {
if ($this->isHtmxRequest()) {
$this->htmxError('Status ist erforderlich');
return;
}
$this->json(['success' => false, 'error' => 'Status is required'], 400);
return;
}
$updatedBy = $input['updated_by'] ?? 'api';
$updatedByType = $input['updated_by_type'] ?? 'human';
$task = $this->updateStatusUseCase->execute((int) $id, $status, $updatedBy, $updatedByType);
// HTMX: Return updated status select
if ($this->isHtmxRequest()) {
$this->partial('tasks.partials.status-select', [
'task' => $task->toArray(),
]);
return;
}
$this->json([
'success' => true,
'data' => $task->toArray(),
]);
} catch (\InvalidArgumentException $e) {
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->json(['success' => false, 'error' => $e->getMessage()], 400);
} catch (\Exception $e) {
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->jsonError($e->getMessage());
}
}
public function storeResult(string $id): void
{
try {
$input = $this->getJsonInput();
$result = $this->saveResultUseCase->execute((int) $id, $input);
$this->json([
'success' => true,
'data' => $result->toArray(),
], 201);
} catch (\InvalidArgumentException $e) {
$this->json(['success' => false, 'error' => $e->getMessage()], 400);
} catch (\Exception $e) {
$this->jsonError($e->getMessage());
}
}
public function getResults(string $id): void
{
try {
$results = $this->resultRepository->findByTaskId((int) $id);
$this->json([
'success' => true,
'data' => array_map(fn ($r) => $r->toArray(), $results),
]);
} catch (\Exception $e) {
$this->jsonError($e->getMessage());
}
}
public function executeAI(string $id): void
{
$this->requireCsrf();
try {
$input = $this->getJsonInput();
$result = $this->executeAIUseCase->execute((int) $id, $input);
// HTMX: Redirect to task page on success
if ($this->isHtmxRequest()) {
$this->htmxRedirect('/tasks/' . $id);
return;
}
$this->json([
'success' => true,
'data' => $result->toArray(),
]);
} catch (\InvalidArgumentException $e) {
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->json(['success' => false, 'error' => $e->getMessage()], 400);
} catch (\RuntimeException $e) {
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->json(['success' => false, 'error' => $e->getMessage()], 503);
} catch (\Exception $e) {
if ($this->isHtmxRequest()) {
$this->htmxError($e->getMessage());
return;
}
$this->jsonError($e->getMessage());
}
}
public function statistics(): void
{
try {
$taskStats = $this->getTasksUseCase->getStatistics();
$tokenStats = $this->resultRepository->getTokenStatistics();
$modelUsage = $this->resultRepository->getModelUsage();
$this->json([
'success' => true,
'data' => [
'tasks' => $taskStats,
'tokens' => $tokenStats,
'models' => $modelUsage,
],
]);
} catch (\Exception $e) {
$this->jsonError($e->getMessage());
}
}
}
Vollständig herunterladen
Aktionen
Andere Versionen dieser Datei
| ID |
Version |
Typ |
Größe |
Datum |
| 2056 |
33 |
modified |
13.0 KB |
2025-12-28 23:28 |
| 2055 |
32 |
modified |
12.9 KB |
2025-12-28 23:28 |
| 2054 |
31 |
modified |
12.8 KB |
2025-12-28 23:28 |
| 2053 |
30 |
modified |
12.7 KB |
2025-12-28 23:28 |
| 2052 |
29 |
modified |
12.6 KB |
2025-12-28 23:27 |
| 2051 |
28 |
modified |
12.5 KB |
2025-12-28 23:27 |
| 2050 |
27 |
modified |
12.4 KB |
2025-12-28 23:27 |
| 2049 |
26 |
modified |
12.4 KB |
2025-12-28 23:27 |
| 2048 |
25 |
modified |
12.3 KB |
2025-12-28 23:27 |
| 2047 |
24 |
modified |
12.2 KB |
2025-12-28 23:27 |
| 2046 |
23 |
modified |
12.1 KB |
2025-12-28 23:27 |
| 2011 |
22 |
modified |
12.1 KB |
2025-12-28 14:20 |
| 1710 |
21 |
modified |
11.4 KB |
2025-12-27 12:25 |
| 1709 |
20 |
modified |
10.8 KB |
2025-12-27 12:25 |
| 1704 |
19 |
modified |
10.3 KB |
2025-12-27 12:22 |
| 1693 |
18 |
modified |
9.5 KB |
2025-12-27 12:12 |
| 1456 |
17 |
modified |
9.4 KB |
2025-12-25 17:01 |
| 1272 |
16 |
modified |
9.4 KB |
2025-12-25 12:52 |
| 703 |
15 |
modified |
9.3 KB |
2025-12-23 07:53 |
| 656 |
14 |
modified |
9.4 KB |
2025-12-23 04:48 |
| 655 |
13 |
modified |
9.4 KB |
2025-12-23 04:48 |
| 654 |
12 |
modified |
9.5 KB |
2025-12-23 04:48 |
| 653 |
11 |
modified |
9.5 KB |
2025-12-23 04:48 |
| 652 |
10 |
modified |
9.5 KB |
2025-12-23 04:48 |
| 651 |
9 |
modified |
9.6 KB |
2025-12-23 04:48 |
| 650 |
8 |
modified |
9.6 KB |
2025-12-23 04:48 |
| 649 |
7 |
modified |
9.7 KB |
2025-12-23 04:48 |
| 648 |
6 |
modified |
9.7 KB |
2025-12-23 04:48 |
| 647 |
5 |
modified |
9.7 KB |
2025-12-23 04:48 |
| 646 |
4 |
modified |
8.3 KB |
2025-12-23 04:48 |
| 309 |
3 |
modified |
8.3 KB |
2025-12-22 08:05 |
| 115 |
2 |
modified |
8.2 KB |
2025-12-20 19:20 |
| 114 |
1 |
modified |
8.2 KB |
2025-12-20 19:20 |
← Zurück zur Übersicht