src/Controller/ApiV2/Residents/ProblemController.php line 100

  1. <?php
  2. namespace App\Controller\ApiV2\Residents;
  3. use App\Controller\ApiV2\AbstractController;
  4. use App\Entity\Task;
  5. use App\Entity\TaskType;
  6. use App\Enums\AttachmentTypeEnum;
  7. use App\Exception\FormException;
  8. use App\Form\ApiV2\BuildingProblemType;
  9. use App\Repository\BuildingRepository;
  10. use App\Repository\FlatRepository;
  11. use App\Repository\TaskFileRepository;
  12. use App\Repository\TaskRepository;
  13. use App\Repository\TaskTypeRepository;
  14. use App\Repository\UserRepository;
  15. use App\Security\Voter\FlatVoter;
  16. use App\Services\MailService;
  17. use App\Services\NotificationTokenService;
  18. use App\Services\TaskFileService;
  19. use App\Services\TaskService;
  20. use Doctrine\ORM\NonUniqueResultException;
  21. use Doctrine\ORM\NoResultException;
  22. use Exception;
  23. use FOS\RestBundle\Controller\Annotations as Rest;
  24. use GuzzleHttp\Exception\GuzzleException;
  25. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  26. use Symfony\Component\HttpFoundation\File\UploadedFile;
  27. use Symfony\Component\HttpFoundation\Request;
  28. use Symfony\Component\HttpKernel\Exception\HttpException;
  29. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  30. class ProblemController extends AbstractController
  31. {
  32. private FlatRepository $flatRepository;
  33. private TaskRepository $taskRepository;
  34. private TaskTypeRepository $taskTypeRepository;
  35. private TaskFileService $taskFileService;
  36. private TaskFileRepository $taskFileRepository;
  37. private TaskService $taskService;
  38. private NotificationTokenService $notificationTokenService;
  39. private UserRepository $userRepository;
  40. private MailService $mailService;
  41. private string $projectDir;
  42. /**
  43. * @param BuildingRepository $buildingRepository
  44. * @param UserRepository $userRepository
  45. * @param FlatRepository $flatRepository
  46. * @param TaskRepository $taskRepository
  47. * @param TaskTypeRepository $taskTypeRepository
  48. * @param TaskFileRepository $taskFileRepository
  49. * @param TaskFileService $taskFileService
  50. * @param TaskService $taskService
  51. * @param NotificationTokenService $notificationTokenService
  52. * @param MailService $mailService
  53. * @param string $projectDir
  54. */
  55. public function __construct(
  56. BuildingRepository $buildingRepository,
  57. UserRepository $userRepository,
  58. FlatRepository $flatRepository,
  59. TaskRepository $taskRepository,
  60. TaskTypeRepository $taskTypeRepository,
  61. TaskFileRepository $taskFileRepository,
  62. TaskFileService $taskFileService,
  63. TaskService $taskService,
  64. NotificationTokenService $notificationTokenService,
  65. MailService $mailService,
  66. string $projectDir
  67. ) {
  68. parent::__construct($buildingRepository);
  69. $this->flatRepository = $flatRepository;
  70. $this->taskRepository = $taskRepository;
  71. $this->taskTypeRepository = $taskTypeRepository;
  72. $this->taskFileService = $taskFileService;
  73. $this->taskFileRepository = $taskFileRepository;
  74. $this->taskService = $taskService;
  75. $this->notificationTokenService = $notificationTokenService;
  76. $this->userRepository = $userRepository;
  77. $this->mailService = $mailService;
  78. $this->projectDir = $projectDir;
  79. }
  80. /**
  81. * @param Request $request
  82. * @param int $id
  83. * @return array<string, mixed>
  84. * @throws NoResultException
  85. * @throws NonUniqueResultException
  86. */
  87. #[Rest\Get('/', name: 'residents_flats_problems_index')]
  88. public function index(Request $request, int $id): array
  89. {
  90. $flat = $this->flatRepository->find($id);
  91. if (!$flat) {
  92. $this->createNotFoundException();
  93. }
  94. $this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
  95. $options = $this->getListOptions($request);
  96. $status = $request->get('status');
  97. $tasks = $this->taskRepository->findTasksByBuildingPaginated2(
  98. $flat->getBuilding(),
  99. $options,
  100. null,
  101. $status
  102. );
  103. $countTask = $this->taskRepository->countTasksByBuildingPaginated2(
  104. $flat->getBuilding(),
  105. $options,
  106. null,
  107. $status
  108. );
  109. return [
  110. 'data' => $tasks,
  111. 'count' => $countTask
  112. ];
  113. }
  114. /**
  115. * @param Request $request
  116. * @param int $id
  117. * @return array<mixed>
  118. * @throws Exception
  119. * @throws GuzzleException
  120. */
  121. #[Rest\Post('/', name: 'residents_flats_problems_store')]
  122. public function store(Request $request, int $id): array
  123. {
  124. $flat = $this->flatRepository->find($id);
  125. if (!$flat) {
  126. throw $this->createNotFoundException('Ovaj stan ne postoji.');
  127. }
  128. $this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
  129. $building = $flat->getBuilding();
  130. $problemTypes = $this->taskTypeRepository->findAllTaskTypeIds();
  131. try {
  132. $problemData = $this->validateForm($request, BuildingProblemType::class, null, [
  133. 'types' => $problemTypes
  134. ]);
  135. $problemData['flatNumber'] = $flat->getDisplayFlatId();
  136. $problemData['email'] = $flat->getOwnerEmail();
  137. $problemData['phoneNumber'] = $flat->getOwnerContact();
  138. $problemData['resident'] = $this->getUser();
  139. $result = $this->taskService->saveTask(null, $building, $problemData);
  140. if (!($result instanceof Task)) {
  141. throw new HttpException($result['code'], $result['message']);
  142. }
  143. $this->notificationTokenService->sendPushNotificationAction($building, $problemData);
  144. $task = $result;
  145. /** @var array<UploadedFile> $uploadedTaskFiles */
  146. $uploadedTaskFiles = $request->files->get('file') ?? [];
  147. foreach ($uploadedTaskFiles as $uploadedTaskFile) {
  148. $originalFilename = pathinfo($uploadedTaskFile->getClientOriginalName(), PATHINFO_FILENAME);
  149. $safeFilename = transliterator_transliterate(
  150. 'Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()',
  151. $originalFilename
  152. );
  153. $newFilename = sprintf("%s-%s.%s", $safeFilename, uniqid(), $uploadedTaskFile->guessClientExtension());
  154. try {
  155. $uploadedTaskFile->move(
  156. $this->getParameter('tasks_files_directory'),
  157. $newFilename
  158. );
  159. } catch (FileException $fileException) {
  160. }
  161. $taskFile = $this->taskFileService->createTaskFile($newFilename, $task);
  162. $task->addFile($taskFile);
  163. $this->taskFileRepository->save($taskFile);
  164. }
  165. return [
  166. 'data' => $task
  167. ];
  168. } catch (FormException $exception) {
  169. return $exception->getFormError();
  170. }
  171. }
  172. /**
  173. * @param Request $request
  174. * @param int $id
  175. * @return array<mixed>
  176. * @throws Exception
  177. * @throws GuzzleException|TransportExceptionInterface
  178. */
  179. #[Rest\Post('/v3', name: 'residents_flats_problems_store_new')]
  180. public function storeNew(Request $request, int $id): array
  181. {
  182. $flat = $this->flatRepository->find($id);
  183. if (!$flat) {
  184. throw $this->createNotFoundException('Ovaj stan ne postoji.');
  185. }
  186. $this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
  187. $building = $flat->getBuilding();
  188. $problemTypes = $this->taskTypeRepository->findAllTaskTypeIds();
  189. try {
  190. $problemData = $this->validateForm($request, BuildingProblemType::class, null, [
  191. 'types' => $problemTypes
  192. ]);
  193. $problemData['flatNumber'] = $flat->getDisplayFlatId();
  194. $problemData['email'] = $flat->getOwnerEmail();
  195. $problemData['resident'] = $this->getUser();
  196. $result = $this->taskService->saveTask(null, $building, $problemData);
  197. if (!($result instanceof Task)) {
  198. throw new HttpException($result['code'], $result['message']);
  199. }
  200. $this->notificationTokenService->sendPushNotificationAction($building, $problemData);
  201. $task = $result;
  202. $user = $this->userRepository->findOneBy(['id' => $flat->getUser()->getId()]);
  203. /** @var UploadedFile|null $uploadedTaskFile */
  204. $uploadedTaskFile = $request->files->get('file') ?? [];
  205. $newFilename = null;
  206. $route = null;
  207. if (!empty($uploadedTaskFile)) {
  208. try {
  209. $originalFilename = pathinfo($uploadedTaskFile->getClientOriginalName(), PATHINFO_FILENAME);
  210. $safeFilename = transliterator_transliterate(
  211. 'Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()',
  212. $originalFilename
  213. );
  214. $newFilename = sprintf(
  215. "%s-%s.%s",
  216. $safeFilename,
  217. uniqid(),
  218. $uploadedTaskFile->guessClientExtension()
  219. );
  220. list($w, $h) = getimagesize($uploadedTaskFile);
  221. $new_width = 735;
  222. $new_height = 1000;
  223. $dst = imagecreatetruecolor($new_width, $new_height);
  224. $src = imagecreatefromjpeg($uploadedTaskFile);
  225. imagecopyresampled($dst, $src, 0, 0, 0, 0, $new_width, $new_height, $w, $h);
  226. $path = sprintf("%s/src/uploads/residentProblems/%s", $this->projectDir, $building->getId());
  227. if (!is_dir($path)) {
  228. mkdir($path, 0777, true);
  229. }
  230. $path = sprintf("%s/%s", $path, $newFilename);
  231. imagejpeg($dst, $path);
  232. $route = sprintf(
  233. "%s%s/%s",
  234. $this->getParameter('tasks_files_directory'),
  235. $building->getId(),
  236. $newFilename
  237. );
  238. $taskFile = $this->taskFileService->createTaskFile($newFilename, $task);
  239. $task->addFile($taskFile);
  240. $this->taskFileRepository->save($taskFile);
  241. } catch (Exception $fileException) {
  242. throw new Exception($fileException->getMessage());
  243. }
  244. }
  245. $subject = 'Prijava problema';
  246. if ($user->getTaskNotificationEmail()) {
  247. $recipient = $user->getTaskNotificationEmail();
  248. } else {
  249. $mainUser = $user->getMainUser();
  250. if ($mainUser === null) {
  251. $recipient = $user->getEmail();
  252. } elseif ($mainUser->getTaskNotificationEmail()) {
  253. $recipient = $mainUser->getTaskNotificationEmail();
  254. } else {
  255. $recipient = $user->getEmail();
  256. }
  257. }
  258. $text = sprintf(
  259. "Poštovani,<br><br>Prijavljen problem za zgradu %s<br>Tip problema: %s<br>Opis problema: %s<br>
  260. Broj stana koji je prijavio problem: %s<br>Broj telefona stanara: %s<br><br>Srdačan pozdrav.",
  261. $building->getAddress(),
  262. $result->getTaskType()->getName(),
  263. $result->getDescription(),
  264. $result->getDisplayFlatId(),
  265. $result->getPhoneNumber()
  266. );
  267. $this->mailService->sendEmail(
  268. $subject,
  269. [$recipient],
  270. null,
  271. $text,
  272. [],
  273. $newFilename == null ? null : AttachmentTypeEnum::FROM_PATH->value,
  274. $route,
  275. $newFilename,
  276. null,
  277. true
  278. );
  279. return [
  280. 'data' => $task,
  281. 'code' => 200
  282. ];
  283. } catch (FormException $exception) {
  284. return $exception->getFormError();
  285. }
  286. }
  287. /**
  288. * @return array<TaskType>
  289. */
  290. #[Rest\Get('/types', name: 'residents_flats_problems_types')]
  291. public function getProblemTypes(): array
  292. {
  293. $types = $this->taskTypeRepository->findAll();
  294. return [
  295. 'data' => $types
  296. ];
  297. }
  298. /**
  299. * @param Request $request
  300. * @param int $id
  301. * @return array<string, mixed>
  302. * @throws NoResultException
  303. * @throws NonUniqueResultException
  304. */
  305. #[Rest\Get('/my', name: 'residents_flats_problems_my')]
  306. public function myTasks(Request $request, int $id): array
  307. {
  308. $flat = $this->flatRepository->find($id);
  309. if (!$flat) {
  310. $this->createNotFoundException();
  311. }
  312. $this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
  313. $options = $this->getListOptions($request);
  314. $status = $request->get('status');
  315. $tasks = $this->taskRepository->findTasksByBuildingPaginated2(
  316. $flat->getBuilding(),
  317. $options,
  318. $flat->getDisplayFlatId(),
  319. $status
  320. );
  321. $countTask = $this->taskRepository->countTasksByBuildingPaginated2(
  322. $flat->getBuilding(),
  323. $options,
  324. $flat->getDisplayFlatId(),
  325. $status
  326. );
  327. return [
  328. 'data' => $tasks,
  329. 'count' => $countTask
  330. ];
  331. }
  332. }