src/Service/AnimalService.php line 564

  1. <?php
  2. namespace App\Service;
  3. use App\Entity\Animal;
  4. use App\Entity\AnimalSearch;
  5. use App\Entity\File;
  6. use App\Entity\Species;
  7. use App\Entity\UserLoyaltyPoint;
  8. use App\Entity\UserLoyaltyPointBid;
  9. use App\Form\AnimalSearchForm;
  10. use App\Repository\AnimalRepository;
  11. use App\Repository\AnimalSearchRepository;
  12. use App\Repository\FileRepository;
  13. use App\Repository\UserLoyaltyPointBidRepository;
  14. use Doctrine\Common\Collections\ArrayCollection;
  15. use Doctrine\ORM\EntityManager;
  16. use Doctrine\ORM\QueryBuilder;
  17. use Doctrine\Persistence\ManagerRegistry;
  18. use Exception;
  19. use Dompdf\Dompdf;
  20. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  21. use Symfony\Bundle\FrameworkBundle\Routing\Router;
  22. use Symfony\Component\Form\Form;
  23. use Symfony\Component\Form\FormFactory;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\HttpFoundation\RequestStack;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\HttpFoundation\Session\Session;
  28. use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
  29. use Symfony\Component\Mailer\MailerInterface;
  30. use Symfony\Component\Mime\Address;
  31. use Symfony\Component\Mime\Part\DataPart;
  32. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
  33. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  34. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  35. use Twig\Environment;
  36. /**
  37.  * Bag of useful animal methods
  38.  *
  39.  * @author MichaÅ‚ Zbieranek <michal.zbieranek@kansi.pl>
  40.  */
  41. class AnimalService
  42. {
  43.     const PDF_VOUCHER_FILE_PATH 'pdf_voucher';
  44.     /** @var ManagerRegistry */
  45.     private ManagerRegistry $entityManager;
  46.     /** @var AuthorizationCheckerInterface */
  47.     private $authorizationChecker;
  48.     /** @var FileRepository */
  49.     private $fileRepository;
  50.     /** @var AnimalRepository */
  51.     private $animalRepository;
  52.     /** @var Router */
  53.     private $router;
  54.     /** @var TokenStorage */
  55.     private $tokenStorage;
  56.     /** @var SortService */
  57.     private $sortService;
  58.     /** @var FormFactory */
  59.     private $formFactory;
  60.     /** @var AnimalSearchRepository */
  61.     private $animalSearchRepository;
  62.     /** @var UserService */
  63.     private $userService;
  64.     /** @var UserLoyaltyPointBidRepository */
  65.     private $userLoyaltyPointBidRepository;
  66.     /** @var bool */
  67.     private $vouchersSending;
  68.     /** @var array */
  69.     private $vouchersAddEmails;
  70.     /** @var DomPdf */
  71.     private $pdf;
  72.     /** @var RequestStack */
  73.     private $requestStack;
  74.     /**
  75.      * @var MailerInterface
  76.      */
  77.     private MailerInterface $mailer;
  78.     public function __construct(
  79.         UserService $userService,
  80.         SortService $sortService,
  81.         ManagerRegistry $entityManager,
  82.         TokenStorageInterface $tokenStorage,
  83.         UserLoyaltyPointBidRepository $userLoyaltyPointBidRepository,
  84.         AuthorizationCheckerInterface $authorizationChecker,
  85.         Environment $templating,
  86.         MailerInterface $mailer
  87.     ) {
  88.         $this->userService $userService;
  89.         $this->sortService $sortService;
  90.         $this->entityManager $entityManager;
  91.         $this->tokenStorage $tokenStorage;
  92.         $this->userLoyaltyPointBidRepository $userLoyaltyPointBidRepository;
  93.         $this->authorizationChecker $authorizationChecker;
  94.         $this->templating $templating;
  95.         $this->mailer $mailer;
  96.     }
  97.     /**
  98.      * @param array $params
  99.      * @return array
  100.      */
  101.     public function prepareSortURLs($params)
  102.     {
  103.         return $this->sortService->prepareSortURLs($params);
  104.     }
  105.     /**
  106.      * Add animal and clear pictures session
  107.      * @param Request $request
  108.      * @param Animal $animal
  109.      * @param Form $form
  110.      * @return void
  111.      */
  112.     public function addAnimal(Request $requestAnimal $animalForm $form)
  113.     {
  114.         $this->addPicturesFromSession($animal$request);
  115.         $this->setFeaturedImage($animal$form);
  116.         $this->entityManager->getManager()->persist($animal);
  117.         $this->entityManager->getManager()->flush();
  118.         $request->getSession()->set('animalPictures', new ArrayCollection());
  119.         $this->sentVoucher(
  120.             $animal,
  121.             [
  122.                 $animal->getTemporaryHouse()->getEmail()
  123.             ]
  124.         );
  125.         if ($this->vouchersSending) {
  126.             //When adding voucher is always sent
  127.             $animal->setIsVoucherDTSent(true);
  128.         }
  129.     }
  130.     private function sendInfoToTempHouse($animal)
  131.     {
  132.         $email = (new TemplatedEmail())
  133.             ->from('no-reply@adopciaki.pl')
  134.             ->to(new Address($animal->getTemporaryHouse()->getEmail()))
  135.             ->subject('Gratulacje')
  136.             ->htmlTemplate('front/animal/emails/publishedAnimal.html.twig')
  137.             ->context([
  138.                 'animal' => $animal,
  139.             ]);
  140.         try {
  141.             $this->mailer->send($email);
  142.         } catch (TransportExceptionInterface $e) {
  143.             return $e->getMessage();
  144.         }
  145.         return true;
  146.     }
  147.     /**
  148.      * @param Animal $animal
  149.      * @param array $email [email => name]
  150.      * @return bool
  151.      */
  152.     public function sentVoucher(Animal $animal, array $email)
  153.     {
  154.         if (!$this->vouchersSending) {
  155.             if (empty($email)) {
  156.                 $email = (new TemplatedEmail())
  157.                     ->from('no-reply@adopciaki.pl')
  158.                     ->to($this->vouchersAddEmails)
  159.                     ->subject('Nie udaÅ‚o siÄ™ wysÅ‚ać vouchera')
  160.                     ->htmlTemplate('admin/animal/no_voucher.html.twig')
  161.                     ->context([
  162.                         'animal' => $animal,
  163.                     ]);
  164.                 try {
  165.                     $this->mailer->send($email);
  166.                 } catch (TransportExceptionInterface $e) {
  167.                     return $e->getMessage();
  168.                 }
  169.             } else {
  170.                 $emails $email;
  171.                 $pdfFile $this->prepareVoucherPdf($animal);
  172.                 $email = (new TemplatedEmail())
  173.                     ->from('no-reply@adopciaki.pl')
  174.                     ->to(...$emails)
  175.                     ->addPart(new DataPart($pdfFile'voucher.pdf''application/pdf'))
  176.                     ->subject('Voucher!')
  177.                     ->htmlTemplate('front/animal/emails/pdf_voucher.html.twig')
  178.                     ->context([
  179.                         'animal' => $animal,
  180.                     ]);
  181.                 try {
  182.                     $this->mailer->send($email);
  183.                 } catch (TransportExceptionInterface $e) {
  184.                     return $e->getMessage();
  185.                 }
  186.             }
  187.         }
  188.         $this->vouchersSending true;
  189.         return true;
  190.     }
  191.     /**
  192.      * @param Animal $animal
  193.      * @param array $email [email => name]
  194.      * @return bool
  195.      */
  196.     public function sentTestVoucher(Animal $animal)
  197.     {
  198.         $testEmail 'develop.kostenko@gmail.com';
  199.         $pdfFile $this->prepareVoucherPdf($animal);
  200.         $email = (new TemplatedEmail())
  201.             ->from('no-reply@adopciaki.pl')
  202.             ->to($testEmail)
  203.             ->addPart(new DataPart($pdfFile'voucher.pdf''application/pdf'))
  204.             ->subject('Voucher!')
  205.             ->htmlTemplate('front/animal/emails/pdf_voucher.html.twig')
  206.             ->context([
  207.                 'animal' => $animal,
  208.             ]);
  209.         try {
  210.             $this->mailer->send($email);
  211.         } catch (TransportExceptionInterface $e) {
  212.             return $e->getMessage();
  213.         }
  214.         return true;
  215.     }
  216.     /**
  217.      * @param Animal $animal
  218.      * @return string path to PDF file
  219.      */
  220.     private function prepareVoucherPdf(Animal $animal)
  221.     {
  222.         $html $this->templating->render('admin/animal/voucher_pdf.html.twig', ['animal' => $animal]);
  223.         $pdf = new Dompdf();
  224.         $pdf->loadHtml($html);
  225.         $options = new \Dompdf\Options();
  226.         $options->set('isFontSubsettingEnabled'true);
  227.         $options->set('isRemoteEnabled'true);
  228.         $pdf->setOptions($options);
  229.         $customPaper = array(0,0,1050,1450);
  230.         $pdf->setPaper($customPaper);
  231.         $pdf->render();
  232.         return $pdf->output();
  233.     }
  234.     /**
  235.      * Add animal and clear pictures session
  236.      * @param Request $request
  237.      * @param Animal $animal
  238.      * @param Form $form
  239.      * @return void
  240.      */
  241.     public function editAnimal(Request $requestAnimal $animalForm $form)
  242.     {
  243.         //if adoption date is just set, send voucher
  244.         $animalDBData $this->entityManager->getManager()->getUnitOfWork()->getOriginalEntityData($animal);
  245.         if (empty($animalDBData['ownerEmail']) && !empty($animal->getOwnerEmail())) {
  246.             $this->sentVoucher($animal, [$animal->getOwnerEmail()]);
  247.             $animal->setIsVoucherDSSent(true);
  248.         }
  249.         $animal->setPictures(new ArrayCollection());
  250.         $this->addPicturesFromSession($animal$request);
  251.         $this->userService->changeAnimalOwnerRole($animal$form);
  252.         $this->setFeaturedImage($animal$form);
  253.         //if points not added check if post is published and add points
  254.         $pointsAdded $animal->getIsPointAdded();
  255.         if (!$pointsAdded) {
  256.             $isPublished $form->getData()->getIsPublished();
  257.             if ($isPublished) {
  258.                 $this->addLoyaltyPoints($animal);
  259.                 $form->getData()->setIsPointAdded(true);
  260.             }
  261.         }
  262.         //if is publishing
  263.         if (!$animalDBData['isPublished']) {
  264.             if ($form->getData()->getIsPublished()) {
  265.                 $this->sendInfoToTempHouse($animal);
  266.             }
  267.         }
  268.         $this->entityManager->getManager()->flush();
  269.         return true;
  270.     }
  271.     /**
  272.      * Return AdvancedSearchedForm with AnimalSearched entity
  273.      * @return Form
  274.      */
  275.     public function prepareAdvancedSearchedForm()
  276.     {
  277.         if ($this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
  278.             $isAuth true;
  279.         } else {
  280.             $isAuth false;
  281.         }
  282.         $user $this->tokenStorage->getToken()->getUser();
  283.         if ($isAuth) {
  284.             $animalSearch $this->animalSearchRepository->findOneBy(['user' => $user]);
  285.         }
  286.         if (empty($animalSearch)) {
  287.             $animalSearch = new AnimalSearch();
  288.             if ($isAuth) {
  289.                 $animalSearch->setUser($user);
  290.             }
  291.         }
  292.         $searchForm $this->formFactory->create(AnimalSearchForm::class, $animalSearch, ['isAuth' => $isAuth]);
  293.         return $searchForm;
  294.     }
  295.     /**
  296.      * @param Request $request
  297.      * @param array $search = []
  298.      * @param type $notPublished = false
  299.      * @param type $notOnFb = false
  300.      * @param type $isPublished = false
  301.      * @param type $adopted = null
  302.      * @param type $olx = null
  303.      * @return QueryBuilder
  304.      */
  305.     public function prepareIndexQB(
  306.         Request $request,
  307.         array $search,
  308.         $notPublished false,
  309.         $notOnFb false,
  310.         $isPublished false,
  311.         $adopted null,
  312.         $olx null
  313.     ) {
  314.         if (
  315.             $this->tokenStorage->getToken() &&
  316.             $this->authorizationChecker->isGranted('ROLE_HOME_TEMPORARY') &&
  317.             !$this->authorizationChecker->isGranted('ROLE_MODERATOR_HOME_TEMPORARY')
  318.         ) {
  319.             $homeTemporary $this->tokenStorage->getToken()->getUser();
  320.         } else {
  321.             $homeTemporary null;
  322.         }
  323.         $order $request->get('o''DESC');
  324.         $sortField $request->get('s''id');
  325.         $animalsQb $this->entityManager->getRepository(Animal::class)->findAllqb(
  326.             $sortField,
  327.             $order,
  328.             $homeTemporary,
  329.             $search,
  330.             $notPublished,
  331.             $notOnFb,
  332.             $isPublished,
  333.             $adopted,
  334.             $olx
  335.         );
  336.         return $animalsQb;
  337.     }
  338.     /**
  339.      * @param Request $request
  340.      * @param $homeTemporary
  341.      * @param $search
  342.      * @return QueryBuilder
  343.      */
  344.     public function prepareHomeTemporaryQB(Request $request$homeTemporary$search)
  345.     {
  346.         $order $request->get('o''DESC');
  347.         $sortField $request->get('s''id');
  348.         $animalsQb $this->entityManager->getRepository(Animal::class)->findAllqb(
  349.             $sortField,
  350.             $order,
  351.             $homeTemporary,
  352.             $search,
  353.             false,
  354.             false,
  355.             false
  356.         );
  357.         return $animalsQb;
  358.     }
  359.     /**
  360.      *
  361.      * Prepare advanced search criteria for frontend part
  362.      * @param AnimalSearch $animalSearch
  363.      * @return array
  364.      */
  365.     public function prepareAdvancedSearchCriteria(AnimalSearch $animalSearch)
  366.     {
  367.         $searchCriteria = [];
  368.         if (!empty($animalSearch->getSpecies())) {
  369.             $searchCriteria['species'] = $animalSearch->getSpecies()->getId();
  370.         }
  371.         $sex $animalSearch->getSex();
  372.         if ($sex->isEmpty() === false) {
  373.             $searchCriteria['sex'] = [];
  374.             foreach ($sex as $item) {
  375.                 $searchCriteria['sex'][] = $item->getId();
  376.             }
  377.         }
  378.         $age $animalSearch->getAge();
  379.         if ($age->isEmpty() === false) {
  380.             $searchCriteria['age'] = [];
  381.             foreach ($age as $item) {
  382.                 $searchCriteria['age'][] = $item;
  383.             }
  384.         }
  385.         $weight $animalSearch->getWeight();
  386.         if ($weight->isEmpty() === false) {
  387.             $searchCriteria['weight'] = [];
  388.             foreach ($weight as $item) {
  389.                 $searchCriteria['weight'][] = $item;
  390.             }
  391.         }
  392.         $size $animalSearch->getSize();
  393.         if ($size->isEmpty() === false) {
  394.             $searchCriteria['size'] = [];
  395.             foreach ($size as $item) {
  396.                 $searchCriteria['size'][] = $item;
  397.             }
  398.         }
  399.         if (!empty($animalSearch->getLifeStyle())) {
  400.             $searchCriteria['lifeStyle'] = $animalSearch->getLifeStyle()->getId();
  401.         }
  402.         $kidAcceptances $animalSearch->getKidAcceptances();
  403.         if ($kidAcceptances->isEmpty() === false) {
  404.             $searchCriteria['kidAcceptances'] = [];
  405.             foreach ($kidAcceptances as $kidAcceptance) {
  406.                 $searchCriteria['kidAcceptances'][] = $kidAcceptance;
  407.             }
  408.         }
  409.         $animalAcceptances $animalSearch->getAnimalAcceptances();
  410.         if ($animalAcceptances->isEmpty() === false) {
  411.             $searchCriteria['notAcceptings'] = [];
  412.             foreach ($animalAcceptances as $animalAcceptance) {
  413.                 $searchCriteria['notAcceptings'][] = $animalAcceptance;
  414.             }
  415.         }
  416.         $preferableLives $animalSearch->getPreferableLives();
  417.         if ($preferableLives->isEmpty() === false) {
  418.             $searchCriteria['preferableLives'] = [];
  419.             foreach ($preferableLives as $preferableLive) {
  420.                 $searchCriteria['preferableLives'][] = $preferableLive->getId();
  421.             }
  422.         }
  423.         if (!empty($animalSearch->getTimeCareNeeded())) {
  424.             $searchCriteria['timeCareNeeded'] = $animalSearch->getTimeCareNeeded()->getId();
  425.         }
  426.         $searchCriteria['isPublished'] = true;
  427.         return $searchCriteria;
  428.     }
  429.     /**
  430.      * Copy pictures from session to entity collection
  431.      * @param Animal $animal
  432.      * @param Request $request
  433.      * @return void
  434.      */
  435.     private function addPicturesFromSession(Animal $animalRequest $request)
  436.     {
  437.         $pictures $request->getSession()->get('animalPictures');
  438.         if (!$pictures->isEmpty()) {
  439.             foreach ($pictures as $picture) {
  440.                 if($picture) {
  441.                     $file $this->entityManager->getRepository(File::class)->find($picture->getId());
  442.                     $animal->addPicture($file);
  443.                 }
  444.             }
  445.         }
  446.         $request->getSession()->set('animalPictures', new ArrayCollection());
  447.     }
  448.     public function getSimilarAnimals(Animal $animal) {
  449.         $criteria = [
  450.             'species' => $animal->getSpecies(),
  451.             'sex' => $animal->getSex(),
  452.             'size' => $animal->getSize(),
  453.             'isPublished' => true,
  454.             'adoptionDate' => null
  455.         ];
  456.         return $this->entityManager->getRepository(Animal::class)->findBy($criteria, [], 6);
  457.     }
  458.     /**
  459.      * @param type $id
  460.      * @return Animal
  461.      */
  462.     public function getSingleAnimal($id$checkRole true)
  463.     {
  464.         $criteria = ['id' => $id];
  465.         if ($checkRole) {
  466.             if ($this->authorizationChecker->isGranted(
  467.                     'ROLE_HOME_TEMPORARY'
  468.                 ) && !$this->authorizationChecker->isGranted('ROLE_MODERATOR_HOME_TEMPORARY')) {
  469.                 $author $this->tokenStorage->getToken()->getUser();
  470.                 $criteria['temporaryHouse'] = $author;
  471.             }
  472.         }
  473.         $animal $this->entityManager->getRepository(Animal::class)->findOneBy($criteria);
  474.         if (empty($animal)) {
  475.             throw new Exception('Zwierzak '.$id.' nie istnieje');
  476.         }
  477.         return $animal;
  478.     }
  479.     /**
  480.      * @param Animal $animal
  481.      * @param Form $form
  482.      */
  483.     private function setFeaturedImage(Animal $animalForm $form)
  484.     {
  485.         $_featuredImageId $form->get('_featuredImageId')->getData();
  486.         if (!empty($_featuredImageId) && count($animal->getPictures()) > 0) {
  487.             //chose featured image from animal pictures collection
  488.             $properImage $animal->getPictures()->filter(
  489.                 function (File $file) use ($_featuredImageId) {
  490.                     if ($_featuredImageId == $file->getId()) {
  491.                         return true;
  492.                     } else {
  493.                         return false;
  494.                     }
  495.                 }
  496.             )->current();
  497.             $animal->setFeaturedImage($properImage);
  498.         }
  499.     }
  500.     /**
  501.      *
  502.      */
  503.     private function addLoyaltyPoints(Animal $animal)
  504.     {
  505.         $user $animal->getTemporaryHouse();
  506.         if ($user->hasRole('ROLE_HOME_TEMPORARY')) {
  507.             //different types for different species
  508.             $bidType UserLoyaltyPointBid::TYPE_ADDING_ANIMAL;
  509.             if ($animal->getSpecies()->getType() == Species::TYPE_DOG) {
  510.                 $bidType UserLoyaltyPointBid::TYPE_ADDING_ANIMAL_DOG;
  511.             }
  512.             $bid $this->userLoyaltyPointBidRepository->findOneBy(['type' => $bidType]);
  513.             $loyaltyPoint = new UserLoyaltyPoint();
  514.             $loyaltyPoint->setUser($user);
  515.             $loyaltyPoint->setName($bid->getName());
  516.             $loyaltyPoint->setType($bid->getType());
  517.             $loyaltyPoint->setValue($bid->getValue());
  518.             $user->addLoyaltyPoint($loyaltyPoint);
  519.             $this->entityManager->getManager()->flush();
  520.         }
  521.     }
  522. }