2025-04-13 19:03:41 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Controllers;
|
|
|
|
|
|
|
|
use Carbon\Carbon;
|
|
|
|
use Carbon\Exceptions\InvalidFormatException;
|
|
|
|
use Exceptions\InvalidTaskDateException;
|
|
|
|
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);
|
|
|
|
|
2025-04-13 20:07:07 +01:00
|
|
|
$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);
|
|
|
|
|
2025-04-13 20:07:07 +01:00
|
|
|
$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 \DomainException('Invalid task date. Start date must not be after end date.');
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (InvalidFormatException | \DomainException $exception)
|
|
|
|
{
|
|
|
|
$this->builder->setError();
|
|
|
|
$this->builder->setErrorMessage($exception->getMessage());
|
|
|
|
$this->builder->setErrorCode(400);
|
|
|
|
|
2025-04-13 20:07:07 +01:00
|
|
|
$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).');
|
|
|
|
|
2025-04-13 20:07:07 +01:00
|
|
|
$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']);
|
|
|
|
|
|
|
|
if (!$this->repository->create($task))
|
|
|
|
{
|
|
|
|
$this->builder->setError()
|
|
|
|
->setErrorMessage('An unexpected error has occurred whilst trying to perform this operation.')
|
|
|
|
->setErrorCode(500);
|
|
|
|
|
2025-04-13 20:07:07 +01:00
|
|
|
$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;
|
|
|
|
}
|
|
|
|
|
2025-04-13 20:07:07 +01:00
|
|
|
$createdResponse = $response->withStatus(201)->withHeader('Content-Type', 'application/json');
|
2025-04-13 19:03:41 +01:00
|
|
|
$this->builder->setOptionalMessage('Task created.')
|
|
|
|
->setPayload($task->persist());
|
|
|
|
|
|
|
|
$createdResponse->getBody()->write($this->builder->build());
|
|
|
|
return $createdResponse;
|
|
|
|
}
|
|
|
|
}
|