src/WebBundle/Service/FiltersService.php line 416

Open in your IDE?
  1. <?php
  2. namespace WebBundle\Service;
  3. use AdmBundle\Helper\Adm;
  4. use Exception;
  5. use FlexApp\Constant\CatalogConst;
  6. use FlexApp\DTO\BrandResponseDTO;
  7. use FlexApp\DTO\FilterCatalogDTO;
  8. use FlexApp\DTO\FilterGroupCatalogDTO;
  9. use FlexApp\DTO\FilterGroupsCatalogDTO;
  10. use FlexApp\DTO\FilterResponseDTO;
  11. use FlexApp\Service\RedisCachePool;
  12. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  13. use WebBundle\Entity\Article;
  14. use WebBundle\Entity\Collection;
  15. use WebBundle\Helper\App;
  16. use WebBundle\Helper\ArrHelper;
  17. use WebBundle\Helper\ConversionHelper;
  18. use WebBundle\Helper\LocaleHelper;
  19. use WebBundle\Helper\RequestHelper;
  20. use WebBundle\Helper\StrHelper;
  21. use WebBundle\Repository\ArticleRepository;
  22. use WebBundle\Repository\CollectionRepository;
  23. use WebBundle\Repository\FilterRepository;
  24. use WebBundle\Repository\LastUrlRepository;
  25. class FiltersService extends ExtendService
  26. {
  27.     private string $locale;
  28.     private ?int $alsoCollViewedId null;
  29.     private ?bool $isOneFilter null;
  30.     private $urlKeyStr = [];
  31.     /** @var array|FilterResponseDTO[] */
  32.     private array $curFilters = [];
  33.     /** массив id фильтров */
  34.     protected $aCurFilterIds = [];
  35.     /** не найденные ключи из строки запроса*/
  36.     protected array $aBadKeys = [];
  37.     /** разделить параметров УРЛ фильтров  '&'*/
  38.     protected string $separator CatalogConst::SEPARATOR;
  39.     /** Массив для фильтра размеров */
  40.     private array $aDimensions = [];
  41.     /** Массив для фильтра БМов */
  42.     private array $aBMs = [];
  43.     /** @var CollectionRepository */
  44.     protected $collRepo;
  45.     /** @var FilterRepository */
  46.     protected $filterRepo;
  47.     /** @var ArticleRepository */
  48.     protected $articleRepo;
  49.     /**
  50.      * @throws Exception
  51.      */
  52.     public function __construct()
  53.     {
  54.         $this->locale App::getCurLocale();
  55.         $this->collRepo App::getRepository('WebBundle:Collection');
  56.         $this->filterRepo App::getRepository('WebBundle:FilterEntity');
  57.         $this->articleRepo App::getRepository('WebBundle:Article');
  58.         return $this;
  59.     }
  60.     /**
  61.      * Сортировка , что бы вывод был в том положении, как лайт меню
  62.      * @return FilterResponseDTO[]
  63.      */
  64.     private function getSortedFiltersLikeInTheLiteMenu()
  65.     {
  66.         $pattern = [
  67.             'brand',
  68.             'effect',
  69.             'style',
  70.             'price',
  71.             'color',
  72.             'using',
  73.             'samples',
  74.         ];
  75.         $arr = [];
  76.         foreach ($this->curFilters as $filter) {
  77.             $arr[$filter->getGroupAltName()][] = $filter;
  78.         }
  79.         $res = [];
  80.         foreach (array_flip($pattern) as $k => $v) {
  81.             if (isset($arr[$k])) {
  82.                 $res[$k] = $arr[$k];
  83.                 unset($arr[$k]);
  84.             }
  85.         }
  86.         $af = [];
  87.         foreach ($res as $v) {
  88.             $af array_merge($af$v);
  89.         }
  90.         foreach ($arr as $v) {
  91.             $af array_merge($af$v);
  92.         }
  93.         return $af;
  94.     }
  95.     /**
  96.      * @param array $curFilters
  97.      */
  98.     private function setCurFilters(array $curFilters)
  99.     {
  100.         $this->curFilters $curFilters;
  101.     }
  102.     private function margeFilters()
  103.     {
  104.         $parentMap $this->filterRepo->getFiltersSubRelation(true);
  105.         $result $this->aCurFilterIds;
  106.         foreach ($parentMap as $parentId => $childIds) {
  107.             // Проверяем, все ли дочерние ID присутствуют в выбранных фильтрах
  108.             $allChildrenPresent true;
  109.             foreach ($childIds as $childId) {
  110.                 if (!in_array($childId$result)) {
  111.                     $allChildrenPresent false;
  112.                     break;
  113.                 }
  114.             }
  115.             // Если все дети присутствуют, заменяем их на родителя
  116.             if ($allChildrenPresent) {
  117.                 $result array_diff($result$childIds); // Удаляем детей
  118.                 $result[] = $parentId// Добавляем родителя
  119.             }
  120.         }
  121.         $this->aCurFilterIds array_values($result);
  122.     }
  123.     public function isMargeFilters(int $filterId 0): bool
  124.     {
  125.         $parentMap $this->filterRepo->getFiltersSubRelation(true);
  126.         if (array_key_exists($filterId$parentMap)) {
  127.             return true;
  128.         }
  129.         return false;
  130.     }
  131.     public function unMargeFilters()
  132.     {
  133.         $parentMap $this->filterRepo->getFiltersSubRelation(true);
  134.         $results $this->aCurFilterIds;
  135.         foreach ($results as $result) {
  136.             // Проверяем, все ли дочерние ID присутствуют в выбранных фильтрах
  137.             $allChildrenPresent true;
  138.             if (array_key_exists($result$parentMap)) {
  139.                 $results array_merge($parentMap[$result], $results);
  140.                 //$results = array_diff($results, [$result]);
  141.             }
  142.         }
  143.         $this->aCurFilterIds array_values($results);
  144.         $filters $this->filterRepo->getSortedByIds($this->aCurFilterIds$this->locale);
  145.         $this->setCurFilters($filters);
  146.     }
  147.     /**
  148.      * Универсальная загрузка данных, написал, но еще не использовал
  149.      * @param null $locale
  150.      * @return $this
  151.      * @throws Exception
  152.      */
  153.     private function loadDataUniversal($locale null)
  154.     {
  155.         $locale = !$locale $this->locale $locale;
  156.         if (!$this->curFilters) {
  157.             if (RequestHelper::isAjax()) {
  158.                 $this->loadBySearchData(RequestHelper::get('data', []));
  159.             } else {
  160.                 $this->loadByUrlKey(App::getRequest()->get('key'), $locale);
  161.             }
  162.         }
  163.         return $this;
  164.     }
  165.     /**
  166.      * Поиск по ID фильтров
  167.      * @param $id
  168.      * @return $this
  169.      */
  170.     public function loadByIds($idstring $lc)
  171.     {
  172.         $id is_array($id) ? $id : [$id];
  173.         $this->aCurFilterIds = [];
  174.         $idsParam = [];
  175.         foreach ($id as $item) {
  176.             // обработка через :: для запросов по размерам, т.к. ID там идет вида 56564::0.5
  177.             // где первое - ID, а второе параметр
  178.             $ids explode('::'$item);
  179.             $this->aCurFilterIds[] = $ids[0];
  180.             if (count($ids) > 1) {
  181.                 $idsParam[$ids[0]] = $ids[1];
  182.             }
  183.         }
  184.         $this->margeFilters();
  185.         $filters $this->filterRepo->getSortedByIds($this->aCurFilterIds$lc);
  186.         foreach ($filters as $i => $filter) {
  187.             // исключаем не активные фильры, если это не фабрики
  188.             if (!$filter->isEnable() and !$filter->getBrand()) {
  189.                 unset($filters[$i]);
  190.             }
  191.         }
  192.         if (count($idsParam) > 0) {
  193.             foreach ($filters as $filter) {
  194.                 if ($filter->isDimension()) {
  195.                     $this->aDimensions[$filter->getAltName()] = $idsParam[$filter->getId()];
  196.                 }
  197.                 if ($filter->isBM()) {
  198.                     $this->aBMs[$filter->getAltName()] = $idsParam[$filter->getId()];
  199.                 }
  200.             }
  201.         }
  202.         $this->setCurFilters($filters);
  203.         return $this;
  204.     }
  205.     public function loadBySearchData($data)
  206.     {
  207.         if (count($data) > 0) {
  208.             $keys $this->findByBaseInOldCommand($data);
  209.             /**
  210.              * Получаем ID сортировки из запроса
  211.              */
  212.             $sortId RequestHelper::get('sort');
  213.             if (!$sortId) {
  214.                 $sortId ArrHelper::get($this->getSearchFilter(), 'getSort.0');
  215.                 $cookies App::getRequest()->cookies;
  216.                 // если нашли ID сортировки, то пишем его в куки
  217.                 if ($sortId) {
  218.                     $cookies->set('sort_catalog'$sortId);
  219.                 }
  220.                 // получаем итоговую сортировку
  221.                 $sortId $cookies->get('sort_catalog');
  222.                 // если не определна. то ставим поппулярность по умолчанию.
  223.                 if (!$sortId) {
  224.                     $cookies->set('sort_catalog'1);
  225.                 }
  226.             }
  227.             $sStyleDesigner $this->isStyleDesignerAndDesigner($keys);
  228.             // пишем ID фильров в массив, из которого и будем формировать всякие URL и прочее
  229.             foreach ($keys as $filter) {
  230.                 if ($filter->isEnable()) {
  231.                     // выкидываем из фильтров сочетание дизайнера + дизайнерский стиль
  232.                     if ($sStyleDesigner) {
  233.                         if ($filter->isDesignerStyle()) {
  234.                             continue;
  235.                         }
  236.                     }
  237.                     if ($filter->isSort()) {
  238.                         continue;
  239.                     }
  240.                     $this->aCurFilterIds[] = $filter->getId();
  241.                     // проверяем на наличие группы фильтров с размерами, если нашли, то
  242.                     // получаем KEY фильтра в текущей локали и по нему ищем значение с троке
  243.                     // после чего формируем массив вида ["size_x" => "40"]
  244.                     if ($filter->isDimension()) {
  245.                         $alias $filter->getAltName();
  246.                         foreach ($data as $iAlias => $aVal) {
  247.                             if ($iAlias == $alias) {
  248.                                 $this->aDimensions[$alias] = $aVal[0];
  249.                             }
  250.                         }
  251.                     }
  252.                     if ($filter->isBM()) {
  253.                         $alias $filter->getAltName();
  254.                         foreach ($data as $iAlias => $aVal) {
  255.                             if ($iAlias == $alias) {
  256.                                 $this->aBMs[$alias] = $aVal[0];
  257.                             }
  258.                         }
  259.                     }
  260.                 }
  261.             }
  262.             // делаем еще запрос в базу, что бы получить объекты фильтров в нужной сортировке
  263.             $this->margeFilters();
  264.             $this->setCurFilters($this->filterRepo->getSortedByIds($this->aCurFilterIds$this->locale));
  265.         }
  266.         return $this;
  267.     }
  268.     /**
  269.      * Инициируем сам класс, по разбору строки запроса
  270.      * с поиском данных в базе фильтров
  271.      * @param string|null $key
  272.      * @param null $locale
  273.      * @return $this
  274.      * @throws Exception
  275.      */
  276.     public function loadByUrlKey($key$locale null)
  277.     {
  278.         if ($key) {
  279.             $keys $this->urlToArray($key);
  280.             $cntDesigner 0;
  281.             if (count($keys) > 0) {
  282.                 $filters $this->findByBase($keys$locale);
  283.                 // если фильтр AlsoCollViewed , то остальные убираем, на вариант с совпадением по ID
  284.                 if (!empty($filters[10504])) {
  285.                     $filters = [$filters[10504]];
  286.                     $this->alsoCollViewedId $keys[1];
  287.                 }
  288.                 /**
  289.                  * пишем ID фильров в массив, из которого и будем формировать всякие URL и прочее
  290.                  */
  291.                 foreach ($filters as $filter) {
  292.                     // исключаем не активные фильры, если это не фабрики
  293.                     if (!$filter->isEnable() and !$filter->isBrand()) {
  294.                         continue;
  295.                     }
  296.                     // фабрики проверяем дополнительно
  297.                     if ($oBrand $filter->getBrand()) {
  298.                         if (!$oBrand->isShowPage()) {
  299.                             continue;
  300.                         }
  301.                     }
  302.                     // для дизайнеров ограничиваем вывод - не более одного фильтруется
  303.                     if ($filter->isDesignerUser()) {
  304.                         if ($cntDesigner !== 0) {
  305.                             continue;
  306.                         }
  307.                         $cntDesigner++;
  308.                     }
  309.                     // если в запросе сортировка, то пишем данные в куки, а сам фильтр исключаем
  310.                     if ($filter->isSort()) {
  311.                         $cookies App::getRequest()->cookies;
  312.                         if (RequestHelper::get('sort-tmp')) {
  313.                             // временное изменение сортировки, для ссылки New Arrivals с главной сайта
  314.                             App::getSession()->set('sort_catalog_tmp'$filter->getSphinxId());
  315.                         } else {
  316.                             $cookies->set('sort_catalog'$filter->getSphinxId());
  317.                         }
  318.                         continue;
  319.                     }
  320.                     $this->aCurFilterIds[] = $filter->getId();
  321.                     $this->aCurFilterIds array_unique($this->aCurFilterIds);
  322.                     // проверяем на наличие группы фильтров с размерами, если нашли, то
  323.                     // получаем KEY фильтра в текущей локали и по нему ищем значение с троке
  324.                     // после чего формируем массив вида ["size_x" => "40"]
  325.                     if ($filter->isDimension()) {
  326.                         foreach ($keys as $iKey) {
  327.                             $keyDimensionsAll $filter->getSlugsLc();
  328.                             foreach ($keyDimensionsAll as $keyDim) {
  329.                                 if (strval($keyDim) && strpos($iKeystrval($keyDim)) !== false) {
  330.                                     $size str_replace($keyDim '-'''$iKey);
  331.                                     $this->aDimensions[$filter->getAltName()] = $size;
  332.                                 }
  333.                             }
  334.                         }
  335.                     }
  336.                     if ($filter->isBM()) {
  337.                         foreach ($keys as $iKey) {
  338.                             $keyBMs $filter->getSlug();
  339.                             if (strval($keyBMs) && strpos($iKeystrval($keyBMs)) !== false) {
  340.                                 $this->aBMs[$filter->getAltName()] = str_replace($keyBMs '-'''$iKey);
  341.                             }
  342.                         }
  343.                     }
  344.                 }
  345.                 // делаем еще запрос в базу, что бы получить объекты фильтров в нужной сортировке
  346.                 if ($this->aCurFilterIds) {
  347.                     $this->margeFilters();
  348.                     $filters $this->filterRepo->getSortedByIds($this->aCurFilterIds$locale);
  349.                     $this->setCurFilters($filters);
  350.                 }
  351.             }
  352.         }
  353.         return $this;
  354.     }
  355.     /**
  356.      * @param $altName
  357.      * @param string $locale
  358.      * @return $this
  359.      * @throws Exception
  360.      */
  361.     public function loadByAltName($altNamestring $locale)
  362.     {
  363.         $altName is_array($altName) ? $altName : [$altName];
  364.         $filters $this->filterRepo->getByAltNames($altName);
  365.         $fids = [];
  366.         foreach ($filters as $filter) {
  367.             $fids[] = $filter->getId();
  368.         }
  369.         $this->loadByIds($fids$locale);
  370.         return $this;
  371.     }
  372.     /**
  373.      * @param null $papam
  374.      * @param null $locale
  375.      * @return mixed
  376.      * @throws Exception
  377.      */
  378.     public function getUrl($papam null$locale null)
  379.     {
  380.         $word $this->getWord($papam$locale);
  381.         return $this->getFullUrlKeyStr($word$locale);
  382.     }
  383.     /**
  384.      * Получение KEY для URL строки
  385.      * @param null $papam
  386.      * @param null $locale
  387.      * @return string
  388.      * @throws Exception
  389.      */
  390.     public function getWord($papam null$locale null)
  391.     {
  392.         $locale = !$locale $this->locale $locale;
  393.         if (!$this->curFilters) {
  394.             if (!$papam) {
  395.                 // если ничего нет, то грузим то, что есть сейчас в зависимости от типа запроса
  396.                 $this->loadDataUniversal($locale);
  397.             } else {
  398.                 if (is_array($papam)) {
  399.                     if (!empty($papam[0])) {
  400.                         // массив индексный
  401.                         if (intval($papam[0]) === $papam[0]) {
  402.                             // ищем по ID
  403.                             $this->loadByIds($papam$locale);
  404.                         } else {
  405.                             // ищем по altName
  406.                             $this->loadByAltName($papam$locale);
  407.                         }
  408.                     } else {
  409.                         // массив именованый, значит имеем вид запроса ['getUsings'=>[10,12,58]]
  410.                         $this->loadBySearchData($papam);
  411.                     }
  412.                 } else {
  413.                     // если значение строковое, то обрабатываем отдельно
  414.                     if (strripos($papam$this->separator) !== false) {
  415.                         // ищем по KEY url
  416.                         $this->loadByUrlKey($papam$locale);
  417.                     } else {
  418.                         if (intval($papam) === $papam) {
  419.                             // ищем по ID
  420.                             $this->loadByIds($papam$locale);
  421.                         } else {
  422.                             // ищем по KEY url
  423.                             $this->loadByUrlKey($papam$locale);
  424.                             if (count($this->curFilters) < 1) {
  425.                                 // ищем по altName
  426.                                 $this->loadByAltName($papam$locale);
  427.                             }
  428.                         }
  429.                     }
  430.                 }
  431.             }
  432.         }
  433.         return $this->getUrlKeyStr($locale);
  434.     }
  435.     /**
  436.      * Получаем полную строку вместе с KEY по загруженным ранее данным
  437.      * @param null $key
  438.      * @param null $locale
  439.      * @return mixed
  440.      */
  441.     public function getFullUrlKeyStr($key null$locale null)
  442.     {
  443.         if (!$key) {
  444.             $key $this->getUrlKeyStr($locale);
  445.         }
  446.         // пока убрал, т.к. через него лезут левые запросы, нам не нужные
  447.         //      $subkey = RequestHelper::syRequest()->get('subkey');
  448.         //      if ($subkey) {
  449.         //          $params['subkey'] = $subkey;
  450.         //      }
  451.         $params['key'] = $key;
  452.         if ($locale) {
  453.             // если локаль соответсвует текущей, то проверяем на страну доставки
  454.             if ($locale == $this->locale) {
  455.                 $locale App::getCurLocale(true);
  456.             }
  457.             $params['_locale'] = $locale;
  458.         }
  459.         return str_replace('%26''&'$this->generateUrl('app_catalog'$params));
  460.     }
  461.     /**
  462.      * Получаем строку KEY по загруженным ранее данным
  463.      * Получение происходит по ID фильтров из массива
  464.      * @param null $locale
  465.      * @return string
  466.      */
  467.     public function getUrlKeyStr($locale null)
  468.     {
  469.         $locale = ($locale != null) ? $locale $this->locale;
  470.         if (empty($this->urlKeyStr[$locale])) {
  471.             $str '';
  472.             $isStyleDesignerClear $this->isStyleDesignerAndDesigner();
  473.             foreach ($this->curFilters as $filter) {
  474.                 // фильтр галвной каталога игнорируем при генерации URL
  475.                 if (!$filter->isRootCataloge()) {
  476.                     $slug $filter->getSlug($locale);
  477.                     if ($filter->isDimension()) {
  478.                         $altName $filter->getAltName();
  479.                         $size = (float) $this->aDimensions[$altName];
  480.                         $slug $slug '-' $size;
  481.                     }
  482.                     if ($filter->isBM()) {
  483.                         $altName $filter->getAltName();
  484.                         $slug $slug '-' $this->aBMs[$altName];
  485.                     }
  486.                     // урл сортировки не выводим
  487.                     if ($filter->isSort()) {
  488.                         $slug '';
  489.                     }
  490.                     if ($isStyleDesignerClear and $filter->isDesignerStyle()) {
  491.                         $slug '';
  492.                     }
  493.                     $str .= $slug $this->separator;
  494.                 }
  495.             }
  496.             $this->urlKeyStr[$locale] = trim($str$this->separator);
  497.         }
  498.         return $this->urlKeyStr[$locale];
  499.     }
  500.     //{"searchFilter":{"getFacturas":["5"]},"searchSort":"2","searchPeriod":null,"locale":"en"}
  501.     public function getSearchFilter()
  502.     {
  503.         $aSearchFilter = [];
  504.         foreach ($this->curFilters as $filter) {
  505.             $alias $filter->getSphinxName();
  506.             $id false;
  507.             if ($filter->isDimension()) {
  508.                 // если фильтр размеров, то ставим значение поиска, вместо ID фильтра
  509.                 // для строки &width-from-12000 это будет 1200
  510.                 $val = (float) $this->aDimensions[$alias];
  511.             } elseif ($filter->isBM()) {
  512.                 // если фильтр bm, то ставим значение поиска, вместо ID фильтра
  513.                 // для строки &bm-123123 это будет 123123
  514.                 $val $this->aBMs[$alias];
  515.             } elseif ($filter->isTop()) {
  516.                 // если фильтр top, то ставим значение subkey, вместо ID фильтра
  517.                 $val RequestHelper::get('subkey');
  518.                 //  $val = $filter->getId();
  519.             } elseif ($filter->isDesignerUser()) {
  520.                 // пока для дизайнеров делаем параметром их имя
  521.                 $val $filter->getNameSingle();
  522.                 $id $filter->getId();
  523.             } else {
  524.                 $val $filter->getSphinxId();
  525.             }
  526.             if ($id != false) {
  527.                 $aSearchFilter[$alias][] = "{$id}";
  528.             }
  529.             $aSearchFilter[$alias][] = "{$val}";
  530.         }
  531.         return (count($aSearchFilter) > 0) ? $aSearchFilter null;
  532.     }
  533.     /**
  534.      * @param array $data
  535.      * @return array|FilterResponseDTO[]
  536.      * @throws \Doctrine\DBAL\Driver\Exception
  537.      * @throws \Doctrine\DBAL\Exception
  538.      */
  539.     private function findByBaseInOldCommand(array $data)
  540.     {
  541.         $aKeysNew = [];
  542.         if (count($data) > 0) {
  543.             $filterRepo $this->filterRepo;
  544.             // первый проход поиска, ищем по колному кею
  545.             foreach ($data as $old_command => $ids) {
  546.                 // исключаем запросы с коллекциями
  547.                 if ($old_command == 'collection') {
  548.                     continue;
  549.                 }
  550.                 if ($old_command == 'factory') {
  551.                     if (count($ids) > 1) {
  552.                         unset($ids[1]);
  553.                     }
  554.                 } elseif ($old_command == 'getAlsoCollViewed') {
  555.                     $ids = [0];
  556.                 }
  557.                 if ($old_command == 'collection') {
  558.                     continue;
  559.                 }
  560.                 if ($old_command == 'getDesigner') {
  561.                     $filters $filterRepo->getSortedByIds($ids$this->locale);
  562.                 } else {
  563.                     if (!is_array($ids)) {
  564.                         $ids = [$ids];
  565.                     }
  566.                     $filters $filterRepo->getByOldCommand($ids$old_command$this->locale);
  567.                 }
  568.                 if ($filters) {
  569.                     unset($data[$old_command]);
  570.                     foreach ($filters as $filter) {
  571.                         $aKeysNew[$filter->getId()] = $filter;
  572.                     }
  573.                 } else {
  574.                     $filters $filterRepo->getFilterDTOByAltName($old_command$this->locale);
  575.                     if (count($filters) == 1) {
  576.                         $filter $filters[0];
  577.                         unset($data[$old_command]);
  578.                         $aKeysNew[$filter->getId()] = $filter;
  579.                     }
  580.                 }
  581.             }
  582.         }
  583.         // если в массиве еще остались значения , то пишем значения в массив в бед кеями
  584.         // что с ним потом делать пока не знаю, но что то делать будет надо
  585.         if (count($data) > 0) {
  586.             foreach ($data as $key) {
  587.                 $this->aBadKeys[] = $key;
  588.             }
  589.         }
  590.         return $aKeysNew;
  591.     }
  592.     /**
  593.      * Ищем значения в базе по имени фильтра
  594.      * @param array $aKeys
  595.      * @param string|null $locale
  596.      * @return array|FilterResponseDTO[]
  597.      * @throws \Doctrine\DBAL\Driver\Exception
  598.      * @throws \Doctrine\DBAL\Exception
  599.      */
  600.     private function findByBase(array $aKeys$locale null)
  601.     {
  602.         $aKeysNew = [];
  603.         $repoFilter $this->filterRepo;
  604.         if (count($aKeys) > 0) {
  605.             $isSort false;
  606.             // первый проход поиска, ищем по полному кею
  607.             foreach ($aKeys as $i => $key) {
  608.                 // доп логика для фильтрации БМов
  609.                 if (preg_match("/^bm-(\d*)$/"$key)) {
  610.                     $key 'bm';
  611.                 }
  612.                 $filter $repoFilter->getByKeyUrl($key$locale);
  613.                 // если фильтр не нашли, то проходимся дополнительно разложив кей на части
  614.                 if (!$filter) {
  615.                     $dopKeys $this->buldExplodeKeys($key);
  616.                     foreach ($dopKeys as $dkey) {
  617.                         $filter $repoFilter->getByKeyUrl($dkey$locale);
  618.                         if ($filter) {
  619.                             break;
  620.                         }
  621.                     }
  622.                     if (!$filter) {
  623.                         foreach ($dopKeys as $dkey) {
  624.                             $filter $repoFilter->getByKeyUrlIsLike($dkey$locale);
  625.                             if ($filter) {
  626.                                 break;
  627.                             }
  628.                         }
  629.                     }
  630.                 }
  631.                 if ($filter) {
  632.                     // проверка на включенный фильтр
  633.                     // фильтр может быть отключен, если это фабрика. Фабрику выводим в любом случае
  634.                     if ($filter->isEnable() or $filter->isBrand()) {
  635.                         // проверяем, что бы сортировка была только одна
  636.                         if ($filter->isSort() && !$isSort) {
  637.                             $isSort true;
  638.                         }
  639.                         unset($aKeys[$i]);
  640.                         $aKeysNew[$filter->getId()] = $filter;
  641.                     }
  642.                 }
  643.             }
  644.             // если в массиве еще остались значения , то дополнительно проверяем на наличие редиректов
  645.             if (count($aKeys) > 0) {
  646.                 /** @var $repoLastUrl LastUrlRepository */
  647.                 $repoLastUrl App::getRepository('WebBundle:LastUrlEntity');
  648.                 foreach ($aKeys as $i => $key) {
  649.                     if ($keyTmp $repoLastUrl->getActualSlugFiflter($key$locale)) {
  650.                         if ($filter $this->filterRepo->getByKeyUrl($keyTmp$locale)) {
  651.                             unset($aKeys[$i]);
  652.                             $aKeysNew[$filter->getId()] = $filter;
  653.                         }
  654.                     }
  655.                 }
  656.             }
  657.         }
  658.         // если в массиве еще остались значения , то пишем значения в массив в бед кеями
  659.         // что с ним потом делать пока не знаю, но что то делать будет надо
  660.         if (count($aKeys) > 0) {
  661.             foreach ($aKeys as $key) {
  662.                 $this->aBadKeys[] = $key;
  663.             }
  664.         }
  665.         return $aKeysNew;
  666.     }
  667.     /**
  668.      * @return array|FilterResponseDTO[]
  669.      */
  670.     public function getCurFilters()
  671.     {
  672.         return $this->curFilters;
  673.     }
  674.     /**
  675.      * @return array
  676.      */
  677.     public function getDimensions()
  678.     {
  679.         return $this->aDimensions;
  680.     }
  681.     /**
  682.      * @param mixed $aDimensions
  683.      */
  684.     public function setDimensions($aDimensions)
  685.     {
  686.         $this->aDimensions $aDimensions;
  687.     }
  688.     /**
  689.      * @return array
  690.      */
  691.     public function getBMs()
  692.     {
  693.         return $this->aBMs;
  694.     }
  695.     /**
  696.      * @param mixed $aBMs
  697.      */
  698.     public function setBMs($aBMs)
  699.     {
  700.         $this->aBMs $aBMs;
  701.     }
  702.     /**
  703.      * Формируем многомерный массив из строки запроса с фильтрами
  704.      * @param $key
  705.      * @return array
  706.      */
  707.     private function urlToArray($key)
  708.     {
  709.         $key StrHelper::toLower($key);
  710.         $key trim(urldecode($key));
  711.         $key $key explode($this->separator$key) : [];
  712.         return array_diff($key, [''' 'nullfalse]);
  713.     }
  714.     /**
  715.      * Получаем объект фабрики, если таковая есть в фильтрах
  716.      * @return null|BrandResponseDTO
  717.      */
  718.     public function getCurBrand()
  719.     {
  720.         foreach ($this->getCurFilters() as $curFilter) {
  721.             if ($brand $curFilter->getBrand()) {
  722.                 return $brand;
  723.             }
  724.         }
  725.         return null;
  726.     }
  727.     /**
  728.      * Определяем сколько фильтров примененно, без учета сортировки
  729.      * @return bool
  730.      */
  731.     public function isOneFilter()
  732.     {
  733.         if ($this->isOneFilter === null) {
  734.             $aCurFilters $this->getCurFilters();
  735.             $countFilters count($aCurFilters);
  736.             if ($countFilters 1) {
  737.                 foreach ($aCurFilters as $filter) {
  738.                     if ($filter->isSort()) {
  739.                         $countFilters--;
  740.                     } else {
  741.                         if (!$filter->isEnable()) {
  742.                             $countFilters--;
  743.                         }
  744.                     }
  745.                 }
  746.             }
  747.             $this->isOneFilter = ($countFilters == 1);
  748.         }
  749.         return $this->isOneFilter;
  750.     }
  751.     /**
  752.      * Проверка на тестовую фабрику
  753.      * @return bool
  754.      */
  755.     public function isTestingBrand()
  756.     {
  757.         foreach ($this->curFilters as $filter) {
  758.             if ($filter->getAltName() == 'testing_factory') {
  759.                 return true;
  760.             }
  761.         }
  762.         return false;
  763.     }
  764.     /**
  765.      * Проверка на принадлежность к топу
  766.      * @return bool
  767.      */
  768.     public function isTopFilter()
  769.     {
  770.         foreach ($this->curFilters as $filter) {
  771.             if ($filter->isTop() && !$filter->isAlsoCollViewed()) {
  772.                 return true;
  773.             }
  774.         }
  775.         return false;
  776.     }
  777.     /**
  778.      * Проверка на сочетание двых выбранных фильтров дизайнерский стиль + любой дизайнер
  779.      * @param array $filters
  780.      * @return bool
  781.      */
  782.     public function isStyleDesignerAndDesigner(array $filters = [])
  783.     {
  784.         $filters $filters ?: $this->curFilters;
  785.         if (count($filters) == 2) {
  786.             $isDesigner $this->isExistDesigner($filters);
  787.             if ($isDesigner) {
  788.                 foreach ($filters as $filter) {
  789.                     if ($filter->isDesignerStyle()) {
  790.                         return true;
  791.                     }
  792.                 }
  793.             }
  794.         }
  795.         return false;
  796.     }
  797.     public function isExistDesigner(array $filters = []): bool
  798.     {
  799.         $filters $filters ?: $this->curFilters;
  800.         foreach ($filters as $filter) {
  801.             if ($filter->isDesignerUser()) {
  802.                 return true;
  803.             }
  804.         }
  805.         return false;
  806.     }
  807.     /**
  808.      * Получаем вильтр сортировки, если таковой был в запросе
  809.      * @return null|FilterResponseDTO
  810.      */
  811.     public function getSortFilter()
  812.     {
  813.         foreach ($this->getCurFilters() as $curFilter) {
  814.             if ($curFilter->isSort()) {
  815.                 return $curFilter;
  816.             }
  817.         }
  818.         return null;
  819.     }
  820.     /**
  821.      * @param FilterGroupsCatalogDTO $filterGroups
  822.      * @param bool $isShot
  823.      * @param bool $isLinkToFilter
  824.      * @param bool $isLinkEdit
  825.      * @return string
  826.      */
  827.     public function buldFiltersToStr(
  828.         FilterGroupsCatalogDTO $filterGroups,
  829.         bool $isShot false,
  830.         bool $isLinkToFilter false,
  831.         bool $isLinkEdit true
  832.     ) {
  833.         if ($this->alsoCollViewedId) {
  834.             return $filterGroups->getFirstGroup()->getFirstFilter()->getTitle();
  835.         }
  836.         $and $this->translate('joinder_and'$this->locale);
  837.         $ceramicTilesName $this->translate('catalog_ceramic_tiles'$this->locale);
  838.         $sTtitle2 "$ceramicTilesName ";
  839.         $isShowLinkStyleDesigner $isLinkToFilter;
  840.         if ($this->isOneFilter()) {
  841.             $sTtitle2 '';
  842.             $isLinkToFilter false;
  843.             $isShowLinkStyleDesigner $this->isExistDesigner();
  844.         }
  845.         if ($this->isOneFilter() && $this->getCurBrand()) {
  846.             $isLinkEdit false;
  847.         }
  848.         // type (вид изделия)
  849.         if ($typeGroup $filterGroups->getProductType()) {
  850.             $sTtitle2 $this->modifyFirstFilter($typeGroup);
  851.         } else {
  852.             // material
  853.             if ($materialGroup $filterGroups->getMaterial()) {
  854.                 $sTtitle2 $this->modifyFirstFilter($materialGroup);
  855.             }
  856.         }
  857.         if ($isShot) {
  858.             $sTtitle2 '';
  859.         }
  860.         $groups $filterGroups->getGroups();
  861.         $maxCntFilters 0;
  862.         foreach ($groups as $group) {
  863.             $cnt count($group->getListFilters());
  864.             if ($cnt $maxCntFilters) {
  865.                 $maxCntFilters $cnt;
  866.             }
  867.         }
  868.         if ($maxCntFilters 2) {
  869.             $separatorGroup ';';
  870.             $separatorFilter ',';
  871.         } else {
  872.             $separatorGroup ',';
  873.             $separatorFilter $and;
  874.         }
  875.         $cntGroup count($groups);
  876.         $isDotBefore false;
  877.         foreach ($groups as $i => $group) {
  878.             $groupName $group->getGroupName();
  879.             $altName $group->getGroupAltName();
  880.             if ($i == || $isDotBefore) {
  881.                 $groupName StrHelper::ucFirstOnly($groupName);
  882.             } else {
  883.                 $groupName StrHelper::toLower($groupName);
  884.             }
  885.             if ($altName == 'dimension' || $altName == 'rewards' || $altName == 'samples') {
  886.                 $groupName '';
  887.             } elseif ($altName == 'bm') {
  888.                 $groupName StrHelper::toUpper($groupName) . ': ';
  889.             } elseif ($altName == 'resistance_abrasion') {
  890.                 $groupName StrHelper::toUpper($groupName);
  891.             }
  892.             if ($this->isOneFilter()) {
  893.                 $groupName '';
  894.             }
  895.             $groupName $groupName "{$groupName} " "";
  896.             $name_ '';
  897.             $listFilters $group->getListFilters();
  898.             $nameCnt count($listFilters);
  899.             foreach ($listFilters as $ii => $filter) {
  900.                 $pref '';
  901.                 if ($ii 0) {
  902.                     $pref $separatorFilter "{$separatorFilter} " ' ';
  903.                     // для последнего ставим
  904.                     if ($nameCnt == $ii) {
  905.                         $pref {$and} ";
  906.                     }
  907.                     // для размеров убираем разделители между двумя одинаковами типами
  908.                     if ($altName == 'dimension') {
  909.                         if (!empty($listFilters[$ii 1])) {
  910.                             $keyPrew $listFilters[$ii 1]->getKey();
  911.                             if ($filter->getKey() == $keyPrew '2') {
  912.                                 $pref ' ';
  913.                             }
  914.                         }
  915.                     }
  916.                 }
  917.                 $elFilterName $filter->getTitle() ?? '';
  918.                 if (!$groupName) {
  919.                     if (($i == && $ii == 0) || $isDotBefore) {
  920.                         $elFilterName StrHelper::ucFirstOnly($elFilterName);
  921.                     } else {
  922.                         $elFilterName StrHelper::toLower($elFilterName);
  923.                     }
  924.                 }
  925.                 $isDotBefore preg_match('/\.\s?<?/'strip_tags($elFilterName));
  926.                 if ($isLinkToFilter) {
  927.                     $elFilterName $this->buildElemetFilter($elFilterName$filter->getSlug());
  928.                 } elseif ($isShowLinkStyleDesigner) {
  929.                     $key $this->filterRepo->getKeyDesignerStyle();
  930.                     $link $this->generateUrl('app_catalog', ['key' => $key]);
  931.                     $pref $this->translate('link_on_designer'null, ['%href%' => $link]) . ' ';
  932.                     $elFilterName $filter->getNameMany();
  933.                 }
  934.                 if ($isLinkEdit) {
  935.                     $elFilterName $this->addElemetFilterLinkEdit($filter->getId(), $filter->getKey(), $elFilterName);
  936.                 }
  937.                 if ($this->isMargeFilters($filter->getId())) {
  938.                     $sub $this->filterRepo->getArrListSubForMenu($filter->getId(), $this->locale);
  939.                     $all_sub = [];
  940.                     foreach ($sub as $subItem) {
  941.                         $all_sub[] = $this->buildElemetFilter($subItem['pageNameMenu'], $subItem['url']);
  942.                     }
  943.                     if ($isLinkToFilter) {
  944.                         $elFilterName .= ' (' implode(', '$all_sub) . ')';
  945.                     } else {
  946.                         $elFilterName .= ': ' implode(', '$all_sub);
  947.                     }
  948.                 }
  949.                 $name_ .= "{$pref}{$elFilterName}";
  950.             }
  951.             // фикс случайных нескольких пробелов на всякий случай
  952.             $name_ preg_replace(['# {2,}#umi'], ' '$name_);
  953.             if ($i == $cntGroup 1) {
  954.                 $sepGroup '';
  955.             } else {
  956.                 $sepGroup "{$separatorGroup} ";
  957.             }
  958.             // если нашли вконце точку, то разделитель убираем
  959.             if ($isDotBefore) {
  960.                 $sepGroup '';
  961.             }
  962.             if ($isLinkToFilter) {
  963.                 $sTtitle2 .= "<span>{$groupName}{$name_}{$sepGroup}</span>";
  964.             } else {
  965.                 $sTtitle2 .= "{$groupName}{$name_}{$sepGroup}";
  966.             }
  967.         }
  968.         return $sTtitle2;
  969.     }
  970.     /**
  971.      * @param string $name
  972.      * @param string $slug
  973.      * @return string
  974.      */
  975.     private function buildElemetFilter(string $namestring $slug): string
  976.     {
  977.         $link $this->generateUrl('app_catalog', ['key' => $slug]);
  978.         return "<a class=\"el-filter\" href=\"{$link}\">{$name}</a>";
  979.     }
  980.     /**
  981.      * @param int $id
  982.      * @param string $key
  983.      * @param string $nameFilterStr
  984.      * @return string
  985.      */
  986.     private function addElemetFilterLinkEdit(int $idstring $keystring $nameFilterStr): string
  987.     {
  988.         $linkEdit $key == 'factory' Adm::linkEdit('adm.brand.edit'$id) : Adm::linkEdit('adm.filter.edit'$id);
  989.         $linkEdit $linkEdit "<sup> <a class=\"link-edit\" href=\"$linkEdit\" target=\"_blank\">edit</a></sup>" null;
  990.         return $linkEdit "{$nameFilterStr}{$linkEdit}$nameFilterStr;
  991.     }
  992.     /**
  993.      * @return FilterGroupsCatalogDTO
  994.      * @throws Exception
  995.      */
  996.     public function buildFilterGroupsDTO(): FilterGroupsCatalogDTO
  997.     {
  998.         $aCurFilters $this->getSortedFiltersLikeInTheLiteMenu();
  999.         $isOneFilter $this->isOneFilter();
  1000.         //$isDesignerUser = $this->filterService()->isDesignerUser();
  1001.         $filterGroups = new FilterGroupsCatalogDTO();
  1002.         // если фильтр размеров есть, то создаем массив с количеством значений по группам, для будущего формирования
  1003.         $aDimensionsCnt = [];
  1004.         if ($aDimensions $this->getDimensions()) {
  1005.             foreach ($aDimensions as $key => $val) {
  1006.                 $key str_replace('2'''$key);
  1007.                 if (!empty($aDimensionsCnt[$key])) {
  1008.                     $aDimensionsCnt[$key] += 1;
  1009.                 } else {
  1010.                     $aDimensionsCnt[$key] = 1;
  1011.                 }
  1012.             }
  1013.         }
  1014.         foreach ($aCurFilters as $filter) {
  1015.             $groupAltName $filter->getGroupAltName();
  1016.             if (!$filterGroup $filterGroups->getGroup($groupAltName)) {
  1017.                 $filterGroup = new FilterGroupCatalogDTO($filter->getGroupId(), $filter->getGroupName(), $groupAltName);
  1018.                 $filterGroups->addGroup($filterGroup);
  1019.             }
  1020.             $nameSingle $filter->getNameSingle();
  1021.             $nameMany $filter->getNameMany();
  1022.             $dopValue null;
  1023.             $slug $filter->getSlug();
  1024.             if ($filter->isDimension()) {
  1025.                 $dopValue $this->aDimensions[$filter->getSphinxName()];
  1026.                 $slug "{$slug}-{$dopValue}";
  1027.             } elseif ($groupAltName == 'bm') {
  1028.                 $dopValue $this->aBMs['bm'];
  1029.                 $slug "{$slug}-{$dopValue}";
  1030.             } elseif ($filter->isAlsoCollViewed()) {
  1031.                 $dopValue $this->alsoCollViewedId;
  1032.             }
  1033.             $filterGroup->addListFilters(
  1034.                 new FilterCatalogDTO(
  1035.                     $filter->getId(),
  1036.                     $filter->getSphinxName(),
  1037.                     $filter->getSphinxId(),
  1038.                     $filter->getCode(),
  1039.                     $filter->getAltName(),
  1040.                     $slug,
  1041.                     $nameSingle,
  1042.                     $nameMany,
  1043.                     $dopValue,
  1044.                 )
  1045.             );
  1046.         }
  1047.         foreach ($filterGroups->getGroups() as $groupDto) {
  1048.             $groupAltName $groupDto->getGroupAltName();
  1049.             foreach ($groupDto->getListFilters() as $filterDto) {
  1050.                 $title $isOneFilter $filterDto->getNameSingle() : $filterDto->getNameMany();
  1051.                 $filterDto->setTitle($title);
  1052.                 switch ($groupAltName) {
  1053.                     case 'antislip_coff':
  1054.                         $groupName $this->translate('antislip_full_name'$this->locale, ['%d%' => '']);
  1055.                         $groupDto->setGroupName($groupName);
  1056.                         break;
  1057.                     case 'resistance_abrasion':
  1058.                         // $title = trim(str_replace('PEI', '', $title));
  1059.                         $filterDto->setTitle($title);
  1060.                         break;
  1061.                     case 'price':
  1062.                         $title LocaleHelper::getNamePriceFilter($title$this->locale);
  1063.                         $title LocaleHelper::getNamePriceFilterWithCurrency($title);
  1064.                         $filterDto->setTitle($title);
  1065.                         break;
  1066.                     case 'bm':
  1067.                         $repoUser App::getRepository('WebBundle:User');
  1068.                         $title $repoUser->getUserEasyNameById($filterDto->getDopValue());
  1069.                         $filterDto->setTitle($title);
  1070.                         break;
  1071.                     case 'top':
  1072.                         if ($filterDto->getKey() == 'getAlsoCollViewed') {
  1073.                             if ($collAlsoId $filterDto->getDopValue()) {
  1074.                                 /** @var Collection $coll */
  1075.                                 $coll $this->collRepo->getCollForAlsoById($collAlsoId);
  1076.                                 if (null === $coll) {
  1077.                                     throw new NotFoundHttpException();
  1078.                                 }
  1079.                                 $factory $coll->getFactory();
  1080.                                 $collName $coll->getName();
  1081.                                 $brandName $factory->getName();
  1082.                                 if ($coll->getStatus() == || $factory->getStatus() == 1) {
  1083.                                     $collUrl $this->generateUrl(
  1084.                                         'app_collection',
  1085.                                         ['factoryUrl' => $factory->getUrl(), 'collectionUrl' => $coll->getUrl()]
  1086.                                     );
  1087.                                     $collName "<a href=\"$collUrl\" title=\"{$coll->getName()}\">{$coll->getName()}</a>";
  1088.                                     $brandUrl $this->generateUrl('app_catalog', ['key' => $factory->getUrl()]);
  1089.                                     $brandName "<a href=\"$brandUrl\" title=\"$brandName\">$brandName</a>";
  1090.                                 }
  1091.                             } else {
  1092.                                 $collName $this->translate('collection');
  1093.                                 $brandName $this->translate('brand');
  1094.                             }
  1095.                             $title str_replace('%collection%'$collName$title);
  1096.                             if (stripos($title'%brand%') !== false) {
  1097.                                 $title str_replace('%brand%'$brandName$title);
  1098.                             }
  1099.                             $filterDto->setTitle($title);
  1100.                         }
  1101.                         break;
  1102.                     case 'dimension':
  1103.                         $sizeVal $aDimensions[$filterDto->getKey()];
  1104.                         $sizeEd $this->translate("left_menu_{$filterDto->getCode()}"$this->locale);
  1105.                         $dimKey str_replace('2'''$filterDto->getKey());
  1106.                         // если группа размеров содержит более одного элемента, формируем дополнительный массив
  1107.                         if ($aDimensionsCnt[$dimKey] > 1) {
  1108.                             $aSizeType explode(' '$title);
  1109.                             $firstTitle array_shift($aSizeType);
  1110.                             $pattern $this->translate('settings_size_from_to'$this->locale);
  1111.                             if ($pattern and $pattern != 'settings_size_from_to') {
  1112.                                 if (preg_match('/(.*%size%)\s(.*%size2%)/'$pattern$out)) {
  1113.                                     if (preg_match('/.*2$/'$filterDto->getKey())) {
  1114.                                         $title str_replace('%size2%'$sizeVal$out[2]);
  1115.                                         $title "{$title} {$sizeEd}";
  1116.                                     } else {
  1117.                                         $title str_replace('%size%'$sizeVal"{$out[1]} ");
  1118.                                         $title "{$firstTitle} {$title}";
  1119.                                     }
  1120.                                 }
  1121.                             }
  1122.                         } else {
  1123.                             $title "{$title} {$sizeVal} {$sizeEd}";
  1124.                         }
  1125.                         $filterDto->setTitle($title);
  1126.                         break;
  1127.                 }
  1128.             }
  1129.         }
  1130.         return $filterGroups;
  1131.     }
  1132.     /**
  1133.      * разбиваем строку кея на полстроки для дополнительного поиска. например для размеров или БМа
  1134.      * @param string $key
  1135.      * @return array
  1136.      */
  1137.     private function buldExplodeKeys(string $key)
  1138.     {
  1139.         $res = [];
  1140.         $aKey explode('-'$key);
  1141.         if (count($aKey) > 2) {
  1142.             // создаем копию массива и удаляем последний элемент
  1143.             $aKeyTmp $aKey;
  1144.             array_pop($aKeyTmp);
  1145.             $res[] = implode('-'$aKeyTmp);
  1146.             // создаем копию массива и удаляем последний элемент
  1147.             $aKeyTmp $aKey;
  1148.             array_shift($aKeyTmp);
  1149.             $res[] = implode('-'$aKeyTmp);
  1150.         }
  1151.         foreach ($aKey as $k) {
  1152.             if (!is_numeric($k) && mb_strlen($k'utf-8') > 2) {
  1153.                 $res[] = $k;
  1154.             }
  1155.         }
  1156.         // в конец добавим полный кей, для LIKE поиска
  1157.         $res[] = $key;
  1158.         return array_unique($res);
  1159.     }
  1160.     /**
  1161.      * Правим фильтр, который должен быть первым и определяющим для страницы
  1162.      * @param FilterGroupCatalogDTO $filterGroup
  1163.      * @return string
  1164.      */
  1165.     private function modifyFirstFilter(FilterGroupCatalogDTO $filterGroup): string
  1166.     {
  1167.         $tilesName $this->translate('footer_tile'$this->locale);
  1168.         if (count($filterGroup->getListFilters()) > 1) {
  1169.             return "{$tilesName}. ";
  1170.         }
  1171.         // ставим отдельным предложением в начало
  1172.         $afterDot $this->isOneFilter() ? '' '. ';
  1173.         $firstFilter $filterGroup->getFirstFilter();
  1174.         $firstFilter->setTitle("{$firstFilter->getNameSingle()}{$afterDot}");
  1175.         $filterGroup->setGroupName('');
  1176.         return '';
  1177.     }
  1178.     private function getSizeInCalc(array $input): array
  1179.     {
  1180.         $items array_keys($input);
  1181.         sort($items);
  1182.         $items array_map(function ($num) {
  1183.             $num = (int)$num;
  1184.             $num $num 100;
  1185.             $n round($num2PHP_ROUND_HALF_DOWN);
  1186.             return ($n == 0.0) ? null $n;
  1187.         }, $items);
  1188.         // Удаляем null'ы
  1189.         $items array_filter($items, function ($val) {
  1190.             return $val !== null;
  1191.         });
  1192.         return array_unique($items);
  1193.     }
  1194.     /**
  1195.      * Перенести из контроллера в сервис поиска, а лучше в сервис фильтров
  1196.      *
  1197.      * @return array|string
  1198.      * @throws Exception
  1199.      */
  1200.     public function getFiltersList()
  1201.     {
  1202.         $lc App::getCurLocale();
  1203.         $cc App::getCurCountry();
  1204.         $lcFull $lc == $cc $lc "{$lc}_$cc";
  1205.         $cur LocaleHelper::getCurrency();
  1206.         $msr LocaleHelper::getUserMeasure();
  1207.         $memcache App::getMemcache();
  1208.         $redisCachePool App::getContainer()->get(RedisCachePool::class)->getPool();
  1209.         //        $memcacheKey = "collection_filter_factory_search_page_list_$lcFull.$cur.$msr";
  1210.         //        $filters = $memcache->get($memcacheKey);
  1211.         //
  1212.         //        if ($filters) {
  1213.         //                  return $filters; //todo тест без кеша
  1214.         //        }
  1215.         $filters = [];
  1216.         $filtersTmp $this->filterRepo->getArrListForFilterMenuNew($lc);
  1217.         //приписываем новые значения Просьба:Подвисает отбор по отзывам на рабочем сайте
  1218.         $memKeyCalc 'all_calculate_' $cc '_' $msr;
  1219.         $allCalculateItem $redisCachePool->getItem($memKeyCalc);
  1220.         if ($allCalculateItem->isHit()) {
  1221.             $allCalculate $allCalculateItem->get();
  1222.             $sizesX $this->getSizeInCalc($allCalculate['size_x']);
  1223.             $sizesY $this->getSizeInCalc($allCalculate['size_y']);
  1224.             $thicks $this->getSizeInCalc($allCalculate['tolsch']);
  1225.             $filtersTmp $this->setNewCount($filtersTmp$allCalculateItem->get());
  1226.         } else {
  1227.             $allCalculate false;
  1228.             $thicks $this->articleRepo->getSizeValues('thick');
  1229.             $sizesY $this->articleRepo->getSizeValues('sizeY');
  1230.             $sizesX $this->articleRepo->getSizeValues('sizeX');
  1231.         }
  1232.         // проверяем наличие вложенных фильтров
  1233.         $sub = [];
  1234.         $pids array_filter($filtersTmp, function ($r) {
  1235.             return $r['pid'] != null;
  1236.         });
  1237.         if ($pids) {
  1238.             foreach ($pids as $id => $r) {
  1239.                 unset($filtersTmp[$id]);
  1240.                 $sub[$r['pid']][$id] = $r;
  1241.             }
  1242.         }
  1243.         foreach ($filtersTmp as $filter) {
  1244.             $fid $filter['id'];
  1245.             $groupAltName $filter['group']['altName'];
  1246.             // вставляем вложенные фильтры, если есть такие
  1247.             if (!empty($sub[$fid])) {
  1248.                 $filter['sub'] = $sub[$fid];
  1249.             }
  1250.             $filters[$groupAltName][$fid] = $filter;
  1251.             // формируем фильтры для БМов
  1252.             if ($groupAltName == 'bm') {
  1253.                 $filters['bm'] = [];
  1254.                 $aUsers $this->collRepo->getListActiveBM();
  1255.                 foreach ($aUsers as $id => $name) {
  1256.                     $filters['bm'][$id] = [
  1257.                         'fid' => $fid,
  1258.                         'id' => $id,
  1259.                         'name' => $name,
  1260.                         'altName' => $id,
  1261.                         'selected' => [],
  1262.                         'group' => $filter['group'],
  1263.                         'count' => 0,
  1264.                     ];
  1265.                 }
  1266.             }
  1267.             // формируем фильтры для размеров
  1268.             if ($groupAltName == 'dimension') {
  1269.                 // проверяем на Дюймы и если что конвертируем
  1270.                 if (LocaleHelper::measureGb()) {
  1271.                     $measure '″';
  1272.                     if (StrHelper::isInStr($filter['altName'], 'tolsch')) {
  1273.                         $koff ConversionHelper::convertInch(0.1ConversionHelper::MM5); //mm так там выходит 0.00394
  1274.                     } else {
  1275.                         $koff ConversionHelper::convertInch(1.0ConversionHelper::CM); //cm
  1276.                     }
  1277.                 } else {
  1278.                     if (StrHelper::isInStr($filter['altName'], 'tolsch')) {
  1279.                         $measure 'left_menu_mm';
  1280.                     } else {
  1281.                         $measure 'left_menu_cm';
  1282.                     }
  1283.                     $measure $this->translate($measure);
  1284.                     $koff 1;
  1285.                 }
  1286.                 if (!StrHelper::isInStr($filter['altName'], '2')) {
  1287.                     $filters[$groupAltName][$fid]['subGroup'] = [
  1288.                         'name' => $this->translate('dimensions_from'),
  1289.                         'altName' => 'from',
  1290.                         'suff' => '',
  1291.                         'measure' => '',
  1292.                     ];
  1293.                 } else {
  1294.                     $filters[$groupAltName][$fid]['subGroup'] = [
  1295.                         'name' => $this->translate('dimensions_to'),
  1296.                         'altName' => 'to',
  1297.                         'suff' => '2',
  1298.                         'measure' => $measure,
  1299.                     ];
  1300.                 }
  1301.                 /** @var $item Article */
  1302.                 if (StrHelper::isInStr($filter['altName'], 'tolsch')) {
  1303.                     $subGroupName $this->translate('left_menu_thickness');
  1304.                     $filters[$groupAltName][$fid]['name'] = $subGroupName;
  1305.                     $sizes = [];
  1306.                     foreach ($thicks as $s) {
  1307.                         $sizes[] = [
  1308.                             'name' => $s $koff,
  1309.                             'val' => $s,
  1310.                         ];
  1311.                     }
  1312.                     if (!StrHelper::isInStr($filter['altName'], '2')) {
  1313.                         array_pop($sizes);
  1314.                     }
  1315.                     $filters[$groupAltName][$fid]['sizes'] = $sizes;
  1316.                     $filters[$groupAltName][$subGroupName][$fid] = $filters[$groupAltName][$fid];
  1317.                 }
  1318.                 if (StrHelper::isInStr($filter['altName'], 'size_y')) {
  1319.                     $subGroupName $this->translate('left_menu_height');
  1320.                     $filters[$groupAltName][$fid]['name'] = $subGroupName;
  1321.                     foreach ($sizesY as $s) {
  1322.                         $filters[$groupAltName][$fid]['sizes'][] = [
  1323.                             'name' => $s $koff,
  1324.                             'val' => $s,
  1325.                         ];
  1326.                     }
  1327.                     $filters[$groupAltName][$subGroupName][$fid] = $filters[$groupAltName][$fid];
  1328.                 }
  1329.                 if (StrHelper::isInStr($filter['altName'], 'size_x')) {
  1330.                     $subGroupName $this->translate('left_menu_width');
  1331.                     $filters[$groupAltName][$fid]['name'] = $subGroupName;
  1332.                     foreach ($sizesX as $s) {
  1333.                         $filters[$groupAltName][$fid]['sizes'][] = [
  1334.                             'name' => $s $koff,
  1335.                             'val' => $s,
  1336.                         ];
  1337.                     }
  1338.                     $filters[$groupAltName][$subGroupName][$fid] = $filters[$groupAltName][$fid];
  1339.                 }
  1340.                 unset($filters[$groupAltName][$fid]);
  1341.             }
  1342.         }
  1343.         // переносим пачку противоскольжения в groupList фильтра Противоскользящая
  1344.         //todo не нужно если перенести противоскользыщие фильтры в подгруппу 10146 в группу 401
  1345.         // UPDATE `filters` SET `parent_id` = '10146', `group_id` = 401 WHERE group_id=422
  1346.         // логика обработки в sphinx
  1347. //        if (!empty($filters['surface']) && !empty($filters['surface']['10146'])) {
  1348. //            if (!empty($filters['antislip_coff'])) {
  1349. //                $filters['surface']['10146']['groupList'] = $filters['antislip_coff'];
  1350. //                unset($filters['antislip_coff']);
  1351. //            }
  1352. //        }
  1353.         $paramGetCollections = [
  1354.             'order' => 'c.name, c.publishDate DESC, c.id',
  1355.             'onlyCF' => true,
  1356.             'leftCollectionCount' => true,
  1357.             'locale' => App::getCurLocale(),
  1358.         ];
  1359.         $aColls $this->collRepo->getCollections($paramGetCollections);
  1360.         //получаем фабрики, которые скрытые в стране
  1361.         $issetCollectionFactory $allCalculate array_keys($allCalculate['factory']) : [];
  1362.         $issetCollection $allCalculate array_keys($allCalculate['c_id']) : [];
  1363.         //$all_coll=[];
  1364.         //        foreach ($aColls as $coll){
  1365.         //            $all_coll[]=$coll['id'];
  1366.         //        }
  1367.         //        $result = array_diff($all_coll, $issetCollection);
  1368.         //
  1369.         //        App::debugExit($paramGetCollections,$result,count($issetCollection),count($all_coll), $issetCollection,$all_coll);
  1370.         foreach ($aColls as $coll) {
  1371.             if (empty($coll['brandUrl']) || empty($coll['url'])) {
  1372.                 continue;
  1373.             }
  1374.             if (!empty($issetCollectionFactory) && !in_array($coll['id'], $issetCollection)) {
  1375.                 //App::debugExit($coll, $issetCollection);
  1376.                 continue;
  1377.             }
  1378.             $filters['collection'][$coll['id']] = [
  1379.                 'id' => $coll['id'],
  1380.                 'url' => $coll['url'],
  1381.                 'name' => $coll['nameFull'],
  1382.                 'altName' => $coll['alternateName'],
  1383.                 'selected' => [],
  1384.                 'brand' => [
  1385.                     'id' => $coll['brandId'],
  1386.                     'url' => $coll['brandUrl'],
  1387.                 ],
  1388.                 'dataLink' => $this->generateUrl(
  1389.                     'app_collection',
  1390.                     ['factoryUrl' => $coll['brandUrl'], 'collectionUrl' => $coll['url']]
  1391.                 ),
  1392.                 'group' => [
  1393.                     'name' => App::getTranslator()->trans('left_menu_collections'),
  1394.                     'altName' => 'collections',
  1395.                 ],
  1396.             ];
  1397.             if (!empty($filters['brand'][$coll['brandId']])) {
  1398.                 if (!in_array($coll['id'], $filters['brand'][$coll['brandId']]['collection'])) {
  1399.                     $filters['brand'][$coll['brandId']]['collection'][] = $coll['id'];
  1400.                 }
  1401.             }
  1402.         }
  1403.         //удаляем бренды которые скрыты
  1404.         if (!empty($issetCollectionFactory)) {
  1405.             //Удаляем фабрики если есть скрытые бренды
  1406.             $old count($filters['brand']);
  1407.             foreach ($filters['brand'] as $brKey => $brV) {
  1408.                 if (!in_array($brV['id'], $issetCollectionFactory)) {
  1409.                     unset($filters['brand'][$brKey]);
  1410.                 }
  1411.             }
  1412.         }
  1413.         // сортируем фабрики по имени
  1414.         if (!empty($filters['brand'])) {
  1415.             $brandSort array_column($filters['brand'], 'name');
  1416.             array_multisort($brandSortSORT_ASC$filters['brand']);
  1417.         }
  1418.         // сортируем выставки по ID
  1419.         if (!empty($filters['exhibition'])) {
  1420.             $exhSort array_column($filters['exhibition'], 'id');
  1421.             array_multisort($exhSortSORT_DESC$filters['exhibition']);
  1422.         }
  1423.         // кешируем на продакшене
  1424.         //        if (App::isGeneral()) {
  1425.         //            $memcache->add($memcacheKey, $filters, MEMCACHE_COMPRESSED, (int)(TimeConstant::HOUR * 12));
  1426.         //        }
  1427.         return $filters;
  1428.     }
  1429.     public function setNewCount(array $filters, array $allCalculate): array
  1430.     {
  1431.         //меняем логику перебираем фильтры и ищем новое значения иначе 0
  1432.         foreach ($filters as $filter) {
  1433.             if (!empty($allCalculate[$filter['oldCommand']][$filter['id']])) {
  1434.                 $filters[$filter['id']]['count'] = $allCalculate[$filter['oldCommand']][$filter['id']];
  1435.             }
  1436. //            else {
  1437. //               // unset($filters[$filter['id']]);//=0; todo не все
  1438. //            }
  1439.         }
  1440. //        foreach ($allCalculate as $group) {
  1441. //            foreach ($group as $id => $count) {
  1442. //                if (!empty($filters[$id])) {
  1443. //                    $filters[$id]['count'] = $count;
  1444. //                }
  1445. //            }
  1446. //        }
  1447.         return $filters;
  1448.     }
  1449. }