<?php 
 
namespace WebBundle\Controller; 
 
use Doctrine\DBAL\DBALException; 
use Exception; 
use FlexApp\Constant\TimeConstant; 
use FlexApp\Service\CacheService; 
use FlexApp\Service\RedisCachePool; 
use Import1CBundle\Helper\v3\BiConst; 
use Memcache; 
use Symfony\Component\HttpFoundation\JsonResponse; 
use Symfony\Component\HttpFoundation\Response; 
use WebBundle\Entity\Article; 
use WebBundle\Entity\Collection; 
use WebBundle\Entity\FilterEntity; 
use WebBundle\Helper\App; 
use WebBundle\Helper\ArrHelper; 
use WebBundle\Helper\ConversionHelper; 
use WebBundle\Helper\LocaleHelper; 
use WebBundle\Helper\RequestHelper; 
use WebBundle\Helper\StrHelper; 
use WebBundle\Helper\SynchronizeFiltersHelper; 
use WebBundle\Repository\ArticleRepository; 
use WebBundle\Repository\CollectionRepository; 
use WebBundle\Repository\FilterHistorySearchRepository; 
use WebBundle\Repository\FilterRepository; 
use WebBundle\Repository\UserRepository; 
use WebBundle\Service\FiltersService; 
 
class FiltersController extends ExtendedController 
{ 
    /** @required */ 
    public CollectionRepository $collectionRepository; 
    /** @required */ 
    public FilterRepository $filterRepository; 
    /** @required */ 
    public FilterHistorySearchRepository $filterHistorySearchRepository; 
    /** @required */ 
    public ArticleRepository $articleRepository; 
 
    /** @required */ 
    public CacheService $cacheService; 
 
    public Memcache $memcached; 
 
    /** 
     * FilterController constructor. 
     * @param CacheService $cacheService 
     * @throws Exception 
     */ 
    public function __construct(CacheService $cacheService) 
    { 
        parent::__construct(); 
        $this->memcached = $cacheService->getMemcache(); 
    } 
 
    /** 
     * @return null|JsonResponse 
     * @throws Exception 
     */ 
    public function ajaxAdvancedSearchAction() 
    { 
        $locale = App::getCurLocale(); 
        $func = RequestHelper::get('func'); 
 
        $respLink = ''; 
        $respCount = 0; 
        $calculate = []; 
        $respDisabledFilters = []; 
        $dataCollection = []; 
        $isInteriors = false; 
 
        if ($func == 'getLinkHistory') { 
            $hash = RequestHelper::get('hash'); 
            if (!$hash) { 
                return $this->error('Not found hash.', 404, true); 
            } 
 
            $row = $this->filterHistorySearchRepository->getRowByHash($hash); 
            if (!$row) { 
                $row_ = $this->filterHistorySearchRepository->getRowByHash($hash, false); 
                if ($row_) { 
                    return $this->error('Access denied.', 403, true); 
                } 
                return $this->error('Not found history.', 404, true); 
            } 
 
            $fids = $row['filterIds']; 
            $filterService = App::getContainer()->get('app.service.filters'); 
 
            if ($row['collId']) { 
                $filterService->loadByIds($fids, $locale); 
 
                $coll = $this->collectionRepository->getCollectionsForMenuFilters(['id' => $row['collId']]); 
                $coll = count($coll) == 1 ? $coll[0] : null; 
                /** @var Collection $coll */ 
                if (!$coll) { 
                    return $this->error('Not found collection.', 404, true); 
                } 
 
                $brand = $coll->getFactory(); 
                /** @var FilterEntity $brand */ 
                if (!$brand) { 
                    return $this->error('Not found brand.', 404, true); 
                } 
 
                $brandUrl = $brand->getFilter()->getUrl()->{'get' . ucfirst($locale)}(); 
                $collUrl = $coll->getUrl(); 
 
                $attrUrl = [ 
                    'factoryUrl' => $brandUrl, 
                    'collectionUrl' => $collUrl, 
                ]; 
                // прикручиваем строки фильтрации к URL коллекции 
                if ($fKey = $filterService->getWord()) { 
                    $fKey = str_replace($attrUrl['factoryUrl'], '', $fKey); 
                    $fKey = trim($fKey, '&'); 
                    if ($fKey) { 
                        $attrUrl['type'] = 'f'; 
                        $attrUrl['elementId'] = $fKey; 
                    } 
                } 
                $respLink = $this->generateUrl('app_collection', $attrUrl); 
            } else { 
                if ($row['brandId']) { 
                    $fids[] = $row['brandId']; 
                } 
                $filterService->loadByIds($fids, $locale); 
 
                $respLink = $filterService->getUrl(); 
            } 
 
            return $this->ok(['link' => $respLink, 'hash' => $hash], true); 
        } 
        if ($func == 'saveHistory') { 
            $hasLiteMenu = RequestHelper::get('lmenu') == 1; 
            $rows = RequestHelper::get('data'); 
            if (!$rows) { 
                return $this->error('Not found values data.', 404, true); 
            } 
            $rows = json_decode($rows, true); 
 
            $collId = null; 
            $brandId = null; 
 
            if (!empty($rows['collection'][0][1])) { 
                $collId = $rows['collection'][0][1]; 
                unset($rows['collection']); 
            } 
 
            if (!empty($rows['brand'][0][1])) { 
                $brandId = $rows['brand'][0][1]; 
                unset($rows['brand']); 
            } 
 
            $fids = []; 
 
            if ($hasLiteMenu) { 
                // логика под короткое меню 
                /** @var $repoFilter FilterRepository */ 
                $repoFilter = App::getRepository('WebBundle:FilterEntity'); 
 
 
                if (!empty($rows['factory'][0])) { 
                    $brandId = $repoFilter->getFilterIdByOldId((int)$rows['factory'][0], 'factory'); 
                    unset($rows['factory']); 
                } 
 
                foreach ($rows as $oldCommand => $oldIds) { 
                    $oldIds = array_filter($oldIds); 
                    if ($oldIds) { 
                        $fids_ = $repoFilter->getFilterIdsByOldIds($oldIds, $oldCommand); 
                        if ($fids_) { 
                            $fids = array_merge($fids, $fids_); 
                        } 
                    } 
                } 
            } else { 
                foreach ($rows as $els) { 
                    foreach ($els as $el) { 
                        $fids[] = $el[1]; 
                    } 
                } 
            } 
 
            $fids = array_unique($fids); 
 
            $this->filterHistorySearchRepository->setHistory($collId, $brandId, $fids); 
 
            $data = [ 
                'state' => 'saved', 
                'list' => $this->getListHistory(), 
            ]; 
            return $this->ok($data, true); 
        } 
        if ($func == 'gethistory') { 
            $data = [ 
                'state' => 'get_history', 
                'list' => $this->getListHistory(), 
            ]; 
            return $this->ok($data, true); 
        } 
        if ($func == 'delLinkHistory') { 
            $hash = RequestHelper::get('hash'); 
            if (!$hash) { 
                return $this->error('Not found hash.', 404, true); 
            } 
 
            $this->filterHistorySearchRepository->delHistory($hash); 
 
            $data = [ 
                'state' => 'deleted', 
                'list' => $this->getListHistory(), 
            ]; 
            return $this->ok($data, true); 
        } 
        if ($func == 'getLink') { 
            $data = RequestHelper::get('data', []); 
 
            // обработка запроса коллекций 
            if (!empty($data['collection'])) { 
                $collId = array_shift($data['collection']); 
                $collId = !empty($collId['val']) ? $collId['val'] : null; 
                if (!$collId) { 
                    return $this->error('ID коллекции не получен'); 
                } 
                $coll = $this->collectionRepository->getCollectionsForMenuFilters(['id' => $collId]); 
                $coll = count($coll) == 1 ? $coll[0] : null; 
                /** @var Collection $coll */ 
                if (!$coll) { 
                    return $this->error('Коллекция не найдена'); 
                } 
 
                $factoryUrl = null; 
 
                if (!empty($data['brand'])) { 
                    $brandId = ArrHelper::get($data, 'brand.brand.val'); 
                    if (!$brandId) { 
                        return $this->error('ID фабрики не получен'); 
                    } 
                    $data[] = $data['brand']; 
                    unset($data['brand']); 
                    unset($data['collection']); 
 
                    /** @var FilterRepository $fRepo */ 
                    $fRepo = App::getRepository('WebBundle:FilterEntity'); 
                    $brand = $fRepo->getBrand(['id' => $brandId]); 
                    $brand = count($brand) == 1 ? $brand[0] : null; 
                    /** @var FilterEntity $brand */ 
                    if (!$brand) { 
                        return $this->error('Фабрика не найдена'); 
                    } 
                    $factoryUrl = $brand->getUrl()->{'get' . ucfirst($locale)}(); 
                } 
 
                if (!$factoryUrl) { 
                    $factoryUrl = $coll->getFactory()->getFilter()->getUrl()->{'get' . ucfirst($locale)}(); 
                } 
                $dataCollection = [ 
                    'c_id' => [$coll->getId()], 
                    'attrUrl' => [ 
                        'factoryUrl' => $factoryUrl, 
                        'collectionUrl' => $coll->getUrl(), 
                    ], 
 
                ]; 
            } 
 
            /** 
             * обработка остальных запросов 
             */ 
            $ids = []; 
            foreach ($data as $items) { 
                foreach ($items as $item) { 
                    $ids[] = $item['val']; 
                } 
            } 
 
 
            $lc = App::getCurLocale(); 
            $cc = App::getCurCountry(); 
            $lcFull = $lc == $cc ? $lc : "{$lc}_$cc"; 
            $memcachedKey = 'collection_filter_factory_AdvancedSearch_null_' . $lcFull; 
            $resCache = $this->memcached->get($memcachedKey); 
            if ($resCache and count($ids) < 1 and !$dataCollection) { 
                $resCache = json_decode($resCache, true); 
                $respLink = $resCache['respLink']; 
                $respCount = $resCache['respCount']; 
                $respDisabledFilters = $resCache['filtered']; 
            } else { 
                $filterService = App::getContainer()->get('app.service.filters'); 
                $filterService->loadByIds($ids, $locale); 
 
                if ($dataCollection) { 
                    $attrUrl = $dataCollection['attrUrl']; 
                    // прикручиваем строки фильтрации к URL коллекции 
                    $fKey = $filterService->getWord(); 
                    if ($fKey) { 
                        $fKey = str_replace($attrUrl['factoryUrl'], '', $fKey); 
                        $fKey = trim($fKey, '&'); 
                        $fKey = str_replace('&&', '&', $fKey); 
                        if ($fKey) { 
                            $attrUrl['type'] = 'f'; 
                            $attrUrl['elementId'] = $fKey; 
                        } 
                    } 
                    $respLink = $this->generateUrl('app_collection', $attrUrl); 
                } else { 
                    $respLink = $filterService->getUrl(); 
                } 
 
                $data = [ 
                    'searchFilter' => [], 
                    'searchSort' => 1, 
                    'searchPeriod' => null, 
                    'locale' => $locale, 
                ]; 
                $filters = $filterService->getCurFilters(); 
 
                foreach ($filters as $filter) { 
                    if ($filter->isDimension()) { 
                        $searchFilterVal = $filterService->getDimensions()[$filter->getAltName()]; 
                    } elseif ($filter->isBM()) { 
                        $searchFilterVal = $filterService->getBMs()[$filter->getAltName()]; 
                    } else { 
                        $searchFilterVal = $filter->getSphinxId(); 
                    } 
 
                    $data['searchFilter'][$filter->getSphinxName()][] = $searchFilterVal; 
                } 
 
                if ($dataCollection) { 
                    $data['searchFilter']['c_id'] = $dataCollection['c_id']; 
                    $data['searchFilter']['inside'] = true; 
                } 
                $data['total_found'] = 1; 
                $searchResult = App::searchSphinx($data, 0, false, false, !empty($data['calculate'])); 
                //если запросили подсчет 
                if (!empty($data['calculate'])) { 
                    $calculate = $searchResult['calculate']; 
                    $aRes = $searchResult['collections']; 
                } else { 
                    $aRes = $searchResult; 
                } 
 
                if ($dataCollection) { 
                    $aRes = !empty($aRes[0]['articles']) 
                        ? array_values(array_unique(array_column($aRes[0]['articles'], 'a_id'))) 
                        : []; 
 
 
                    if (!$aRes) { 
                        $aRes = !empty($searchTrue[0]['interiors']) 
                            ? array_values(array_unique(array_column($searchTrue[0]['interiors'], 'i_id'))) 
                            : []; 
                        $isInteriors = true; 
                    } 
                } 
 
                $respCount = isset($searchResult['total_found']) ? $searchResult['total_found'] : count($aRes); 
 
                // если есть выбранная коллекция, то показываем в количестве ее одну или ничего 
                if ($dataCollection) { 
                    $respCount = $respCount ? 1 : 0; 
                } 
                // проверяем результат сочетаний с другими фильтрами 
                if (count($ids) > 0) { 
                    //todo вынести в отдельную команду так как кешируеться на всех зеркалах а просчитаться может на одном 
                    // проверка на количество коллекций в поиске с сохранением в поле фильтра 
//                    if (count($filters) == 1) { 
//                        $filter = $filters[0]; 
//                        $filterResCount = 0; 
//                        if ($filter instanceof FilterEntity) { 
//                            $filterResCount = $filter->getParam()->getCount(); 
//                        } elseif ($filter instanceof FilterResponseDTO) { 
//                            $filterResCount = $filter->getCount(); 
//                        } 
//                        if ($filter && $respCount != $filterResCount) { 
//                            SynchronizeFiltersHelper::runSynchCountFilters($filter->getId()); 
//                        } 
//                    } 
 
                    if ($checkIds = RequestHelper::get('checkIds', [])) { 
                        /** @var FilterRepository $fRepo */ 
                        $fRepo = App::getRepository('WebBundle:FilterEntity'); 
                        $filtersCheck = $fRepo->getByIds($checkIds); 
 
                        foreach ($filtersCheck as $filter) { 
                            if (!in_array($filter->getId(), $ids)) { 
                                $dataSS = $data; 
                                $dataSS['searchFilter'][$filter->getOldCommand()][] = $filter->getOldId(); 
                                $aRes = App::searchSphinx($dataSS, 3); 
                                if (count($aRes) < 1) { 
                                    $respDisabledFilters['ids'][] = $filter->getId(); 
                                } 
                            } 
                        } 
                    } 
                } else { 
                    // если массив запросов пустой, то пишем данные в кеш и оттуда будем выдавать //Todo а на всякий случай загоним не тут а при открытии фильтра 
                    $data = [ 
                        'respLink' => $respLink, 
                        'respCount' => $respCount, 
                        'filtered' => $respDisabledFilters, 
                    ]; 
                    $data = json_encode($data); 
                    // кешируем на продакшене 
                    if (App::isGeneral()) { 
                        $this->memcached->add($memcachedKey, $data, false, (int)TimeConstant::HOUR * 12); 
                    } 
                } 
            } 
        } 
 
        if ($dataCollection) { 
            if ($isInteriors) { 
                $countPluralType = 'interior'; 
            } else { 
                $countPluralType = 'articles'; 
            } 
        } else { 
            $countPluralType = 'collection'; 
        } 
 
        $btnInfo = $this->translate('left_menu_show'); 
 
        $response = [ 
            'link' => urldecode($respLink), 
            'count' => $respCount, 
            'btnInfo' => $btnInfo, 
            'filtered' => $respDisabledFilters, 
            'countPluralType' => $countPluralType, 
            'calculate' => $calculate, 
        ]; 
 
        return $this->ok($response, true); 
    } 
 
 
    /** 
     * проставляем выбранные фильтры 
     */ 
    private function setFilterSelected(array $selected, string $alt, array $filters): array 
    { 
        $selectedReact = []; 
        foreach ($filters as $i => $item) { 
            if ($alt == 'collection') { 
                foreach ($selected['collections'] as $k => $v) { 
                    if (StrHelper::toLower($item['url']) == StrHelper::toLower($k)) { 
                        if (StrHelper::toLower($item['brand']['url']) == StrHelper::toLower($selected['brand'])) { 
                            $filters[$i]['selected'][] = $item['id']; 
                            $selectedReactItem = []; 
                            $selectedReactItem[] = 'collection'; 
                            $selectedReactItem[] = $item['id']; 
                            $selectedReact[] = $selectedReactItem; 
                        } 
                    } 
                } 
            } else { 
                foreach ($selected['filters'] as $k => $v) { 
                    if (!empty($item['groupList'])) { 
                        $response = $this->setFilterSelected($selected, $alt, $item['groupList']); 
                        $filters[$i]['groupList'] = $response['items']; 
                        $selectedSubFiltersReact = $response['selectedReact']; 
                    } 
 
                    if (!empty($item['sub'])) { 
                        $response = $this->setFilterSelected($selected, $alt, $item['sub']); 
                        $filters[$i]['sub'] = $response['items']; 
                        $selectedSubFiltersReact = $response['selectedReact']; 
                    } 
 
                    if ($alt == 'dimension') { 
                        foreach ($item as $ii => $d) { 
                            if (strripos($k, $d['key']) !== false) { 
                                $val = trim(str_replace($d['key'], '', $k), '-'); 
                                $filters[$i][$ii]['selected'][] = $val; 
                                $selectedReactItem = []; 
                                $selectedReactItem[] = $d['altName']; 
                                $selectedReactItem[] = "{$d['id']}::{$val}"; 
                                $selectedReact[] = $selectedReactItem; 
                            } 
                        } 
                    } elseif ($alt == 'bm') { 
                        if (preg_match("/.*-{$item['id']}$/", $k)) { 
                            $filters[$i]['selected'][] = $item['id']; 
                            $selectedReactItem = []; 
                            $selectedReactItem[] = 'bm'; 
                            $selectedReactItem[] = "{$item['fid']}::{$item['id']}"; 
                            $selectedReact[] = $selectedReactItem; 
                        } 
                    } elseif ($item['key'] == $k) { 
                        $filters[$i]['selected'][] = $item['id']; 
                        $selectedReactItem = []; 
                        if ($alt == 'brand') { 
                            $selectedReactItem[] = 'brand'; 
                        } else { 
                            $selectedReactItem[] = $item['name']; 
                        } 
                        $selectedReactItem[] = $item['id']; 
                        $selectedReact[] = $selectedReactItem; 
                    } 
                } 
                // добавляем выбранные вложенные фильтры 
                if (!empty($selectedSubFiltersReact) && (!empty($item['sub']) || !empty($item['groupList']))) { 
                    $selectedReact = array_merge($selectedReact, $selectedSubFiltersReact); 
                } 
            } 
        } 
 
        return [ 
            'items' => $filters, 
            'selectedReact' => $selectedReact, 
        ]; 
    } 
 
    /** 
     * карта фильтров 
     * @param $filters 
     * @return array|string 
     * @throws Exception 
     */ 
    private function getFiltersMap($filters) 
    { 
        $lc = App::getCurLocale(); 
        $cur = LocaleHelper::getCurrency(); 
        $msr = LocaleHelper::getUserMeasure(); 
 
 
        $memcacheKey = "collection_filter_factory_search_page_map_{$lc}.{$cur}.{$msr}"; 
        $map = $this->memcached->get($memcacheKey); 
 
        if (!$map) { 
            $groups = []; 
            $filtersTmp = $this->filterRepository->getArrListForFilterMenuNew($lc); 
 
            foreach ($filtersTmp as $filter) { 
                $groupAltName = $filter['group']['altName']; 
                $groups[$groupAltName] = $filter['group']; 
            } 
 
            $groups['collection'] = [ 
                'name' => App::getTranslator()->trans('left_menu_collections'), 
                'altName' => 'collections', 
            ]; 
 
            // для категории цены вывел вылюту 
            $priceName = $groups['price']['name']; 
            $priceName = $priceName . ', ' . html_entity_decode($cur) . '/' . $msr . '²'; 
 
 
            $map = [ 
                'coll_1' => [ 
                    'brand' => $groups['brand']['name'], 
                    'collection' => $groups['collection']['name'], 
                    'bm' => $groups['bm']['name'], 
                    'effect' => $groups['effect']['name'], 
                    'style' => $groups['style']['name'], 
                    'price' => $priceName, 
                ], 
                'coll_2' => [ 
                    'color' => $groups['color']['name'], 
                    'using' => $groups['using']['name'], 
                    'material' => $groups['material']['name'], 
                ], 
                'coll_3' => [ 
                    'samples' => !empty($groups['samples']) && $groups['samples']['name'], 
                    'type' => $groups['type']['name'], 
                    'surface' => $groups['surface']['name'], 
                    'apply' => $groups['apply']['name'], 
                ], 
                'coll_4' => [ 
                    'shape' => $groups['shape']['name'], 
                    'motiv' => $groups['motiv']['name'], 
                    'country' => $groups['country']['name'], 
                ], 
                'coll_5' => [ 
                    'dimension' => $groups['dimension']['name'], 
                    'granite' => $groups['granite']['name'], 
                    'edge_type' => $groups['edge_type']['name'], 
                    'other' => $groups['other']['name'], 
                    'rewards' => $groups['rewards']['name'], 
                    'reviews' => $groups['reviews']['name'], 
                ], 
            ]; 
 
            // кешируем на продакшене 
            if (App::isGeneral()) { 
                $this->memcached->add($memcacheKey, $map, MEMCACHE_COMPRESSED, 600); 
            } 
        } 
 
        // убираем из карты поля, под которые нет фильтров 
        foreach ($map as $col => $row) { 
            foreach ($row as $alt => $item) { 
                if (empty($filters[$alt])) { 
                    unset($map[$col][$alt]); 
                } 
            } 
        } 
 
        return $map; 
    } 
 
    /** 
     * Формирование страницы расширенных фильтров 
     * @return array 
     * @throws Exception 
     */ 
    private function getAdvancedSearchPageData(): array 
    { 
        $locale = App::getCurLocale(); 
        $curCountry = LocaleHelper::getCurCountry(); 
 
        // формируем выбранные фильтры из строки запроса 
        $selected = [ 
            'filters' => [], 
            'collections' => [], 
            'brand' => null, 
        ]; 
        $uri = urldecode(RequestHelper::syRequest()->getRequestUri()); 
        $uri = parse_url($uri, PHP_URL_QUERY); 
        $uri = str_replace('c=/', '', $uri); 
        $uri = trim($uri, '/'); 
        $uri = StrHelper::toLower($uri); 
        $uri = explode('/', $uri); 
        array_shift($uri); 
 
        if (count($uri) > 1) { 
            if ($uri[0] == 'catalogue') { 
                $uri = $uri[1]; 
                foreach (explode('&', $uri) as $item) { 
                    $selected['filters'][$item] = $item; 
                } 
            } 
            if ($uri[0] == 'tile') { 
                $selected['filters'][$uri[1]] = $uri[1]; 
                $selected['brand'] = $uri[1]; 
                $selected['collections'][$uri[2]] = $uri[2]; 
                // получение фильтров для коллекций 
                if ($uriFilters = ArrHelper::get($uri, 4)) { 
                    foreach (explode('&', $uriFilters) as $item) { 
                        $selected['filters'][$item] = $item; 
                    } 
                } 
            } 
        } 
 
        $filterService = new FiltersService(); 
        $filtersList = $filterService->getFiltersList(); 
        // удаляем БМом, если роль не позволяет 
        if (!$this->isGranted('ROLE_BM')) { 
            unset($filtersList['bm']); 
        } 
 
        // формируем выбранные фильтры из строки 
        $selectedFilters = []; 
        $selectedFiltersQty = 0; 
        foreach ($filtersList as $alt => $items) { 
            $filterSelectedResponse = $this->setFilterSelected($selected, $alt, $items); 
            $filtersList[$alt] = $filterSelectedResponse['items']; 
            $selectedFilters[$alt] = $filterSelectedResponse['selectedReact']; 
            $selectedFiltersQty += count($filterSelectedResponse['selectedReact']); 
        } 
        // формируем фильтры цен 
        foreach ($filtersList['price'] as $i => $item) { 
            if ($curCountry != $locale) { 
                $name = LocaleHelper::getNamePriceFilter($item['name'], $locale, $curCountry); 
                $filtersList['price'][$i]['name'] = $name; 
            } 
        } 
 
 
        $filtersMap = $this->getFiltersMap($filtersList); 
 
 
        $isNullSelected = !(count($selected['collections']) > 0 or count($selected['filters']) > 0); 
 
        $resLink = null; 
 
        if ($isNullSelected) { 
            $resLink = $this->generateUrl('app_catalog'); 
        } 
 
        $lc = App::getCurLocale(); 
        $cc = App::getCurCountry(); 
        $lcFull = $lc == $cc ? $lc : "{$lc}_$cc"; 
        $memcachedKey = 'collection_filter_factory_AdvancedSearch_null_' . $lcFull; 
        $resCache = $this->memcached->get($memcachedKey); 
        if (!$resCache) { 
            $cntCollAll = App::getContainer()->get('app.service.collection')->countNotFilteredCollection(); 
            $data = [ 
                'respLink' => $resLink, 
                'respCount' => $cntCollAll, 
                'filtered' => [], 
            ]; 
            $data = json_encode($data); 
            // кешируем на продакшене 
            if (App::isGeneral()) { 
                $this->memcached->add($memcachedKey, $data, false, (int)TimeConstant::HOUR * 12); 
            } 
        } else { 
            $resCache = json_decode($resCache, true); 
            $cntCollAll = $resCache['respCount']; 
        } 
        //todo дублируется выдача при выборе группы 
        foreach ($filtersList as $groupKey => &$group) { 
            foreach ($group as $itemKey => &$item) { 
                if (!empty($item['selected']) && isset($item['sub']) && !empty($item['sub'])) { 
                    $selectedFiltersQty--; // :) а вот так :) иначе фронт ляжет 
                    $item['selected'] = []; //пробовал удалять из выбранных родителя не помогло 
                    //удаляем родителя 
                    $value_to_remove = $item['id']; // Переменная с переданным значением 
                    $selectedFilters[$groupKey] = array_filter( 
                        $selectedFilters[$groupKey], 
                        function ($item_) use ($value_to_remove) { 
                            return $item_[1] != $value_to_remove; 
                        } 
                    ); 
                    $selectedFilters[$groupKey] = array_values($selectedFilters[$groupKey]); 
 
                    foreach ($item['sub'] as $subKey => &$subItem) { 
                        $subItem['selected'] = [$subItem['id']]; 
                        $selected['filters'][$subItem['key']] = $subItem['key']; 
                        $selectedFilters[$groupKey][] = [$subItem['name'], $subItem['id']]; 
                        $selectedFiltersQty++; 
                    } 
                } 
            } 
        } 
        return [ 
            'action' => urldecode($this->generateUrl('app_filters_advanced_search_json')), 
            'map' => $filtersMap, 
            'filters' => $filtersList, 
            'selected' => $selected, 
            'cntCollAll' => $cntCollAll, 
            'resLink' => $resLink, 
            'isNullSelected' => $isNullSelected, 
            'noFloor' => true, 
            'selectedFilters' => $selectedFilters, 
            'selectedFiltersQty' => $selectedFiltersQty, 
            'countPluralType' => 'collection', 
        ]; 
    } 
 
    /** 
     * @param bool $noResponse 
     * @return array|null|string|JsonResponse 
     * @throws Exception 
     */ 
    public function ajaxListMenuFactoryAction(bool $noResponse = false) 
    { 
        //todo скрыть скрытые фабрики 
        $locale = App::getCurLocale(); 
        $cacheKey = "left_menu_lite_factory_filter_{$locale}_1" . App::getCurCountry(); 
        $factories = App::getMemcache()->get($cacheKey); 
        $redisCachePool = App::getContainer()->get(RedisCachePool::class)->getPool(); 
        $cc = App::getCurCountry(); 
        $msr = LocaleHelper::getUserMeasure(); 
        $memKeyCalc = 'all_calculate_' . $cc . '_' . $msr; // 
        $allCalculateItem = $redisCachePool->getItem($memKeyCalc); 
        if ($allCalculateItem->isHit()) { 
            $allCalculate = $allCalculateItem->get(); 
        } else { 
            $allCalculate = false; 
        } 
        $issetCollectionFactory = $allCalculate ? array_keys($allCalculate['factory']) : []; 
        if (!$factories || App::isDev()) { 
            $translator = $this->get('translator'); 
            /** @var FilterRepository $repoFilter */ 
            $repoFilter = App::getRepository('WebBundle:FilterEntity'); 
            $brands = $repoFilter->getListBrandsForMenu($locale, $translator); 
 
            foreach ($brands as $i => $brand) { 
                if (!empty($issetCollectionFactory) && !in_array($brand['filter_id'], $issetCollectionFactory)) { 
                    unset($brands[$i]); 
                } 
            } 
            $factoryAllCount = count($brands); 
            if ($factoryAllCount > 0) { 
                $factories = [ 
                    'data' => $brands, 
                    'all' => $factoryAllCount, 
                    'to' => 'brand', 
                ]; 
                App::getMemcache()->set($cacheKey, $factories, false, TimeConstant::DAY); 
            } 
        } 
 
        if ($noResponse) { 
            $response = $factories; 
        } else { 
            $response = $this->ok($factories, true); 
        } 
 
        return $response; 
    } 
 
    /** 
     * @param bool $noResponse 
     * @param null $brands 
     * @return array|null|string|JsonResponse 
     * @throws Exception 
     */ 
    public function ajaxListMenuCollectionAction($noResponse = false, $brands = null) 
    { 
        $collectionId = RequestHelper::get('collectionId', null); 
        $_locale = App::getCurLocale('full'); 
        $redisCachePool = App::getContainer()->get(RedisCachePool::class)->getPool(); 
        $cc = App::getCurCountry(); 
        $msr = LocaleHelper::getUserMeasure(); 
        $memKeyCalc = 'all_calculate_' . $cc . '_' . $msr; // 
        $allCalculateItem = $redisCachePool->getItem($memKeyCalc); 
        if ($allCalculateItem->isHit()) { 
            $allCalculate = $allCalculateItem->get(); 
        } else { 
            $allCalculate = false; 
        } 
        $issetCollectionFactory = $allCalculate ? array_keys($allCalculate['factory']) : []; 
        $issetCollection = $allCalculate ? array_keys($allCalculate['c_id']) : []; 
        $memcacheName = 'left_menu_collection.0.' . $collectionId . $_locale . (App::isRole('ROLE_TEST') ? 1 : 0); 
        $collections = $this->memcached->get($memcacheName); 
 
        if (!$collections || App::isDev()) { 
            $isStatusWork = $this->collectionRepository->findOneBy([ 
                'status' => BiConst::STATE_DISCONTINUED, 
                'id' => $collectionId, 
            ]); 
 
            $collectionId = ($isStatusWork) ? $collectionId : null; 
 
            $param = [ 
                'order' => 'c.name, f.name', 
                'onlyCF' => true, 
                'collectionId' => $collectionId, 
                'leftCollectionCount' => true, 
                'locale' => App::getCurLocale(), 
            ]; 
 
 
            if ($brands) { 
                foreach ($brands as $brand) { 
                    $param['factoryId'][] = $brand['id']; 
                } 
            } 
 
            $aColls = $this->collectionRepository->getListForMenu($param); 
 
            foreach ($aColls as $i => $coll) { 
                if (!empty($issetCollectionFactory) && !in_array($coll['id'], $issetCollection)) { 
                    unset($aColls[$i]); 
                    continue; 
                } 
                $coll['dataLink'] = $this->generateUrl( 
                    'app_collection', 
                    [ 
                        'factoryUrl' => $coll['factory']['slug'], 
                        'collectionUrl' => $coll['slug'], 
                    ] 
                ); 
                $aColls[$i] = $coll; 
            } 
 
            $collectionAllCount = count($aColls); 
            if ($collectionAllCount > 0) { 
                $collections = [ 
                    'data' => $aColls, 
                    'all' => $collectionAllCount, 
                    'to' => 'collection', 
                ]; 
 
                // кешируем на продакшене 
                if (App::isGeneral()) { 
                    $this->memcached->add($memcacheName, $collections, false, (int)TimeConstant::MINUTE * 10); 
                } 
            } 
        } 
 
        if ($noResponse) { 
            $response = $collections; 
        } else { 
            $response = $this->ok($collections, true); 
        } 
 
        return $response; 
    } 
 
    /** 
     * Страница фильтров под реакт 
     * @return JsonResponse|Response|null 
     * @throws Exception 
     */ 
    public function pageAdvancedSearchReactAction() 
    { 
        $data = $this->getAdvancedSearchPageData(); 
 
        $data['trans'] = [ 
            'countPluralInterior' => App::transPluralStrToArray($this->translate('filter.res.count.interior')), 
            'countPluralArticles' => App::transPluralStrToArray($this->translate('filter.res.count.articles')), 
            'countPluralCollection' => App::transPluralStrToArray($this->translate('filter.res.count.collection')), 
            'searchHistory' => $this->translate('search_history_advancedsearch'), 
            'leftMenuCriteria' => $this->translate('left_menu_criteria'), 
            'leftMenuShow' => $this->translate('left_menu_show'), 
            'leftAdvancedReset' => $this->translate('left_advanced_reset'), 
            'leftAdvancedSearch' => $this->translate('left_advanced_search'), 
            'leftMenuSelect' => $this->translate('left_menu_select'), 
            'leftMenuCollections' => $this->translate('left_menu_collections'), 
            'searchNoResult' => $this->translate('search_no_result'), 
            'factoryFirstLi' => $this->translate('factory_first_li'), 
            'factoryFirstLiLink' => $this->translate('factory_first_li_link'), 
            'factoryFirstLiHelp' => $this->translate('factory_first_li_help'), 
            'leftMenuFactories' => $this->translate('left_menu_factories'), 
            'filterHideFilters' => $this->translate('filter_hide_filters'), 
            'filterShowAllFilters' => $this->translate('filter_show_all_filters'), 
            'leftMenuAll' => $this->translate('left_menu_all'), 
            'clear' => $this->translate('clear'), 
            'filtersTipsWallAndFloor' => $this->translate('filters.tips.wallAndFloor'), 
            'hintCollGroupTypeBassein' => $this->translate('hint_coll_group_type_bassein'), 
            'hintCollGroupTypeBorder' => $this->translate('hint_coll_group_type_border'), 
            'hintCollGroupTypePencil' => $this->translate('hint_coll_group_type_pencil'), 
            'hintCollGroupTypeRiser' => $this->translate('hint_coll_group_type_riser'), 
            'hintCollGroupTypeStep' => $this->translate('hint_coll_group_type_step'), 
            'hintCollGroupTypeTypeCorner' => $this->translate('hint_coll_group_type_type_corner'), 
            'hintCollGroupTypeCornerProfile' => $this->translate('hint_coll_group_type_corner_profile'), 
            'hintCollGroupTypeCornerElement' => $this->translate('hint_coll_group_type_corner_element'), 
            'hintCollGroupTypeBaseboard' => $this->translate('hint_coll_group_type_baseboard'), 
            'hintCollGroupTypePanel' => $this->translate('hint_coll_group_type_panel'), 
            'hintCollGroupTypeMosaicImitation' => $this->translate('hint_coll_group_type_mosaic_imitation'), 
            'hintCollGroupTypeMosaic' => $this->translate('hint_coll_group_type_mosaic'), 
            'chooseDropdownTooltip' => $this->translate('choose_dropdown_tooltip'), 
        ]; 
 
        $data['path'] = App::getRouter()->generate('app_request', ['action' => 'get']); 
        $data['map'] = array_values($data['map']); 
 
        foreach ($data['filters'] as $i => $fl) { 
            if ($i == 'dimension') { 
                foreach ($fl as $ii => $fll) { 
                    $fl[$ii] = array_values($fll); 
                } 
            } else { 
                $fl = array_values($fl); 
            } 
            $data['filters'][$i] = $fl; 
        } 
        $data['history']['actionSave'] = App::getRouter()->generate( 
            'app_filters_advanced_search_json', 
            ['func' => 'saveHistory'] 
        ); 
        $data['history']['actionGet'] = App::getRouter()->generate( 
            'app_filters_advanced_search_json', 
            ['func' => 'gethistory'] 
        ); 
        $data['history']['list'] = [];//$this->getListHistory(); // TODO Удалить если сделаю через  ?func=gethistory или вернуть 
 
        return $this->renderReact('@Web/Filters/React/page.html.twig', [ 
            'meta' => [ 
                'title' => $this->translate('left_advanced_search') . ' · ' . App::getParameter('site_name'), 
                'description' => '', 
                'keywords' => '', 
            ], 
            'initialState' => ['filters' => $data], 
        ]); 
    } 
 
    /** 
     * @return array 
     * @throws DBALException 
     * @throws Exception 
     */ 
    private function getListHistory() 
    { 
        $items = []; 
 
        $rows = $this->filterHistorySearchRepository->getHistoryForCurUser(); 
 
        foreach ($rows as $row) { 
            $names = []; 
            if ($row['collId']) { 
                if ($nameColl = $this->collectionRepository->getNameForFilterHistorySearch($row['collId'])) { 
                    $names[] = $nameColl; 
                } 
            } 
            if ($row['brandId']) { 
                $row['filterIds'][] = $row['brandId']; 
            } 
 
            // новый объект для фронта, из которого можно собрать значения группы - фильтр 
            $groupedFilter = []; 
 
            if ($row['filterIds']) { 
                $idsParam = []; 
                $fids = []; 
                $namesF = []; 
 
                foreach ($row['filterIds'] as $fid) { 
                    $ids = explode('::', $fid); 
                    if (!$ids[0]) { 
                        continue; 
                    } 
                    $fids[] = $ids[0]; 
                    // обработка через :: для запросов по размерам, т.к. ID там идет вида 56564::0.5 
                    // где первое - ID, а второе параметр 
                    if (count($ids) > 1) { 
                        $idsParam[$ids[0]] = $ids[1]; 
                    } 
                } 
 
                $filters = $this->filterRepository->getForFilterNameHistorySearch($fids); 
                $dimensions = []; 
 
                if ($filters) { 
                    foreach ($filters as $fl) { 
                        $name = $fl['name']; 
                        $groupAltName = $fl['groupAltName']; 
                        $groupLeftMenu = $fl['groupLeftMenu']; 
 
                        // если группа размеров содержит более одного элемента, формируем дополнительный массив $dimensions 
                        if ($groupAltName == 'dimension') { 
                            if (!empty($idsParam[$fl['id']])) { 
                                $size = $idsParam[$fl['id']]; 
                                $sizeEd = App::trans('left_menu_' . $fl['code']); 
                                $type = str_replace('2', '', $fl['altName']); 
                                $ind = $type == $fl['altName'] ? 1 : 2; 
                                $dim = array_merge($fl, [ 
                                    'size' => $size, 
                                    'sizeEd' => $sizeEd, 
                                    'type' => $type, 
                                ]); 
 
                                $dimensions[$type][$ind] = $dim; 
                                $name = null; 
                            } 
                            // логика для БМов 
                        } elseif ($groupAltName == 'bm') { 
                            if (!empty($idsParam[$fl['id']])) { 
                                $bmId = $idsParam[$fl['id']]; 
                                /** @var UserRepository $repoUser */ 
                                $repoUser = App::getRepository('WebBundle:User'); 
                                $name = $repoUser->getUserEasyNameById($bmId); 
                                $name = "{$fl['name']}: {$name}"; 
                            } 
                        } else { 
                            if (!isset($groupedFilter[$groupAltName])) { 
                                $groupedFilter[$groupAltName] = [ 
                                    'name' => App::trans($groupLeftMenu ?: $groupAltName), 
                                    'values' => [], 
                                ]; 
                            } 
                            $groupedFilter[$groupAltName]['values'][] = $name; 
                        } 
 
                        if ($name) { 
                            $namesF[] = $name; 
                        } 
                    } 
                } 
 
                if ($dimensions) { 
                    $groupedFilter['dimension'] = [ 
                        'name' => App::trans('left_menu_dimensions'), 
                        'values' => [], 
                    ]; 
                    foreach ($dimensions as $type => $dims) { 
                        // для создания вывода фильтров единой строкой, а не по отдельности 
                        if (count($dims) > 1) { 
                            $d1 = $dims[1]; 
                            $d2 = $dims[2]; 
                            $first = explode(' ', $d1['name']); 
                            $first = array_shift($first); 
 
                            $name = App::trans( 
                                'settings_size_from_to', 
                                null, 
                                ['%size%' => $d1['size'], '%size2%' => $d2['size']] 
                            ); 
                            $name = "{$first} {$name} {$d1['sizeEd']}"; 
                        } else { 
                            $d = array_shift($dims); 
                            $name = "{$d['name']} {$d['size']} {$d['sizeEd']}"; 
                        } 
                        $groupedFilter['dimension']['values'][$type] = $name; 
                        $namesF[] = $name; 
                    } 
                } 
 
                asort($namesF); 
                $names = array_merge($names, $namesF); 
            } 
 
            $name = implode(', ', $names); 
            $items[] = [ 
                'name' => $name, 
                'groupAltName' => $groupedFilter, 
                'getElLink' => App::getRouter()->generate( 
                    'app_filters_advanced_search_json', 
                    ['func' => 'getLinkHistory', 'hash' => $row['hash']] 
                ), 
                'delEl' => App::getRouter()->generate( 
                    'app_filters_advanced_search_json', 
                    ['func' => 'delLinkHistory', 'hash' => $row['hash']] 
                ), 
            ]; 
        } 
 
        return $items; 
    } 
 
    /** 
     * Меню для реакта 
     * @return JsonResponse|Response|null 
     * @throws Exception 
     */ 
    public function ajaxListMenuLite() 
    { 
        $oLeftService = App::getContainer()->get('app.service.leftmenu'); 
        $output = $oLeftService->getDataMenuLite(); 
        return $this->ok($output, true); 
    } 
}