johnykvsky /
spisywarka
| 1 | <?php |
||||
| 2 | |||||
| 3 | namespace App\Controller\Api; |
||||
| 4 | |||||
| 5 | use App\Command\CreateLoanCommand; |
||||
| 6 | use App\Command\UpdateLoanCommand; |
||||
| 7 | use App\Command\DeleteLoanCommand; |
||||
| 8 | use App\Error\ApiError; |
||||
| 9 | use App\Repository\Exception\LoanNotFoundException; |
||||
| 10 | use App\Repository\LoanRepository; |
||||
| 11 | use App\Request\CreateLoanRequest; |
||||
| 12 | use App\Request\UpdateLoanRequest; |
||||
| 13 | use App\Traits\JsonErrorResponse; |
||||
| 14 | use Psr\Log\LoggerInterface; |
||||
| 15 | use Ramsey\Uuid\Uuid; |
||||
| 16 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; |
||||
| 17 | use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
||||
| 18 | use Symfony\Component\HttpFoundation\JsonResponse; |
||||
| 19 | use Symfony\Component\HttpFoundation\Request; |
||||
| 20 | use Symfony\Component\HttpFoundation\Response; |
||||
| 21 | use Symfony\Component\Messenger\MessageBusInterface; |
||||
| 22 | use Symfony\Component\Routing\Annotation\Route; |
||||
| 23 | use Symfony\Component\Validator\ConstraintViolationListInterface; |
||||
| 24 | use Swagger\Annotations as SWG; |
||||
| 25 | use App\CommandHandler\Exception\LoanNotDeletedException; |
||||
| 26 | use Nelmio\ApiDocBundle\Annotation\Model; |
||||
| 27 | |||||
| 28 | class LoanController extends AbstractController |
||||
| 29 | { |
||||
| 30 | use JsonErrorResponse; |
||||
| 31 | |||||
| 32 | /** |
||||
| 33 | * @var MessageBusInterface |
||||
| 34 | */ |
||||
| 35 | private $commandBus; |
||||
| 36 | /** |
||||
| 37 | * @var LoggerInterface |
||||
| 38 | */ |
||||
| 39 | private $logger; |
||||
| 40 | /** |
||||
| 41 | * @var LoanRepository |
||||
| 42 | */ |
||||
| 43 | private $repository; |
||||
| 44 | |||||
| 45 | /** |
||||
| 46 | * @param MessageBusInterface $commandBus |
||||
| 47 | * @param LoggerInterface $logger |
||||
| 48 | * @param LoanRepository $repository |
||||
| 49 | */ |
||||
| 50 | public function __construct( |
||||
| 51 | MessageBusInterface $commandBus, |
||||
| 52 | LoggerInterface $logger, |
||||
| 53 | LoanRepository $repository |
||||
| 54 | ) |
||||
| 55 | { |
||||
| 56 | $this->commandBus = $commandBus; |
||||
| 57 | $this->logger = $logger; |
||||
| 58 | $this->repository = $repository; |
||||
| 59 | } |
||||
| 60 | |||||
| 61 | /** |
||||
| 62 | * @Route("/api/loan", name="create_loan", methods={"POST"}) |
||||
| 63 | * |
||||
| 64 | * @ParamConverter("request", converter="fos_rest.request_body") |
||||
| 65 | * |
||||
| 66 | * @SWG\Tag(name="Loan") |
||||
| 67 | * @SWG\Post( |
||||
| 68 | * @SWG\Parameter( |
||||
| 69 | * name="body", |
||||
| 70 | * in="body", |
||||
| 71 | * required=true, |
||||
| 72 | * format="application/json", |
||||
| 73 | * @SWG\Schema( |
||||
| 74 | * required={"name"}, |
||||
| 75 | * @SWG\Property(property="itemId", type="string", format="UUID"), |
||||
| 76 | * @SWG\Property(property="loaner", type="string", maxLength=255), |
||||
| 77 | * @SWG\Property(property="loanDate", type="string", format="Y-m-d H:i"), |
||||
| 78 | * @SWG\Property(property="returnDate", type="string", format="Y-m-d H:i"), |
||||
| 79 | * ) |
||||
| 80 | * ) |
||||
| 81 | * ) |
||||
| 82 | * @SWG\Response( |
||||
| 83 | * response=201, |
||||
| 84 | * description="Returns ID of created Loan", |
||||
| 85 | * @SWG\Schema( |
||||
| 86 | * @SWG\Property(property="id", type="string", format="UUID") |
||||
| 87 | * ) |
||||
| 88 | * ) |
||||
| 89 | * @SWG\Response( |
||||
| 90 | * response=422, |
||||
| 91 | * description="Loan was not created" |
||||
| 92 | * ) |
||||
| 93 | * |
||||
| 94 | * @param CreateLoanRequest $request |
||||
| 95 | * @param ConstraintViolationListInterface $validationErrors |
||||
| 96 | * @return JsonResponse |
||||
| 97 | */ |
||||
| 98 | public function create(CreateLoanRequest $request, ConstraintViolationListInterface $validationErrors): JsonResponse |
||||
| 99 | { |
||||
| 100 | if ($validationErrors->count()) { |
||||
| 101 | $response = $this->jsonError(ApiError::ENTITY_VALIDATION_ERROR, |
||||
|
0 ignored issues
–
show
Unused Code
introduced
by
Loading history...
|
|||||
| 102 | 'Validations errors for create Loan', |
||||
| 103 | Response::HTTP_BAD_REQUEST, |
||||
| 104 | $this->parseFormErrors($validationErrors) |
||||
| 105 | ); |
||||
| 106 | } |
||||
| 107 | |||||
| 108 | try { |
||||
| 109 | $id = Uuid::uuid4(); |
||||
| 110 | $command = new CreateLoanCommand( |
||||
| 111 | $id, |
||||
| 112 | $request->getItemId(), |
||||
| 113 | $request->getLoaner(), |
||||
| 114 | $request->getLoanDate(), |
||||
| 115 | $request->getReturnDate() |
||||
| 116 | ); |
||||
| 117 | $this->commandBus->dispatch($command); |
||||
| 118 | return $this->json(['id' => $id], Response::HTTP_CREATED); |
||||
| 119 | } catch (\Exception $e) { |
||||
| 120 | $this->logger->critical($e->getMessage()); |
||||
| 121 | return $this->jsonError(ApiError::ENTITY_CREATE_ERROR, |
||||
| 122 | $e->getMessage(), |
||||
| 123 | Response::HTTP_UNPROCESSABLE_ENTITY |
||||
| 124 | ); |
||||
| 125 | } |
||||
| 126 | } |
||||
| 127 | |||||
| 128 | /** |
||||
| 129 | * @Route("/api/loan", name="update_loan", methods={"PATCH"}) |
||||
| 130 | * |
||||
| 131 | * @ParamConverter("request", converter="fos_rest.request_body") |
||||
| 132 | * |
||||
| 133 | * @SWG\Tag(name="Loan") |
||||
| 134 | * @SWG\Patch( |
||||
| 135 | * @SWG\Parameter( |
||||
| 136 | * name="body", |
||||
| 137 | * in="body", |
||||
| 138 | * required=true, |
||||
| 139 | * format="application/json", |
||||
| 140 | * @SWG\Schema( |
||||
| 141 | * required={"name"}, |
||||
| 142 | * @SWG\Property(property="id", type="string", format="UUID"), |
||||
| 143 | * @SWG\Property(property="itemId", type="string", format="UUID"), |
||||
| 144 | * @SWG\Property(property="loaner", type="string", maxLength=255), |
||||
| 145 | * @SWG\Property(property="loanDate", type="string", format="Y-m-d H:i"), |
||||
| 146 | * @SWG\Property(property="returnDate", type="string", format="Y-m-d H:i"), |
||||
| 147 | * ) |
||||
| 148 | * ) |
||||
| 149 | * ) |
||||
| 150 | * @SWG\Response( |
||||
| 151 | * response=201, |
||||
| 152 | * description="Returns ID of updated Loan", |
||||
| 153 | * @SWG\Schema( |
||||
| 154 | * @SWG\Property(property="id", type="string", format="UUID") |
||||
| 155 | * ) |
||||
| 156 | * ) |
||||
| 157 | * @SWG\Response( |
||||
| 158 | * response=422, |
||||
| 159 | * description="Loan was not updated" |
||||
| 160 | * ) |
||||
| 161 | * |
||||
| 162 | * @param UpdateLoanRequest $request |
||||
| 163 | * @param ConstraintViolationListInterface $validationErrors |
||||
| 164 | * @return JsonResponse |
||||
| 165 | */ |
||||
| 166 | public function update(UpdateLoanRequest $request, ConstraintViolationListInterface $validationErrors): JsonResponse |
||||
| 167 | { |
||||
| 168 | if ($validationErrors->count()) { |
||||
| 169 | return $this->jsonError(ApiError::ENTITY_VALIDATION_ERROR, |
||||
| 170 | 'Validations errors for update Loan', |
||||
| 171 | Response::HTTP_BAD_REQUEST, |
||||
| 172 | $this->parseFormErrors($validationErrors) |
||||
| 173 | ); |
||||
| 174 | } |
||||
| 175 | |||||
| 176 | try { |
||||
| 177 | $command = new UpdateLoanCommand( |
||||
| 178 | $request->getId(), |
||||
| 179 | $request->getItemId(), |
||||
| 180 | $request->getLoaner(), |
||||
| 181 | $request->getLoanDate(), |
||||
| 182 | $request->getReturnDate() |
||||
| 183 | ); |
||||
| 184 | $this->commandBus->dispatch($command); |
||||
| 185 | $loan = $this->repository->getLoan($command->getId()); |
||||
| 186 | return $this->json($loan, Response::HTTP_OK); |
||||
| 187 | } catch (\Exception $e) { |
||||
| 188 | $this->logger->critical($e->getMessage()); |
||||
| 189 | return $this->jsonError(ApiError::ENTITY_CREATE_ERROR, |
||||
| 190 | $e->getMessage(), |
||||
| 191 | Response::HTTP_UNPROCESSABLE_ENTITY |
||||
| 192 | ); |
||||
| 193 | } |
||||
| 194 | } |
||||
| 195 | |||||
| 196 | /** |
||||
| 197 | * Delete Loan |
||||
| 198 | * |
||||
| 199 | * @SWG\Tag(name="Loan") |
||||
| 200 | * @SWG\Response( |
||||
| 201 | * response="204", |
||||
| 202 | * description="Loan was deleted" |
||||
| 203 | * ) |
||||
| 204 | * @SWG\Response( |
||||
| 205 | * response="404", |
||||
| 206 | * description="Loan not found", |
||||
| 207 | * ) |
||||
| 208 | * |
||||
| 209 | * @SWG\Response( |
||||
| 210 | * response="422", |
||||
| 211 | * description="Loan was not deleted", |
||||
| 212 | * ) |
||||
| 213 | * |
||||
| 214 | * @Route("/api/loan/{id}", name="loan_delete", methods={"DELETE"}) |
||||
| 215 | * @param string $id |
||||
| 216 | * @return JsonResponse |
||||
| 217 | */ |
||||
| 218 | public function delete(string $id): JsonResponse |
||||
| 219 | { |
||||
| 220 | try { |
||||
| 221 | $uuid = Uuid::fromString($id); |
||||
| 222 | $command = new DeleteLoanCommand($uuid); |
||||
| 223 | $this->commandBus->dispatch($command); |
||||
| 224 | return $this->json(null, Response::HTTP_NO_CONTENT); |
||||
| 225 | } catch (\Ramsey\Uuid\Exception\InvalidUuidStringException $e) { |
||||
| 226 | $response = $this->jsonError(ApiError::ENTITY_UUID_ERROR, |
||||
|
0 ignored issues
–
show
|
|||||
| 227 | $e->getMessage(), |
||||
| 228 | Response::HTTP_UNPROCESSABLE_ENTITY |
||||
| 229 | ); |
||||
|
0 ignored issues
–
show
In this branch, the function will implicitly return
null which is incompatible with the type-hinted return Symfony\Component\HttpFoundation\JsonResponse. Consider adding a return statement or allowing null as return value.
For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example: interface ReturnsInt {
public function returnsIntHinted(): int;
}
class MyClass implements ReturnsInt {
public function returnsIntHinted(): int
{
if (foo()) {
return 123;
}
// here: null is implicitly returned
}
}
Loading history...
|
|||||
| 230 | } catch (LoanNotFoundException $e) { |
||||
| 231 | $response = $this->jsonError(ApiError::ENTITY_READ_ERROR, |
||||
| 232 | $e->getMessage(), |
||||
| 233 | Response::HTTP_NOT_FOUND |
||||
| 234 | ); |
||||
|
0 ignored issues
–
show
In this branch, the function will implicitly return
null which is incompatible with the type-hinted return Symfony\Component\HttpFoundation\JsonResponse. Consider adding a return statement or allowing null as return value.
For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example: interface ReturnsInt {
public function returnsIntHinted(): int;
}
class MyClass implements ReturnsInt {
public function returnsIntHinted(): int
{
if (foo()) {
return 123;
}
// here: null is implicitly returned
}
}
Loading history...
|
|||||
| 235 | } catch (LoanNotDeletedException $e) { |
||||
| 236 | $response = $this->jsonError(ApiError::ENTITY_DELETE_ERROR, |
||||
| 237 | $e->getMessage(), |
||||
| 238 | Response::HTTP_BAD_REQUEST |
||||
| 239 | ); |
||||
|
0 ignored issues
–
show
In this branch, the function will implicitly return
null which is incompatible with the type-hinted return Symfony\Component\HttpFoundation\JsonResponse. Consider adding a return statement or allowing null as return value.
For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example: interface ReturnsInt {
public function returnsIntHinted(): int;
}
class MyClass implements ReturnsInt {
public function returnsIntHinted(): int
{
if (foo()) {
return 123;
}
// here: null is implicitly returned
}
}
Loading history...
|
|||||
| 240 | } |
||||
| 241 | } |
||||
| 242 | |||||
| 243 | /** |
||||
| 244 | * List loaned items |
||||
| 245 | * |
||||
| 246 | * @SWG\Tag(name="Loan") |
||||
| 247 | * @SWG\Response( |
||||
| 248 | * response=200, |
||||
| 249 | * description="List of loaned items", |
||||
| 250 | * @SWG\Schema( |
||||
| 251 | * type="array", |
||||
| 252 | * @SWG\Items(ref=@Model(type=App\Entity\Item::class)) |
||||
| 253 | * ) |
||||
| 254 | * ) |
||||
| 255 | * |
||||
| 256 | * @param Request $request |
||||
| 257 | * @Route("/api/loaned", name="loaned-items-list", methods={"GET"}) |
||||
| 258 | * @return JsonResponse |
||||
| 259 | */ |
||||
| 260 | public function getLoanedItems(Request $request): JsonResponse |
||||
|
0 ignored issues
–
show
The parameter
$request is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. Loading history...
|
|||||
| 261 | { |
||||
| 262 | try { |
||||
| 263 | return $this->json($this->repository->listLoans()); |
||||
| 264 | } catch (\Exception$e) { |
||||
| 265 | $this->logger->critical($e->getMessage()); |
||||
| 266 | return $this->jsonError(ApiError::ENTITY_CREATE_ERROR, |
||||
| 267 | $e->getMessage(), |
||||
| 268 | Response::HTTP_UNPROCESSABLE_ENTITY |
||||
| 269 | ); |
||||
| 270 | } |
||||
| 271 | } |
||||
| 272 | } |
||||
| 273 |