src/Controller/Account/ProfileEditingController.php line 55

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by simpson <simpsonwork@gmail.com>
  4.  * Date: 2019-04-29
  5.  * Time: 18:00
  6.  */
  7. namespace App\Controller\Account;
  8. use AngelGamez\TranslatableBundle\Entity\TranslatableValue;
  9. use App\Entity\Location\City;
  10. use App\Entity\Profile\Photo;
  11. use App\Entity\Profile\Profile;
  12. use App\Entity\Profile\Selfie;
  13. use App\Entity\Profile\Video;
  14. use App\Entity\User;
  15. use App\Event\Profile\ProfileDataChanged;
  16. use App\Form\CreateOrEditProfileForm;
  17. use App\Service\ApprovalService;
  18. use App\Service\Features;
  19. use App\Service\ModerationService;
  20. use App\Service\ProfilePersister;
  21. use Doctrine\ORM\EntityManagerInterface;
  22. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  23. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  24. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  25. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  26. use Symfony\Component\Form\FormInterface;
  27. use Symfony\Component\HttpFoundation\Request;
  28. use Symfony\Component\HttpFoundation\Response;
  29. use Symfony\Component\Routing\Annotation\Route;
  30. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  31. class ProfileEditingController extends AbstractController
  32. {
  33.     const LEGACY_MASSEUR_PRECHECK_PARAM 'massagers';
  34.     private bool $featureHasProfilesTranslation;
  35.     public function __construct(
  36.         private EntityManagerInterface $entityManager,
  37.         private Features $features
  38.     )
  39.     {
  40.         $this->featureHasProfilesTranslation $features->has_translations() && $features->has_profile_translations();
  41.     }
  42.     /**
  43.      * @throws \Exception
  44.      */
  45.     #[Route(path'/add'name'account.profile_editing.create')]
  46.     #[Route(path'/add/masseur'name'account.profile_editing.create_masseur')]
  47.     #[Route(path'/edit/{profile}'name'account.profile_editing.edit')]
  48.     #[IsGranted('ROLE_ADVERTISER')]
  49.     public function editForm(Request $requestProfilePersister $profilePersisterApprovalService $approvalService,
  50.         ModerationService $moderationServiceProfile $profile null,
  51.         EventDispatcherInterface $eventDispatcherParameterBagInterface $parameterBag): Response
  52.     {
  53.         //если профиль деактивирован
  54.         if ('account.profile_editing.edit' == $request->get('_route') && null == $profile) {
  55.             throw $this->createNotFoundException();
  56.         }
  57.         //если ожидает модерации
  58.         if (true === $this->features->hard_moderation() && $profile && $moderationService->isProfileWaitingModeration($profile)) {
  59.             throw new AccessDeniedException('You cannot access profile editing while it is on moderation');
  60.         }
  61.         /** @var User $account */
  62.         $account $this->getUser();
  63.         if (null !== $profile && !$profile->isOwnedBy($account)) {
  64.             throw $this->createNotFoundException();
  65.         }
  66.         $precheckMasseur $request->query->has(self::LEGACY_MASSEUR_PRECHECK_PARAM)
  67.             || 'account.profile_editing.create_masseur' === $request->attributes->get('_route');
  68.         $form $this->createProfileForm(false$profile$account->getCity(), $precheckMasseur);
  69.         if ($request->request->has('submit')) { //submitted
  70.             try {
  71.                 $successFlashMessage sprintf('Анкета успешно %s'$profile 'отредактирована' 'создана');
  72.                 if($profile && $this->isProfileModerationNeeded($profile$request)) {
  73.                     $fakeForm $this->createProfileForm(true$profile$account->getCity(), $precheckMasseur);
  74.                     $profileFormValues = [];
  75.                     foreach ($fakeForm->all() as $child) {
  76.                         $profileFormValues[$child->getName()] = $request->request->get($child->getName());
  77.                     }
  78.                     
  79.                     $profileFormValues['un_approve'] = 0;
  80.                     if ($this->isProfileApprovalResetNeeded($profile$request)) {
  81.                         if(true === $this->features->approval_by_video()) {
  82.                             $approvalService->reApplyLastNotRejectedRequestForApproval($profile);
  83.                         } else {
  84.                             if ($this->features->hard_moderation()) {
  85.                                 $profileFormValues['un_approve'] = 1;
  86.                             } else {
  87.                                 $approvalService->revokeProfileApproval($profile);
  88.                             }
  89.                         }
  90.                     }
  91.                     $fakeForm->handleRequest($request);
  92.                     if ($fakeForm->isSubmitted() && $fakeForm->isValid()) {
  93.                         //здесь чтобы узнать был ли файл и после флаша
  94.                         if(null != $fakeForm->get('approval_photo')->getData()) {
  95.                             $approvalService->sendForApproval($profile$fakeForm->get('approval_photo')->getData()[0]);
  96.                         }
  97.                         if(false === $this->features->hard_moderation()) {
  98.                             //пересоздаем основную форму, т.к. fake-форма после handleRequest почему-то перезаписывает конфиг основной
  99.                             $form $this->createProfileForm(false$profile$account->getCity(), $precheckMasseur);
  100.                             $form->handleRequest($request);
  101.                             if ($form->isSubmitted() && $form->isValid()) {
  102.                                 /** @var Profile $profile */
  103.                                 $profile $form->getData();
  104.                                 $eventDispatcher->dispatch(new ProfileDataChanged($profile), ProfileDataChanged::NAME);
  105.                                 $this->entityManager->flush();
  106.                             }
  107.                         }
  108.                         $moderationService->requestModeration($profile$profileFormValues);
  109.                         $redirectRoute false == $this->features->non_masseur_on_account_profile_list() && $profile->isMasseur()
  110.                             ? 'account.profile_management.list_masseur'
  111.                             'account.profile_management.list';
  112.                         if($this->features->redirect_to_account_main_after_profile_edit()) {
  113.                             $redirectRoute 'account';
  114.                         }
  115.                         $this->addFlash('success'$successFlashMessage);
  116.                         return $this->redirectToRoute($redirectRoute);
  117.                     } else {
  118.                         //переносим ошибки и данные в основную форму чтобы показать
  119.                         foreach ($fakeForm->getErrors() as $error) {
  120.                             $form->addError($error);
  121.                         }
  122.                         foreach ($fakeForm->all() as $item) {
  123.                             foreach ($item->getErrors() as $error) {
  124.                                 $form->get($item->getName())->addError($error);
  125.                             }
  126.                             $form->get($item->getName())->setData($item->getData());
  127.                         }
  128.                     }
  129.                 } else {
  130.                     $form->handleRequest($request);
  131.                     if ($form->isSubmitted() && $form->isValid()) {
  132.                         /** @var Profile $profile */
  133.                         $profile $form->getData();
  134.                         $isDraft $profile->isDraft();
  135.                         if($isDraft) {
  136.                             $profilePersister->persist($profile);
  137.                             $moderationService->requestModeration($profile);
  138.                         } else {
  139.                             $eventDispatcher->dispatch(new ProfileDataChanged($profile), ProfileDataChanged::NAME);
  140.                         }
  141.                         $this->entityManager->flush();
  142.                         //здесь чтобы узнать был ли файл и после флаша
  143.                         if(null != $form->get('approval_photo')->getData()) {
  144.                             $approvalService->sendForApproval($profile$form->get('approval_photo')->getData()[0]);
  145.                         }
  146.                         $redirectRoute false == $this->features->non_masseur_on_account_profile_list() && $profile->isMasseur()
  147.                             ? 'account.profile_management.list_masseur'
  148.                             'account.profile_management.list';
  149.                         if($this->features->redirect_to_account_main_after_profile_edit()) {
  150.                             $redirectRoute 'account';
  151.                         }
  152.                         $this->addFlash('success'$successFlashMessage);
  153.                         return $this->redirectToRoute($redirectRoute);
  154.                     }
  155.                 }
  156.             } catch (\DomainException $ex) {
  157.                 $this->addFlash('error'$ex->getMessage());
  158.                 if (null !== $profile) {
  159.                     $redirectResponse $this->redirectToRoute('account.profile_editing.edit', ['profile' => $profile->getId()]);
  160.                 } else {
  161.                     $redirectRoute $precheckMasseur 'account.profile_editing.create_masseur' 'account.profile_editing.create';
  162.                     $redirectResponse $this->redirectToRoute($redirectRoute);
  163.                 }
  164.                 return $redirectResponse;
  165.             }
  166.         }
  167.         return $this->render('account/profiles/profile_form.html.twig', [
  168.             'form' => $form->createView(),
  169.             'videos_in_process' => $profile?->videosInProcess(),
  170.             'approval_media_upload_domain' => $parameterBag->get('app.approval_media_upload_domain'),
  171.             'mirror_domain' => $parameterBag->get('app.mirror_domain') ?: $parameterBag->get('app.main_domain'),
  172.             'approved_by_video' => null === $profile || $profile->isDraft() ? false $approvalService->isProfileApprovedByVideo($profile),
  173.         ]);
  174.     }
  175.     protected function createProfileForm(bool $isFake, ?Profile $profile, ?City $citybool $precheckMasseur): FormInterface
  176.     {
  177.         if(true === $isFake && null === $profile) {
  178.             throw new \Exception('Fake form should only be used after editing with profile instance');
  179.         }
  180.         //Для fake формы обязательно нужно передать
  181.         //'original_profile_data' => [ 'id' => $profile->getId(), 'description' => $profile->getDescription() ]
  182.         $form $this->createForm(CreateOrEditProfileForm::class, $isFake null $profile, [
  183.             'default_city' => $city,
  184.             'precheck_masseur' => $precheckMasseur,
  185.             'check_description_is_unique' => true,
  186.             'original_profile_data' => [
  187.                 'id' => $profile $profile->getId() : null,
  188.                 'description' => $profile $profile->getDescription() : null,
  189.             ],
  190.             'is_fake' => $isFake,
  191.         ]);
  192.         return $form;
  193.     }
  194.     protected function isProfileModerationNeeded(Profile $profileRequest $request): bool
  195.     {
  196.         $needModeration 0;
  197.         $submittedDescription = (new TranslatableValue())->ru($request->request->get('about'));
  198.         if ($this->featureHasProfilesTranslation) {
  199.             $submittedDescription $submittedDescription->en($request->request->get('about_en'));
  200.         }
  201.         if($submittedDescription->getTranslation('ru') != $profile->getDescription()->getTranslation('ru')
  202.             || ($this->featureHasProfilesTranslation && $submittedDescription->getTranslation('en') != $profile->getDescription()->getTranslation('en'))) {
  203.             $needModeration++;
  204.         }
  205.         $originalVideos $profile->getVideos()->map(function(Video $video): string { return $video->getPath(); })->toArray();
  206.         $requestVideos $request->request->get('videos') ?? [];
  207.         $videoPathsToAdd array_diff($requestVideos$originalVideos);
  208.         $videoPathsToRemove array_diff($originalVideos$videoPathsToAdd);
  209.         if (count($videoPathsToAdd) || count($videoPathsToRemove)) {
  210.             $needModeration++;
  211.         }
  212.         $needModeration += (int)$this->areProfilePhotosChanged($profile$request);
  213.         return $needModeration 0;
  214.     }
  215.     protected function isProfileApprovalResetNeeded(Profile $profileRequest $request): bool
  216.     {
  217.         $needModeration 0;
  218.         $originalVideos $profile->getVideos()->map(function(Video $video): string { return $video->getPath(); })->toArray();
  219.         $videoPathsToAdd array_diff($request->request->get('videos') ?? [], $originalVideos);
  220.         if(count($videoPathsToAdd))
  221.             $needModeration++;
  222.         $needModeration += (int)$this->areProfilePhotosChanged($profile$request);
  223.         return $needModeration 0;
  224.     }
  225.     protected function areProfilePhotosChanged(Profile $profileRequest $request): bool
  226.     {
  227.         $needModeration 0;
  228.         $originalPhotos $profile->getPhotos()->map(function(Photo $photo): string { return $photo->getPath(); })->toArray();
  229.         $originalSelfies $profile->getSelfies()->map(function(Selfie $selfie): string { return $selfie->getPath(); })->toArray();
  230.         if($profile->getAvatar() && $profile->getAvatar()->getPath() != $request->request->get('avatar'))
  231.             $needModeration++;
  232.         if($profile->getMainPhoto() && $profile->getMainPhoto()->getPath() != $request->request->get('main_photo'))
  233.             $needModeration++;
  234.         $photoPathsToAdd array_diff($request->request->get('photos') ?? [], $originalPhotos);
  235.         if(count($photoPathsToAdd))
  236.             $needModeration++;
  237.         $selfiePathsToAdd array_diff($request->request->get('selfies') ?? [], $originalSelfies);
  238.         if(count($selfiePathsToAdd))
  239.             $needModeration++;
  240.         return $needModeration 0;
  241.     }
  242. }