<?php
namespace App\Controller\ApiV2\Residents;
use App\Controller\ApiV2\AbstractController;
use App\Entity\Task;
use App\Enums\AttachmentTypeEnum;
use App\Exception\FormException;
use App\Form\ApiV2\BuildingProblemType;
use App\Repository\BuildingRepository;
use App\Repository\FlatRepository;
use App\Repository\TaskFileRepository;
use App\Repository\TaskRepository;
use App\Repository\TaskTypeRepository;
use App\Repository\UserRepository;
use App\Security\Voter\FlatVoter;
use App\Services\MailService;
use App\Services\NotificationTokenService;
use App\Services\TaskFileService;
use App\Services\TaskService;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Exception;
use FOS\RestBundle\Controller\Annotations as Rest;
use GuzzleHttp\Exception\GuzzleException;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
class ProblemController extends AbstractController
{
private FlatRepository $flatRepository;
private TaskRepository $taskRepository;
private TaskTypeRepository $taskTypeRepository;
private TaskFileService $taskFileService;
private TaskFileRepository $taskFileRepository;
private TaskService $taskService;
private NotificationTokenService $notificationTokenService;
private UserRepository $userRepository;
private MailService $mailService;
private string $projectDir;
/**
* @param BuildingRepository $buildingRepository
* @param UserRepository $userRepository
* @param FlatRepository $flatRepository
* @param TaskRepository $taskRepository
* @param TaskTypeRepository $taskTypeRepository
* @param TaskFileRepository $taskFileRepository
* @param TaskFileService $taskFileService
* @param TaskService $taskService
* @param NotificationTokenService $notificationTokenService
* @param MailService $mailService
* @param string $projectDir
*/
public function __construct(
BuildingRepository $buildingRepository,
UserRepository $userRepository,
FlatRepository $flatRepository,
TaskRepository $taskRepository,
TaskTypeRepository $taskTypeRepository,
TaskFileRepository $taskFileRepository,
TaskFileService $taskFileService,
TaskService $taskService,
NotificationTokenService $notificationTokenService,
MailService $mailService,
string $projectDir
) {
parent::__construct($buildingRepository);
$this->flatRepository = $flatRepository;
$this->taskRepository = $taskRepository;
$this->taskTypeRepository = $taskTypeRepository;
$this->taskFileService = $taskFileService;
$this->taskFileRepository = $taskFileRepository;
$this->taskService = $taskService;
$this->notificationTokenService = $notificationTokenService;
$this->userRepository = $userRepository;
$this->mailService = $mailService;
$this->projectDir = $projectDir;
}
/**
* @Rest\Get("/", name="residents_flats_problems_index")
* @param Request $request
* @param int $id
* @return array<string, mixed>
* @throws NoResultException
* @throws NonUniqueResultException
*/
public function index(Request $request, int $id): array
{
$flat = $this->flatRepository->find($id);
if (!$flat) {
$this->createNotFoundException();
}
$this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
$options = $this->getListOptions($request);
$status = $request->get('status');
$tasks = $this->taskRepository->findTasksByBuildingPaginated2(
$flat->getBuilding(),
$options,
$status
);
$countTask = $this->taskRepository->countTasksByBuildingPaginated2(
$flat->getBuilding(),
$options,
$status
);
return [
'data' => $tasks,
'count' => $countTask
];
}
/**
* @Rest\Post("/", name="residents_flats_problems_store")
* @param Request $request
* @param int $id
* @return array<mixed>
* @throws Exception
* @throws GuzzleException
*/
public function store(Request $request, int $id): array
{
$flat = $this->flatRepository->find($id);
if (!$flat) {
throw $this->createNotFoundException('Ovaj stan ne postoji.');
}
$this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
$building = $flat->getBuilding();
$problemTypes = $this->taskTypeRepository->findAllTaskTypeIds();
try {
$problemData = $this->validateForm($request, BuildingProblemType::class, null, [
'types' => $problemTypes
]);
$problemData['flatNumber'] = $flat->getDisplayFlatId();
$problemData['email'] = $flat->getOwnerEmail();
$problemData['phoneNumber'] = $flat->getOwnerContact();
$problemData['resident'] = $this->getUser();
$result = $this->taskService->saveTask(null, $building, $problemData);
if (!($result instanceof Task)) {
throw new HttpException($result['code'], $result['message']);
}
$this->notificationTokenService->sendPushNotificationAction($building, $problemData);
$task = $result;
/** @var array<UploadedFile> $uploadedTaskFiles */
$uploadedTaskFiles = $request->files->get('file') ?? [];
foreach ($uploadedTaskFiles as $uploadedTaskFile) {
$originalFilename = pathinfo($uploadedTaskFile->getClientOriginalName(), PATHINFO_FILENAME);
$safeFilename = transliterator_transliterate(
'Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()',
$originalFilename
);
$newFilename = sprintf("%s-%s.%s", $safeFilename, uniqid(), $uploadedTaskFile->guessClientExtension());
try {
$uploadedTaskFile->move(
$this->getParameter('tasks_files_directory'),
$newFilename
);
} catch (FileException $fileException) {
}
$taskFile = $this->taskFileService->createTaskFile($newFilename, $task);
$task->addFile($taskFile);
$this->taskFileRepository->save($taskFile);
}
return [
'data' => $task
];
} catch (FormException $exception) {
return $exception->getFormError();
}
}
/**
* @Rest\Post("/v3", name="residents_flats_problems_store_new")
* @param Request $request
* @param int $id
* @return array<mixed>
* @throws Exception
* @throws GuzzleException|TransportExceptionInterface
*/
public function storeNew(Request $request, int $id): array
{
$flat = $this->flatRepository->find($id);
if (!$flat) {
throw $this->createNotFoundException('Ovaj stan ne postoji.');
}
$this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
$building = $flat->getBuilding();
$problemTypes = $this->taskTypeRepository->findAllTaskTypeIds();
try {
$problemData = $this->validateForm($request, BuildingProblemType::class, null, [
'types' => $problemTypes
]);
$problemData['flatNumber'] = $flat->getDisplayFlatId();
$problemData['email'] = $flat->getOwnerEmail();
$problemData['resident'] = $this->getUser();
$result = $this->taskService->saveTask(null, $building, $problemData);
if (!($result instanceof Task)) {
throw new HttpException($result['code'], $result['message']);
}
$this->notificationTokenService->sendPushNotificationAction($building, $problemData);
$task = $result;
$user = $this->userRepository->findOneBy(['id' => $flat->getUser()->getId()]);
/** @var UploadedFile|null $uploadedTaskFile */
$uploadedTaskFile = $request->files->get('file') ?? [];
$newFilename = null;
$route = null;
if (!empty($uploadedTaskFile)) {
try {
$originalFilename = pathinfo($uploadedTaskFile->getClientOriginalName(), PATHINFO_FILENAME);
$safeFilename = transliterator_transliterate(
'Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()',
$originalFilename
);
$newFilename = sprintf(
"%s-%s.%s",
$safeFilename,
uniqid(),
$uploadedTaskFile->guessClientExtension()
);
list($w, $h) = getimagesize($uploadedTaskFile);
$new_width = 735;
$new_height = 1000;
$dst = imagecreatetruecolor($new_width, $new_height);
$src = imagecreatefromjpeg($uploadedTaskFile);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $new_width, $new_height, $w, $h);
$path = sprintf("%s/src/uploads/residentProblems/%s", $this->projectDir, $building->getId());
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$path = sprintf("%s/%s", $path, $newFilename);
imagejpeg($dst, $path);
$route = sprintf(
"%s%s/%s",
$this->getParameter('tasks_files_directory'),
$building->getId(),
$newFilename
);
$taskFile = $this->taskFileService->createTaskFile($newFilename, $task);
$task->addFile($taskFile);
$this->taskFileRepository->save($taskFile);
} catch (Exception $fileException) {
throw new Exception($fileException->getMessage());
}
}
$subject = 'Prijava problema';
$recipient = $user->getTaskNotificationEmail() ? $user->getTaskNotificationEmail() : $user->getEmail();
$subtype = ' ';
if (($st = $result->getTaskSubtype()) != null) {
$subtype = sprintf(', podtip %s, ', $st->getName());
}
$text = sprintf(
"Poštovani,<br/><br/>Prijavljen problem za zgradu %s<br/>Tip problema: %s%s<br/>Opis problema: %s<br/>
Broj stana koji je prijavio problem: %s<br/>Broj telefona stanara: %s<br/><br/>Srdačan pozdrav.",
$building->getAddress(),
$result->getTaskType()->getName(),
$subtype,
$result->getDescription(),
$result->getDisplayFlatId(),
$result->getPhoneNumber()
);
$this->mailService->sendEmail(
$subject,
$recipient,
$text,
[],
$newFilename == null ? null : AttachmentTypeEnum::FROM_PATH->value,
$route,
$newFilename,
null,
true
);
return [
'data' => $task
];
} catch (FormException $exception) {
return $exception->getFormError();
}
}
}