tasklist-backend/src/Controllers/TaskController.php

158 lines
5.8 KiB
PHP
Raw Normal View History

2025-04-13 19:03:41 +01:00
<?php
namespace Controllers;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use Exceptions\InvalidTaskDateException;
use Exceptions\TaskNotFoundException;
2025-04-13 19:03:41 +01:00
use Models\Task;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Repositories\TaskRepository;
use Utils\Enums\TaskStatus;
use Utils\StructuredResponseBuilder;
class TaskController
{
private $repository, $builder;
// instead of requesting the builder here, we could simply make it static
public function __construct(TaskRepository $taskRepository, StructuredResponseBuilder $builder)
{
$this->repository = $taskRepository;
$this->builder = $builder;
}
// response is immutable. psr-7 impl makes copies of stuff.
// TODO: There's a LOT of validation here. We need to build a validator, use a library, or refactor this method.
public function addTask(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
$params = $request->getParsedBody();
$requiredKeys = ['name', 'description', 'status', 'start', 'end'];
if (!array_key_exists('tasks', $params)) {
$this->builder->setError();
$this->builder->setErrorMessage('Malformed request payload. Please try again.');
$this->builder->setErrorCode(400);
$errorResponse = $response->withStatus(400, 'Invalid payload')->withHeader('Content-Type', 'application/json');
2025-04-13 19:03:41 +01:00
$errorResponse->getBody()->write($this->builder->build());
return $errorResponse;
}
$missingKeys = [];
foreach ($requiredKeys as $key)
{
if (!array_key_exists($key, $params['tasks'])) {
$missingKeys[] = $key;
}
}
if (!empty($missingKeys)) {
$this->builder->setError();
$this->builder->setErrorMessage("The following parameters are missing: " . implode(', ', $missingKeys));
$this->builder->setErrorCode(400);
$errorResponse = $response->withStatus('400', 'Missing arguments')->withHeader('Content-Type', 'application/json');
2025-04-13 19:03:41 +01:00
$errorResponse->getBody()->write($this->builder->build());
return $errorResponse;
}
try
{
$start = Carbon::parse($params['tasks']['start']);
$end = Carbon::parse($params['tasks']['end']);
if ($start->gt($end) || $end->lt($start)) {
throw new InvalidTaskDateException('Invalid task date. Start date must not be after end date.');
2025-04-13 19:03:41 +01:00
}
} catch (InvalidFormatException | \DomainException $exception)
{
$this->builder->setError();
$this->builder->setErrorMessage($exception->getMessage());
$this->builder->setErrorCode(400);
$errorResponse = $response->withStatus(400)->withHeader('Content-Type', 'application/json');
2025-04-13 19:03:41 +01:00
$errorResponse->getBody()->write($this->builder->build());
return $errorResponse;
}
if (is_null(TaskStatus::tryFrom($params['tasks']['status']))) {
$this->builder->setError();
$this->builder->setErrorCode(400);
$this->builder->setErrorMessage('Invalid task status code. Status must range from 1-4 (started, in progress, blocked, completed).');
$errorResponse = $response->withStatus(400)->withHeader('Content-Type', 'application/json');
2025-04-13 19:03:41 +01:00
$errorResponse->getBody()->write($this->builder->build());
return $errorResponse;
}
$task = new Task();
$task->setTitle($params['tasks']['name'])
->setStatus(TaskStatus::tryFrom((int) $params['tasks']['status']))
->setDescription($params['tasks']['description'])
->setStartDt($params['tasks']['start'])
->setEndDt($params['tasks']['end']);
2025-04-13 22:18:14 +01:00
$createdTask = $this->repository->create($task);
if ($createdTask == 0)
2025-04-13 19:03:41 +01:00
{
$this->builder->setError()
->setErrorMessage('An unexpected error has occurred whilst trying to perform this operation.')
->setErrorCode(500);
$errorResponse = $response->withStatus(500)->withHeader('Content-Type', 'application/json');
2025-04-13 19:03:41 +01:00
$errorResponse->getBody()->write($this->builder->build());
return $errorResponse;
}
$createdResponse = $response->withStatus(201)->withHeader('Content-Type', 'application/json');
2025-04-13 19:03:41 +01:00
$this->builder->setOptionalMessage('Task created.')
2025-04-13 22:18:14 +01:00
->setPayload($task->setId($createdTask)->persist());
2025-04-13 19:03:41 +01:00
$createdResponse->getBody()->write($this->builder->build());
return $createdResponse;
}
2025-04-13 22:18:14 +01:00
public function getTasks(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
$tasks = $this->repository->readAll();
$payload['tasks'] = $tasks;
$this->builder->setPayload($payload)->setOptionalMessage('Listing all tasks: ');
$response->getBody()->write($this->builder->build());
return $response;
}
public function getTask(ServerRequestInterface $request, ResponseInterface $response, string $id): ResponseInterface
{
try {
$payload['task'] = $this->repository->readById((int)$id)->persist();
$this->builder->setPayload($payload)->setOptionalMessage("Task retrieved.");
$response->getBody()->write($this->builder->build());
return $response;
} catch (TaskNotFoundException $e) {
$this->builder->setError()->setErrorMessage($e->getMessage())->setErrorCode(404);
$errorResponse = $response->withStatus(404, $e->getMessage());
$response->getBody()->write($this->builder->build());
return $errorResponse;
}
}
2025-04-13 19:03:41 +01:00
}