src/WebBundle/Service/CollectionService.php line 703

Open in your IDE?
  1. <?php
  2. namespace WebBundle\Service;
  3. use AdmBundle\Helper\StrAdm;
  4. use Exception;
  5. use FlexApp\Repository\CommentRepository;
  6. use FlexApp\Service\LastUrlService;
  7. use FlexApp\Service\RedisCachePool;
  8. use Import1CBundle\Helper\v3\BiConst;
  9. use Import1CBundle\Helper\v3\TranslitNameHelper;
  10. use Monolog\Logger;
  11. use Symfony\Component\HttpFoundation\RedirectResponse;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\HttpFoundation\Session\Session;
  15. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  16. use WebBundle\Entity\Article;
  17. use WebBundle\Entity\Collection;
  18. use WebBundle\Entity\FilterEntity;
  19. use WebBundle\Enum\CollectionAndFactoryStateEnum;
  20. use WebBundle\Enum\MeasureEnum;
  21. use WebBundle\Filler\MessageFiller;
  22. use WebBundle\Helper\App;
  23. use WebBundle\Helper\ArrHelper;
  24. use WebBundle\Helper\FilterHelper;
  25. use WebBundle\Helper\LocaleHelper;
  26. use WebBundle\Helper\PathHelper;
  27. use WebBundle\Helper\StrHelper;
  28. use WebBundle\Helper\TranslitHelper;
  29. use WebBundle\Helper\UserHelper;
  30. use WebBundle\Repository\ArticleRepository;
  31. use WebBundle\Repository\CollectionRepository;
  32. use WebBundle\Repository\FilterRepository;
  33. use WebBundle\Repository\InteriorRepository;
  34. class CollectionService extends ExtendService
  35. {
  36.     /** @required */
  37.     public LastUrlService $lastUrlService;
  38.     /** @required */
  39.     public FiltersService $filtersService;
  40.     /** @required */
  41.     public SliderService $sliderService;
  42.     /** @required */
  43.     public CollectionRepository $collectionRepository;
  44.     /** @required */
  45.     public FilterRepository $filterRepository;
  46.     /** @required */
  47.     public CommentRepository $commentRepository;
  48.     /** @required */
  49.     public MessageFiller $messageFiller;
  50.     /** @var Request $oRequest */
  51.     protected $oRequest;
  52.     /** @var Session $oSession */
  53.     protected $oSession;
  54.     /** Текущая локаль запроса */
  55.     protected string $sLocale;
  56.     private Logger $oLogger;
  57.     private array $readySettings = [];
  58.     public function __construct(Logger $logger)
  59.     {
  60.         $this->oSession App::getContainer()->get('session');
  61.         $this->oRequest App::getRequest();
  62.         $this->sLocale $this->oRequest->getLocale();
  63.         $this->oLogger $logger;
  64.     }
  65.     /**
  66.      * @param string $unid
  67.      * @return array
  68.      * @throws Exception
  69.      */
  70.     public function getCommentsCountData(string $unid): array
  71.     {
  72.         return [
  73.             'questions' => $this->commentRepository->getCommentCountData($unidApp::getCurLocale(), false),
  74.             'answers' => $this->commentRepository->getCommentCountData($unidApp::getCurLocale()),
  75.         ];
  76.     }
  77.     /**
  78.      * Залипуха, что бы количество коллекций было одинаковым в разных местах, если нет фильтрации
  79.      * @return int
  80.      * @throws Exception
  81.      */
  82.     public function countNotFilteredCollection(): int
  83.     {
  84.         $redisCachePool App::getContainer()->get(RedisCachePool::class)->getPool();
  85.         $memKey 'collection_count_not_filtered' App::getCurCountry(); //ну как же без учета страны?
  86.         $cntItem $redisCachePool->getItem($memKey);
  87.         if (!$cntItem->isHit()) {
  88.             $data = [
  89.                 'searchFilter' => [],
  90.                 'searchSort' => 1,
  91.                 'searchPeriod' => null,
  92.                 'locale' => App::getCurLocale(),
  93.             ];
  94.             $aRes App::searchSphinx($data300false);
  95.             $cnt count($aRes);
  96.             $cntItem->set($cnt);
  97.             $cntItem->expiresAfter(86400);
  98.             $redisCachePool->save($cntItem);
  99.         } else {
  100.             $cnt $cntItem->get();
  101.         }
  102.         return (int) $cnt;
  103.     }
  104.     /**
  105.      * @param $coll
  106.      * @param bool $flag
  107.      * @param string $format
  108.      * @param null $locale
  109.      * @return array|Response|null
  110.      * @throws Exception
  111.      */
  112.     public function settingsListAction($collbool $flag falsestring $format 'html'$locale null)
  113.     {
  114.         $settings = [];
  115.         $marker = [];
  116.         $offShade = [];
  117.         $sliding = [];
  118.         $nonSlip false;
  119.         $authorLink false;
  120.         $locale $locale $locale App::getCurLocale();
  121.         /** @var ArticleRepository $repoArticle */
  122.         $repoArticle App::getRepository('WebBundle:Article');
  123.         /** @var InteriorRepository $repoInterior */
  124.         $repoInterior App::getRepository('WebBundle:Interior');
  125.         /** @var $collectionRepository CollectionRepository */
  126.         $collectionRepository App::getRepository('WebBundle:Collection');
  127.         if (is_array($coll)) {
  128.             $collection $coll;
  129.             $collectionAuthor $collection['author'];
  130.             $collection['interiors'] = $repoInterior->getInteriorsByCollection($coll['id']);
  131.             $collection['articles'] = $repoArticle->getArticleByCollection($coll['id']);
  132.             $exhibitions = !empty($collection['exhibition']) ? $collection['exhibition'] : [];
  133.         } else {
  134.             $collection['articles'] = $repoArticle->getArticleByCollection($coll);
  135.             $collection['interiors'] = $repoInterior->getInteriorsByCollection($coll);
  136.             /** @var Collection $collection */
  137.             $collectionAuthor $collectionRepository->getCollAuthor($coll);
  138.             $exhibitions $collection->getExhibition()->toArray();
  139.         }
  140.         $collection['articles'] = $this->sliderService->prepareDiscountAmountForEachArticle($collection['articles']);
  141.         // приводим дизайнеров к массиву
  142.         if ($collectionAuthor and !is_array($collectionAuthor)) {
  143.             $collectionAuthor explode(','$collectionAuthor);
  144.             $collectionAuthor array_map('trim'$collectionAuthor);
  145.             $collectionAuthor array_diff($collectionAuthor, ['']);
  146.         }
  147.         // смотрим интерьеры если accessible не TRUE
  148.         if (!$collection['accessible']) {
  149.             foreach ($collection['interiors'] as $interior) {
  150.                 if (!empty($interior['applies'])) {
  151.                     $settings $this->parseFiltersForSettings($interior['applies'], $settings'getUsings'$collectionAuthor);
  152.                 }
  153.                 if (!empty($interior['styles'])) {
  154.                     $settings $this->parseFiltersForSettings($interior['styles'], $settings'getStyles'$collectionAuthor);
  155.                 }
  156.                 if (!empty($interior['textures'])) {
  157.                     foreach ($interior['textures'] as $i => $texture) {
  158.                         if ($texture['alias'] == 'left_menu_mono_color') {
  159.                             $settings $this->parseFiltersForSettings($texture$settings'getColors'$collectionAuthor);
  160.                         } else {
  161.                             $settings $this->parseFiltersForSettings($texture$settings'getFacturas'$collectionAuthor);
  162.                         }
  163.                     }
  164.                 }
  165.             }
  166.         }
  167.         /** @var Article|array $article */
  168.         foreach ($collection['articles'] as $article) {
  169.             // /en/tile/Serenissima-Cir/Marble-Style
  170.             if (!empty($article['pei'])) {
  171.                 $settings $this->parseFiltersForSettings($article$settings'Pei'$collectionAuthor);
  172.             }
  173.             if (!empty($article['style'])) {
  174.                 $settings $this->parseFiltersForSettings($article['style'], $settings'getStyles'$collectionAuthor);
  175.             }
  176.             if (!empty($article['type']) && $article['type']['id'] == 24) {
  177.                 $article['type']['name'] = App::getTranslator()->trans($article['type']['alias']);
  178.                 $settings $this->parseFiltersForSettings($article['type'], $settings'getType'$collectionAuthor);
  179.             }
  180.             if (!empty($article['material'])) {
  181.                 if ($article['thinGranite'] == 1) {
  182.                     $article['material']['name'] = App::getTranslator()->trans('left_menu_thin_porcelain_tile');
  183.                 } else {
  184.                     $article['material']['name'] = App::getTranslator()->trans($article['material']['alias']);
  185.                 }
  186.                 $settings $this->parseFiltersForSettings($article['material'], $settings'getMaterials'$collectionAuthor);
  187.             }
  188.             // пока так сделал.
  189.             if (!empty($article['using']) && $article['using']['hide'] == 0) {
  190.                 $name $locale != 'de' ?
  191.                     mb_convert_case(App::getTranslator()->trans($article['using']['alias']), MB_CASE_LOWER"UTF-8") :
  192.                     App::getTranslator()->trans($article['using']['alias']);
  193.                 $code FilterHelper::normaliseAltName($name);
  194.                 $searchLink $name;
  195.                 $searchLink str_replace([' ''-'], '_'StrHelper::toLower($searchLink));
  196.                 $link FilterHelper::getUrl($searchLink$locale);
  197.                 $val = [
  198.                     'name' => $name,
  199.                     'link' => $this->fixLink($link),
  200.                 ];
  201.                 if (
  202.                     empty($settings['getTypeUsings'])
  203.                     || (
  204.                         !in_array($val$settings['getTypeUsings'])
  205.                         && ($article['using']['id'] == || !in_array(4$marker['getTypeUsings']))
  206.                     )
  207.                 ) {
  208.                     $settings['getTypeUsings'][$article['using']['alias']] = $val;
  209.                     $marker['getTypeUsings'][$code] = $article['using']['id'];
  210.                 }
  211.             }
  212.             if (!empty($article['surface'])) {
  213.                 if ($article['surface']['id'] == 8) {
  214.                     $article['surface']['name'] = App::getTranslator()->trans('catalog.options.non_slip');
  215.                 } else {
  216.                     $article['surface']['name'] = App::getTranslator()->trans($article['surface']['alias']);
  217.                 }
  218.                 $settings $this->parseFiltersForSettings($article['surface'], $settings'getSurfaces'$collectionAuthor);
  219.                 if ($article['surface']['id'] == 8) {
  220.                     $name App::getTranslator()->trans($article['surface']['alias']);
  221.                     $nonSlip FilterHelper::normaliseAltName($name);
  222.                 }
  223.             }
  224.             if (!empty($article['textures'])) {
  225.                 foreach ($article['textures'] as $i => $texture) {
  226.                     if ($texture['alias'] == 'left_menu_mono_color') {
  227.                         $settings $this->parseFiltersForSettings($texture$settings'getColors'$collectionAuthor);
  228.                     } else {
  229.                         $settings $this->parseFiltersForSettings($texture$settings'getFacturas'$collectionAuthor);
  230.                     }
  231.                 }
  232.             }
  233.             if (!empty($article['edgeType'])) {
  234.                 $settings $this->parseFiltersForSettings($article['edgeType'], $settings'getEdgeType'$collectionAuthor);
  235.             }
  236.             if (!empty($article['sliding']) && !empty($article['sliding']['id'])) {
  237.                 $elem = [
  238.                     'name' => 'R' $article['sliding']['id'],
  239.                     'title' => App::getTranslator()->trans(
  240.                         'catalog.options.non_slip_rating',
  241.                         ['%d%' => 'R' $article['sliding']['id']]
  242.                     ),
  243.                 ];
  244.                 if (!in_array($elem$sliding)) {
  245.                     $sliding[] = $elem;
  246.                 }
  247.             }
  248.             if (!empty($article['offShade'])) {
  249.                 if (!in_array('V' $article['offShade']['id'], $offShade)) {
  250.                     $offShade[] = 'V' $article['offShade']['id'];
  251.                 }
  252.             }
  253.         }
  254.         if (!empty($settings['getStylesDesigners']) and !empty($settings['getStyles'])) {
  255.             unset($settings['getStyles']['left_menu_designer']);
  256.             if (isset($settings['getStyles'])) {
  257.                 unset($settings['getStyles']);
  258.             }
  259.         }
  260.         if ($nonSlip !== false) {
  261.             $settings['getSurfaces'][$nonSlip]['list'] = $sliding;
  262.         }
  263.         if (count($offShade) > 0) {
  264.             $nm App::getTranslator()->trans('catalog.options.shade_variation', ['%d%' => implode(', '$offShade)]);
  265.             $settings['offShade'][] = [
  266.                 'name' => App::getCurCountry() != 'de' StrHelper::lcFirstOnly($nm) : StrHelper::ucFirstOnly($nm),
  267.                 'link' => null,
  268.             ];
  269.         }
  270.         if (empty($settings['getEdgeType'])) {
  271.             $name App::getTranslator()->trans('left_menu_no_retified');
  272.             $code FilterHelper::normaliseAltName($name);
  273.             $link FilterHelper::getUrl(str_replace([' ''-'], '_'StrHelper::toLower($name)));
  274.             $val = [
  275.                 'name' => $name,
  276.                 'link' => $this->fixLink($link),
  277.             ];
  278.             $settings['getEdgeType'][$code] = $val;
  279.         }
  280.         if (!empty($settings['getSurfaces'])) {
  281.             $surfaceList ArrHelper::get($settings'getSurfaces.antislip_surface.list');
  282.             if (!empty($settings['getSurfaces']['left_menu_antislip']) and $surfaceList) {
  283.                 unset($settings['getSurfaces']['antislip_surface']);
  284.                 $settings['getSurfaces']['left_menu_antislip']['list'] = $surfaceList;
  285.             }
  286.         }
  287.         // перенес дизайнеров в конец, что бы перечислением хоть как то адекватно вписалось к остальным свойствам
  288.         if (!empty($settings['getStylesDesigners'])) {
  289.             $designers $settings['getStylesDesigners'];
  290.             unset($settings['getStylesDesigners']);
  291.             $settings['getStylesDesigners'] = $designers;
  292.         }
  293.         $rankService App::getContainer()->get('app.service.rank');
  294.         if ($exhibitions) {
  295.             $exhibitions array_values($this->filterRepository->getExhibitions($collection['exhibition']));
  296.             foreach ($exhibitions as $i => $e) {
  297.                 $r = [
  298.                     'name' => $e['name'],
  299.                     'title' => $e['tooltip'],
  300.                     'link' => $e['urlLocal'],
  301.                     'nameGroup' => 'exhibition',
  302.                     'rank' => 0,
  303.                 ];
  304.                 $exhibitions[$i] = $r;
  305.             }
  306.             // добавляем хитро в начало
  307.             $settings array_reverse($settingstrue);
  308.             $settings['exhibitions'] = $exhibitions;
  309.             $settings array_reverse($settingstrue);
  310.         }
  311.         $settingsJoin = [];
  312.         foreach ($settings as $k => $row) {
  313.             // выстраиваем в ряд значения PEI, если их больше одного
  314.             if ($k == 'Pei' && count($row) > 1) {
  315.                 $pei = ['name' => 'PEI '];
  316.                 foreach ($row as $item) {
  317.                     $pei['name'] = $pei['name'] . trim(str_replace('PEI'''$item['name'])) . ', ';
  318.                     $pei['link'] = $this->fixLink($item['link']);
  319.                     $pei['title'] = $item['title'];
  320.                     $pei['noLower'] = $item['noLower'];
  321.                 }
  322.                 $pei['name'] = trim(trim($pei['name']), ',');
  323.                 $row = ['pei' => $pei];
  324.             }
  325.             foreach ($row as $i => $item) {
  326.                 $rank ArrHelper::get($item'rank'0);
  327.                 $row[$i]['rank'] = $rank;
  328.                 $row[$i]['size'] = $rankService->fontSizeByRank($rank);
  329.             }
  330.             $settingsJoin array_merge($settingsJoin$row);
  331.         }
  332.         // формируем размеры под свойства на основании RANK
  333.         //////////////////////////////////////////////////////////////
  334.         $rankArr = [];
  335.         foreach ($settingsJoin as $k => $row) {
  336.             // задаем значение для сортировки
  337.             $rankArr[$k] = $row['rank'];
  338.         }
  339.         $settingsSorting $settingsJoin;
  340.         array_multisort($rankArrSORT_DESC$settingsSorting);
  341.         // Формируем пороги для выделения размеров, выделяем первые две четверти
  342.         $cnt count($settingsJoin);
  343.         // количество выделяемых в четверти
  344.         $cnt = (int) ceil($cnt 4);
  345.         $i 0;
  346.         foreach ($settingsSorting as $key => $row) {
  347.             if (StrHelper::isInStr($key'pei_') or $key == 'antislip_surface' or !$key) {
  348.                 $settingsJoin[$key]['size'] = $rankService->fontSizeByRank(50);
  349.             } else {
  350.                 $i++;
  351.                 if ($i <= $cnt) {
  352.                     // первая четверть
  353.                     $settingsJoin[$key]['size'] = $rankService->fontSizeByRank(100);
  354.                 } elseif ($i $cnt and $i <= ($cnt 2)) {
  355.                     // вторая четверть
  356.                     $settingsJoin[$key]['size'] = $rankService->fontSizeByRank(80);
  357.                 } else {
  358.                     //  остальное
  359.                     $settingsJoin[$key]['size'] = $rankService->fontSizeByRank(50);
  360.                 }
  361.             }
  362.         }
  363.         if ($format == 'json') {
  364.             return new Response(json_encode($settingsJoin));
  365.         } elseif ($format == 'array') {
  366.             return $settingsJoin;
  367.         } elseif ($format == 'comby') {
  368.             $html $this->render(
  369.                 '@Web/Collection/setting.html.twig',
  370.                 [
  371.                     'locale' => $locale,
  372.                     'settings' => $settingsJoin,
  373.                     'flag' => $flag,
  374.                     'authorLink' => $authorLink,
  375.                 ]
  376.             );
  377.             $html trim(trim($html), ',');
  378.             return [
  379.                 'html' => $html,
  380.                 'array' => $settingsJoin,
  381.             ];
  382.         } else {
  383.             return new Response($this->render(
  384.                 '@Web/Collection/setting.html.twig',
  385.                 [
  386.                     'locale' => $locale,
  387.                     'settings' => $settingsJoin,
  388.                     'flag' => $flag,
  389.                     'authorLink' => $authorLink,
  390.                 ]
  391.             ));
  392.         }
  393.     }
  394.     /**
  395.      * @param $link
  396.      * @return string|string[]|null
  397.      */
  398.     private function fixLink($link)
  399.     {
  400.         return preg_replace('#/' App::getCurLocale() . '/#isUu''/' App::getCurLocale(true) . '/'$link);
  401.     }
  402.     /**
  403.      * @param array $collection
  404.      * @return string
  405.      * @throws Exception
  406.      */
  407.     public function getSettings(array $collection): string
  408.     {
  409.         if (empty($collection['fids'])) {
  410.             return '';
  411.         }
  412.         $filterGroups $this->filtersService
  413.             ->loadByIds($collection['fids'], App::getCurLocale())
  414.             ->buildFilterGroupsDTO();
  415.         // https://te2.remote.team/discus/BA6DD5B6-8F79-DA20-E6E6-7F983685A57D
  416.         $filterGroups
  417.             ->deleteGroup('apply')
  418.             ->deleteGroup('material')
  419.             ->deleteGroup('samples')
  420.             ->deleteGroup('using')
  421.             ->deleteGroup('designer')
  422.             ->deleteGroup('type');
  423.         $settings $this->filtersService->buldFiltersToStr($filterGroupstruefalsefalse);
  424.         return $settings;
  425.     }
  426.     /**
  427.      * @param array $aData
  428.      * @param array $aSettings
  429.      * @param $nameGroup
  430.      * @param null $author
  431.      * @return array
  432.      * @throws Exception
  433.      */
  434.     public function parseFiltersForSettings(array $aData, array $aSettings$nameGroup$author null)
  435.     {
  436.         if ($nameGroup == 'Pei') {
  437.             return $this->parsePeiForSettings($aData$aSettings);
  438.         }
  439.         return $this->parseBaseForSettings($aData$aSettings$nameGroup$author);
  440.     }
  441.     /**
  442.      * @param array $data
  443.      * @param array $aSettings
  444.      * @return array
  445.      * @throws Exception
  446.      */
  447.     private function parsePeiForSettings(array $data, array $aSettings)
  448.     {
  449.         $code FilterHelper::normaliseAltName($data['pei']);
  450.         if (!ArrHelper::get($aSettings'Pei.' $code)) {
  451.             $val = [
  452.                 'name' => $data['pei'],
  453.                 'link' => '',
  454.                 'title' => App::getTranslator()->trans('catalog.options.pei'),
  455.                 'noLower' => true,
  456.                 'rank' => 50,
  457.             ];
  458.             $aSettings['Pei'][$code] = $val;
  459.         }
  460.         return $aSettings;
  461.     }
  462.     /**
  463.      * @param array $aData
  464.      * @param array $aSettings
  465.      * @param $nameGroup
  466.      * @param null $author
  467.      * @return array
  468.      * @throws Exception
  469.      */
  470.     private function parseBaseForSettings(array $aData, array $aSettings$nameGroup$author null)
  471.     {
  472.         $aData = !ArrHelper::get($aData"0.id") ? [$aData] : $aData;
  473.         $lcFull App::getCurLocale(true);
  474.         $linkCatalog $url $this->generateUrl('app_catalog', ['_locale' => $lcFull]);
  475.         foreach ($aData as $data) {
  476.             // оптимизируем, проверяя на дубли свойств
  477.             $keyReady $nameGroup $data['id'];
  478.             if (in_array($keyReady$this->readySettings)) {
  479.                 continue;
  480.             }
  481.             $this->readySettings[] = $keyReady;
  482.             if ($nameGroup == 'getType') {
  483.                 $nameGroup 'getTypes';
  484.                 // фикс для моноколор
  485.             } elseif ($nameGroup == 'getFacturas' and $data['id'] == '99') {
  486.                 $nameGroup 'getColors';
  487.                 // фикс не верноого фильтра для типа карая Неректифицированный
  488.             } elseif ($nameGroup == 'getEdgeType' and $data['id'] == '5') {
  489.                 $data['id'] = 4;
  490.                 // спрятал из свойств стиль модерн по просьбе Жени https://te.remote.team/#/discus/89E08181-AE1F-67AC-0FA3-EDACFF049082/
  491.             } elseif ($nameGroup == 'getStyles' and $data['id'] == '11') {
  492.                 unset($aSettings[$nameGroup]);
  493.                 continue;
  494.             } elseif ($nameGroup == 'getFacturas') {
  495.                 // фактуры объемная и состаренная стали объемной и состаренной поверхностями.
  496.                 // https://te.remote.team/#/discus/07F31922-2ADC-9129-5616-86112BCFD072/
  497.                 if ($data['id'] == '14') {
  498.                     $nameGroup 'getSurfaces';
  499.                     $data['id'] = 11;
  500.                 } elseif ($data['id'] == '11') {
  501.                     $nameGroup 'getSurfaces';
  502.                     $data['id'] = 12;
  503.                 }
  504.             }
  505.             $code FilterHelper::normaliseAltName($data['alias']);
  506.             if (!ArrHelper::get($aSettings"{$nameGroup}.{$code}")) {
  507.                 $filter $this->filterRepository->findFilterForSettingsColletion($data['id'], $nameGroup);
  508.                 if ($filter) {
  509.                     $link $this->generateUrl('app_catalog', ['_locale' => $lcFull'key' => $filter['url']]);
  510.                     $name $filter['name'];
  511.                     // фикс для DE локали, там нужны заглавные
  512.                     if (App::getCurLocale() == 'de') {
  513.                         $name ucfirst($name);
  514.                     }
  515.                     // Если ссылка ведет на главную каталога, значит проблема. пишем в лог
  516.                     if ($link == $linkCatalog) {
  517.                         $this->oLogger->critical("[bad_collection_settings_link] nameGroup: {$nameGroup}, name: {$name}, alias: {$data['alias']}, url: {$this->oRequest->getRequestUri()}");
  518.                     }
  519.                     if (ArrHelper::get($aData'hide')) {
  520.                         $link '';
  521.                     }
  522.                     $link str_replace("?_locale={$lcFull}"''$link);
  523.                     $val = [
  524.                         'name' => $name,
  525.                         'link' => $link,
  526.                         'nameGroup' => $nameGroup,
  527.                         'rank' => ArrHelper::get($filter'rank'50),
  528.                     ];
  529.                     $aSettings[$nameGroup][$code] = $val;
  530.                 } else {
  531.                     // если фильтр не найден, тоже пишем в лог
  532.                     $this->oLogger->critical("[bad_collection_settings_link] NOT FOUND nameGroup: {$nameGroup}, id: {$data['id']}, alias: {$data['alias']}, url: {$this->oRequest->getRequestUri()}");
  533.                 }
  534.             }
  535.             // по старому ID стиля определяем дизайнеровский и выводим дизайнеров
  536.             if ($data['id'] == 17) {
  537.                 $authors $author ?: [];
  538.                 foreach ($authors as $i => $authorLink) {
  539.                     $authorLink trim($authorLink);
  540.                     $fAltName FilterHelper::normaliseAltName($authorLink);
  541.                     $code StrHelper::toLower($fAltName);
  542.                     if (!ArrHelper::get($aSettings'getStylesDesigners.' $code)) {
  543.                         // формируем заголовок для дизайнера со всякими приставками и ссылками
  544.                         $key $this->filterRepository->getKeyDesignerStyle();
  545.                         $href App::getRouter()->generate('app_catalog', ['key' => $key]);
  546.                         $header App::getTranslator()->trans('collection_header_designer');
  547.                         $replace FilterEntity::REPLACE_DESIGNE_RUSER;
  548.                         $replace $replace '|' StrHelper::toLower($replace);
  549.                         $header preg_replace_callback("/{$replace}/i", function ($matches) use ($href) {
  550.                             $name $matches[0];
  551.                             return "<a href=\"{$href}\">#{$name}</a>";
  552.                         }, $header);
  553.                         if ($i != 0) {
  554.                             $header null;
  555.                         }
  556.                         $val = [
  557.                             'header' => $header,
  558.                             'name' => $authorLink,
  559.                             'link' => $this->fixLink(FilterHelper::getUrl($fAltName)),
  560.                             'url' => $this->fixLink(FilterHelper::getUrl($fAltName)),
  561.                             'authorLink' => $authorLink,
  562.                         ];
  563.                         $aSettings['getStylesDesigners'][$code] = $val;
  564.                     }
  565.                 }
  566.             }
  567.         }
  568.         return $aSettings;
  569.     }
  570.     /**
  571.      * Получаем валидную коллекцию из базы
  572.      * @param $factoryUrl
  573.      * @param $collectionUrl
  574.      * @return array
  575.      * @throws Exception
  576.      */
  577.     public function findCollectionInDb($factoryUrl$collectionUrl): array
  578.     {
  579.         // Получаем коллекцию по редиректу
  580.         $curRoute App::getRequest()->get('_route');
  581.         $params App::getRequest()->get('_route_params');
  582.         $currentUrl App::getRequest()->getUri();
  583.         // перенаправляем те, что с _  на -,
  584.         $searchChar '_';
  585.         $changeChar '-';
  586.         $collUrl str_replace($searchChar$changeChar$collectionUrl);
  587.         $facUrl str_replace($searchChar$changeChar$factoryUrl);
  588.         if ($factoryUrl != $facUrl || $collectionUrl != $collUrl) {
  589.             $params['factoryUrl'] = $facUrl;
  590.             $params['collectionUrl'] = $collUrl;
  591.             $url $this->generateUrl($curRoute$params);
  592.             // если есть параметр gclid (добавляется AdWords), то оставляем его
  593.             if (strpos($currentUrl'gclid')) {
  594.                 $gclid substr($currentUrlstrpos($currentUrl'?gclid'));
  595.                 $url $url $gclid;
  596.             }
  597.             $redirect = new RedirectResponse(urldecode($url), 301);
  598.             return ['return' => $redirect];
  599.         }
  600.         $collection $this->collectionRepository->getMainBaseCollectionLight($factoryUrl$collectionUrl);
  601.         // проверка на сменный URL коллекции
  602.         if (!$collection) {
  603.             $redirect $this->lastUrlService->getCollectionRedirectUrl($collectionUrl$factoryUrl);
  604.             if ($redirect) {
  605.                 $response = new RedirectResponse($redirect);
  606.                 return ['return' => $response];
  607.             }
  608.         }
  609.         $collection $this->getMainBaseCollectionHandler($collection);
  610.         // Получаем коллекцию без фильтрации по статусу, и фильтруем руками, отдавая свою заглушку вместо стандартного 404
  611.         if (
  612.             !$collection
  613.             || $collection['status'] != CollectionAndFactoryStateEnum::STATE_PUBLISHED
  614.             && $collection['status'] != CollectionAndFactoryStateEnum::STATE_DISCONTINUED
  615.             && $collection['status'] != CollectionAndFactoryStateEnum::STATE_WORK_CONTINUED
  616.             && $collection['status'] != CollectionAndFactoryStateEnum::STATE_CHECKING
  617.             && $collection['publishDate'] == null //на основании https://te.remote.team/#/discus/7B2C1D62-1AFC-B81F-1E11-0DABFD79046D/
  618.         ) {
  619.             // сказали не разделять 404 теперь
  620.             throw new NotFoundHttpException('collection not found');
  621.         }
  622.         //на основании https://te.remote.team/#/discus/7B2C1D62-1AFC-B81F-1E11-0DABFD79046D/
  623.         if ($collection['status'] > 3) {
  624.             $collection['status'] = 3;
  625.         }
  626.         $user App::getCurUser();
  627.         if ($collection['testAccess'] && !($user && UserHelper::isEmployee($user->getEmail()))) {
  628.             throw new NotFoundHttpException('collection not found');
  629.         }
  630.         if ($collection['url'] != $collectionUrl || $collection['factory']['url'] != $factoryUrl) {
  631.             $params['factoryUrl'] = TranslitHelper::clearUrl($collection['factory']['url'], true);
  632.             $params['collectionUrl'] = TranslitHelper::clearUrl($collection['url'], true);
  633.             $url $this->generateUrl($curRoute$params);
  634.             // если есть параметр gclid (добавляется AdWords), то оставляем его
  635.             if (strpos($currentUrl'gclid')) {
  636.                 $gclid substr($currentUrlstrpos($currentUrl'?gclid'));
  637.                 $url $url $gclid;
  638.             }
  639.             $asJson App::getRequest()->get('as_json'null);
  640.             if ($asJson) {
  641.                 $url $url '?as_json=1';
  642.             }
  643.             $redirect = new RedirectResponse(urldecode($url), 301);
  644.             return ['return' => $redirect];
  645.         }
  646.         if (!empty($collection['id'])) {//count visits
  647.             $collId $collection['id'];
  648.             $oSession App::getSession();
  649.             $sessionCollData $oSession->get('collectionData');
  650.             //Session has not collId  >so> Collection->setViews(+1) && upd session  else -  continue
  651.             if (empty($sessionCollData[$collId])) {
  652.                 $this->collectionRepository->increaseViewByCollectionId((int) $collId);
  653.                 //upd session
  654.                 $sessionCollData[$collId] = '1';
  655.                 $oSession->set('collectionData'$sessionCollData);
  656.             }
  657.         }
  658.         return ['collection' => $collection];
  659.     }
  660.     /**
  661.      * Получаем строку с примененными фильтрами из FilterService, чистим ее и выдаем почищенную
  662.      * @param SearchService $oSearchService
  663.      * @return mixed|string
  664.      * @throws Exception
  665.      */
  666.     public function getSettingsFiltersCollection(SearchService $oSearchService)
  667.     {
  668.         $oFilterService App::getContainer()->get('app.service.filters');
  669.         $oSearchService->buildPageParams($oFilterService);
  670.         $list $oSearchService->getTitleHtml();
  671.         preg_match_all('#<strong>(.+?)</strong>#is'$list$arr);
  672.         $list trim(ArrHelper::get($arr'0.0'));
  673.         return $list;
  674.     }
  675.     /**
  676.      * Снята с производства коллекция или фабрика закрыта
  677.      * @param array $collection
  678.      * @return array|null
  679.      */
  680.     public function getAlertMessageIfCollectionInDiscontinuedState(array $collection): ?array
  681.     {
  682.         if (
  683.             $collection['status'] !== CollectionAndFactoryStateEnum::STATE_DISCONTINUED
  684.             && $collection['factory']['status'] !== CollectionAndFactoryStateEnum::STATE_DISCONTINUED
  685.         ) {
  686.             return null;
  687.         }
  688.         if ($collection['factory']['status'] == CollectionAndFactoryStateEnum::STATE_PUBLISHED) {
  689.             $url $this->generateUrl('app_catalog', [
  690.                 'key' => $collection['factory']['url'],
  691.             ]);
  692.             return $this->messageFiller->getMessageForDiscontinuedCollection($collection['name'], $collection['factory']['name'], $url);
  693.         }
  694.         $url $this->generateUrl('app_catalog');
  695.         return $this->messageFiller->getMessageForDiscontinuedFactory($collection['name'], $url);
  696.     }
  697.     private function getMainBaseCollectionHandler($collection): ?array
  698.     {
  699.         if ($collection && count($collection) > 0) {
  700.             $locale App::getCurLocale();
  701.             $body = !empty($collection['body']) ? $collection['body'][$locale] : null;
  702.             if ($body) {
  703.                 $body LocaleHelper::modifeLinkForLocales($body);
  704.                 $body StrHelper::replaceUmlautChar($body);
  705.                 $body TranslitNameHelper::replacePrime($bodyfalse);
  706.             }
  707.             $collection['body'] = $body;
  708.             $collection['metaKeywords'] = $collection['metaKeywords'] ? $collection['metaKeywords'][$locale] : null;
  709.             $collection['metaDescription'] = $collection['metaDescription'] ? $collection['metaDescription'][$locale] : null;
  710.             if (BiConst::CHOICE_ADDRESS_URL) {
  711.                 $furl StrAdm::toLower($collection['factory']['url']);
  712.                 $collection['factory']['url'] = $furl;
  713.                 $curl StrAdm::toLower($collection['url']);
  714.                 $collection['url'] = $curl;
  715.                 $collection['path'] = PathHelper::getImgWebPath() .
  716.                     $furl '/' .
  717.                     $curl .
  718.                     '/' BiConst::PER_SITO '/';
  719.             } else {
  720.                 $collection['path'] = PathHelper::getImgWebPath() .
  721.                     rawurlencode(TranslitHelper::clearDirName(StrAdm::toLower($collection['factory']['name']))) .
  722.                     '/' rawurlencode(str_replace(['~q~''&prime;'], '\''StrAdm::toLower($collection['name']))) . '/per_sito/';
  723.             }
  724.             $actualName = empty($collection['factory']['alternateName'])
  725.                 ? $collection['factory']['name']
  726.                 : $collection['factory']['alternateName'];
  727.             $collection['factory']['ActualName'] = str_replace(['~q~''&prime;'], '\''$actualName);
  728.             $actualName = empty($collection['alternateName']) ? $collection['name'] : $collection['alternateName'];
  729.             $collection['ActualName'] = str_replace(['~q~''&prime;'], '\''$actualName);
  730.             $collection['alt'] = $collection['factory']['ActualName'] . ' ' $collection['ActualName'] . ' ';
  731.             return $collection;
  732.         }
  733.         return null;
  734.     }
  735.     public function getCollectionForInformer(int $collectionId): array
  736.     {
  737.         $collection $this->collectionRepository->getCollectionForInformer($collectionId);
  738.         // проверяем наличие выставок и получаем по ним данные, если есть
  739.         $exhibitions = [];
  740.         if (!empty($collection['exhibition'])) {
  741.             $exhibitions $this->filterRepository->getExhibitions($collection['exhibition']);
  742.         }
  743.         $collection['exhibition'] = $exhibitions;
  744.         return $collection;
  745.     }
  746.     public function getPriceByCollection(array $collection): string
  747.     {
  748.         $typeDO true// флаг, что хоть один арт в м2
  749.         $measure null;
  750.         $minPrice 0;
  751.         /** @var Article $article */
  752.         foreach ($collection['articles'] ?? [] as $article) {
  753.             if (!empty($article['measure']) && $article['measure']['id'] == MeasureEnum::MQ) {
  754.                 $typeDO false;
  755.                 break;
  756.             } else {
  757.                 $newMinPrice LocaleHelper::getPrice($article);
  758.                 if ($minPrice $newMinPrice && $newMinPrice != || $minPrice == 0) {
  759.                     $minPrice $newMinPrice;
  760.                     if ($article['measure']) {
  761.                         $measure $article['measure']['id'] ?? null;
  762.                     }
  763.                 }
  764.             }
  765.         }
  766.         $prMin LocaleHelper::getPrMin($collection);
  767.         if ($typeDO) {
  768.             $transItem 'measure_unit';
  769.             if ($measure === MeasureEnum::SET) {
  770.                 $transItem 'measure_set';
  771.             } elseif ($measure === MeasureEnum::BOX) {
  772.                 $transItem 'measure_box';
  773.             }
  774.             return LocaleHelper::floatSign($minPrice) . ' ' LocaleHelper::getCurrency() . '/' $this->get('translator')->trans($transItem);
  775.         }
  776.         $measure LocaleHelper::measureGb() ? 'measure_ft' 'measure_mq';
  777.         $price LocaleHelper::floatSign($prMin) . ' ' LocaleHelper::getCurrency() .
  778.             '/' $this->get('translator')->trans($measure);
  779.         return $price;
  780.     }
  781. }