TaskController.php

Code Hygiene Score: 76

Keine Issues gefunden.

Dependencies 20

Klassen 1

Funktionen 12

Versionen 33

Code

<?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) {
            error_log(sprintf('[API.Task.updateStatus] %s: %s', get_class($e), $e->getMessage()));
            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) {
            error_log(sprintf('[API.Task.storeResult] %s: %s', get_class($e), $e->getMessage()));
            $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) {
            error_log(sprintf('[API.Task.getResults] %s: %s', get_class($e), $e->getMessage()));
            $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) {
            error_log(sprintf('[API.Task.executeAI] %s: %s', get_class($e), $e->getMessage()));
            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) {
            error_log(sprintf('[API.Task.statistics] %s: %s', get_class($e), $e->getMessage()));
            $this->jsonError($e->getMessage());
        }
    }
}
← Übersicht Graph