src/Controller/Profile/ProfileController.php line 56

Open in your IDE?
  1. <?php
  2. /*
  3.  * @since 1.0.0
  4.  * @copyright Copyright (C) 2020 ArtMedia. All rights reserved.
  5.  * @website http://artmedia.biz.pl
  6.  * @author Arkadiusz Tobiasz
  7.  * @email kontakt@artmedia.biz.pl
  8.  */
  9. namespace App\Controller\Profile;
  10. use App\Controller\AbstractController;
  11. use App\Entity\Profile;
  12. use App\Entity\ProfileType as ProfileTypeEntity;
  13. use App\Entity\Profile\Follow;
  14. use App\Entity\Profile\Note;
  15. use App\Entity\User\Notification;
  16. use App\Entity\Profile\Mute;
  17. use App\Form\Profile\ProfileType;
  18. use App\Repository\ProfileRepository;
  19. use Symfony\Component\HttpFoundation\RedirectResponse;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\Routing\Annotation\Route;
  22. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  23. use App\Settings\SettingsManager;
  24. use Symfony\Component\HttpFoundation\Response;
  25. use Symfony\Component\HttpFoundation\JsonResponse;
  26. use App\Form\Profile\SearchType;
  27. use App\Events\Core\MetaInfoAddEvent;
  28. use App\Form\Profile\ContactType;
  29. use App\Events\Core\MailAddEvent;
  30. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  31. use App\Events\User\ProfileCreatedEvent;
  32. use App\Events\User\ProfileBeforeDeleteEvent;
  33. use App\Events\User\ProfileWidgetAddEvent;
  34. use App\Events\Core\NotificationEvent;
  35. use App\Entity\Media\Credit;
  36. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  37. class ProfileController extends AbstractController
  38. {
  39.     /*
  40.     // translations from Twig/Profile
  41.         $this->translator->trans('Good news! {profile} is going to be in your area ({city}) from {start} to {end}', [], 'profile_feed');
  42.         $this->translator->trans('{profile} added a new image to their Portfolio', [], 'profile_feed');
  43.         $this->translator->trans('{profile} credited you on this image. Why don’t you add it to your Portfolio as well?', [], 'profile_feed');
  44.         $this->translator->trans('{profile} was credited in this image', [], 'profile_feed');
  45.         $this->translator->trans('(Directions)', [], 'profile_view');
  46.         $this->translator->trans('Manage links', [], 'profile_view');
  47.         $this->translator->trans('Send me email', [], 'profile_view');
  48.         $this->translator->trans('I\'m currently in {city}', [], 'profile_view');
  49.     */
  50.     /**
  51.      * @Route("/{slug}", name="profile", priority="-1", methods={"GET"})
  52.      */
  53.     public function profile(
  54.         Profile $profile
  55.         SettingsManager $settingsManager,
  56.         EventDispatcherInterface $eventDispatcher
  57.     ): Response
  58.     {
  59.         $sendMoney false;
  60.         $receiveTips false;
  61.         if ($profile->getCreatedBy() !== $this->getUser()) {
  62.             $configs $settingsManager->get([
  63.                 SettingsManager::MONEY_ENABLED,
  64.                 SettingsManager::MONEY_SEND_BETWEEN_USERS,
  65.                 SettingsManager::MONEY_RECEIVE_TIPS,
  66.                 SettingsManager::MONEY_GROUP_RECEIVE_TIPS,
  67.             ], true);
  68.             $sendMoney = ((bool) $configs[SettingsManager::MONEY_ENABLED] && (bool) $configs[SettingsManager::MONEY_SEND_BETWEEN_USERS]);
  69.             $receiveTips = ((bool) $configs[SettingsManager::MONEY_ENABLED] && (bool) $configs[SettingsManager::MONEY_RECEIVE_TIPS] && $configs[SettingsManager::MONEY_GROUP_RECEIVE_TIPS] && $profile->getUser()->getGroups([$configs[SettingsManager::MONEY_GROUP_RECEIVE_TIPS]])->count());
  70.         }
  71.         
  72.         $params = [
  73.             'sendMoney' => $sendMoney,
  74.             'receiveTips' => $receiveTips,
  75.         ];
  76.         $profileWidgetAddEvent = new ProfileWidgetAddEvent($profile$this->getUser());
  77.         $eventDispatcher->dispatch($profileWidgetAddEventProfileWidgetAddEvent::NAME);
  78.         return $this->renderTemplate('profile/view.html.twig', [
  79.             'profile' => $profile,
  80.             'params' => $params,
  81.             'widgets' => $profileWidgetAddEvent->getWidgets(),
  82.         ], [
  83.             '%name%' => $profile->getName(),
  84.             '%type%' => $profile->getProfileType()->getName(),
  85.         ]);
  86.     }
  87.     /**
  88.      * @Route("/{slug}/credits", name="profile_credits", priority="-1", methods={"GET", "POST"})
  89.      */
  90.     public function credits(
  91.         Request $request,
  92.         Profile $profile,
  93.         EventDispatcherInterface $eventDispatcher,
  94.         SettingsManager $settingsManager
  95.     ): Response
  96.     {
  97.         $user $this->getUser();
  98.         $owner $user && $user == $profile->getUser();
  99.         $profiles = [];
  100.         $viewersProfiles = [];
  101.         $commonProfiles = [];
  102.         $moreLink false;
  103.         $creditedProfiles $this->getDoctrine()->getRepository(Credit::class)->getWorkProfiles($profile);
  104.         if ($creditedProfiles) {
  105.             foreach ($creditedProfiles as $creditedProfile) {
  106.                 $profiles[$creditedProfile->getId()] = $creditedProfile;
  107.             }
  108.         }
  109.         if ($profiles) {
  110.             if ($user && !$owner) {
  111.                 if ($user->getProfiles()) {
  112.                     foreach ($user->getProfiles() as $viewerProfile) {
  113.                         if (isset($profiles[$viewerProfile->getId()])) {
  114.                             $viewersProfiles[] = $profiles[$viewerProfile->getId()];
  115.                             unset($profiles[$viewerProfile->getId()]);
  116.                         }
  117.                     }
  118.                 }
  119.                 $viewersCredits $this->getDoctrine()->getRepository(Profile::class)->getUserWorkProfiles($user);
  120.                 if ($viewersCredits) {
  121.                     foreach ($viewersCredits as $credit) {
  122.                         if (isset($profiles[$credit->getId()])) {
  123.                             $commonProfiles[] = $profiles[$credit->getId()];
  124.                             unset($profiles[$credit->getId()]);
  125.                         }
  126.                     }
  127.                 }
  128.             }
  129.         }
  130.         return $this->renderTemplate('profile/credits.html.twig', [
  131.             'profile' => $profile,
  132.             'profiles' => $profiles,
  133.             'viewersProfiles' => $viewersProfiles,
  134.             'commonProfiles' => $commonProfiles,
  135.         ], [
  136.             '%name%' => $profile->getName(),
  137.             '%type%' => $profile->getProfileType()->getName(),
  138.         ]);
  139.     }
  140.     /**
  141.      * @Route("/{slug}/contact", name="profile_contact", priority="-1", methods={"GET", "POST"})
  142.      */
  143.     public function contact(
  144.         Request $request,
  145.         Profile $profile,
  146.         EventDispatcherInterface $eventDispatcher,
  147.         SettingsManager $settingsManager
  148.     ): Response
  149.     {
  150.         if (!$profile->isEnableContact()) {
  151.             throw new AccessDeniedException($this->translator->trans("Profile don't allow contact via site", [], 'profile_contact'));
  152.         }
  153.         $configs $settingsManager->get([
  154.             SettingsManager::CORE_RECAPTCHA_PUBLIC_KEY,
  155.             SettingsManager::CORE_SITE_MAIL,
  156.         ], true);
  157.         $form $this->createForm(
  158.             ContactType::class,
  159.             null,
  160.             [
  161.                 'site_key' => $configs[SettingsManager::CORE_RECAPTCHA_PUBLIC_KEY],
  162.             ]
  163.         );
  164.         if ($this->getUser()) {
  165.             $form->get('email')->setData($this->getUser()->getEmail());
  166.         }
  167.         $form->handleRequest($request);
  168.         if($form->isSubmitted()) {
  169.             if ($form->isValid()) {
  170.                 $data $form->getData();
  171.                 $email $profile->getEmail() ? $profile->getEmail() : $profile->getUser()->getEmail();
  172.                 $mailAddEvent = new MailAddEvent(
  173.                     $configs[SettingsManager::CORE_SITE_MAIL],
  174.                     $email,
  175.                     $data['subject'],
  176.                     'profile/email/contact.html.twig',
  177.                     'profile/email/contact.txt.twig',
  178.                     [
  179.                         'email' => $data['email'],
  180.                         'user' => $this->getUser(),
  181.                         'message' => $data['text'],
  182.                         'profile' => $profile,
  183.                     ],
  184.                     [],
  185.                     true,
  186.                     1
  187.                 );
  188.                 $eventDispatcher->dispatch($mailAddEventMailAddEvent::NAME);
  189.                 $this->addFlash('success'$this->translator->trans('Message was successfully sended!', [], 'profile_contact'));
  190.                 return $this->redirectToRoute('profile', ['slug' => $profile->getSlug()]);
  191.             } else {
  192.                 $this->addFlash('error'$this->translator->trans('Could not send email because the form is invalid.', [], 'profile_contact'));
  193.             }
  194.         }
  195.         return $this->renderTemplate('profile/contact.html.twig', [
  196.             'profile' => $profile,
  197.             'form' => $form->createView(),
  198.         ], [
  199.             '%name%' => $profile->getName(),
  200.             '%type%' => $profile->getProfileType()->getName(),
  201.         ]);
  202.     }
  203.     /**
  204.      * @Route("/profiles", name="profile_index", methods={"GET"})
  205.      */
  206.     public function index(): Response
  207.     {
  208.         return $this->renderTemplate('profile/index.html.twig', [
  209.             'profiles' => $this->getDoctrine()->getRepository(Profile::class)->findByUser($this->getUser())
  210.         ]);
  211.     }
  212.     /**
  213.      * @Route("/profiles/new", name="profile_new", methods={"POST", "GET"})
  214.      * @Route("/profiles/new/{type}", name="profile_new_type", methods={"POST", "GET"})
  215.      * @IsGranted("ROLE_USER")
  216.      */
  217.     public function new(
  218.         Request $request
  219.         ?ProfileTypeEntity $type null,
  220.         SettingsManager $settingsManager,
  221.         EventDispatcherInterface $eventDispatcher
  222.     )
  223.     {
  224.         $configs $settingsManager->get([
  225.             SettingsManager::PROFILE_ENABLE_FOR,
  226.             SettingsManager::PROFILE_ENABLE_GROUPS,
  227.             SettingsManager::PROFILE_MAX_COUNT,
  228.         ], true);
  229.         $user $this->getUser();
  230.         if ($configs[SettingsManager::PROFILE_ENABLE_FOR] == 'groups') {
  231.             $groups = [];
  232.             foreach ($user->getGroups() as $group) {
  233.                 $groups[] = $group->getId();
  234.             }
  235.             if (!count(array_intersect($groupsjson_decode($configs[SettingsManager::PROFILE_ENABLE_GROUPS], true)))) {
  236.                 throw new AccessDeniedException($this->translator->trans('You can\'t create profiles', [], 'core'));
  237.             }
  238.         }
  239.         if ($configs[SettingsManager::PROFILE_MAX_COUNT]) {
  240.             $count $this->getDoctrine()->getRepository(Profile::class)->count(['user' => $user]);
  241.             if ($count >= (int)$configs[SettingsManager::PROFILE_MAX_COUNT]) {
  242.                 throw new AccessDeniedException($this->translator->trans('You can\'t create more than %count% profiles', [
  243.                     '%count%' => $count
  244.                 ], 'core'));
  245.             }
  246.         }
  247.         if (!$type) {
  248.             return $this->renderTemplate('profile/types.html.twig', [
  249.                 'types' => $this->getDoctrine()->getRepository(ProfileTypeEntity::class)->findAvailableForUser($user),
  250.             ]);
  251.         }
  252.         $class '\App\Entity';
  253.         if ($type->getEntity() != 'profile') {
  254.             $class .= '\Profile\Type';
  255.         }
  256.         $class .= '\\' ucfirst($type->getEntity());
  257.         $profile = new $class();
  258.         $profile->setProfileType($type);
  259.         $profile->setUser($this->getUser());
  260.         $profile->setEmail($this->getUser()->getEmail());
  261.         $form $this->createForm(ProfileType::class, $profile);
  262.         $form->handleRequest($request);
  263.         if ($form->isSubmitted()) {
  264.             if ($form->isValid()) {
  265.                 $em $this->getDoctrine()->getManager();
  266.                 $em->persist($profile);
  267.                 $em->flush();
  268.                 $profileCreatedEvent = new ProfileCreatedEvent($profile);
  269.                 $eventDispatcher->dispatch($profileCreatedEventProfileCreatedEvent::NAME);
  270.                 $this->addFlash('success'$this->translator->trans('New profile was successfully added!', [], 'profile'));
  271.                 return $this->redirectToRoute('profile_index');
  272.             } else {
  273.                 $this->addFlash('error'$this->translator->trans('Could not save data because the form is invalid.', [], 'profile'));
  274.             }
  275.         }
  276.         return $this->renderTemplate('profile/new.html.twig', [
  277.             'profile' => $profile,
  278.             'form' => $form->createView(),
  279.         ]);
  280.     }
  281.     /**
  282.      * @Route("/profiles/{id}", name="profile_edit", methods={"POST", "GET"})
  283.      */
  284.     public function edit(Request $requestProfile $profile)
  285.     {
  286.         $this->denyAccessUnlessGranted('ROLE_CREATOR'$profile);
  287.         $class '\App\Form\Profile\Edit' ucfirst($profile->getType()) . 'Type';
  288.         $form $this->createForm($class$profile);
  289.         if (!$profile->getEmail()) {
  290.             $form->get('email')->setData($this->getUser()->getEmail());
  291.         }
  292.         $form->handleRequest($request);
  293.         if ($form->isSubmitted()) {
  294.             if ($form->isValid()) {
  295.                 $this->getDoctrine()->getManager()->flush();
  296.                 $this->addFlash('success'$this->translator->trans('Profile was successfully updated!', [], 'profile'));
  297.                 return $this->redirectToRoute('profile_index');
  298.             } else {
  299.                 $this->addFlash('error'$this->translator->trans('Could not save data because the form is invalid.', [], 'profile'));
  300.             }
  301.         }
  302.         return $this->renderTemplate('profile/edit_' $profile->getType() . '.html.twig', [
  303.             'profile' => $profile,
  304.             'form' => $form->createView(),
  305.         ]);
  306.     }
  307.     /**
  308.      * @Route("/profiles/{id}", name="profile_delete", methods={"DELETE"})
  309.      * @param EntityManagerInterface $entityManager
  310.      * @param Profile $profile
  311.      * @return RedirectResponse
  312.      */
  313.     public function delete(
  314.         Profile $profile,
  315.         EventDispatcherInterface $eventDispatcher
  316.     ): RedirectResponse
  317.     {
  318.         $this->denyAccessUnlessGranted('ROLE_CREATOR'$profile);
  319.         $profileBeforeDeleteEvent = new ProfileBeforeDeleteEvent($profile);
  320.         $eventDispatcher->dispatch($profileBeforeDeleteEventProfileBeforeDeleteEvent::NAME);
  321.         $em $this->getDoctrine()->getManager();
  322.         $em->remove($profile);
  323.         $em->flush();
  324.         $this->addFlash('success'$this->translator->trans('Profile was successfully deleted!', [], 'profile'));
  325.         return $this->redirectToRoute('profile_index');
  326.     }
  327.     /**
  328.      * @Route("profiles-responder", methods={"POST", "GET"}, name="profile_responder")
  329.      */
  330.     public function responder(
  331.         Request $request
  332.     ): Response {
  333.         $type $request->get('type');
  334.         $result = [];
  335.         switch ($type) {
  336.             case 'profiles':
  337.                 $term $request->get('q');
  338.                 $profiles $this->getDoctrine()->getRepository(Profile::class)->findByTerm($term);
  339.                 if ($profiles) {
  340.                     foreach ($profiles as $profile) {
  341.                         $result[] = [
  342.                             'value' => $profile['id'],
  343.                             'text' => $profile['name'],
  344.                             'url' => $this->generateUrl('profile', ['slug' => $profile['slug']]),
  345.                         ];
  346.                     }
  347.                 }
  348.             break;
  349.             case 'note':
  350.                 $profile = (int)$request->request->get('profile');
  351.                 $content $request->request->get('content');
  352.                 $profile $this->getDoctrine()->getRepository(Profile::class)->find($profile);
  353.                 if ($profile) {
  354.                     $user $this->getUser();
  355.                     $note $this->getDoctrine()->getRepository(Note::class)->findOneBy([
  356.                         'profile' => $profile,
  357.                         'user' => $user,
  358.                     ]);
  359.                     if ($note) {
  360.                         $note->setContent($content);
  361.                         $this->getDoctrine()->getManager()->flush();
  362.                     } else {
  363.                         $note = new Note();
  364.                         $note->setProfile($profile);
  365.                         $note->setUser($user);
  366.                         $note->setContent($content);
  367.                         $em $this->getDoctrine()->getManager();
  368.                         $em->persist($note);
  369.                         $em->flush();
  370.                     }
  371.                     $result = [
  372.                         'response' => 'success',
  373.                         'message' => $this->translator->trans('Private note was saved!', [], 'profile_note')
  374.                     ];
  375.                 } else {
  376.                     $result = [
  377.                         'response' => 'error',
  378.                         'message' => $this->translator->trans('Private note wasn\'t saved!', [], 'profile_note')
  379.                     ];
  380.                 }
  381.             break;
  382.         }
  383.         return new JsonResponse($result);
  384.     }
  385.     /**
  386.      * @Route("/search/profiles", methods="GET|POST", name="profile_search")
  387.      */
  388.     public function search(
  389.         Request $request,
  390.         SettingsManager $settingsManager
  391.     ): Response {
  392.         $processed false;
  393.         $results = [];
  394.         $configs $settingsManager->get([
  395.             SettingsManager::PROFILE_SEARCH,
  396.             SettingsManager::PROFILE_SEARCH_GROUPS,
  397.             SettingsManager::PROFILE_SEARCH_RADIUS,
  398.             SettingsManager::PROFILE_SEARCH_RADIUS_GROUPS,
  399.         ], true);
  400.         $query $request->get('q'null);
  401.         if ($configs[SettingsManager::PROFILE_SEARCH] == 'groups') {
  402.             $groups = [];
  403.             if ($this->getUser()) {
  404.                 foreach ($this->getUser()->getGroups() as $group) {
  405.                     $groups[] = $group->getId();
  406.                 }
  407.             }
  408.             if (!count(array_intersect($groupsjson_decode($configs[SettingsManager::PROFILE_SEARCH_GROUPS], true)))) {
  409.                 throw new AccessDeniedException($this->translator->trans('You can\'t use advanced search', [], 'profile_search'));
  410.             }
  411.         }
  412.         $radius true;
  413.         if ($configs[SettingsManager::PROFILE_SEARCH_RADIUS] == 'groups') {
  414.             $groups = [];
  415.             if ($this->getUser()) {
  416.                 foreach ($this->getUser()->getGroups() as $group) {
  417.                     $groups[] = $group->getId();
  418.                 }
  419.             }
  420.             if (!count(array_intersect($groupsjson_decode($configs[SettingsManager::PROFILE_SEARCH_RADIUS_GROUPS], true)))) {
  421.                 $radius false;
  422.             }
  423.         }
  424.         $form $this->createForm(SearchType::class, null, [
  425.             'radius' => $radius,
  426.         ]);
  427.         if ($query) {
  428.             $form->get('name')->setData($query);
  429.         }
  430.         $form->handleRequest($request);
  431.         $location null;
  432.         $user $this->getUser();
  433.         if ($user && $user->getLocation()) {
  434.             // we get location from profile
  435.             $location $user->getLocation();
  436.         }
  437.         if ($form->isSubmitted() && $form->isValid()) {
  438.             $data $form->getData();
  439.             $data['coords'] = $location ?: false;
  440.             $results $this->getDoctrine()->getRepository(Profile::class)->search($data);
  441.             $processed true;
  442.         } elseif ($query) {
  443.             $results $this->getDoctrine()->getRepository(Profile::class)->search([
  444.                 'name' => $query,
  445.             ]);
  446.             $processed true;
  447.         }
  448.         return $this->renderTemplate('profile/search.html.twig', [
  449.             'form' => $form->createView(),
  450.             'radius' => $radius,
  451.             'results' => $results,
  452.             'processed' => $processed,
  453.             'location' => $location true false,
  454.         ]);
  455.     }
  456.     /**
  457.      * @Route("/action/{profile}/{type}", name="profile_action", methods={"POST", "GET"})
  458.      * @IsGranted("ROLE_USER")
  459.      */
  460.     public function action(Profile $profilestring $typeEventDispatcherInterface $eventDispatcher)
  461.     {
  462.         $user $this->getUser();
  463.         $em $this->getDoctrine()->getManager();
  464.         switch ($type) {
  465.             case Follow::ACTION:
  466.                 $em $this->getDoctrine()->getManager();
  467.                 $follow $this->getDoctrine()->getRepository(Follow::class)->findOneBy([
  468.                     'profile' => $profile,
  469.                     'user' => $user,
  470.                 ]);
  471.                 if ($follow) {
  472.                     $em->remove($follow);
  473.                     $this->addFlash('success'$this->translator->trans('You unfollowed this profile', [], 'profile'));
  474.                 } else {
  475.                     $follow = new Follow($profile$user);
  476.                     $em->persist($follow);
  477.                     $this->addFlash('success'$this->translator->trans('You now follow this profile', [], 'profile'));
  478.                     if ($user != $profile->getUser()) {
  479.                         $notification $this->getDoctrine()->getRepository(Notification::class)->findOneBy([
  480.                             'name' => Follow::NOTIFICATION,
  481.                             'user' => $profile->getUser(),
  482.                         ]);
  483.                         if (!$notification || ($notification && $notification->isActive())) {
  484.                             $notificationEvent = new NotificationEvent(
  485.                                 Follow::NOTIFICATION,
  486.                                 $profile->getUser(),
  487.                                 $this->translator->trans('{name} now follow your profile {profile}', [
  488.                                     '{name}' => $user->getDisplayName(),
  489.                                     '{profile}' => $profile->getName(),
  490.                                 ], 'email_notification'),
  491.                                 'profile/email/follow_notification',
  492.                                 [
  493.                                     'name' => $user->getDisplayName(),
  494.                                     'profile' => $profile->getName(),
  495.                                     'user' => $profile->getUser()->getDisplayName(),
  496.                                 ]
  497.                             );
  498.                             $eventDispatcher->dispatch($notificationEventNotificationEvent::NAME);
  499.                         }
  500.                     }
  501.                 }
  502.             break;
  503.             case Mute::ACTION:
  504.                 $em $this->getDoctrine()->getManager();
  505.                 $mute $this->getDoctrine()->getRepository(Mute::class)->findOneBy([
  506.                     'profile' => $profile,
  507.                     'user' => $user,
  508.                 ]);
  509.                 if ($mute) {
  510.                     $em->remove($mute);
  511.                     $this->addFlash('success'$this->translator->trans('You unmuted this profile', [], 'profile'));
  512.                 } else {
  513.                     $mute = new Mute($profile$user);
  514.                     $em->persist($mute);
  515.                     $this->addFlash('success'$this->translator->trans('You now muted this profile', [], 'profile'));
  516.                 }
  517.             break;
  518.             default:
  519.                 $this->addFlash('danger'$this->translator->trans('Error: Unrecognized action!', [], 'profile'));
  520.             break;
  521.         }
  522.         $em->flush();
  523.         return $this->redirectToRoute('profile', ['slug' => $profile->getSlug()]);
  524.     }
  525. }