src/WebBundle/Controller/IdeaController.php line 95

Open in your IDE?
  1. <?php
  2. namespace WebBundle\Controller;
  3. use DateTime;
  4. use Doctrine\ORM\OptimisticLockException;
  5. use Doctrine\ORM\ORMException;
  6. use Exception;
  7. use FlexApp\Enum\LoggerJobNameEnum;
  8. use FlexApp\Service\LogsManager;
  9. use FlexApp\Service\RedisCachePool;
  10. use Monolog\Logger;
  11. use Symfony\Component\HttpFoundation\JsonResponse;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use WebBundle\Entity\Collection;
  15. use WebBundle\Entity\Idea;
  16. use WebBundle\Entity\Interior;
  17. use WebBundle\Entity\InteriorHistory;
  18. use WebBundle\Helper\App;
  19. use WebBundle\Helper\CookieHelper;
  20. use WebBundle\Helper\ResponseApiHelper;
  21. use WebBundle\Helper\TwigTe;
  22. use WebBundle\Helper\UserHelper;
  23. use WebBundle\Repository\CollectionRepository;
  24. use WebBundle\Repository\FilterRepository;
  25. use WebBundle\Repository\IdeaRepository;
  26. use WebBundle\Repository\IdeasShareRepository;
  27. use WebBundle\Repository\InteriorHistoryRepository;
  28. use WebBundle\Repository\InteriorRepository;
  29. use WebBundle\Service\IdeaService;
  30. /**
  31.  * Class IdeaController
  32.  * @package WebBundle\Controller
  33.  */
  34. class IdeaController extends ExtendedController
  35. {
  36.     private const COUNT_IDEAS_ON_POPUP 6;
  37.     private const HEIGHT_STRING 60;
  38.     private array $message = [
  39.         'getTokenByKey' => 'Ключ авторизации не правильный, либо вышел срок его действия',
  40.         'deleteIdea' => 'Не найдены соответствующий проект идей для удаления',
  41.         'editIdea' => 'Не найдены соответствующий проект идей для редактирования',
  42.         'copyIdea' => 'Попытка скопировать не существующий проект',
  43.         'copySelfIdea' => 'Попытка скопировать свой проект',
  44.         'noArrayInteriorsId' => 'Отсутствует массив идентификаторов интерьеров',
  45.         'noArrayInteriorsObj' => 'Не найдено интерьеров для слияния',
  46.         'noInterior' => 'Не найдено интерьера с данным идентификатором',
  47.         'noIdea' => 'Не найдено проекта идей с данным идентификатором',
  48.     ];
  49.     protected Logger $logger;
  50.     /** @required */
  51.     public CollectionRepository $collectionRepository;
  52.     /** @required */
  53.     public InteriorRepository $interiorRepository;
  54.     /** @required */
  55.     public InteriorHistoryRepository $interiorHistoryRepository;
  56.     private IdeaRepository $ideaRepository;
  57.     private LogsManager $logsManager;
  58.     protected string $token;
  59.     /**
  60.      * IdeaController constructor.
  61.      * @param Logger $logger
  62.      * @param IdeaRepository $repo
  63.      * @throws Exception
  64.      */
  65.     public function __construct(
  66.         Logger $logger,
  67.         IdeaRepository $repo,
  68.         LogsManager $logsManager
  69.     ) {
  70.         parent::__construct();
  71.         $this->logger $logger;
  72.         $this->ideaRepository $repo;
  73.         $this->token UserHelper::getInstance()->getToken();
  74.         $this->logsManager $logsManager;
  75.     }
  76.     /**
  77.      * Страница проектов идей
  78.      * @param Request $request
  79.      * @return Response
  80.      * @throws OptimisticLockException
  81.      * @throws Exception
  82.      */
  83.     public function indexAction(Request $request): Response
  84.     {
  85.         /** @var Idea $idea */
  86.         $ideas $this->ideaRepository->getIdeasByToken($this->token);
  87. //        App::dumpExit($ideas);
  88.         $noR = (null !== $request->query->get('noR')) ? $request->query->get('noR') : null;
  89.         if (count($ideas) == && empty($noR)) {
  90.             /** @var Idea $idea */
  91.             $idea $ideas[0];
  92.             return $this->redirect(TwigTe::ideaUrl($idea));
  93.         }
  94.         $lastUpdate null;
  95.         $list = [];
  96.         /** @var Idea $idea */
  97.         foreach ($ideas as $idea) {
  98.             if (!$lastUpdate) {
  99.                 $lastUpdate $idea->getUpdateDate() ?: $idea->getCreateDate();
  100.             }
  101.             $interiorSrc = empty($idea->getInteriors()[0]) ? ' no-img' $idea->getInteriors()[0]->getWebPathPreview();
  102.             $interiorAlt = empty($idea->getInteriors()[0]) ? '' $idea->getInteriors()[0]->getName();
  103.             $list[] = [
  104.                 'id' => $idea->getId(),
  105.                 'url' => TwigTe::ideaUrl($idea),
  106.                 'interiors' => $idea->getInteriors()->count(),
  107.                 'src' => $interiorSrc,
  108.                 'name' => $idea->getName(),
  109.                 'alt' => $interiorAlt
  110.             ];
  111.         }
  112.         return $this->renderReact(
  113.             '@Web/Idea/index.html.twig',
  114.             [
  115.                 'title' => App::trans('idea_header_list'),
  116.                 'description' => App::trans('ideas_description'),
  117.                 'initialState' => [
  118.                     'ideas' => [
  119.                         'list' => $list,
  120.                         'userLocale' => App::getCurLocale(),
  121.                         'lastUpdate' => $lastUpdate,
  122.                         'paths' => $this->paths(),
  123.                         'trans' => $this->trans()
  124.                     ]
  125.                 ]
  126.             ]
  127.         );
  128.     }
  129.     /**
  130.      * Всплывающее окно проектов идей
  131.      * @param Request $request
  132.      * @return Response
  133.      * @throws Exception
  134.      */
  135.     public function lastIdeasAction(Request $request): Response
  136.     {
  137.         $targetHeight $request->query->get('targetHeight');
  138.         $countString = ($targetHeight) ? floor($targetHeight self::HEIGHT_STRING) : self::COUNT_IDEAS_ON_POPUP;
  139.         $token UserHelper::getInstance()->getToken();
  140.         /** @var Idea $idea */
  141.         $ideas $this->ideaRepository->getIdeasByToken($token);
  142.         return $this->render(
  143.             '@Web/Idea/last-ideas.html.twig',
  144.             [
  145.                 'ideas' => $ideas,
  146.                 'countString' => $countString,
  147.             ]
  148.         );
  149.     }
  150.     /**
  151.      * Страница идеи
  152.      * @param string $url
  153.      * @param ?string $name
  154.      * @return Response
  155.      * @throws Exception
  156.      */
  157.     public function showAction(string $url, ?string $name null): Response
  158.     {
  159.         $idea $this->ideaRepository->getIdeaByUrl(str_replace([' ''%20'], '_'urldecode($url)), urldecode($name));
  160.         if (!$idea) {
  161.             $this->logger->error('не найдена идея: (' json_encode($idea) . ') по параметрам url:(' .
  162.                 str_replace([' ''%20'], '_'urldecode($url)) . ') name:(' urldecode($name) . ')');
  163.             $this->logsManager->logError(
  164.                 [
  165.                     'message' => 'не найдена идея: (' json_encode($idea) . ') по параметрам url:(' .
  166.                         str_replace([' ''%20'], '_'urldecode($url)) . ') name:(' urldecode($name) . ')',
  167.                 ],
  168.                 LoggerJobNameEnum::IDEA_CONTROLLER_LOG
  169.             );
  170.             throw $this->createNotFoundException($this->message['noIdea']);
  171.         } else {
  172.             if ($idea->getUser() == null) {
  173.                 $user App::getCurUser();
  174.                 if ($user) {
  175.                     $idea->setUser($user);
  176.                 }
  177.             }
  178.             $sort CookieHelper::get('ideaSort'3);
  179.             $interiors $this->interiorRepository->getInteriorsByIdeaSort($idea->getId(), $sort);
  180.             /** @var IdeasShareRepository $ideasShareRepo */
  181.             $ideasShareRepo App::getRepository('WebBundle:IdeasShare');
  182.             $clickIdeaShareToSocials $ideasShareRepo->getClickIdeaShareToSocials($idea->getId());
  183.             /** @var FilterRepository $filterRepo */
  184.             $filterRepo App::getRepository('WebBundle:FilterEntity');
  185.             $listSort $filterRepo->getSortListCataloge();
  186.             $sortVariants = [];
  187.             if (!empty($listSort[1])) {
  188.                 $sortVariants[1] = $listSort[1];
  189.             }
  190.             if (!empty($listSort[3])) {
  191.                 $sortVariants[3] = $listSort[3];
  192.             }
  193.             if (!empty($listSort[4])) {
  194.                 $sortVariants[4] = $listSort[4];
  195.             }
  196.             $output = [
  197.                 'idea' => $idea,
  198.                 'sort' => $sort,
  199.                 'sortList' => $sortVariants,
  200.                 'interiors' => $interiors,
  201.                 'clickIdeaShareToSocialsItem' => $clickIdeaShareToSocials,
  202.                 'master' => UserHelper::getInstance()->getToken() == $idea->getToken(),
  203.             ];
  204.             return $this->render(
  205.                 '@Web/Idea/show.html.twig',
  206.                 $output
  207.             );
  208.         }
  209.     }
  210.     /**
  211.      * Страница сортировки идеи
  212.      * @param int $id
  213.      * @param ?int $sort
  214.      * @return Response
  215.      * @throws Exception
  216.      */
  217.     public function showSortAction(int $id, ?int $sort 3): Response
  218.     {
  219.         /** @var InteriorRepository $interiorRepo */
  220.         $interiorRepo App::getRepository('WebBundle:Interior');
  221.         $interiors $interiorRepo->getInteriorsByIdeaSort($id$sort);
  222.         // сохраняем выбранный вариант сортировки идей
  223.         CookieHelper::set('ideaSort'$sort);
  224.         $owner false;
  225.         if ($this->ideaRepository->checkMasterIdea($id)) {
  226.             $owner true;
  227.         }
  228.         return $this->render(
  229.             '@Web/Idea/idea_elements.html.twig',
  230.             [
  231.                 'ideaId' => $id,
  232.                 'interiors' => $interiors,
  233.                 'owner' => $owner
  234.             ]
  235.         );
  236.     }
  237.     /**
  238.      * Страница списка идей
  239.      *
  240.      * @param int $id
  241.      * @param ?int $oldIdeaId Старый id идеи, (null - по умолчанию)
  242.      * @param ?string $type Тип добавление (add - по умолчанию) или передвижение (add | move)
  243.      * @return Response
  244.      * @throws Exception
  245.      */
  246.     public function listAction(int $id, ?int $oldIdeaId null, ?string $type 'add')
  247.     {
  248.         $token UserHelper::getInstance()->getToken();
  249.         /** @var Idea $idea */
  250.         $ideas $this->ideaRepository->getIdeasByToken($token);
  251.         // если ещё нет проекта, то создаем
  252.         if (count($ideas) == 0) {
  253.             $idea = new Idea();
  254.             $idea->setCreateDate(new DateTime());
  255.             $idea->setUpdateDate(new DateTime());
  256.             $idea->setName(App::trans('idea_new_project'));
  257.             $idea->setToken($token);
  258.             $this->ideaRepository->save($ideatrue);
  259.             $ideas[] = $idea;
  260.         }
  261.         if (count($ideas) == 1) {
  262.             if ($type == 'move') {
  263.                 return new JsonResponse(
  264.                     [
  265.                         'html' => $this->render(
  266.                             '@Web/Idea/message.html.twig',
  267.                             [
  268.                                 'showMessage' => !$this->getUser(),
  269.                                 'handler' => $type,
  270.                             ]
  271.                         )->getContent(),
  272.                     ]
  273.                 );
  274.             } else {
  275.                 /** @var Idea $idea */
  276.                 $idea $ideas[0];
  277.                 return $this->redirect(
  278.                     $this->generateUrl(
  279.                         'app_idea_interior_change',
  280.                         [
  281.                             'interiorId' => $id,
  282.                             'ideaId' => $idea->getId(),
  283.                             'type' => $type
  284.                         ]
  285.                     )
  286.                 );
  287.             }
  288.         } else {
  289.             $interior App::getRepository('WebBundle:Interior')->findOneBy(['id' => $id]);
  290.             $active = [];
  291.             /** @var Idea $idea */
  292.             foreach ($ideas as $idea) {
  293.                 if ($idea->getInteriors()->contains($interior)) {
  294.                     $active[$idea->getId()] = true;
  295.                 }
  296.             }
  297.             return new JsonResponse(
  298.                 [
  299.                     'html' => $this->render(
  300.                         '@Web/Idea/list.html.twig',
  301.                         [
  302.                             'interiorId' => $id,
  303.                             'ideas' => $ideas,
  304.                             'showMessage' => !$this->getUser(),
  305.                             'active' => $active,
  306.                             'handler' => $type,
  307.                             'oldIdeaId' => $oldIdeaId,
  308.                         ]
  309.                     )->getContent(),
  310.                 ]
  311.             );
  312.         }
  313.     }
  314.     /**
  315.      * Создание проекта идей
  316.      * @param string $name Название проекта
  317.      * @return Response
  318.      * @throws OptimisticLockException
  319.      * @throws Exception
  320.      */
  321.     public function createAction(?string $name)
  322.     {
  323.         $res = new ResponseApiHelper();
  324.         $token UserHelper::getInstance()->getToken();
  325.         if ($res->isValid()) {
  326.             $name IdeaService::getNameIdea($token$name ?? 'null');
  327.             $idea = new Idea();
  328.             $user App::getCurUser();
  329.             if ($user) {
  330.                 $idea->setUser($user);
  331.             }
  332.             $idea->setToken($token);
  333.             $idea->setName($name);
  334.             $idea->setProcess(1);
  335.             $idea->setCreateDate(new DateTime());
  336.             $idea->setUpdateDate(new DateTime());
  337.             $em App::em();
  338.             $em->persist($idea);
  339.             $em->flush();
  340.             $interiorSrc = empty($idea->getInteriors()[0]) ? ' no-img' $idea->getInteriors()[0]->getWebPathPreview();
  341.             $interiorAlt = empty($idea->getInteriors()[0]) ? '' $idea->getInteriors()[0]->getName();
  342.             $res->setResponse('res', [
  343.                 'state' => 'created',
  344.                 'idea' => [
  345.                     'id' => $idea->getId(),
  346.                     'url' => TwigTe::ideaUrl($idea),
  347.                     'interiors' => $idea->getInteriors()->count(),
  348.                     'src' => $interiorSrc,
  349.                     'name' => $idea->getName(),
  350.                     'alt' => $interiorAlt,
  351.                     'notification' => App::trans(
  352.                         'idea.create.msg',
  353.                         App::getCurLocale(),
  354.                         ['%name%' => '<b>' $idea->getName() . '</b>']
  355.                     )
  356.                 ]
  357.             ]);
  358.         }
  359.         return new JsonResponse($res->result());
  360.     }
  361.     /**
  362.      * Редактирование проекта идей
  363.      * @param int $id - код проекта идеи
  364.      * @param string $name - название проекта
  365.      * @return Response
  366.      * @throws OptimisticLockException
  367.      * @throws Exception
  368.      */
  369.     public function editAction(int $idstring $name)
  370.     {
  371.         /** @var ResponseApiHelper $response */
  372.         $res = new ResponseApiHelper();
  373.         $token UserHelper::getInstance()->getToken();
  374.         if ($res->isValid()) {
  375.             $idea App::getContainer()->get('app.repo.idea')->findOneBy(
  376.                 ['token' => $token'id' => $id]
  377.             );
  378.             if (!$idea) {
  379.                 $res->validate('editIdea'null'empty'$this->message['editIdea']);
  380.             } else {
  381.                 $name str_replace('/'''$name);
  382.                 $name IdeaService::getNameIdea($token$name$idea->getId());
  383.                 $idea->setToken($token);
  384.                 $idea->setName($name);
  385.                 $idea->setCreateDate(new DateTime());
  386.                 $idea->setUpdateDate(new DateTime());
  387.                 $this->ideaRepository->save($ideatrue);
  388.                 $result = [
  389.                     'state' => 'updated',
  390.                     'idea' => [
  391.                         'id' => $idea->getId(),
  392.                         'name' => $idea->getName(),
  393.                         'url' => TwigTe::ideaUrl($idea)
  394.                     ],
  395.                 ];
  396.                 $res->setResponse('res'$result);
  397.             }
  398.         }
  399.         return new JsonResponse($res->result());
  400.     }
  401.     /**
  402.      * Удаление проектов идей
  403.      * @param string $id - идентификаторы проектов идей разделённые |
  404.      * @return mixed
  405.      * @throws OptimisticLockException
  406.      * @throws Exception
  407.      */
  408.     public function deleteAction(string $id): JsonResponse
  409.     {
  410.         /** @var ResponseApiHelper $response */
  411.         $res = new ResponseApiHelper();
  412.         $token UserHelper::getInstance()->getToken();
  413.         if ($res->isValid()) {
  414.             $ideas App::getContainer()->get('app.repo.idea')->findBy(
  415.                 ['token' => $token'id' => explode('|'$id)]
  416.             );
  417.             if (!$ideas) {
  418.                 $res->validate('deleteIdea'null'empty'$this->message['deleteIdea']);
  419.             } else {
  420.                 $em App::em();
  421.                 $result = ['action' => 'ok'];
  422.                 /** @var Idea $idea */
  423.                 foreach ($ideas as $idea) {
  424.                     /** @var Interior $interior */
  425.                     foreach ($idea->getInteriors() as $interior) {
  426.                         $result['c_rating'][$interior->getCollection()->getId()] = (int)($interior->getCollection()->getRating() - 1);
  427.                         $result['i_rating'][$interior->getId()] = (int)($interior->getIdeas()->count() - 1);
  428.                     }
  429.                     $em->remove($idea);
  430.                     $em->flush();
  431.                 }
  432.                 /** @var IdeaRepository $repoIdea */
  433.                 $repoIdea App::getContainer()->get('app.repo.idea');
  434.                 $result['all'] = $repoIdea->countByToken($token);
  435.                 $res->setResponse('result'$result);
  436.             }
  437.         }
  438.         return new JsonResponse($res->result());
  439.     }
  440.     /**
  441.      * Добавление удаление интерьера из идей
  442.      * @param int $interiorId - идентификаторы интерьера
  443.      * @param int $ideaId - идентификатор проекта идеи
  444.      * @param ?string $type
  445.      * @return mixed
  446.      * @throws Exception
  447.      */
  448.     public function changeIdeaInteriorAction(int $interiorIdint $ideaId, ?string $type null): JsonResponse
  449.     {
  450.         /** @var ResponseApiHelper $response */
  451.         $res = new ResponseApiHelper();
  452.         $token UserHelper::getInstance()->getToken();
  453.         $interior $this->interiorRepository->find($interiorId);
  454.         if (!$interior) {
  455.             $res->validate('noInterior'null'empty'$this->message['noInterior']);
  456.         }
  457.         $idea $this->ideaRepository->find($ideaId);
  458.         if (!$idea) {
  459.             $res->validate('noIdea'null'empty'$this->message['noIdea']);
  460.         }
  461.         if (!$res->isValid()) {
  462.             return new JsonResponse($res->result());
  463.         }
  464.         $collection $this->collectionRepository->find($interior->getCollection()->getId());
  465.         $rating $collection->getRating();
  466.         $memcache App::getMemcache();
  467.         $memcache->set('updateCollections'time(), false600);
  468.         $redisCachePool App::getContainer()->get(RedisCachePool::class)->getPool();
  469.         $cacheItem $redisCachePool->getItem('updateCollections');
  470.         $cacheItem->expiresAfter(600);
  471.         $cacheItem->set(time());
  472.         $redisCachePool->save($cacheItem);
  473.         if ($idea->getInteriors()->contains($interior) === false) {
  474.             $active true;
  475.             $idea->getInteriors()->add($interior);
  476.             $interior->getIdeas()->add($idea);
  477.             $collection->setRating($rating 1);
  478.             $this->setIdeaInterior($idea$interiorInteriorHistory::ADD);
  479.             $this->updateFactoryIdeas($collection->getFactory()->getId());
  480.         } elseif ($type != 'add') {
  481.             $active false;
  482.             $idea->getInteriors()->removeElement($interior);
  483.             $interior->getIdeas()->removeElement($idea);
  484.             $collection->setRating(($rating 1) ? $rating $rating);
  485.             $this->setIdeaInterior($idea$interiorInteriorHistory::DEL);
  486.             $this->updateFactoryIdeas($collection->getFactory()->getId(), false);
  487.         } else {
  488.             $active true;
  489.         }
  490.         $this->interiorRepository->save($interiortrue);
  491.         $this->ideaRepository->save($ideatrue);
  492.         $result = [
  493.             'iRating' => (int) $interior->getIdeas()->count(),
  494.             'cRating' => (int) $interior->getCollection()->getRating(),
  495.             'all' => (int) $this->ideaRepository->countByToken($token),
  496.             'active' => $active,
  497.             'projects' => [
  498.                 [
  499.                     'name' => $idea->getName(),
  500.                     'url' => TwigTe::ideaUrl($idea),
  501.                 ],
  502.             ],
  503.         ];
  504.         $res->setResponse('res'$result);
  505.         return new JsonResponse($res->result());
  506.     }
  507.     /**
  508.      * Добавление удаление интерьера из идей
  509.      * @param int $interiorId идентификаторы интерьера
  510.      * @return mixed
  511.      * @throws OptimisticLockException
  512.      * @throws ORMException
  513.      * @throws Exception
  514.      * @internal param int $ideaId идентификатор проекта идеи
  515.      */
  516.     public function changeIdeasInteriorAction(int $interiorId): JsonResponse
  517.     {
  518.         /** @var ResponseApiHelper $response */
  519.         $res = new ResponseApiHelper();
  520.         $token UserHelper::getInstance()->getToken();
  521.         $ideasAction = [];
  522.         if (!empty($_POST['ideas'])) {
  523.             $ideasAction $_POST['ideas'];
  524.         }
  525.         /** @var InteriorRepository $interiorRepo */
  526.         $interiorRepo App::getRepository('WebBundle:Interior');
  527.         /** @var Interior $interiorChange */
  528.         $interiorChange $interiorRepo->getInteriorForIdea($interiorId);
  529.         if (!$interiorChange) {
  530.             $res->validate('noInterior'null'empty'$this->message['noInterior']);
  531.         }
  532.         /** @var Idea $idea */
  533.         $ideas $this->ideaRepository->getIdeas(array_keys($ideasAction), false);
  534.         $rating $interiorChange $interiorChange->getCollection()->getRating() : null;
  535.         if ($res->isValid()) {
  536.             $active false;
  537.             $em App::em();
  538.             $projects = [];
  539.             /** @var Idea $idea */
  540.             foreach ($ideas as $idea) {
  541.                 if (isset($ideasAction[$idea->getId()])) {
  542.                     if ($ideasAction[$idea->getId()] == 1) { // добавление интерьера в проект инеи
  543.                         if (!$idea->getInteriors()->contains($interiorChange)) {
  544.                             $idea->getInteriors()->add($interiorChange);
  545.                             $interiorChange->getIdeas()->add($idea);
  546.                             $this->setIdeaInterior($idea$interiorChange'add');
  547.                             $rating $rating 1;
  548.                         }
  549.                         $active true;
  550.                     } else { // удаление интерьера из проекта идеи
  551.                         if ($idea->getInteriors()->contains($interiorChange)) {
  552.                             $idea->getInteriors()->removeElement($interiorChange);
  553.                             $interiorChange->getIdeas()->removeElement($idea);
  554.                             $this->setIdeaInterior($idea$interiorChange'del');
  555.                             $rating = ($rating 1) ? $rating $rating;
  556.                         }
  557.                     }
  558.                 }
  559.                 $interiorChange->getCollection()->setRating($rating);
  560.                 $this->updateFactoryIdeas($interiorChange->getCollection()->getFactory()->getId(), $active);
  561.                 $em->persist($interiorChange);
  562.                 $em->persist($interiorChange->getCollection());
  563.                 $em->persist($idea);
  564.                 $em->flush();
  565.                 $projects[] = [
  566.                     'name' => $idea->getName(),
  567.                     'url' => TwigTe::ideaUrl($idea)
  568.                 ];
  569.             }
  570.             /** @var IdeaRepository $repoIdea */
  571.             $repoIdea App::getContainer()->get('app.repo.idea');
  572.             $result = [
  573.                 'iRating' => $interiorChange->getIdeas()->count(),
  574.                 'cRating' => $interiorChange->getCollection()->getRating(),
  575.                 'all' => (int)$repoIdea->countByToken($token),
  576.                 'active' => $active,
  577.                 'projects' => $projects
  578.             ];
  579.             $res->setResponse('res'$result);
  580.         }
  581.         return new JsonResponse($res->result());
  582.     }
  583.     /**
  584.      * @param Idea $idea
  585.      * @param Interior $interior
  586.      * @param bool $action
  587.      * @throws Exception
  588.      */
  589.     private function setIdeaInterior(Idea $ideaInterior $interiorbool $action)
  590.     {
  591.         $interiorHistory $this->interiorHistoryRepository->getInteriorHistory($interior->getId(), $idea->getId());
  592.         if (!$interiorHistory) {
  593.             $interiorHistory = new InteriorHistory();
  594.             $interiorHistory->setInterior($interior);
  595.             $interiorHistory->setIdea($idea);
  596.         }
  597.         $interiorHistory->setAction($action);
  598.         $interiorHistory->setDate(new DateTime());
  599.         $this->interiorHistoryRepository->save($interiorHistorytrue);
  600.     }
  601.     /**
  602.      * @param int $ideaId
  603.      * @param int $interiorId
  604.      * @return JsonResponse
  605.      * @throws OptimisticLockException
  606.      * @throws ORMException
  607.      * @throws Exception
  608.      */
  609.     public function delInteriorAction(int $ideaIdint $interiorId): JsonResponse
  610.     {
  611.         $res = new ResponseApiHelper();
  612.         $token UserHelper::getInstance()->getToken();
  613.         /** @var Idea $idea */
  614.         $idea $this->ideaRepository->getIdeaById($ideaId);
  615.         if (!$idea) {
  616.             throw $this->createNotFoundException('Not found idea');
  617.         } elseif ($idea->getToken() != $token) {
  618.             throw $this->createAccessDeniedException();
  619.         }
  620.         /** @var Interior $interiorChange */
  621.         $interiorChange App::getRepository('WebBundle:Interior')->findOneBy(
  622.             ['id' => $interiorId]
  623.         );
  624.         $collection $interiorChange->getCollection();
  625.         $rating $collection->getRating();
  626.         $idea->getInteriors()->removeElement($interiorChange);
  627.         $interiorChange->getIdeas()->removeElement($idea);
  628.         $this->setIdeaInterior($idea$interiorChangeInteriorHistory::DEL);
  629.         $collection->setRating(($rating 1) ? $rating $rating);
  630.         $this->updateFactoryIdeas($interiorChange->getCollection()->getFactory()->getId(), false);
  631.         App::em()->persist($collection);
  632.         App::em()->persist($interiorChange);
  633.         App::em()->persist($idea);
  634.         App::em()->flush();
  635.         /** @var IdeaRepository $repoIdea */
  636.         $repoIdea App::getContainer()->get('app.repo.idea');
  637.         $result = [
  638.             'iRating' => (int) $interiorChange->getIdeas()->count(),
  639.             'cRating' => (int) $interiorChange->getCollection()->getRating(),
  640.             'all' => (int) $repoIdea->countByToken($token),
  641.             'active' => false,
  642.             'projects' => [
  643.                 [
  644.                     'name' => $idea->getName(),
  645.                     'url' => TwigTe::ideaUrl($idea),
  646.                 ],
  647.             ],
  648.         ];
  649.         $res->setResponse('res'$result);
  650.         return new JsonResponse($res->result());
  651.     }
  652.     /**
  653.      * Перемещение интерьера в другой проект
  654.      *
  655.      * @param Request $request
  656.      * @param int $oldIdeaId
  657.      * @param int $interiorId
  658.      * @return JsonResponse
  659.      * @throws ORMException
  660.      * @throws OptimisticLockException
  661.      */
  662.     public function moveInteriorAction(Request $requestint $oldIdeaIdint $interiorId): JsonResponse
  663.     {
  664.         $res = new ResponseApiHelper();
  665.         $this->changeIdeasInteriorAction($interiorId);
  666.         $this->delInteriorAction($oldIdeaId$interiorId);
  667.         $result = [
  668.             'oldIdeaId' => $oldIdeaId,
  669.             'targetIdeaId' => $request->get('ideas'),
  670.             'interiorId' => $interiorId,
  671.         ];
  672.         $res->setResponse('res'$result);
  673.         return new JsonResponse($res->result());
  674.     }
  675.     /**
  676.      * updateFactoryIdeas - Функция по увеличению/уменьшению кол-ва идей для фабрики.
  677.      *
  678.      * @see Collection entity for duplicate #of shared ideas.
  679.      *      sum of all "rating" where (Collection->getFactory = $factoryId)  === Factory->ideas
  680.      *
  681.      * @param int $factoryId - Factory id where increase or decrease interiors stat
  682.      * @param ?bool $isAdded - if True - increase counter, else decrease
  683.      * @return void - Or mb need return boolean :  True - all ok, False - not good
  684.      * @throws ORMException
  685.      * @throws Exception
  686.      */
  687.     private function updateFactoryIdeas(int $factoryId, ?bool $isAdded true)
  688.     {
  689.         $oFactory App::getRepository('WebBundle:Factory')->findOneBy(['id' => $factoryId]);
  690.         if (!$oFactory) {
  691.             return;
  692.         }
  693.         $em App::em();
  694.         $i $oFactory->getTotalIdeas() ?? 0;//get current ideas
  695.         if ($isAdded) {
  696.             //new idea added. +1 to stat in the factory
  697.             $oFactory->setTotalIdeas($i 1);
  698.         } else {
  699.             // idea is deleted. -1 to stat in the factory
  700.             if ($i 0) {
  701.                 $oFactory->setTotalIdeas($i 1);
  702.             }
  703.         }
  704.         if ($i != $oFactory->getTotalIdeas()) {
  705.             //write changes
  706.             $em->persist($oFactory);
  707.             $em->flush();//// ? mb move out from this function for one  persist+flush  functions
  708.         }
  709.     }
  710.     /**
  711.      * @return array
  712.      * @throws Exception
  713.      */
  714.     private function trans(): array
  715.     {
  716.         return [
  717.             'ideaHeaderList' => App::trans('idea_header_list'),
  718.             'ideaUpdateDate' => App::trans('idea_update_date'),
  719.             'ideaAddProject' => App::trans('idea_add_project'),
  720.             'ideaBookEmpty' => App::trans('user.ideabook_empty'),
  721.             'interiorIdeaDelete' => App::trans('interior_idea_dellete'),
  722.             'confirmHeader' => App::trans('buyOrder.confirm.header'),
  723.             'ideaEmpty' => App::trans('idea_empty'),
  724.             'cancel' => App::trans('cancel'),
  725.             'save' => App::trans('save'),
  726.             'yes' => App::trans('yes'),
  727.             'no' => App::trans('no'),
  728.             'rename' => App::trans('rename'),
  729.             'share' => App::trans('share'),
  730.             'delete' => App::trans('idea.button_delete'),
  731.             'delInteriorAllIdeas' => App::trans('idea_del_interior_msg'),
  732.             'copy' => App::trans('copy'),
  733.             'ideaDeleteTitle' => App::trans('idea.del_project'),
  734.             'interiorDeleteTitle' => App::trans('idea_msg_active'),
  735.             'ideaRenameTitle' => App::trans('idea.rename_coll'),
  736.             'ideaShareTitle' => App::trans('idea_share_header'),
  737.             'ideaShareDescr' => App::trans('idea_share_link_can'),
  738.             'shareOnSocial' => App::trans('share_social_network'),
  739.             'ideaNewProject' => App::trans('idea_new_project'),
  740.         ];
  741.     }
  742.     /**
  743.      * @return array
  744.      * @throws Exception
  745.      */
  746.     private function paths(): array
  747.     {
  748.         return [
  749.             'appIdeaDel' => App::generateUrl('app_idea_del', ['id' => 0]),
  750.             'appIdeaEdit' => App::generateUrl('app_idea_edit', ['id' => 0'name' => '-name-']),
  751.             'appIdeaCreate' => App::generateUrl('app_idea_create')
  752.         ];
  753.     }
  754. }