src/Service/AdoptionPollService.php line 168
<?php
namespace App\Service;
use Exception;
use App\Entity\Animal;
use App\Entity\AnimalPoll;
use App\Entity\AnimalPollStatus;
use App\Entity\Species;
use App\Entity\User;
use App\Entity\UserLoyaltyPoint;
use App\Entity\UserLoyaltyPointBid;
use App\Form\AnimalPoll\Step1Form;
use App\Form\AnimalPoll\Step2Form;
use App\Form\AnimalPoll\Step3Form;
use App\Form\AnimalPoll\Step4Form;
use App\Form\AnimalPoll\Step5Form;
use App\Form\AnimalPoll\Step6Form;
use App\Form\AnimalPoll\Step7Form;
use App\Form\AnimalPoll\Step8Form;
use App\Form\AnimalPoll\Step9Form;
use App\Form\AnimalPoll\Step10Form;
use App\Form\AnimalPoll\Step11Form;
use App\Form\AnimalPoll\Step12Form;
use App\Form\AnimalPoll\Step13Form;
use App\Form\AnimalPoll\Step14Form;
use App\Form\AnimalPoll\Step15Form;
use App\Form\AnimalPoll\Step16Form;
use App\Repository\AnimalPollRepository;
use App\Repository\AnimalPollStatusRepository;
use App\Repository\AnimalRepository;
use App\Repository\UserLoyaltyPointBidRepository;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\RawMessage;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Security;
use Twig\Environment;
/**
* Bag of useful adoption poll methods
*
* @author Michał Zbieranek <michal.zbieranek@kansi.pl>
*/
class AdoptionPollService
{
/** @var ManagerRegistry */
private $entityManager;
/** @var Router */
private $router;
/** @var TokenStorage */
private $tokenStorage;
/** @var FormFactory */
private $formFactory;
/** @var RequestStack */
private $requestStack;
/** @var AnimalRepository */
private $animalRepository;
/** @var AnimalPollRepository */
private $animalPollRepository;
/** @var AuthorizationCheckerInterface */
private $authorizationChecker;
/** @var AnimalPollStatusRepository */
private $animalPollStatusRepository;
/** @var UserLoyaltyPointBidRepository */
private $userLoyaltyPointBidRepository;
private Security $security;
private $forms = [
Step1Form::class,
Step2Form::class,
Step3Form::class,
Step4Form::class,
Step5Form::class,
Step6Form::class,
Step7Form::class,
Step8Form::class,
Step9Form::class,
Step10Form::class,
Step11Form::class,
Step12Form::class,
Step13Form::class,
Step14Form::class,
Step15Form::class,
Step16Form::class,
];
/**
* @var Environment
*/
private Environment $templating;
/**
* @var MailerInterface
*/
private MailerInterface $mailer;
public function __construct(
ManagerRegistry $entityManager,
RouterInterface $router,
TokenStorageInterface $tokenStorage,
FormFactoryInterface $formFactory,
RequestStack $requestStack,
AnimalRepository $animalRepository,
AnimalPollRepository $animalPollRepository,
AnimalPollStatusRepository $animalPollStatusRepository,
UserLoyaltyPointBidRepository $userLoyaltyPointBidRepository,
AuthorizationCheckerInterface $authorizationChecker,
Security $security,
Environment $templating,
MailerInterface $mailer
) {
$this->entityManager = $entityManager;
$this->router = $router;
$this->tokenStorage = $tokenStorage;
$this->formFactory = $formFactory;
$this->requestStack = $requestStack;
$this->animalRepository = $animalRepository;
$this->animalPollRepository = $animalPollRepository;
$this->authorizationChecker = $authorizationChecker;
$this->animalPollStatusRepository = $animalPollStatusRepository;
$this->userLoyaltyPointBidRepository = $userLoyaltyPointBidRepository;
$this->security = $security;
$this->templating = $templating;
$this->mailer = $mailer;
}
/**
* Return existing AnimalPoll entity or just created new one
*
* @param int $animalId
* @return AnimalPoll
*/
public function preparePollEntity($animalId, $animalPollToken = null)
{
$animalPoll = null;
$user = $this->tokenStorage->getToken()->getUser();
if (!$user instanceof User) {
$user = null;
}
if (empty($animalPollToken)) {
if ($user) {
$existingPoll = $this->findAnimalPollFromUser($user, $animalId);
} else {
$existingPoll = null;
}
} else {
$existingPoll = $this->animalPollRepository->findOneBy(['token' => $animalPollToken]);
}
if ($existingPoll) {
$animalPoll = $existingPoll;
} else {
if ($user) {
$existingPoll = $this->findAnimalPollFromUser($user);
} else {
$existingPoll = null;
}
if ($existingPoll) {
$newPoll = $existingPoll;
$newPoll->setCurrentStep(0);
$newPoll->setMessage('');
$newPoll->setIsMessageSend(false);
//Token has to be unique so we don't want to copy it - make new one
$newPoll->setToken(md5(uniqid("", true)));
} else {
$newPoll = new AnimalPoll();
if ($user) {
$newPoll->setCreatedBy($user);
}
}
$newPoll->setAnimal($this->animalRepository->find($animalId));
$newPoll->setStatus(
$this->animalPollStatusRepository->findOneBy(['type' => AnimalPollStatus::TYPE_INPROGRESS])
);
if ($user) {
$user->addAnimalPoll($newPoll);
}
$animalPoll = $newPoll;
}
if (!$this->entityManager->getManager()->contains($animalPoll)) {
$this->entityManager->getManager()->persist($animalPoll);
}
$this->entityManager->getManager()->flush();
return $animalPoll;
}
/**
*
* @param User $user
* @param int $animalId = null
* @return AnimalPoll|null
*/
private function findAnimalPollFromUser(User $user, $animalId = null)
{
$existingPoll = $user->getAnimalPolls()->filter(
function ($entry) use ($animalId) {
if ($animalId) {
if ($entry->getAnimal()->getId() == $animalId) {
return $entry;
} else {
return null;
}
} else {
return $entry;
}
}
)->first();
if ($existingPoll) {
return $existingPoll;
} else {
return null;
}
}
/**
* @param AnimalPoll $animalPoll
*/
private function saveOrAddPollEntity(AnimalPoll $animalPoll)
{
$animalPoll->setCurrentStep($this->requestStack->getCurrentRequest()->get('step', 0));
if (!$this->entityManager->getManager()->contains($animalPoll)) {
$this->entityManager->getManager()->persist($animalPoll);
}
$this->entityManager->getManager()->flush();
}
/**
* Current form
* @param int $step
* @param int $id
* @param AnimalPoll $animalPoll
*/
private function prepareCurrentForm($step, $id, AnimalPoll $animalPoll)
{
$request = $this->requestStack->getCurrentRequest();
//prev-next urls
if ($step > 0) {
$prevUrl = $this->router->generate(
$request->get('_route'),
['id' => $id, 'step' => $step - 1, 'animalPollToken' => $animalPoll->getToken()]
);
} else {
$prevUrl = null;
}
if ($step < count($this->forms) - 1) {
$nextUrl = $this->router->generate(
$request->get('_route'),
['id' => $id, 'step' => $step + 1, 'animalPollToken' => $animalPoll->getToken()]
);
} else {
$nextUrl = null;
}
$currentForm = $this->formFactory->create(
$this->forms[$step],
$animalPoll,
['nextUrl' => $nextUrl, 'prevUrl' => $prevUrl]
);
return $currentForm;
}
/**
* Prepare form and perform handleRequest
* @param int $step
* @param AnimalPoll $animalPoll
* @return Form
*/
private function prepareNextForm($step, AnimalPoll $animalPoll)
{
if ($step < count($this->forms) - 1) {
$nextForm = $this->formFactory->create(
$this->forms[$step + 1],
$animalPoll,
['nextUrl' => "", 'prevUrl' => ""]
);
$nextForm->handleRequest($this->requestStack->getCurrentRequest());
} else {
$nextForm = null;
}
return $nextForm;
}
/**
* Prepare form and perform handleRequest
* @param int $step
* @param AnimalPoll $animalPoll
* @return Form
*/
private function preparePrevForm($step, AnimalPoll $animalPoll)
{
if ($step > 0) {
$prevForm = $this->formFactory->create(
$this->forms[$step - 1],
$animalPoll,
['nextUrl' => "", 'prevUrl' => ""]
);
$prevForm->handleRequest($this->requestStack->getCurrentRequest());
} else {
$prevForm = null;
}
return $prevForm;
}
/**
* Return final form, depends on context
* @param AnimalPoll $animalPoll
* @return Form
*/
public function prepareForm(AnimalPoll $animalPoll)
{
$id = $this->requestStack->getCurrentRequest()->get('id');
$step = $this->requestStack->getCurrentRequest()->get('step');
$prevForm = $this->preparePrevForm($step, $animalPoll);
$nextForm = $this->prepareNextForm($step, $animalPoll);
$currentForm = $this->prepareCurrentForm($step, $id, $animalPoll);
//submit prev
if ($nextForm && $nextForm->isSubmitted()) {
if ($nextForm->isValid()) {
$this->saveOrAddPollEntity($animalPoll);
} else {
$currentForm = $nextForm;
}
}
if ($this->requestStack->getCurrentRequest()->get('send') == 1) {
if (count($this->forms) == $animalPoll->getCurrentStep() + 1) {
$status = $this->animalPollStatusRepository->findOneBy(['type' => AnimalPollStatus::TYPE_WAITING]);
$animalPoll->setStatus($status);
$this->finalStepActions($animalPoll);
}
$this->saveOrAddPollEntity($animalPoll);
}
//submit next
if ($prevForm && $prevForm->isSubmitted()) {
if ($prevForm->isValid()) {
$this->saveOrAddPollEntity($animalPoll);
//handle final step
} else {
$currentForm = $prevForm;
}
}
return $currentForm;
}
/**
* @param AnimalPoll $animalPoll
*/
private function finalStepActions(AnimalPoll $animalPoll)
{
$user = $this->security->getUser();
$this->sendThanksEmail($animalPoll, $user);
$this->sendNewAdoptionFormInfoEmail($animalPoll->getAnimal()->getTemporaryHouse(), $animalPoll->getAnimal());
}
/**
* @param AnimalPoll $animalPoll
* @param User|null $user
*/
private function sendThanksEmail(AnimalPoll $animalPoll, User $user = null)
{
if ($user) {
$userEmail = $user->getEmail();
$userName = $user->getFirstName();
} else {
$userEmail = $animalPoll->getEmail();
$userName = $animalPoll->getFirstName();
}
$email = (new TemplatedEmail())
->from('no-reply@adopciaki.pl')
->to(new Address($userEmail))
->subject('Podziekowania za wypelnienie ankiety adopcyjnej')
->htmlTemplate('front/animal/pollThanksEmail.html.twig')
->context([
'name' => $userName
]);
try {
$this->mailer->send($email);
} catch (TransportExceptionInterface $e) {
return $e->getMessage();
}
return true;
}
/**
* @param User $user
* @param Animal $animal
* @return int
*/
private function sendNewAdoptionFormInfoEmail(User $user, Animal $animal)
{
$email = (new TemplatedEmail())
->from('no-reply@adopciaki.pl')
->bcc('serwis@adopciaki.pl')
->to(new Address($user->getEmail()))
->subject('Nowa ankieta adopcyjna dla Twojego Adopciaka')
->htmlTemplate('front/animal/newAdoptionFormInfoEmail.html.twig')
->context([
'name' => $user->getFirstName(),
'animalName' => $animal->getName()
]);
try {
$this->mailer->send($email);
} catch (TransportExceptionInterface $e) {
return $e->getMessage();
}
return true;
}
/**
* @param Request $request
* @param array $search = []
* @param array $statusTypes = [string]
* @param null $isMessageSend
* @param null $type
* @return QueryBuilder
* @throws Exception
*/
public function prepareIndexQB(
Request $request,
array $search,
$statusTypes = [],
$isMessageSend = null,
$type = null
) {
$order = $request->get('o', 'DESC');
$sortField = $request->get('s', 'id');
$animalId = $request->get('animalId');
if ($this->authorizationChecker->isGranted('ROLE_MODERATOR_HOME_TEMPORARY')) {
$animals = null;
} else {
$animals = $this->security->getUser()->getAnimals();
}
$statuses = [];
if (!empty($statusTypes)) {
foreach ($statusTypes as $statusType) {
$status = $this->entityManager->getRepository(AnimalPollStatus::class)->findOneBy(['type' => $statusType]);
if (empty($status)) {
throw new Exception('Unrecognized status type: '.$statusType);
}
$statuses[] = $status->getId();
}
}
$animalsQb = $this->entityManager->getRepository(AnimalPoll::class)->findAllqb(
$sortField,
$order,
$search,
$animalId,
$animals,
$statuses,
$isMessageSend,
$type
);
return $animalsQb;
}
/**
* @param AnimalPoll $animalPoll
* @return int
*/
public function sendPollResultEmail(AnimalPoll $animalPoll)
{
$email = (new TemplatedEmail())
->from('no-reply@adopciaki.pl')
->to(new Address($animalPoll->getEmail()))
->subject('Twoja ankieta adopcyjna została rozpatrzona!')
->htmlTemplate('admin/animal_poll/pollResultEmail.html.twig')
->context([
'animalPoll' => $animalPoll
]);
try {
$this->mailer->send($email);
} catch (TransportExceptionInterface $e) {
return $e->getMessage();
}
return true;
}
/**
* @param AnimalPoll $animalPoll
* @param Form $noteForm
* @return boolean
*/
public function handleComment(AnimalPoll $animalPoll, Form $noteForm)
{
$request = $this->requestStack->getCurrentRequest();
$noteForm->handleRequest($request);
if ($noteForm->isSubmitted() && $noteForm->isValid()) {
$animalPollNote = $noteForm->getData();
$animalPollNote->setAnimalPoll($animalPoll);
$animalPoll->addNote($animalPollNote);
$this->entityManager->getManager()->flush();
$this->requestStack->getSession()->getFlashBag()->add('info', 'Komentarz został dodany');
$this->addCommentLoyaltyPoints($animalPoll);
return true;
}
return false;
}
/**
*
* @param AnimalPoll $animalPoll
* @param Form $acceptanceForm
* @return boolean
*/
public function handleAcceptance(AnimalPoll $animalPoll, Form $acceptanceForm)
{
$request = $this->requestStack->getCurrentRequest();
$acceptanceForm->handleRequest($request);
if ($acceptanceForm->isSubmitted()) {
if ($acceptanceForm->get('accept')->isClicked()) {
$animalPoll->setStatus(
$this->animalPollStatusRepository->findOneBy(['type' => AnimalPollStatus::TYPE_ACCEPTED])
);
$this->entityManager->getManager()->flush();
$this->requestStack->getSession()->getFlashBag()->add('info', 'Ankieta została zaakceptowana');
}
if ($acceptanceForm->get('reject')->isClicked()) {
$animalPoll->setStatus(
$this->animalPollStatusRepository->findOneBy(['type' => AnimalPollStatus::TYPE_REJECTED])
);
$this->entityManager->getManager()->flush();
$this->requestStack->getSession()->getFlashBag()->add('info', 'Ankieta została odrzucona');
}
$this->addAceptanceLoyaltyPoints($animalPoll);
return true;
}
return false;
}
/**
*
* @param AnimalPoll $animalPoll
* @param Form $messageForm
* @return boolean
*/
public function handleMessage(AnimalPoll $animalPoll, Form $messageForm)
{
$request = $this->requestStack->getCurrentRequest();
$messageForm->handleRequest($request);
if ($messageForm->isSubmitted() && $messageForm->isValid()) {
if ($messageForm->get('accept')->isClicked()) {
//if dont sent message is checked not send message
if ($messageForm->get('dontSendMessage')->getViewData() == '1') {
$this->requestStack->getSession()->getFlashBag()->add(
'info',
'Ankieta jest zmoderowana, wiadomość nie została wysłana do użytkownika'
);
$animalPoll->setDontSendMessage(true);
$animalPoll->setIsMessageSend(true);
$this->entityManager->getManager()->flush();
} else {
$animalPoll->setIsMessageSend(true);
$this->entityManager->getManager()->flush();
$this->sendPollResultEmail($animalPoll);
$this->requestStack->getSession()->getFlashBag()->add(
'info',
'Wiadomość została zaakceptowana i zostanie wysłana do użytkownika'
);
}
return true;
}
}
return false;
}
/**
*
*/
private function addAceptanceLoyaltyPoints(AnimalPoll $animalPoll)
{
$acceptType = UserLoyaltyPointBid::TYPE_ADOPTION_ACCEPTANCE;
if ($animalPoll->getAnimal()->getSpecies()->getType() == Species::TYPE_DOG) {
$acceptType = UserLoyaltyPointBid::TYPE_ADOPTION_ACCEPTANCE_DOG;
}
$this->addLoyaltyPoints($acceptType);
}
/**
* Add points for comment (only first by that user)
*/
private function addCommentLoyaltyPoints(AnimalPoll $animalPoll)
{
$pollCommType = UserLoyaltyPointBid::TYPE_ADOPTION_POLL_COMMENT;
if ($animalPoll->getAnimal()->getSpecies()->getType() == Species::TYPE_DOG) {
$pollCommType = UserLoyaltyPointBid::TYPE_ADOPTION_POOL_COMMENT_DOG;
}
$userNumberOfNotes = $animalPoll->getNotes()->count();
if ($userNumberOfNotes == 1) {
$this->addLoyaltyPoints($pollCommType);
}
}
/**
*
* @param type $type UserLoyaltyPointBid::TYPE_*
*/
private function addLoyaltyPoints($type)
{
$user = $this->tokenStorage->getToken()->getUser();
if ($user->hasRole('ROLE_HOME_TEMPORARY')) {
$bid = $this->userLoyaltyPointBidRepository->findOneBy(['type' => $type]);
$loyaltyPoint = new UserLoyaltyPoint();
$loyaltyPoint->setUser($user);
$loyaltyPoint->setName($bid->getName());
$loyaltyPoint->setType($bid->getType());
$loyaltyPoint->setValue($bid->getValue());
$user->addLoyaltyPoint($loyaltyPoint);
$this->entityManager->getManager()->flush();
}
}
/**
* Ugly! Proxy method, should be refactored
* @param AnimalPoll $poll
* @todo final steps should be moved to AnimalPollManager class
*/
public function finalizeProxy(AnimalPoll $poll): void
{
$this->finalStepActions($poll);
}
/**
* Ugly! Proxy method, should be refactored
* @param AnimalPoll $animalPoll
* @todo sending emails should be moved to AnimalPollManager class
*/
public function ProxySendNewAdoptionFormInfoEmail(AnimalPoll $animalPoll)
{
$this->sendNewAdoptionFormInfoEmail($animalPoll->getAnimal()->getTemporaryHouse(), $animalPoll->getAnimal());
}
}