TaskController.php
- Pfad:
src/Controller/Api/TaskController.php - Namespace: Controller\Api
- Zeilen: 414 | Größe: 13,418 Bytes
- Geändert: 2025-12-28 23:28:29 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 76
- Dependencies: 50 (25%)
- LOC: 43 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 20
- extends Framework\Controller
- constructor UseCases\Task\GetTasksUseCase
- constructor UseCases\Task\CreateTaskUseCase
- constructor UseCases\Task\DeleteTaskUseCase
- constructor UseCases\Task\AssignTaskUseCase
- constructor UseCases\Task\UpdateTaskStatusUseCase
- constructor UseCases\Task\SaveTaskResultUseCase
- constructor UseCases\Task\ExecuteAITaskUseCase
- constructor Domain\Repository\TaskRepositoryInterface
- constructor Domain\Repository\TaskResultRepositoryInterface
- 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
Klassen 1
-
TaskControllerclass Zeile 20
Funktionen 12
-
__construct()public Zeile 32 -
index()public Zeile 54 -
show()public Zeile 92 -
store()public Zeile 113 -
update()public Zeile 154 -
destroy()public Zeile 221 -
assign()public Zeile 238 -
updateStatus()public Zeile 257 -
storeResult()public Zeile 313 -
getResults()public Zeile 332 -
executeAI()public Zeile 347 -
statistics()public Zeile 392
Versionen 33
-
v33
2025-12-28 23:28 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v32
2025-12-28 23:28 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v31
2025-12-28 23:28 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v30
2025-12-28 23:28 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v29
2025-12-28 23:27 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v28
2025-12-28 23:27 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v27
2025-12-28 23:27 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v26
2025-12-28 23:27 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v25
2025-12-28 23:27 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v24
2025-12-28 23:27 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v23
2025-12-28 23:27 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v22
2025-12-28 14:20 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v21
2025-12-27 12:25 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v20
2025-12-27 12:25 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v19
2025-12-27 12:22 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v18
2025-12-27 12:12 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v17
2025-12-25 17:01 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v16
2025-12-25 12:52 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v15
2025-12-23 07:53 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v14
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v13
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v12
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v11
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v10
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v9
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v8
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v7
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v6
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v5
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v4
2025-12-23 04:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v3
2025-12-22 08:05 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v2
2025-12-20 19:20 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v1
2025-12-20 19:20 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation
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());
}
}
}