src/Aqarmap/Bundle/DiscussionBundle/Controller/DiscussionController.php line 122

Open in your IDE?
  1. <?php
  2. namespace Aqarmap\Bundle\DiscussionBundle\Controller;
  3. use App\Exception\BadRequestHttpException;
  4. use Aqarmap\Bundle\DiscussionBundle\Constant\DiscussionSearchTabs;
  5. use Aqarmap\Bundle\DiscussionBundle\Constant\DiscussionStatus;
  6. use Aqarmap\Bundle\DiscussionBundle\Entity\Comment;
  7. use Aqarmap\Bundle\DiscussionBundle\Entity\Discussion;
  8. use Aqarmap\Bundle\DiscussionBundle\Form\CommentType;
  9. use Aqarmap\Bundle\DiscussionBundle\Form\DiscussionSearchType;
  10. use Aqarmap\Bundle\DiscussionBundle\Form\DiscussionType;
  11. use Aqarmap\Bundle\DiscussionBundle\Repository\CategoryRepository;
  12. use Aqarmap\Bundle\DiscussionBundle\Repository\CommentRepository;
  13. use Aqarmap\Bundle\DiscussionBundle\Repository\DiscussionRepository;
  14. use Aqarmap\Bundle\DiscussionBundle\Service\DiscussionManager;
  15. use Aqarmap\Bundle\DiscussionBundle\Service\WordpressManager;
  16. use Aqarmap\Bundle\ListingBundle\Entity\Location;
  17. use Aqarmap\Bundle\ListingBundle\Form\QuickLeadType;
  18. use Aqarmap\Bundle\ListingBundle\Repository\ListingRepository;
  19. use Aqarmap\Bundle\ListingBundle\Repository\LocationRepository;
  20. use Aqarmap\Bundle\ListingBundle\Repository\SectionRepository;
  21. use Aqarmap\Bundle\ListingBundle\Service\LocationManager;
  22. use Aqarmap\Bundle\ListingBundle\Service\SupplyDemandManager;
  23. use Aqarmap\Bundle\MainBundle\Form\ConfirmFormType;
  24. use Aqarmap\Bundle\NotificationBundle\DatabaseNotification;
  25. use Aqarmap\Bundle\UserBundle\Entity\User;
  26. use Aqarmap\Bundle\UserBundle\Form\QuickRegistrationFormType;
  27. use Aqarmap\Bundle\UserBundle\Repository\UserInterestRepository;
  28. use Aqarmap\Bundle\UserBundle\Services\UserInterestManager;
  29. use Aqarmap\Bundle\UserBundle\Services\UserManager;
  30. use Doctrine\ORM\EntityManagerInterface;
  31. use Knp\Component\Pager\PaginatorInterface;
  32. use Predis\Client;
  33. use Psr\Log\LoggerInterface;
  34. use Psr\Log\LogLevel;
  35. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  36. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  37. use Symfony\Component\Form\FormInterface;
  38. use Symfony\Component\HttpFoundation\RedirectResponse;
  39. use Symfony\Component\HttpFoundation\Request;
  40. use Symfony\Component\HttpFoundation\Response;
  41. use Symfony\Component\Routing\Annotation\Route;
  42. use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
  43. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  44. use Symfony\Contracts\Translation\TranslatorInterface;
  45. /**
  46.  * Discussion controller.
  47.  */
  48. class DiscussionController extends AbstractController
  49. {
  50.     /**
  51.      * @var DiscussionManager
  52.      */
  53.     private $discussionManager;
  54.     private $wordpressManager;
  55.     private $userInterestRepository;
  56.     private $userInterestManager;
  57.     private $em;
  58.     private $locationRepository;
  59.     private $discussionRepository;
  60.     private $listingRepository;
  61.     private $sectionRepository;
  62.     private $categoryRepository;
  63.     private $commentRepository;
  64.     private $supplyDemandManager;
  65.     private $parameterBag;
  66.     private $translator;
  67.     private $paginator;
  68.     private UserManager $userManager;
  69.     public function __construct(
  70.         DiscussionManager $discussionManager,
  71.         WordpressManager $wordpressManager,
  72.         UserInterestRepository $userInterestRepository,
  73.         UserInterestManager $userInterestManager,
  74.         EntityManagerInterface $em,
  75.         Client $redisClient,
  76.         LocationRepository $locationRepository,
  77.         DiscussionRepository $discussionRepository,
  78.         ListingRepository $listingRepository,
  79.         SectionRepository $sectionRepository,
  80.         CategoryRepository $categoryRepository,
  81.         TokenStorageInterface $tokenStorage,
  82.         SupplyDemandManager $supplyDemandManager,
  83.         ParameterBagInterface $parameterBag,
  84.         TranslatorInterface $translator,
  85.         PaginatorInterface $paginator,
  86.         UserManager $userManager,
  87.         CommentRepository $commentRepository,
  88.         EventDispatcherInterface $eventDispatcher,
  89.         LoggerInterface $logger
  90.     ) {
  91.         $this->discussionManager $discussionManager;
  92.         $this->wordpressManager $wordpressManager;
  93.         $this->userInterestRepository $userInterestRepository;
  94.         $this->userInterestManager $userInterestManager;
  95.         $this->em $em;
  96.         $this->locationRepository $locationRepository;
  97.         $this->discussionRepository $discussionRepository;
  98.         $this->listingRepository $listingRepository;
  99.         $this->sectionRepository $sectionRepository;
  100.         $this->categoryRepository $categoryRepository;
  101.         $this->supplyDemandManager $supplyDemandManager;
  102.         $this->parameterBag $parameterBag;
  103.         $this->translator $translator;
  104.         $this->paginator $paginator;
  105.         $this->userManager $userManager;
  106.         $this->commentRepository $commentRepository;
  107.     }
  108.     /**
  109.      * Lists all Discussion entities.
  110.      *
  111.      * @Route("ask-neighbors/", name="neighborhood_discussion_list", methods={"GET"})
  112.      * @Route("discussion/", name="discussion_list", methods={"GET"})
  113.      * @Route("question/", name="neighborhood_question_discussion_list", methods={"GET"})
  114.      */
  115.     public function discussions(Request $requestLocationManager $locationManager)
  116.     {
  117.         $response $this->removePageQuery($request);
  118.         if ($response instanceof RedirectResponse) {
  119.             return $response;
  120.         }
  121.         if ('discussion_list' == $request->get('_route')) {
  122.             return $this->redirect(
  123.                 $this->generateUrl('neighborhood_discussion_list'$request->query->all()),
  124.                 Response::HTTP_MOVED_PERMANENTLY
  125.             );
  126.         }
  127.         $this->getDoctrine()->getManager();
  128.         $user $this->container->get('security.token_storage')->getToken()->getUser();
  129.         $userInterests = [];
  130.         if ($user instanceof User) {
  131.             $userInterests $this->userInterestRepository->getUserInterests($user4)->getQuery()->getResult();
  132.         }
  133.         $userInterests = !empty($userInterests) ? $userInterests : [$this->userInterestManager->getListingsMayBeInterested()];
  134.         $interestsListings $this->discussionManager->getInterestsListings($userInterests);
  135.         $location $request->query->get('location') ? $this->locationRepository->find($request->query->get('location')) : null;
  136.         $discussion = new Discussion();
  137.         $discussionForm $form $this->createForm(DiscussionType::class, $discussion, [
  138.             'action' => $this->generateUrl('neighborhood_discussion_create'),
  139.             'method' => 'POST',
  140.             'flatLocations' => [],
  141.             'selectedLocation' => $location ? [$location->getTitle() => $location->getId()] : [],
  142.             'selectedLocationId' => $location $location->getId() : null,
  143.         ]);
  144.         $discussionSearchForm $form $this->createForm(DiscussionSearchType::class, $discussion, [
  145.             'action' => $this->generateUrl('neighborhood_discussion_list'),
  146.             'method' => 'GET',
  147.             'flatLocations' => serialize($locationManager->getFlatByMaxLevel(2)),
  148.             'selectedLocation' => $location ? [$location->getTitle() => $location->getId()] : [],
  149.             'selectedLocationId' => $location $location->getId() : null,
  150.         ]);
  151.         $locationChildren = [];
  152.         if ($location) {
  153.             $locationChildren $this->supplyDemandManager->getLocationChildren($location);
  154.         }
  155.         $criteria = [
  156.             'status' => DiscussionStatus::APPROVED,
  157.             'location' => $locationChildren,
  158.             'category' => $request->query->get('category'),
  159.             'tab' => $request->query->get('tab'DiscussionSearchTabs::TRENDING),
  160.             'sort' => 'commentsCounter',
  161.         ];
  162.         $discussions $this->discussionRepository->filter($criteria);
  163.         if (
  164.             $request->query->get('submitted')
  165.             && DiscussionSearchTabs::TRENDING == $request->query->get('tab')
  166.             && empty($discussions)
  167.         ) {
  168.             $criteria $request->query->all();
  169.             $criteria['tab'] = DiscussionSearchTabs::ALLQUESTIONS;
  170.             return $this->redirectToRoute('neighborhood_discussion_list'$criteria);
  171.         }
  172.         $discussions $this->paginator->paginate(
  173.             $discussions,
  174.             $request->query->get('page'1),
  175.             10
  176.         );
  177.         $latestLocationListings = [];
  178.         if ($location) {
  179.             $latestLocationListings $this->listingRepository->getLatestListings(4$this->supplyDemandManager->getLocationChildren($location))->getQuery()->getResult();
  180.         }
  181.         return $this->render('@AqarmapDiscussionBundle/Discussion/discussions.html.twig', [
  182.             'subLinksSections' => $this->sectionRepository->getSearchableSection(),
  183.             'discussionForm' => $discussionForm->createView(),
  184.             'responsiveDiscussionForm' => $discussionForm->createView(),
  185.             'discussionSearchForm' => $discussionSearchForm->createView(),
  186.             'discussions' => $discussions,
  187.             'interestsListings' => $interestsListings,
  188.             'quick_registration_form' => $this->createForm(QuickRegistrationFormType::class, null, [
  189.                 'method' => 'POST',
  190.                 'action' => $this->generateUrl('aqarmap_user_quick_registration'),
  191.             ])->createView(),
  192.             'location' => $location,
  193.             'latestLocationListings' => $latestLocationListings,
  194.             'popularArticles' => json_decode(
  195.                 $this->wordpressManager->getCachedPosts($request->getLocale(), 4),
  196.                 true
  197.             ),
  198.             'aqarmap_advice_link' => $this->parameterBag->get('aqarmap_advice_url'),
  199.             'form' => $this->createQuickLeadForm()->createView(),
  200.             'metaDescriptionContent' => $this->discussionManager->concatTitles($discussions->getItems()),
  201.             'selectedCategory' => $request->get('category') ?
  202.                 $this->categoryRepository->find($request->get('category')) : null,
  203.         ]);
  204.     }
  205.     /**
  206.      * Creates a new Discussion entity.
  207.      *
  208.      * @Route("question/create/", name="neighborhood_discussion_create", methods={"POST"})
  209.      */
  210.     public function create(Request $requestLocationManager $locationManager): RedirectResponse
  211.     {
  212.         $entity = new Discussion();
  213.         $form $this->createForm(DiscussionType::class, $entity, [
  214.             'action' => $this->generateUrl('neighborhood_discussion_create'),
  215.             'method' => 'POST',
  216.             'flatLocations' => serialize($locationManager->getLocationsArrayWithParent($request->getLocale())['searchable']) ?? serialize([]),
  217.         ]);
  218.         $location null;
  219.         if ($locationId $request->request->get('location')) {
  220.             $location $this->locationRepository->find($locationId);
  221.             $request->request->set('location'null);
  222.             $form->get('location')->setData(null);
  223.         }
  224.         $form->handleRequest($request);
  225.         if ($form->isValid() && $this->getUser()) {
  226.             $entity->setLocation($location);
  227.             $entity->setUser($this->getUser());
  228.             $this->em->persist($entity);
  229.             $this->em->flush();
  230.             $this->discussionManager->createSubscriber($this->getUser(), $entity);
  231.             $this->get('session')->getFlashBag()->add(
  232.                 'success',
  233.                 $this->translator->trans('neighborhoods.discussion.success_message')
  234.             );
  235.         }
  236.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  237.     }
  238.     /**
  239.      * Lists all Discussion comments.
  240.      *
  241.      * @Route("ask-neighbors/{discussion}/answers/", name="neighborhood_discussion_comments", methods={"GET"})
  242.      * @Route("discussion/{discussion}/comments/", name="discussion_comments", methods={"GET"})
  243.      * @Route("question/{discussion}/comments/", name="neighborhood_question_discussion_comments", methods={"GET"})
  244.      */
  245.     public function discussionComments(Request $requestDatabaseNotification $databaseNotificationLoggerInterface $logger, ?Discussion $discussion null)
  246.     {
  247.         if ($request->get('notification')) {
  248.             try {
  249.                 $databaseNotification->markOneAsRead($request->get('notification'));
  250.             } catch (\Exception $exception) {
  251.                 $logger->log(LogLevel::ERROR$exception->getMessage());
  252.             }
  253.         }
  254.         if (!$discussion) {
  255.             return $this->redirect($this->generateUrl('neighborhood_discussion_list'), Response::HTTP_MOVED_PERMANENTLY);
  256.         }
  257.         if ($discussion->getDeletedAt()) {
  258.             if ($discussion->getUser() != $this->getUser()) {
  259.                 return $this->redirectWhenDiscussionDeleted($discussion);
  260.             }
  261.             $this->get('session')->getFlashBag()->add(
  262.                 'warning',
  263.                 $this->translator->trans('neighborhoods.discussion.already_deleted')
  264.             );
  265.         } elseif (DiscussionStatus::PENDING == $discussion->getStatus()) {
  266.             $this->get('session')->getFlashBag()->add(
  267.                 'warning',
  268.                 $this->translator->trans('neighborhoods.discussion.pending_approval')
  269.             );
  270.         }
  271.         if (\in_array($request->get('_route'), [
  272.             'neighborhood_question_discussion_comments',
  273.             'discussion_comments',
  274.         ])) {
  275.             return $this->redirect(
  276.                 $this->generateUrl(
  277.                     'neighborhood_discussion_comments',
  278.                     array_merge(['discussion' => $discussion->getId()], $request->query->all())
  279.                 ),
  280.                 Response::HTTP_MOVED_PERMANENTLY
  281.             );
  282.         }
  283.         $comment = new Comment();
  284.         $commentForm $this->createForm(CommentType::class, $comment, [
  285.             'action' => $this->generateUrl('neighborhood_comment_create', ['discussion' => $discussion->getId()]),
  286.             'method' => 'POST',
  287.         ]);
  288.         $user $this->container->get('security.token_storage')->getToken()->getUser();
  289.         $userInterests = [];
  290.         if ($user instanceof User) {
  291.             $userInterests $this->userInterestRepository->getUserInterests($user4)->getQuery()->getResult();
  292.         }
  293.         $userInterests[] = $this->userInterestManager->getListingsMayBeInterested($discussion->getLocation());
  294.         $interestsListings $this->discussionManager->getInterestsListings($userInterests);
  295.         return $this->render('@AqarmapDiscussionBundle/Discussion/discussionComments.html.twig', [
  296.             'commentForm' => $commentForm->createView(),
  297.             'discussion' => $discussion,
  298.             'discussionComments' => $this->commentRepository->getCommentsWithLikes($discussion),
  299.             'interestsListings' => $interestsListings,
  300.             'quick_registration_form' => $this->createForm(QuickRegistrationFormType::class, null, [
  301.                 'method' => 'POST',
  302.                 'action' => $this->generateUrl('aqarmap_user_quick_registration'),
  303.             ])->createView(),
  304.             'popularArticles' => json_decode(
  305.                 $this->wordpressManager->getCachedPosts($request->getLocale(), 4),
  306.                 true
  307.             ),
  308.             'aqarmap_advice_link' => $this->parameterBag->get('aqarmap_advice_url'),
  309.         ]);
  310.     }
  311.     /**
  312.      * Add Discussion Subscribers.
  313.      *
  314.      * @Route("question/add/subscriber/{discussion}/", name="neighborhood_discussion_add_subscriber")
  315.      */
  316.     public function addDiscussionSubscriber(Discussion $discussionRequest $request): RedirectResponse
  317.     {
  318.         $user $this->getUser();
  319.         $this->discussionManager->createSubscriber($user$discussion);
  320.         $this->get('session')->getFlashBag()->add(
  321.             'success',
  322.             $this->translator->trans('neighborhoods.discussion.subscriber_success_message')
  323.         );
  324.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  325.     }
  326.     /**
  327.      * Remove Discussion Subscribers.
  328.      *
  329.      * @Route("question/remove/subscriber/{discussion}/", name="neighborhood_discussion_remove_subscriber")
  330.      */
  331.     public function unsetDiscussionSubscriber(Discussion $discussionRequest $request): RedirectResponse
  332.     {
  333.         $this->discussionManager->unsetSubscriber($this->getUser(), $discussion);
  334.         $this->get('session')->getFlashBag()->add(
  335.             'success',
  336.             $this->container->get('translator')->trans('neighborhoods.discussion.subscriber_unset_message')
  337.         );
  338.         return $this->redirect($request->headers->get('referer') ?: $this->generateUrl('homepage'));
  339.     }
  340.     /**
  341.      * @Route("question/un-subscribe/{user}/{discussion}/", name="neighborhood_discussion_mail_remove_subscriber")
  342.      *
  343.      * @return RedirectResponse
  344.      *
  345.      * @throws BadRequestHttpException
  346.      */
  347.     public function unsubscribeConfirm(User $userDiscussion $discussionRequest $request)
  348.     {
  349.         /* Valid User Md5 valid */
  350.         if (md5($user->getId()).$this->parameterBag->get('secret') !== $request->query->get('token')) {
  351.             throw new BadRequestHttpException('Permission Denied !');
  352.         }
  353.         // Create confirmation form (button)
  354.         $form $this->createForm(ConfirmFormType::class, null, [
  355.             'method' => 'POST',
  356.             'action' => $this->generateUrl(
  357.                 'neighborhood_discussion_mail_remove_subscriber',
  358.                 ['discussion' => $discussion->getId(), 'user' => $user->getId(), 'token' => $request->query->get('token')]
  359.             ),
  360.         ]);
  361.         $form->handleRequest($request);
  362.         if ($form->isSubmitted() && $form->isValid()) {
  363.             if ($form->get('confirm')->isClicked()) {
  364.                 $this->discussionManager->unsetSubscriber($user$discussion);
  365.                 $this->get('session')->getFlashBag()->add(
  366.                     'success',
  367.                     $this->translator->trans('neighborhoods.discussion.subscriber_unset_message')
  368.                 );
  369.                 return $this->redirect($this->generateUrl('homepage'));
  370.             }
  371.         }
  372.         return $this->render('@AqarmapDiscussionBundle/Discussion/unsubscribeConfirm.html.twig', [
  373.             'form' => $form->createView(),
  374.             'discussion' => $discussion,
  375.         ]);
  376.     }
  377.     /**
  378.      * Edit Comment entity.
  379.      *
  380.      * @Route("question/{discussion}/edit", name="neighborhood_discussion_edit")
  381.      *
  382.      * @return array|RedirectResponse
  383.      */
  384.     public function edit(Request $requestDiscussion $discussionLocationManager $locationManager)
  385.     {
  386.         $form $this->createForm(DiscussionType::class, $discussion, [
  387.             'action' => $this->generateUrl('neighborhood_discussion_edit', [
  388.                 'discussion' => $discussion->getId(),
  389.             ]),
  390.             'method' => 'POST',
  391.             'flatLocations' => serialize($locationManager->getLocationsArrayWithParent($request->getLocale())['searchable']) ?? serialize([]),
  392.         ]);
  393.         $form->handleRequest($request);
  394.         if ($form->isSubmitted() && $form->isValid()) {
  395.             $em $this->getDoctrine()->getManager();
  396.             $discussion->setStatus(DiscussionStatus::PENDING);
  397.             $em->persist($discussion);
  398.             $em->flush();
  399.             $this->get('session')->getFlashBag()->add(
  400.                 'success',
  401.                 $this->translator->trans('neighborhoods.comment.edit_success_message')
  402.             );
  403.             return $this->redirect($this->generateUrl('neighborhood_discussion_comments', ['discussion' => $discussion->getId()]));
  404.         }
  405.         return $this->render('@AqarmapDiscussionBundle/Discussion/edit.html.twig', [
  406.             'form' => $form->createView(),
  407.             'discussion' => $discussion,
  408.         ]);
  409.     }
  410.     /**
  411.      * Delete Discussion.
  412.      *
  413.      * @Route("question/{discussion}/delete", name="discussion_delete")
  414.      *
  415.      * @return RedirectResponse|Response
  416.      */
  417.     public function delete(Discussion $discussion): RedirectResponse
  418.     {
  419.         if (!$discussion) {
  420.             throw $this->createNotFoundException('The Discussion does not exist');
  421.         }
  422.         $this->discussionManager->remove($discussion);
  423.         $this->get('session')->getFlashBag()->add(
  424.             'success',
  425.             $this->translator->trans('neighborhoods.discussion.delete_success_message')
  426.         );
  427.         return $this->redirect($this->generateUrl('neighborhood_discussion_list'));
  428.     }
  429.     /**
  430.      * Redirect when the discssuion is deleted.
  431.      *
  432.      * @return RedirectResponse
  433.      */
  434.     public function redirectWhenDiscussionDeleted(?Discussion $discussion null)
  435.     {
  436.         $criteria = [];
  437.         if ($discussion) {
  438.             $location $discussion->getLocation();
  439.             if ($location) {
  440.                 $criteria['location'] = $location->getId();
  441.             }
  442.             $category $discussion->getCategory();
  443.             if ($category) {
  444.                 $criteria['category'] = $category->getId();
  445.             }
  446.         }
  447.         return $this->redirect(
  448.             $this->generateUrl('neighborhood_discussion_list'$criteria),
  449.             Response::HTTP_MOVED_PERMANENTLY
  450.         );
  451.     }
  452.     /**
  453.      * Create Quick Lead Form.
  454.      */
  455.     private function createQuickLeadForm(): FormInterface
  456.     {
  457.         return $this->createForm(
  458.             QuickLeadType::class,
  459.             null,
  460.             [
  461.                 'action' => $this->generateUrl('add_quick_lead'),
  462.                 'method' => 'POST',
  463.             ]
  464.         );
  465.     }
  466.     /**
  467.      * @Route("unsubscribe-ask-neighbors/{token}/{location}", requirements={"id" = "\d+"}, name="aqarmap_discussion_unsubscribe", methods={"GET"})
  468.      */
  469.     public function unsubscribe(Request $request, ?Location $location null): RedirectResponse
  470.     {
  471.         $user $this->userManager->findEncryptedBy($request->get('token'));
  472.         if (!$user) {
  473.             throw new \Exception('User Not Found!');
  474.         }
  475.         $criteria = [
  476.             'user' => $user,
  477.         ];
  478.         if ($location) {
  479.             $criteria['location'] = $location;
  480.         }
  481.         $this->userInterestManager->removeBy($criteria);
  482.         $this->get('session')->getFlashBag()->add(
  483.             'success',
  484.             $this->translator
  485.                 ->trans($location 'neighborhoods.unsubscribe_from_successeded' 'neighborhoods.unsubscribe_all_successeded', ['%location%' => $location])
  486.         );
  487.         return $this->redirect($this->generateUrl('homepage'));
  488.     }
  489.     /**
  490.      * Remove the page query if equals one.
  491.      *
  492.      * @return RedirectResponse|void
  493.      */
  494.     private function removePageQuery(Request $request)
  495.     {
  496.         if ($request->query->get('page') && == $request->query->get('page')) {
  497.             $request->query->remove('page');
  498.             return $this->redirect(
  499.                 $this->generateUrl(
  500.                     $request->get('_route'),
  501.                     $request->query->all()
  502.                 ),
  503.                 Response::HTTP_MOVED_PERMANENTLY
  504.             );
  505.         }
  506.     }
  507. }