<?php
namespace App\Controller\ApiV2\Residents;
use App\Controller\ApiV2\AbstractController;
use App\Entity\Flat;
use App\Entity\MoneyLog;
use App\Entity\Poll;
use App\Exception\FormException;
use App\Form\ApiV2\PollOptionIdType;
use App\Repository\BuildingRepository;
use App\Repository\FlatRepository;
use App\Repository\PollOptionRepository;
use App\Repository\PollRepository;
use App\Security\Voter\DTO\FlatPoll;
use App\Security\Voter\FlatPollVoter;
use App\Security\Voter\FlatVoter;
use App\Services\PollService;
use App\Services\SendGrid\SendBillsSendGridService;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use FOS\RestBundle\Controller\Annotations as Rest;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class PollController extends AbstractController
{
private FlatRepository $flatRepository;
private PollService $pollService;
private PollRepository $pollRepository;
private PollOptionRepository $pollOptionRepository;
private SendBillsSendGridService $sendBillsSendGridService;
private string $sendGridMailFromName;
private string $pollsFilesDirectory;
/**
* @param BuildingRepository $buildingRepository
* @param FlatRepository $flatRepository
* @param PollRepository $pollRepository
* @param PollOptionRepository $pollOptionRepository
* @param PollService $pollService
* @param SendBillsSendGridService $sendBillsSendGridService
* @param string $sendGridMailFromName
* @param string $pollsFilesDirectory
*/
public function __construct(
BuildingRepository $buildingRepository,
FlatRepository $flatRepository,
PollRepository $pollRepository,
PollOptionRepository $pollOptionRepository,
PollService $pollService,
SendBillsSendGridService $sendBillsSendGridService,
string $sendGridMailFromName,
string $pollsFilesDirectory
) {
parent::__construct($buildingRepository);
$this->flatRepository = $flatRepository;
$this->pollService = $pollService;
$this->pollRepository = $pollRepository;
$this->pollOptionRepository = $pollOptionRepository;
$this->sendBillsSendGridService = $sendBillsSendGridService;
$this->sendGridMailFromName = $sendGridMailFromName;
$this->pollsFilesDirectory = $pollsFilesDirectory;
}
/**
* @Rest\Get("/", name="residents_flats_polls_index")
* @param Request $request
* @param int $id
* @return array<string, mixed>
* @throws NoResultException
* @throws NonUniqueResultException
*/
public function index(Request $request, int $id): array
{
$status = $request->query->get('status') ?? 'active';
$flat = $this->flatRepository->find($id);
$this->isFlatAccessible($flat);
$queryOptions = $this->getListOptions($request);
if ($status === 'active') {
return $this->pollService->getActiveBuildingPolls($flat->getBuilding(), $queryOptions);
}
return $this->pollService->getFinishedBuildingPolls($flat->getBuilding(), $queryOptions);
}
/**
* @Rest\Get("/{pollId}", name="residents_flats_polls_show")
* @param int $id
* @param int $pollId
* @return array<string, mixed>
* @throws NonUniqueResultException
*/
public function show(int $id, int $pollId): array
{
$flat = $this->flatRepository->find($id);
/** @var Poll $poll */
$poll = $this->pollRepository->find($pollId);
$this->isPollAccessible($flat, $poll);
return [
'data' => $this->pollRepository->getPollWithFlatVotes($poll->getId())
];
}
/**
* @Rest\Post("/{pollId}/options", name="residents_flats_polls_vote")
* @param Request $request
* @param int $id
* @param int $pollId
* @return array<string, mixed>
*/
public function vote(Request $request, int $id, int $pollId): array
{
$flat = $this->flatRepository->find($id);
/** @var Poll $poll */
$poll = $this->pollRepository->find($pollId);
$this->isPollAccessible($flat, $poll);
try {
$pollVoteData = $this->validateForm($request, PollOptionIdType::class, null, [
'optionTypes' => $this->pollService->getAllPollOptionIdsForPoll($poll)
]);
$pollOption = $this->pollOptionRepository->find($pollVoteData['option_type']);
$hasVotedForSameOption = $flat->getVotedOptions()->contains($pollOption);
foreach ($poll->getPollOptions() as $option) {
if ($flat->getVotedOptions()->contains($option)) {
$flat->removePollOption($option);
}
}
if (!$hasVotedForSameOption) {
$flat->addPollOption($pollOption);
}
$subject = sprintf("eGlasanje za zgradu %s", $flat->getBuilding()->getAddress());
$text = sprintf(
"Poštovani, <br><br>
Vlasnik stana <b>%s</b>, broj stana <b>%s</b>, dana <b>%s</b> glasao/la je <b>%s</b> po pitanju:<br>
<b>%s</b><br><br>
Glasanje je započeto dana <b>%s</b>, a zaršava se dana <b>%s</b> <br>
Ova potvrda predstavlja pisani trag u skladu sa Zakonom o stanovanju i održavanju zgrada<br>
(Sl. glasnik RS, br. 104/2016 i 9/2020).<br><br><hr>
<i>Ovim potvrđujem da je glasanje sprovedeno elektronskim putem preko aplikacije Troškovi,<br>
koja omogućava validno e-glasanje u skladu sa važećim zakonskim propisima.</i>",
sprintf('%s %s', $flat->getOwnerLastname(), $flat->getOwnerName()),
$flat->getDisplayFlatId(),
date("d.m.Y."),
$pollOption->getDescription(),
$poll->getDescription(),
$poll->getStartsAt()->format('d.m.Y.'),
$poll->getEndsAt()->format('d.m.Y.')
);
// $this->sendBillsSendGridService->sendEmail(
// $subject,
// [$flat->getUser()->getEmail()],
// $this->sendGridMailFromName,
// $text,
// [],
// null,
// null,
// null,
// null,
// true,
// );
$this->flatRepository->save($flat);
return [
'data' => $pollOption
];
} catch (FormException $exception) {
return $exception->getFormError();
}
}
/**
* @param Flat|null $flat
*/
private function isFlatAccessible(?Flat $flat): void
{
if (!$flat) {
throw $this->createNotFoundException('Stan nije pronađen.');
}
$this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
}
/**
* @param Flat $flat
* @param Poll|null $poll
*/
private function isPollAccessible(Flat $flat, ?Poll $poll): void
{
$this->isFlatAccessible($flat);
if (!$poll) {
throw $this->createNotFoundException('Elektronsko glasanje nije pronađeno.');
}
$this->denyAccessUnlessGranted(
FlatPollVoter::FLAT_AND_POLL_BELONG_TO_SAME_BUILDING,
new FlatPoll($flat, $poll)
);
}
/**
* @Rest\Get("/pdf/{pollId}", name="resident_poll_pdf")
* @param int $id
* @param int $pollId
* @return Response
*/
public function getPollPdf(int $id, int $pollId): Response
{
$flat = $this->flatRepository->find($id);
$this->denyAccessUnlessGranted(FlatVoter::FLAT_BELONGS_TO_RESIDENT, $flat);
if (!$flat) {
throw $this->createNotFoundException('Stan nije pronađen.');
}
/** @var Poll $poll */
$poll = $this->pollRepository->find($pollId);
$this->isPollAccessible($flat, $poll);
$filePath = sprintf("%s%s", $this->pollsFilesDirectory, $poll->getFile());
$fileContent = file_get_contents($filePath);
return new Response($fileContent, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => sprintf("%s.pdf", md5($pollId))
]);
}
}