<?php
namespace App\Controller\Front;
use JsonException;
use Exception;
use Throwable;
use App\Controller\PageController;
use App\Dto\Input\RegisterDTO;
use App\Exception\EmailAlreadyExistsException;
use App\Exception\ExpiredCodeException;
use App\Exception\InvalidFieldException;
use App\Form\ClientType;
use App\Form\VehicleType;
use App\Model\Appointment;
use App\Model\Client;
use App\Model\Vehicle;
use App\Repository\MenuRepository;
use App\Service\AppointmentService;
use App\Service\ClientService;
use App\Service\ValidatorService;
use App\Service\VehicleService;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @Route("/client", priority="1", options={"expose"=true})
*
* @IsGranted("ROLE_CLIENT")
*/
class ClientController extends PageController
{
use SecurityTokenTrait;
use RequestRefererTrait;
private LoggerInterface $logger;
private ValidatorService $validator;
private ClientService $clientService;
private TokenStorageInterface $tokenStorage;
public function __construct(
ManagerRegistry $doctrine,
MenuRepository $menuRepository,
LoggerInterface $logger,
ValidatorService $validator,
ClientService $clientService,
TokenStorageInterface $tokenStorage
) {
parent::__construct($doctrine, $menuRepository);
$this->logger = $logger;
$this->validator = $validator;
$this->clientService = $clientService;
$this->tokenStorage = $tokenStorage;
}
/**
* @Route("/account/{type}", name="client_account")
*
* @param VehicleService $vehicleService
*
* @throws JsonException
*/
public function account(string $type, Request $request): Response
{
$this->getPageByType($type);
$this->_initDatas($request);
/** @var Client $client */
$client = $this->getUser();
if (!$client->isInformationConfirmed()) {
$this->setReferer($request);
return $this->redirectToRoute('registration_profil');
}
$responseData = ['type' => $type];
// profil
$profil = $this->profil($client, $request);
// vehicle
$vehicle = $this->vehicle($request);
// history
$history = $this->history($request);
// appointment
$appointment = $this->appointment($request);
$responseData = array_merge($profil, $responseData);
$responseData = array_merge($responseData, $vehicle);
$responseData = array_merge($responseData, $history);
$responseData = array_merge($responseData, $appointment);
return $this->render('front/client/account.html.twig', $this->getDatas($responseData));
}
/**
* @throws Exception
*/
protected function profil(Client $client, Request $request): array
{
$form = $this->createForm(ClientType::class, $client);
$form->handleRequest($request);
return [
'clientForm' => $form->createView(),
'client' => $client,
];
}
/**
* @Route("/profil/validate", name="client_validate_profil", methods={"POST"})
*
* @throws JsonException
*/
public function validateProfil(Request $request, ClientService $clientService): Response
{
/** @var Client $client */
$client = $this->getUser();
$form = $this->createForm(ClientType::class, $client);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if($form->isValid()) {
// ** @var Client $user */
$user = $this->getUser();
$client->setToken($user->getToken());
try {
$datas = $request->request->get('client')['login'];
$datas['code'] = $request->request->get('code');
$clientService->updateProfil($client);
$needReconnect = $clientService->updateLogin($datas);
if ($needReconnect) {
return $this->json(['reconnect_url' => $this->generateUrl('client_auth')]);
}
$clientService->updateUser($client);
} catch (Throwable $exception) {
$this->logger->error($exception->getMessage());
if ($exception instanceof ExpiredCodeException) {
return $this->json(['code' => $exception->getMessage()], Response::HTTP_BAD_REQUEST);
}
return $this->json(['error' => true], Response::HTTP_INTERNAL_SERVER_ERROR);
}
} else {
$errors = $this->validator->getErrors($form);
$this->logger->error(json_encode($errors, JSON_THROW_ON_ERROR));
return $this->json([
'error' => $errors,
], Response::HTTP_BAD_REQUEST);
}
}
return $this->render('front/client/profil.html.twig', $this->getDatas([
'clientForm' => $form->createView(),
'client' => $client,
]));
}
/**
* @Route("/profil/email/update", name="client_email_update")
*
* @return JsonResponse|Response
*
* @throws Exception
*/
public function sendCodeEmail(Request $request, ClientService $clientService, ValidatorInterface $validator): Response
{
$datas = [];
try {
$datas['email'] = $request->request->get('email');
$resend = 'true' == $request->request->get('resend');
$clientService->sendCodeEmail($datas['email'], $resend);
} catch (EmailAlreadyExistsException|InvalidFieldException $exception) {
return $this->json([
'email' => true,
'message' => $exception->getMessage(),
], Response::HTTP_BAD_REQUEST);
} catch (Throwable $e) {
return $this->json([
'error' => true,
'message' => $e->getMessage(),
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
return $this->json(['success' => true]);
}
/**
* @throws Exception
*/
protected function vehicle(Request $request): array
{
$form = $this->createForm(VehicleType::class);
$form->handleRequest($request);
/** @var Appointment $appointment */
$appointment = $request->getSession()->get('appointment');
$appointmentVehicleID = '';
if ($appointment && $appointment->getVehicle()) {
$appointmentVehicleID = $appointment->getVehicle()->getId();
}
return [
'vehicleForm' => $form->createView(),
'vehicleID' => $appointmentVehicleID,
];
}
/**
* @Route("/vehicle/upsert/{id}", name="client_vehicle_upsert", methods={"PUT", "POST"}, defaults={"id": null})
*
* @ParamConverter("vehicle", class="App\Model\Vehicle")
*
* @throws JsonException
*/
public function vehicleValidate(Request $request, ClientService $clientService, AppointmentService $appointmentService, ?Vehicle $vehicle = null): JsonResponse
{
$form = $this->createForm(VehicleType::class, $vehicle);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$clientService->upsertVehicle($vehicle);
$appointmentService->needReinitVehicleStep($request->getSession(), $vehicle->getId());
return $this->json([
'success' => true,
'data' => $vehicle,
]);
} catch (Throwable $exception) {
$this->logger->error($exception->getMessage());
}
} else {
$errors = $this->validator->getErrors($form);
$this->logger->error(json_encode($errors, JSON_THROW_ON_ERROR));
return $this->json([
'error' => $errors,
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
return $this->json([
'error' => true,
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
/**
* @Route("/vehicles/{id}", name="client_vehicles_delete", methods={"DELETE"})
*
* @throws Exception
*/
public function deleteVehicle(Request $request, string $id, ClientService $clientService, AppointmentService $appointmentService): JsonResponse
{
try {
$clientService->deleteVehicle($id);
$appointmentService->needReinitVehicleStep($request->getSession(), $id);
} catch (Throwable $exception) {
$this->logger->error($exception->getMessage());
return $this->json([
'error' => true,
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
return $this->json([
'success' => true,
]);
}
/**
* @Route("/vehicles", name="client_vehicles")
*
* @param Request $request
*
* @throws Exception
*/
public function getCars(ClientService $clientService): JsonResponse
{
/** @var Client $client */
$client = $this->getUser();
$cars = [];
try {
$cars = $clientService->formatCars($client->getVehicles());
} catch (Throwable $exception) {
$this->logger->error(__METHOD__.' : '.$exception->getMessage());
}
return $this->json([
'cars' => $cars,
]);
}
protected function appointment(Request $request)
{
$appointments = $this->clientService->getAppointments();
return [
'appointments' => $appointments,
];
}
private function history(Request $request)
{
$appointments = $this->clientService->getAppointments(false);
return [
'histories' => $appointments,
];
}
}