src/WebBundle/Repository/FilterRepository.php line 824

Open in your IDE?
  1. <?php
  2. namespace WebBundle\Repository;
  3. use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
  4. use Doctrine\DBAL\Types\Types;
  5. use Doctrine\ORM\NonUniqueResultException;
  6. use Doctrine\ORM\NoResultException;
  7. use Doctrine\ORM\QueryBuilder;
  8. use Doctrine\Persistence\ManagerRegistry;
  9. use Exception;
  10. use FlexApp\Constant\TimeConstant;
  11. use FlexApp\DTO\BrandResponseDTO;
  12. use FlexApp\DTO\FilterCountryResponseDTO;
  13. use FlexApp\DTO\FilterResponseDTO;
  14. use FlexApp\Service\CacheService;
  15. use FlexApp\Service\RedisCachePool;
  16. use FlexApp\ValueObject\LocaleVo;
  17. use Import1CBundle\Helper\v3\BiConst;
  18. use Symfony\Contracts\Translation\TranslatorInterface;
  19. use Throwable;
  20. use WebBundle\Entity\FilterEntity;
  21. use WebBundle\Enum\FilterGroupEnum;
  22. use WebBundle\Helper\App;
  23. use WebBundle\Helper\ArrHelper;
  24. use WebBundle\Helper\HideFactoryCountriesHelper;
  25. use WebBundle\Helper\LocaleHelper;
  26. use WebBundle\Helper\PathHelper;
  27. use WebBundle\Helper\StrHelper;
  28. use WebBundle\Traits\RepoTrait;
  29. class FilterRepository extends ServiceEntityRepository
  30. {
  31.     use RepoTrait;
  32.     private const QUERY_CACHE_LIFETIME 600;
  33.     private CacheService $cacheService;
  34.     public function __construct(ManagerRegistry $registryCacheService $cacheService)
  35.     {
  36.         parent::__construct($registryFilterEntity::class);
  37.         $this->cacheService $cacheService;
  38.     }
  39.     public function joinQuery($alias 'f'): QueryBuilder
  40.     {
  41.         return $this->createQueryBuilder($alias)
  42.             ->SELECT(
  43.                 "$alias, url, page, param, brand, groups, articles, htmlShow, country, nameForMetaTitle, nameForMetaDescr"
  44.             )
  45.             ->leftJoin("$alias.url"'url')
  46.             ->leftJoin("$alias.page"'page')
  47.             ->leftJoin("$alias.param"'param')
  48.             ->leftJoin("$alias.brand"'brand')
  49.             ->leftJoin("brand.user"'user')
  50.             ->leftJoin("$alias.groups"'groups')
  51.             ->leftJoin("$alias.articles"'articles')
  52.             ->leftJoin("$alias.htmlShow"'htmlShow')
  53.             ->leftJoin("$alias.country"'country')
  54.             ->leftJoin("$alias.nameForMetaTitle"'nameForMetaTitle')
  55.             ->leftJoin("$alias.nameForMetaDescr"'nameForMetaDescr');
  56.     }
  57.     /**
  58.      * @param string $filterUrl
  59.      * @param string $locale
  60.      * @return FilterResponseDTO|null
  61.      * @throws \Doctrine\DBAL\Driver\Exception
  62.      * @throws \Doctrine\DBAL\Exception
  63.      */
  64.     public function getByKeyUrlIsLike(string $filterUrlstring $locale): ?FilterResponseDTO
  65.     {
  66.         return $this->getByUrl($filterUrl$localetrue);
  67.     }
  68.     /**
  69.      * @param string $filterUrl
  70.      * @param string $locale
  71.      * @return FilterResponseDTO|null
  72.      * @throws \Doctrine\DBAL\Driver\Exception
  73.      * @throws \Doctrine\DBAL\Exception
  74.      */
  75.     public function getByKeyUrl(string $filterUrlstring $locale): ?FilterResponseDTO
  76.     {
  77.         return $this->getByUrl($filterUrl$locale);
  78.     }
  79.     /**
  80.      * @param int|null $filterId
  81.      * @return array
  82.      * @throws \Doctrine\DBAL\Exception
  83.      */
  84.     public function getIDsForSynchCountFiltersOnlyParent(?int $filterId null): array
  85.     {
  86.         $filterId $filterId "AND (f.parent_id = '$filterId' OR f.id = '$filterId')" '';
  87.         $sql "SELECT DISTINCT f.parent_id
  88.                 FROM filters f
  89.                 WHERE f.parent_id IS NOT NULL $filterId
  90.                 ";
  91.         $conn $this->getEntityManager()->getConnection();
  92.         $ids $conn->fetchAllAssociative($sql);
  93.         if ($ids) {
  94.             $ids array_column($ids'parent_id');
  95.         }
  96.         return $ids;
  97.     }
  98.     /**
  99.      * Получаем subFilter
  100.      * @param bool $new
  101.      * @return array
  102.      * @throws \Doctrine\DBAL\Exception
  103.      */
  104.     public function getFiltersSubRelation(bool $new false): array
  105.     {
  106.         $where $new ' AND p.show_menu != 0 ' ' AND p.show_menu_advanced != 0';
  107.         $sql "SELECT
  108.     f2.id,
  109.     f2.name,
  110.     f2.old_command,
  111.     f2.old_id,
  112.     GROUP_CONCAT(f.id) AS ids,
  113.     GROUP_CONCAT(f.old_id) AS old_ids
  114. FROM
  115.     `filters` f
  116. LEFT JOIN filters f2 ON
  117.     f.parent_id = f2.id
  118. LEFT JOIN filter_params p ON
  119.     f.param_id = p.id
  120. WHERE
  121.     f.parent_id IS NOT NULL AND p.is_enable = 1 $where
  122. GROUP BY
  123.     f.parent_id;";
  124.         $conn $this->getEntityManager()->getConnection();
  125.         $filterData $conn->fetchAllAssociative($sql);
  126.         $parentMap = [];
  127.         if ($new) {
  128.             foreach ($filterData as $row) {
  129.                 $ids explode(','$row['ids']);
  130.                 $parentMap[$row['id']] = $ids;
  131.             }
  132.         } else {
  133.             foreach ($filterData as $row) {
  134.                 $ids explode(','$row['old_ids']);
  135.                 $parentMap[$row['old_command']][$row['old_id']] = $ids;
  136.             }
  137.         }
  138.         return $parentMap;
  139.     }
  140.     /**
  141.      * Получение списка фильтров для синхронизации количества
  142.      * @param int $filterParentId
  143.      * @return array
  144.      */
  145.     public function getListForSynchCountFiltersOnlyChildren(int $filterParentId): array
  146.     {
  147.         $q $this->createQueryBuilder('f')
  148.             ->select(
  149.                 'f.id id, f.name name, f.oldId oldId, f.oldCommand oldCommand, parent.id pid, param.id fpId, param.count fpCount'
  150.             )
  151.             ->leftJoin('f.param''param')
  152.             ->leftJoin('f.parent''parent')
  153.             ->andWhere('parent.id = :pid')->setParameter('pid'$filterParentId)
  154.             ->andWhere('f.oldCommand != :bm')->setParameter('bm''bm'// исключаем из проверок фильтр БМом
  155.         ;
  156.         $q $q->getQuery();
  157.         return $q->getArrayResult();
  158.     }
  159.     /**setCollections
  160.      * Получение списка фильтров для синхронизации количества
  161.      * WebBundle/Command/SynchronizeCommand::runSynchCountFilters()
  162.      * @param array|null $filterIds
  163.      * @param array|null $fidsExclude
  164.      * @return array|null
  165.      */
  166.     public function getListForSynchCountFilters(?array $filterIds = [], ?array $fidsExclude = []): ?array
  167.     {
  168.         $q $this->createQueryBuilder('f')
  169.             ->select(
  170.                 'f.id id, f.name name, f.oldId oldId, f.oldCommand oldCommand, parent.id pid, param.id fpId, param.count fpCount'
  171.             )
  172.             ->leftJoin('f.param''param')
  173.             ->leftJoin('f.parent''parent')
  174.             ->andWhere('f.oldCommand != :bm')->setParameter('bm''bm'// исключаем из проверок фильтр БМом
  175.         ;
  176.         if ($filterIds) {
  177.             $q->andWhere('f.id IN (:filterId)')->setParameter('filterId'$filterIds);
  178.         }
  179.         if ($fidsExclude) {
  180.             $q->andWhere('f.id NOT IN (:filterIdExclude)')->setParameter('filterIdExclude'$fidsExclude);
  181.         }
  182.         $q $q->getQuery();
  183.         return $q->getArrayResult();
  184.     }
  185.     public function getListForOneC(): array
  186.     {
  187.         $q $this->joinQuery('f');
  188.         $r $q->getQuery();
  189.         $cacheName $this->buildCacheName('filter', ['getListForOneC']);
  190.         $r->useQueryCache(true)->enableResultCache((int)TimeConstant::DAY$cacheName);
  191.         return $r->getArrayResult();
  192.     }
  193.     /**
  194.      * @param array $oldIds
  195.      * @param string $oldCommand
  196.      * @param string $locale
  197.      * @return array|FilterResponseDTO[]
  198.      * @throws \Doctrine\DBAL\Driver\Exception
  199.      * @throws \Doctrine\DBAL\Exception
  200.      */
  201.     public function getByOldCommand(array $oldIdsstring $oldCommandstring $locale): array
  202.     {
  203.         $oldIds array_map('intval'$oldIds);
  204.         $oldIds array_unique($oldIds);
  205.         $oldIds array_filter($oldIds);
  206.         if ($oldIds) {
  207.             $fidsStr implode(','$oldIds);
  208.             $fidsStr "f.old_id IN ($fidsStr) AND";
  209.         } else {
  210.             $fidsStr '';
  211.         }
  212.         $sql "SELECT f.id AS `id` FROM filters f WHERE $fidsStr f.old_command = '$oldCommand'";
  213.         return $this->getKeysBySql($sql$locale);
  214.     }
  215.     /**
  216.      * @param string $filterAltName
  217.      * @param string $locale
  218.      * @return FilterResponseDTO[]
  219.      * @throws \Doctrine\DBAL\Driver\Exception
  220.      * @throws \Doctrine\DBAL\Exception
  221.      */
  222.     public function getFilterDTOByAltName(string $filterAltNamestring $locale): array
  223.     {
  224.         $sql "SELECT f.id AS `id` FROM filters f WHERE f.alt_name = '$filterAltName'";
  225.         return $this->getKeysBySql($sql$locale);
  226.     }
  227.     /**
  228.      * Получаем key для URL для дизайнерского стиля
  229.      * @param null $lc
  230.      * @return mixed|null
  231.      */
  232.     public function getKeyDesignerStyle($lc null)
  233.     {
  234.         $lc $lc ?: LocaleHelper::getCurLocale();
  235.         $q $this->createQueryBuilder('f');
  236.         $q->select("url.$lc")
  237.             ->leftJoin('f.url''url')
  238.             ->andWhere("f.altName = :filterAltName")
  239.             ->setParameter('filterAltName''designer')
  240.             ->setMaxResults(1);
  241.         $cacheName $this->buildCacheName('filter_designer_style', [$lc]);
  242.         $r $q->getQuery()->useQueryCache(true)->enableResultCache(TimeConstant::WEEK$cacheName);
  243.         try {
  244.             $item $r->getSingleResult();
  245.             $item $item[$lc];
  246.         } catch (Exception $e) {
  247.             return null;
  248.         }
  249.         return $item;
  250.     }
  251.     /**
  252.      * @param null $filterAltName
  253.      * @param null $groupAltName
  254.      * @param bool $isLike
  255.      * @return mixed
  256.      */
  257.     public function getByAltName($filterAltName null$groupAltName nullbool $isLike false)
  258.     {
  259.         $aParams = [];
  260.         $operate $isLike 'LIKE' '=';
  261.         $q $this->createQueryBuilder('f');
  262.         $q->select('f, groups, page, url, nameForMetaTitle, nameForMetaDescr')
  263.             ->leftJoin('f.groups''groups')
  264.             ->leftJoin('f.page''page')
  265.             ->leftJoin('f.url''url')
  266.             ->leftJoin('f.nameForMetaTitle''nameForMetaTitle')
  267.             ->leftJoin('f.nameForMetaDescr''nameForMetaDescr');
  268.         if ($filterAltName) {
  269.             $q->andWhere("f.altName $operate :filterAltName");
  270.             if ($isLike) {
  271.                 $filterAltName '%' $filterAltName '%';
  272.             }
  273.             $aParams['filterAltName'] = $filterAltName;
  274.         }
  275.         if ($groupAltName) {
  276.             $q->andWhere("groups.altName $operate :groupAltName");
  277.             if ($isLike) {
  278.                 $groupAltName '%' $groupAltName '%';
  279.             }
  280.             $aParams['groupAltName'] = $groupAltName;
  281.         }
  282.         $q->setParameters($aParams);
  283.         $r $q->getQuery();
  284.         $cacheName $this->buildCacheName('filter_getByAltName', [$filterAltName$groupAltName]);
  285.         $r->useQueryCache(true)->enableResultCache(TimeConstant::DAY$cacheName);
  286.         return $r->getResult();
  287.     }
  288.     /**
  289.      * @param int $oldId
  290.      * @return array
  291.      * @throws \Doctrine\DBAL\Exception
  292.      */
  293.     public function getFilterIdsByOldId(int $oldId): array
  294.     {
  295.         $sql "SELECT f.id
  296.                 FROM filters f
  297.                 WHERE f.old_id = $oldId
  298.                 ";
  299.         $memcache $this->cacheService->getMemcache();
  300.         $memcacheKey md5($sql);
  301.         $ids $memcache->get($memcacheKey);
  302.         if ($ids) {
  303.             return $ids;
  304.         }
  305.         $conn $this->getEntityManager()->getConnection();
  306.         $ids $conn->fetchAllAssociative($sql);
  307.         $memcache->set($memcacheKey$ids);
  308.         return $ids;
  309.     }
  310.     /**
  311.      * Получение одного ID по OldID
  312.      * @param int $oldId
  313.      * @param string $oldCommand
  314.      * @return int|null
  315.      */
  316.     public function getFilterIdByOldId(int $oldIdstring $oldCommand): ?int
  317.     {
  318.         $sql "SELECT f.id FROM filters f WHERE f.old_id = '$oldId' AND f.old_command = '$oldCommand' LIMIT 1";
  319.         $memcache $this->cacheService->getMemcache();
  320.         $memcacheKey md5($sql);
  321.         $id $memcache->get($memcacheKey);
  322.         if ($id) {
  323.             return $id;
  324.         }
  325.         try {
  326.             $conn $this->getEntityManager()->getConnection();
  327.             $id $conn->executeQuery($sql)->fetchOne();
  328.         } catch (Throwable $e) {
  329.             return null;
  330.         }
  331.         if ($id) {
  332.             $id = (int)$id;
  333.             $memcache->set($memcacheKey$id);
  334.         }
  335.         return $id ?: null;
  336.     }
  337.     /**
  338.      * Получение массива ID по массиву OldID
  339.      * @param array $oldIds
  340.      * @param string $oldCommand
  341.      * @return array
  342.      * @throws \Doctrine\DBAL\Exception
  343.      */
  344.     public function getFilterIdsByOldIds(array $oldIdsstring $oldCommand): array
  345.     {
  346.         $conn $this->getEntityManager()->getConnection();
  347.         $isDesigner $oldCommand == 'getDesigner';
  348.         $oldCommand $conn->quote($oldCommand);
  349.         $oldIds array_map('intval'array_filter($oldIds'is_numeric'));
  350.         $oldIds implode("', '"$oldIds);
  351.         $oldIds "'$oldIds'";
  352.         $sql "SELECT f.id FROM filters f WHERE f.old_id IN ($oldIds) AND f.old_command = $oldCommand;";
  353.         // для дизайнеров дополнительно ищем по f.id
  354.         if ($isDesigner) {
  355.             $sql "SELECT f.id FROM filters f WHERE (f.old_id IN ($oldIds) OR f.id IN ($oldIds)) AND f.old_command = $oldCommand;";
  356.         }
  357.         $memcache $this->cacheService->getMemcache();
  358.         $memcacheKey md5($sql);
  359.         $ids $memcache->get($memcacheKey);
  360.         if ($ids) {
  361.             return $ids;
  362.         }
  363.         $ids $conn->fetchAllAssociative($sql);
  364.         if ($ids) {
  365.             $ids array_column($ids'id');
  366.         } else {
  367.             $ids = [];
  368.         }
  369.         $memcache->set($memcacheKey$ids);
  370.         return $ids;
  371.     }
  372.     /**
  373.      * Поиск фильтра по url значению
  374.      * @code (
  375.      *     $oRepoFilters->getByKeyUrl('bathroom');
  376.      *     $oRepoFilters->getByKeyUrl('bathroom', 'en');
  377.      * )
  378.      * @param string $filterSlug URL имя фильтра
  379.      * @param string $lc Локаль
  380.      * @param bool $isLike
  381.      * @return FilterResponseDTO|null
  382.      * @throws \Doctrine\DBAL\Driver\Exception
  383.      * @throws \Doctrine\DBAL\Exception
  384.      */
  385.     private function getByUrl(string $filterSlugstring $lcbool $isLike false): ?FilterResponseDTO
  386.     {
  387.         $aLocales LocaleHelper::getListAvailable();
  388.         $aLocales array_column($aLocales'code');
  389.         $andWhere '';
  390.         if ($isLike) {
  391.             $filterSlug '%' $filterSlug '%';
  392.         }
  393.         foreach ($aLocales as $loc) {
  394.             if ($isLike) {
  395.                 $andWhere .= "url.$loc LIKE :slug OR ";
  396.             } else {
  397.                 $andWhere .= "url.$loc = :slug OR ";
  398.             }
  399.         }
  400.         $andWhere trim(trim($andWhere), 'OR');
  401.         $sql $this->buildSQLSelectForFilterResponseDTO($lc);
  402.         $sql "$sql WHERE $andWhere";
  403.         $sql preg_replace('/[\s\n\r]+/'' '$sql);
  404.         $memcache $this->cacheService->getMemcache();
  405.         $memcacheKey $filterSlug md5($sql);
  406.         $dtoArray $memcache->get($memcacheKey);
  407.         if ($dtoArray) {
  408.             return $this->buildFilterResponseDTO($dtoArray);
  409.         }
  410.         $conn $this->getEntityManager()->getConnection();
  411.         $stmt $conn->prepare($sql);
  412.         $stmt->bindValue("slug"$filterSlugTypes::STRING);
  413.         $item $stmt->executeQuery()->fetchAllAssociative();
  414.         if ($lc == 'zh') {
  415.             $sql $this->buildSQLSelectForFilterResponseDTO('en');
  416.             $sql "$sql WHERE $andWhere";
  417.             $sql preg_replace('/[\s\n\r]+/'' '$sql);
  418.             $conn $this->getEntityManager()->getConnection();
  419.             $stmt $conn->prepare($sql);
  420.             $stmt->bindValue("slug"$filterSlugTypes::STRING);
  421.             $itemEn $stmt->executeQuery()->fetchAllAssociative();
  422.             $item $this->fillEmptyFields($item$itemEn);
  423.         }
  424.         if (!$item) {
  425.             return null;
  426.         }
  427.         // если значений несколько, значит не корректный запрос по каким-то причинам
  428.         if (count($item) > 1) {
  429.             return null;
  430.         }
  431.         $memcache->set($memcacheKey$item[0]);
  432.         return $this->buildFilterResponseDTO($item[0]);
  433.     }
  434.     /**
  435.      * @param $altNames
  436.      * @return float|int|mixed|string
  437.      */
  438.     public function getByAltNames($altNames)
  439.     {
  440.         $q $this->joinQuery('f');
  441.         $altNames is_string($altNames) ? explode(','$altNames) : $altNames;
  442.         $q->andWhere('f.altName IN (:altNames)');
  443.         $q->addOrderBy('groups.sort''ASC');
  444.         $q->addOrderBy('f.sort''ASC');
  445.         $q->setParameter('altNames'$altNames);
  446.         $r $q->getQuery();
  447.         $cacheName $this->buildCacheName('filter_getByAltNames'$altNames);
  448.         $r->useQueryCache(true)->enableResultCache((int)TimeConstant::DAY$cacheName);
  449.         return $r->getResult();
  450.     }
  451. // Вспомогательная функция для рекурсивного заполнения
  452.     public function fillEmptyFields($zhArray$enArray)
  453.     {
  454.         $result $zhArray;
  455.         foreach ($enArray as $key => $value) {
  456.             // Если ключа нет в китайском массиве или значение пустое
  457.             if (!isset($result[$key]) || (is_string($result[$key]) && empty(trim($result[$key])))) {
  458.                 $result[$key] = $value;
  459.             } elseif (is_array($value) && isset($zhArray[$key]) && is_array($zhArray[$key])) {
  460.                 // Рекурсивно обрабатываем вложенные массивы
  461.                 $result[$key] = $this->fillEmptyFields($zhArray[$key], $value);
  462.             }
  463.         }
  464.         return $result;
  465.     }
  466.     /**
  467.      * @param array $ids
  468.      * @param string $lc
  469.      * @return array|FilterResponseDTO[]
  470.      * @throws \Doctrine\DBAL\Driver\Exception
  471.      * @throws \Doctrine\DBAL\Exception
  472.      */
  473.     public function getSortedByIds(array $idsstring $lc)
  474.     {
  475.         if (!$ids) {
  476.             return [];
  477.         }
  478.         $conn $this->getEntityManager()->getConnection();
  479.         $inQuery implode(','array_fill(0count($ids), '?'));
  480.         $sql $this->buildSQLSelectForFilterResponseDTO($lc);
  481.         $sql "$sql WHERE f.id IN ($inQuery) ORDER BY gr.sort, f.sort";
  482.         $sql preg_replace('/[\s\n\r]+/'' '$sql);
  483.         $memcache $this->cacheService->getMemcache();
  484.         $memcacheKey md5($sql) . implode('.'$ids);
  485.         $rows $memcache->get($memcacheKey);
  486.         if ($rows) {
  487.             return $rows;
  488.         }
  489.         $stmt $conn->prepare($sql);
  490.         foreach ($ids as $i => $id) {
  491.             $stmt->bindValue(($i 1), $id);
  492.         }
  493.         $items $stmt->executeQuery()->fetchAllAssociative();
  494.         if ($lc == 'zh') {
  495.             $sql $this->buildSQLSelectForFilterResponseDTO('en');
  496.             $sql "$sql WHERE f.id IN ($inQuery) ORDER BY gr.sort, f.sort";
  497.             $sql preg_replace('/[\s\n\r]+/'' '$sql);
  498.             $stmt $conn->prepare($sql);
  499.             foreach ($ids as $i => $id) {
  500.                 $stmt->bindValue(($i 1), $id);
  501.             }
  502.             $itemsEn $stmt->executeQuery()->fetchAllAssociative();
  503.             $items $this->fillEmptyFields($items$itemsEn);
  504.         }
  505.         $rows = [];
  506.         foreach ($items as $item) {
  507.             $row $this->buildFilterResponseDTO($item);
  508.             if ($row) {
  509.                 $rows[] = $row;
  510.             }
  511.         }
  512.         $memcache->set($memcacheKey$rows);
  513.         return $rows;
  514.     }
  515.     /**
  516.      * Осноной запрос получения фильтров из базы по ID с сортировкой по Filter SORT и FilterGroup SORT
  517.      * @param      $id
  518.      * @param bool $toArray
  519.      * @return array|null
  520.      */
  521.     public function getByIds($idbool $toArray false)
  522.     {
  523.         $q $this->joinQuery('f');
  524.         $ids is_string($id) ? explode(','$id) : $id;
  525.         if (count($ids) == 1) {
  526.             $q->andWhere('f.id = :ids');
  527.         } else {
  528.             $q->andWhere('f.id IN (:ids)');
  529.         }
  530.         $q->andWhere('f.id IN (:ids)');
  531.         $q->addOrderBy('groups.sort''ASC');
  532.         $q->addOrderBy('f.sort''ASC');
  533.         $q->setParameter('ids'$ids);
  534.         $r $q->getQuery();
  535.         $cacheName $this->buildCacheName('filter_getByIds'$id);
  536.         $r->useQueryCache(true)->enableResultCache((int)TimeConstant::DAY$cacheName);
  537.         if ($toArray) {
  538.             $items $r->getArrayResult();
  539.         } else {
  540.             $items $r->getResult();
  541.         }
  542.         return $items;
  543.     }
  544.     /**
  545.      * Осноной запрос получения фильтров из базы по ID с сортировкой по Filter SORT и FilterGroup SORT
  546.      * @param $altName
  547.      * @return array|null
  548.      */
  549.     public function getByGroupAlias($altName)
  550.     {
  551.         $q $this->joinQuery('f');
  552.         $q->andWhere('groups.altName = :altName');
  553.         $q->addOrderBy('groups.sort''ASC');
  554.         $q->setParameter('altName'$altName);
  555.         $r $q->getQuery();
  556.         $cacheName $this->buildCacheName('filter_getByGroupAlias'$altName);
  557.         $r->useQueryCache(true)->enableResultCache((int)TimeConstant::DAY$cacheName);
  558.         $items $r->getResult();
  559.         return (count($items) == 1) ? $items[0] : $items;
  560.     }
  561.     public function getListDesignersByGroupAlias($altName)
  562.     {
  563.         $q $this->joinQuery('f');
  564.         $q->andWhere('groups.altName = :altName');
  565.         $q->andWhere('param.count > 0');
  566.         $q->addOrderBy('f.name''ASC');
  567.         $q->addOrderBy('groups.sort''ASC');
  568.         $q->setParameter('altName'$altName);
  569.         $r $q->getQuery();
  570.         $cacheName $this->buildCacheName('filter_getListDesignersByGroupAlias'$altName);
  571.         $r->useQueryCache(true)->enableResultCache((int)TimeConstant::DAY$cacheName);
  572.         return $r->getResult();
  573.     }
  574.     /**
  575.      * Формирование массива ссылок на фильтры в футере
  576.      * @return array
  577.      * @throws Exception
  578.      */
  579.     public function getForFooterByGroupAlias(): array
  580.     {
  581.         $memcache $this->cacheService->getMemcache();
  582.         $lcFull App::getCurLocale(true);
  583.         $list $memcache->get('footer.links.filter.' App::isDev() . $lcFull);
  584.         if (!$list) {
  585.             $ids = [1004010136101321011110147106171064610146];
  586.             $idsStr '10040,10136,10132,10111,10147,10617,10646,10146';
  587.             $locales LocaleHelper::getListAvailable();
  588.             $router App::getContainer()->get('router');
  589.             $translator App::getTranslator();
  590.             $urlStrSql = [];
  591.             foreach ($locales as $item) {
  592.                 $urlStrSql[] = "url.{$item['code']} AS `url.{$item['code']}`";
  593.             }
  594.             $urlStrSql implode(', '$urlStrSql);
  595.             $sql "SELECT
  596.                 f.id,
  597.                 f.left_menu AS leftMenu, $urlStrSql
  598.                 FROM filters f
  599.                 LEFT JOIN `locale_url` `url` ON `url`.filter_id = f.id
  600.                 WHERE f.id IN ($idsStr)
  601.                 ";
  602.             $sql preg_replace('/[\s\n\r]+/'' '$sql);
  603.             $items $this->getEntityManager()->getConnection()->fetchAllAssociative($sql);
  604.             // в многомерные массивы переводим
  605.             foreach ($items as $i => $item) {
  606.                 foreach ($item as $k => $v) {
  607.                     if (preg_match("~(.*)\.(.*)~ui"$k$out)) {
  608.                         $k1 $out[1];
  609.                         $k2 $out[2];
  610.                         if (empty($item[$k1])) {
  611.                             $item[$k1] = [];
  612.                         }
  613.                         $item[$k1][$k2] = $v;
  614.                         unset($item[$k]);
  615.                     }
  616.                 }
  617.                 $items[$i] = $item;
  618.             }
  619.             $ids array_flip($ids);
  620.             $lc_ App::getCurLocale();
  621.             // выставляем порядок и сразу формируем имя и урл
  622.             foreach ($items as $i => $item) {
  623.                 $key $item['leftMenu'] . '_footer';
  624.                 //$key = $item['leftMenu'];
  625.                 $name $translator->trans($key, [], null$lc_);
  626.                 $ids[$item['id']] = [
  627.                     'name' => $name,
  628.                     'url' => urldecode(
  629.                         $router->generate(
  630.                             'app_catalog',
  631.                             [
  632.                                 'key' => $item['url'][$lc_],
  633.                                 '_locale' => $lcFull,
  634.                             ]
  635.                         )
  636.                     ),
  637.                 ];
  638.             }
  639.             $list $ids;
  640.             $memcache->add('footer.links.filter.' App::isDev() . $lcFull$listfalse3600 24 30);
  641.         }
  642.         return $list;
  643.     }
  644.     /**
  645.      * Получение фабрики через фильтры.
  646.      * @param array $param
  647.      * @return array|null
  648.      * @throws NonUniqueResultException
  649.      * @throws Exception
  650.      * @see WebBundle/Repository/FactoryRepository::getFactory()
  651.      */
  652.     public function getBrand(array $param = [])
  653.     {
  654.         if (!empty($param['count'])) {
  655.             $q $this->createQueryBuilder('f')
  656.                 ->select('COUNT(f.id)')
  657.                 ->leftJoin('f.brand''brand')
  658.                 ->leftJoin('f.param''param');
  659.         } else {
  660.             $q $this->joinQuery('f');
  661.         }
  662.         $q
  663.             ->andWhere('f.brand IS NOT NULL')
  664.             ->andWhere('f.id != 10639')// 10639 это тестовая фабрика, выкидываем ее
  665.             ->andWhere('brand.status = :status')
  666.             ->andWhere('param.isEnabled = true')
  667.             ->andWhere('param.count >= 0')
  668.             ->andWhere('brand.unid IS NOT NULL')
  669.             ->setParameter('status'BiConst::STATE_PUBLISHED)
  670.             ->orderBy('f.name');
  671.         if (!empty($param['url'])) {
  672.             $q->andWhere('f.url = :url')
  673.                 ->setParameter('url'$param['url']);
  674.         }
  675.         if (!empty($param['name'])) {
  676.             $q->andWhere('f.name = :name')
  677.                 ->setParameter('name'$param['name']);
  678.         }
  679.         if (!empty($param['id'])) {
  680.             $q->andWhere('f.id = :filterId');
  681.             $q->setParameter('filterId'$param['id']);
  682.         }
  683.         if (!App::isRole('ROLE_TEST')) {
  684.             $q->andWhere('brand.testAccess IS NULL');
  685.         }
  686.         $r $q->getQuery();
  687.         $r->useQueryCache(true)->enableResultCache((int)TimeConstant::HOUR); // час
  688.         if (!empty($param['count'])) {
  689.             $items $r->getSingleScalarResult();
  690.         } else {
  691.             if (empty($param['asArray'])) {
  692.                 $items $r->getResult();
  693.             } else {
  694.                 $items $r->getArrayResult();
  695.             }
  696.         }
  697.         return $items;
  698.     }
  699.     /**
  700.      * Хелпер по получению записей брендов
  701.      * @param array $param
  702.      * @return array|null
  703.      */
  704.     public function getBrands(array $param = [])
  705.     {
  706.         $parameters = [];
  707.         $q $this->joinQuery('f');
  708.         $q
  709.             ->andWhere("groups.altName = 'brand'")
  710.             //->andWhere('f.brand IS NOT NULL')
  711.             //->addSelect('country')
  712.             //->leftJoin('brand.country', 'country')
  713.         ;
  714.         if (!is_array($param)) {
  715.             $paramId intval($param);
  716.             if ($paramId) {
  717.                 $param = ['id' => $paramId];
  718.             }
  719.         }
  720.         if (!empty($param['id'])) {
  721.             $q->andWhere('f.id = :brandId');
  722.             $parameters['brandId'] = $param['id'];
  723.         }
  724.         if (isset($param['noBrand'])) {
  725.             $q->andWhere('f.brand IS NULL');
  726.         }
  727.         if (!empty($param['factoryId'])) {
  728.             $q->andWhere('f.brand = :factoryId');
  729.             $parameters['factoryId'] = $param['factoryId'];
  730.         }
  731.         if (!empty($param['name'])) {
  732.             $q->andWhere('f.name = :name');
  733.             $parameters['name'] = $param['name'];
  734.         }
  735.         if (count($parameters) > 0) {
  736.             $q->setParameters($parameters);
  737.         }
  738.         $r $q->getQuery();
  739.         $r->useQueryCache(true)->enableResultCache((int)TimeConstant::HOUR); // час
  740.         if (empty($param['asArray'])) {
  741.             $items $r->getResult();
  742.         } else {
  743.             $items $r->getArrayResult();
  744.         }
  745.         return $items;
  746.     }
  747.     /**
  748.      * Получение списка фильтров для меню фильтрации
  749.      * @return array|null
  750.      */
  751.     public function getArrListForFilterMenu()
  752.     {
  753.         $q $this->joinQuery('f');
  754.         $q
  755.             ->andWhere('param.isEnabled = 1')
  756.             //->andWhere('param.showMenuAdvanced = 1')
  757.             //->andWhere('param.count > 0')
  758.             //->andWhere("(param.showMenuAdvanced = 1 AND f.oldCommand != 'factory')")
  759.             ->orderBy('f.sort ASC, f.name');
  760.         $r $q->getQuery();
  761.         $r->useQueryCache(true)->enableResultCache((int)TimeConstant::HOUR); // час
  762.         return $r->getResult();
  763.     }
  764.     /**
  765.      * Выборка для расширенного меню фильтров
  766.      * @param $lc
  767.      * @return array
  768.      * @throws \Doctrine\DBAL\Exception
  769.      */
  770.     public function getArrListForFilterMenuNew($lc): array
  771.     {
  772.         $sql "SELECT
  773.                 f.id,
  774.                 f.alt_name AS `altName`,
  775.                 f.sort AS `sort`,
  776.                 f.parent_id AS `pid`,
  777.                 f.old_command AS `oldCommand`,
  778.                 fp.name_menu_$lc AS `name`,
  779.                    u.$lc AS `url`,
  780.                 p.count AS `count`,
  781.                 p.hex_code AS `hexCode`,
  782.                 p.show_menu_advanced AS `showMenuAdvanced`,
  783.                 g.id AS `group.id`,
  784.                 g.alt_name AS `group.altName`,
  785.                 gname.$lc AS `group.name`,
  786.                 tooltip.$lc AS `tooltip`,
  787.                 c.id AS `country.id`,
  788.                 c.old_id AS `country.code`,
  789.                    c.alt_name AS `country.altName`,
  790.                 cp.name_menu_$lc AS `country.name`,
  791.                 b.id AS `brand.id`,
  792.                 b.name AS `brand.name`
  793.             FROM
  794.                 filters f
  795.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  796.             LEFT JOIN filter_params p ON p.id = f.param_id
  797.             LEFT JOIN filter_groups g ON g.id = f.group_id
  798.             LEFT JOIN locale_text gname ON gname.filter_group_name = g.id
  799.             LEFT JOIN locale_text tooltip ON tooltip.filter_tooltip = f.id
  800.             LEFT JOIN filters c ON c.id = f.country_id
  801.             LEFT JOIN filter_pages cp ON cp.id = c.page_id
  802.             LEFT JOIN locale_url u ON u.filter_id = f.id
  803.             LEFT JOIN factory b ON b.id = f.brand
  804.             WHERE (g.alt_name <> 'brand' AND p.show_menu_advanced = 1 OR g.alt_name = 'brand' AND b.status = 1) AND
  805.             (p.count > 0 OR g.alt_name = 'brand' OR g.alt_name = 'reviews') AND
  806.             p.is_enable = 1 AND p.hide != 1 AND p.hide_all != 1 AND f.id != '10639'
  807.             ORDER BY f.sort, f.name";
  808.         $memcache $this->cacheService->getMemcache();
  809.         $memcacheKey md5($sql);
  810.         $rows $memcache->get($memcacheKey);
  811.         if ($rows) {
  812.             return $rows;
  813.         }
  814.         $items $this->getEntityManager()->getConnection()->fetchAllAssociative($sql);
  815.         $rows = [];
  816.         foreach ($items as $item) {
  817.             $name $item['name'];
  818.             $group = [
  819.                 'id' => intval($item['group.id']),
  820.                 'name' => $item['group.name'],
  821.                 'altName' => $item['group.altName'],
  822.             ];
  823.             // выносим в отдельную категорию крупный размер плитки
  824.             if ($item['oldCommand'] == 'size_big') {
  825.                 $group = [
  826.                     'id' => 0,
  827.                     'name' => 'Other',
  828.                     'altName' => 'other',
  829.                 ];
  830.             }
  831.             $country null;
  832.             if (!empty($item['country.id'])) {
  833.                 $country = [
  834.                     'id' => intval($item['country.id']),
  835.                     'code' => intval($item['country.code']),
  836.                     'name' => $item['country.name'],
  837.                     'altName' => $item['country.altName'],
  838.                 ];
  839.             }
  840.             $brand null;
  841.             if (!empty($item['brand.id'])) {
  842.                 $brand = [
  843.                     'id' => intval($item['brand.id']),
  844.                     'name' => $item['brand.name'],
  845.                 ];
  846.                 // меняем основное имя на имя фабрики, на всякий случай
  847.                 $name $item['brand.name'];
  848.             }
  849.             // ID родительского фильтра
  850.             $pid intval($item['pid']);
  851.             $pid $pid ?: null;
  852.             // исключил все случайно попадающие награды в список фильтров
  853.             if ($group['altName'] == 'rewards') {
  854.                 if ($item['id'] != '10546') {
  855.                     continue;
  856.                 }
  857.             }
  858.             $row = [
  859.                 'id' => intval($item['id']),
  860.                 'pid' => $pid,
  861.                 'name' => $name,
  862.                 'altName' => $item['altName'],
  863.                 'tooltip' => $item['tooltip'],
  864.                 'oldCommand' => $item['oldCommand'],
  865.                 'key' => $item['url'],
  866.                 'hexCode' => $item['hexCode'],
  867.                 'count' => intval($item['count']),
  868.                 'sort' => intval($item['sort']),
  869.                 'showMenuAdvanced' => boolval($item['showMenuAdvanced']),
  870.                 'group' => $group,
  871.                 'brand' => $brand,
  872.                 'country' => $country,
  873.                 'collection' => [],
  874.                 'selected' => [],
  875.                 'sub' => [],
  876.                 'groupList' => [],
  877.             ];
  878.             $rows[$row['id']] = $row;
  879.         }
  880.         $memcache->set($memcacheKey$rows);
  881.         return $rows;
  882.     }
  883.     /**
  884.      * Выборка для истории фильтров
  885.      *
  886.      * @param $lc
  887.      *
  888.      * @return array
  889.      * @throws \Doctrine\DBAL\Exception
  890.      */
  891.     public function getNamePerFilter($lc): array
  892.     {
  893.         $sql "SELECT filters.id, filter_pages.name_many_$lc as name FROM `filters` left join filter_pages on `filters`.page_id=filter_pages.id where filter_pages.name_many_$lc is not null;";
  894.         $memcache $this->cacheService->getMemcache();
  895.         $memcacheKey md5($sql);
  896.         $rows $memcache->get($memcacheKey);
  897.         if ($rows) {
  898.             return $rows;
  899.         }
  900.         $items $this->getEntityManager()
  901.             ->getConnection()
  902.             ->fetchAllAssociative($sql);
  903.         $memcache->set($memcacheKey$items);
  904.         return $items;
  905.     }
  906.     /**
  907.      * Получаем массив всех фильтров для меню
  908.      * @param null $groups
  909.      * @param      $lc
  910.      * @param bool $ignoreEnabled
  911.      * @return array|null
  912.      * @throws Exception
  913.      */
  914.     public function getArrListForMenu($groups$lcbool $ignoreEnabled false): ?array
  915.     {
  916.         $lcUc ucfirst($lc);
  917.         $selectByLc "url.$lc url$lcUc, page.nameMenu$lcUc pageNameMenu$lcUc,";
  918.         // костыль для фильтра цен, что бы показывать верно для разных стран
  919.         $lcPrice LocaleHelper::getLocaleForPriceFilter($lc);
  920.         if ($lc != $lcPrice) {
  921.             $lcUcPrice ucfirst($lcPrice);
  922.             $selectByLc .= "url.$lcPrice url$lcUcPrice, page.nameMenu$lcUcPrice pageNameMenu$lcUcPrice,";
  923.         }
  924.         $q $this->createQueryBuilder('f')
  925.             ->select(
  926.                 "
  927.             f,
  928.             f.id,
  929.             f.oldCommand,
  930.             f.oldId,
  931.             f.leftMenu,
  932.             parent.id pid,
  933.             f.important,
  934.             $selectByLc
  935.             groups.altName groupsAltName,
  936.             param.count paramCount,
  937.             country
  938.             "
  939.             )
  940.             ->leftJoin('f.url''url')
  941.             ->leftJoin('f.page''page')
  942.             ->leftJoin('f.param''param')
  943.             ->leftJoin('f.groups''groups')
  944.             ->leftJoin('f.country''country')
  945.             ->leftJoin('f.parent''parent');
  946.         if (!$ignoreEnabled) {
  947.             $q
  948.                 ->andWhere('param.isEnabled = 1')
  949.                 ->andWhere('param.showMenu = 1 OR param.showMenuAdvanced = 1')
  950.                 ->andWhere('url.' $lc '  is not null')
  951.                 ->andWhere('param.count > 0');
  952.         }
  953.         $q->orderBy('f.sort ASC, f.name');
  954.         if ($groups) {
  955.             $groups is_array($groups) ? $groups : [$groups];
  956.             $q->andWhere('groups.altName IN (:groups)')
  957.                 ->setParameter('groups'$groups);
  958.         }
  959.         $r $q->getQuery();
  960.         $cacheName $this->buildCacheName('filter_getArrListForMenu3_' $lc $lcPrice$groups);
  961.         $r->useQueryCache(true);
  962.         if (!App::isDev() or !$ignoreEnabled) {
  963.             $r->enableResultCache(TimeConstant::DAY$cacheName);
  964.         }
  965.         $res = [];
  966.         $items $r->getArrayResult();
  967.         /** @var FilterEntity $item */
  968.         foreach ($items as $item) {
  969.             $f $item[0];
  970.             unset($item[0]);
  971.             $item['country'] = $f['country'];
  972.             $res[$item['groupsAltName']][] = $item;
  973.         }
  974.         return $res;
  975.     }
  976.     /**
  977.      * Получаем массив всех детей по рабителю для фейк тегов
  978.      * @param null $groups
  979.      * @param      $lc
  980.      * @param bool $ignoreEnabled
  981.      * @return array|null
  982.      * @throws Exception
  983.      */
  984.     public function getArrListSubForMenu($pid$lcbool $ignoreEnabled false): ?array
  985.     {
  986.         $lcUc ucfirst($lc);
  987.         $selectByLc "url.$lc url$lcUc, page.nameMenu$lcUc pageNameMenu$lcUc,";
  988.         // костыль для фильтра цен, что бы показывать верно для разных стран
  989.         $lcPrice LocaleHelper::getLocaleForPriceFilter($lc);
  990.         if ($lc != $lcPrice) {
  991.             $lcUcPrice ucfirst($lcPrice);
  992.             $selectByLc .= "url.$lcPrice url$lcUcPrice, page.nameMenu$lcUcPrice pageNameMenu$lcUcPrice,";
  993.         }
  994.         $q $this->createQueryBuilder('f')
  995.             ->select(
  996.                 "
  997.             $selectByLc
  998.             f
  999.             "
  1000.             )
  1001.             ->leftJoin('f.url''url')
  1002.             ->leftJoin('f.page''page')
  1003.             ->leftJoin('f.param''param')
  1004.             ->leftJoin('f.groups''groups')
  1005.             ->leftJoin('f.country''country')
  1006.             ->leftJoin('f.parent''parent');
  1007.         if (!$ignoreEnabled) {
  1008.             $q
  1009.                 ->andWhere('param.isEnabled = 1')
  1010.                 ->andWhere('parent.id = ' $pid)
  1011.                 ->andWhere('param.showMenu = 1 OR param.showMenuAdvanced = 1')
  1012.                 ->andWhere('url.' $lc '  is not null')
  1013.                 ->andWhere('param.count > 0');
  1014.         }
  1015.         $q->orderBy('f.sort ASC, f.name');
  1016.         $r $q->getQuery();
  1017.         $cacheName $this->buildCacheName('filter_getArrListSubMenu_' $lc $lcPrice$pid);
  1018.         // $r->useQueryCache(true);
  1019.         if (!App::isDev() or !$ignoreEnabled) {
  1020.             $r->enableResultCache(TimeConstant::DAY$cacheName);
  1021.         }
  1022.         $res = [];
  1023.         $items $r->getArrayResult();
  1024.         /** @var FilterEntity $item */
  1025.         foreach ($items as $item) {
  1026.             $f $item[0];
  1027.             unset($item[0]);
  1028.             $item['url'] = $item["url$lcUc"];
  1029.             $item['pageNameMenu'] = $item["pageNameMenu$lcUc"];
  1030.             $res[] = $item;
  1031.         }
  1032.         return $res;
  1033.     }
  1034.     public function getFilterIdForSettingsCollectionByLeft($leftMenu)
  1035.     {
  1036.         $q $this->createQueryBuilder('f')
  1037.             ->select('f.id, f.name')
  1038.             ->leftJoin('f.url''url')
  1039.             ->leftJoin('f.page''page')
  1040.             ->andWhere('f.leftMenu = :leftMenu')
  1041.             ->setParameter('leftMenu'$leftMenu)
  1042.             ->getQuery()
  1043.             ->enableResultCache(TimeConstant::DAY);
  1044.         $id $q->getArrayResult();
  1045.         return $id $id[0] : null;
  1046.     }
  1047.     public function getFilterIdForSettingsColletionByIdDesigner(int $id)
  1048.     {
  1049.         $q $this->createQueryBuilder('f')
  1050.             ->select('f.id, f.name')
  1051.             ->leftJoin('f.url''url')
  1052.             ->leftJoin('f.page''page')
  1053.             ->andWhere('f.id = :id')->setParameter('id'$id)
  1054.             ->andWhere('f.oldCommand != :oldCommand')->setParameter('oldCommand''factory');
  1055.         $q $q->getQuery()->enableResultCache(TimeConstant::DAY);
  1056.         $id $q->getArrayResult();
  1057.         return $id $id[0] : null;
  1058.     }
  1059.     /**
  1060.      * Получаем массив данных фильтра для свойств коллекции
  1061.      * URL и имя формируется сразу по локали
  1062.      * @param      $oldId
  1063.      * @param      $oldCommand
  1064.      * @param null $locale
  1065.      * @return mixed|null
  1066.      * @throws Exception
  1067.      */
  1068.     public function findFilterForSettingsColletion($oldId$oldCommand$locale null)
  1069.     {
  1070.         $locale $locale ?: App::getCurLocale();
  1071.         $localeUc ucfirst($locale);
  1072.         $key 'filter_' $oldId '_' $oldCommand '_' $locale;
  1073.         $res App::getMemcache()->get($key);
  1074.         if (!$res) {
  1075.             $q $this->createQueryBuilder('f');
  1076.             $q->select('f, f.id, f.oldId, f.oldCommand, f.altName, f.rank, url, page');
  1077.             $q
  1078.                 ->leftJoin('f.url''url')
  1079.                 ->leftJoin('f.page''page');
  1080.             $q
  1081.                 ->andWhere("f.oldId = :old_id")
  1082.                 ->setParameter('old_id'$oldId)
  1083.                 ->andWhere("f.oldCommand = :old_command")
  1084.                 ->setParameter('old_command'$oldCommand);
  1085.             $q->setMaxResults(1);
  1086.             $r $q->getQuery()->enableResultCache(TimeConstant::DAY);
  1087.             $item ArrHelper::get($r->getArrayResult(), '0');
  1088.             if (!$item) {
  1089.                 return null;
  1090.             }
  1091.             $item['url'] = ArrHelper::get($item"0.url.$locale");
  1092.             $item['name'] = ArrHelper::get($item"0.page.nameMany$localeUc");
  1093.             unset($item[0]);
  1094.             if (!defined('DB_NOT_CASHED')) {
  1095.                 App::getMemcache()->set($key$itemfalse, (int)TimeConstant::WEEK); // неделя
  1096.             }
  1097.             $res $item;
  1098.         }
  1099.         return $res;
  1100.     }
  1101.     /**
  1102.      * Получаем список активных фильтров для просчета ранга
  1103.      * @return array|null
  1104.      */
  1105.     public function getForCalcRank()
  1106.     {
  1107.         $q $this->createQueryBuilder('f');
  1108.         $q->select('f.id, f.name, f.rank, param.count, groups.id gid')
  1109.             ->leftJoin('f.groups''groups')
  1110.             ->leftJoin('f.param''param')
  1111.             ->andWhere("groups.id != 406")// исключаем бренды
  1112.             //->andWhere("groups.id != 411")// исключаем дизайнеров
  1113.             ->andWhere("groups.id != 408")// исключаем Размер
  1114.             ->andWhere("groups.id != 412")// исключаем top
  1115.             ->andWhere("groups.id != 415")// исключаем page
  1116.             ->andWhere("groups.id != 416")// исключаем БМ
  1117.             ->andWhere("groups.id != 407")// исключаем Сортировка
  1118.             ->andWhere("groups.id != 399")// исключаем распродажа
  1119.             ->andWhere("param.isEnabled = 1")//->andWhere("param.showMenu = 1")
  1120.         ;
  1121.         $result $q->getQuery()->enableResultCache(TimeConstant::DAY);
  1122.         $res = [];
  1123.         foreach ($result->getArrayResult() as $i => $item) {
  1124.             $res[$item['id']] = $item;
  1125.         }
  1126.         return $res;
  1127.     }
  1128.     /**
  1129.      * @param string $key
  1130.      * @return FilterEntity|null
  1131.      */
  1132.     public function admGetExhibitionByKeyForConsole(string $key)
  1133.     {
  1134.         $q $this->createQueryBuilder('f');
  1135.         $q->select('f, groups, param, page')
  1136.             ->leftJoin('f.groups''groups')
  1137.             ->leftJoin('f.param''param')
  1138.             ->leftJoin('f.page''page')
  1139.             ->andWhere("f.name LIKE '$key%'")
  1140.             ->andWhere('param.isEnabled = 1')
  1141.             ->andWhere('groups.id = 420 OR groups.id = 417')
  1142.             ->orderBy('f.id''DESC')
  1143.             ->setMaxResults(1);
  1144.         try {
  1145.             return $q->getQuery()->getSingleResult();
  1146.         } catch (NoResultException NonUniqueResultException $e) {
  1147.             return null;
  1148.         }
  1149.     }
  1150.     /**
  1151.      * Получаем последний ID для сфинкса из группы
  1152.      * @param int $groupId
  1153.      * @return int
  1154.      * @throws Throwable
  1155.      */
  1156.     public function admGetExhibitionLastOldIdForConsole(int $groupId): int
  1157.     {
  1158.         $sql "SELECT  f.old_id AS `oldId`
  1159.                 FROM filters f
  1160.                 WHERE f.group_id = $groupId
  1161.                 ORDER BY f.old_id DESC LIMIT 1";
  1162.         $oldId $this->getEntityManager()
  1163.             ->getConnection()
  1164.             ->executeQuery($sql)
  1165.             ->fetchOne();
  1166.         return intval($oldId);
  1167.     }
  1168.     /**
  1169.      * Получение последнего дизайнера, для использования в качестве шаблона для создания нового
  1170.      * @return FilterEntity|null
  1171.      */
  1172.     public function admLastDesigner(): ?FilterEntity
  1173.     {
  1174.         $q $this->createQueryBuilder('f');
  1175.         $q->select('f, groups, param, page')
  1176.             ->leftJoin('f.groups''groups')
  1177.             ->leftJoin('f.param''param')
  1178.             ->leftJoin('f.page''page')
  1179.             ->andWhere("f.parentKey = 'designer'")
  1180.             ->andWhere('param.isEnabled = 1')
  1181.             ->orderBy('f.id''DESC')
  1182.             ->setMaxResults(1);
  1183.         try {
  1184.             return $q->getQuery()->getSingleResult();
  1185.         } catch (NoResultException NonUniqueResultException $e) {
  1186.             return null;
  1187.         }
  1188.     }
  1189.     /**
  1190.      * Поиск последней заполненной переводами записи награды.
  1191.      */
  1192.     public function getLastRewards(): ?FilterEntity
  1193.     {
  1194.         $q $this->createQueryBuilder('f');
  1195.         $q->select('f, groups, param, page')
  1196.             ->innerJoin('f.groups''groups')
  1197.             ->leftJoin('f.param''param')
  1198.             ->innerJoin('f.page''page')
  1199.             ->where('groups.id = :groupId')
  1200.             ->andWhere('param.isEnabled = 1')
  1201.             ->andWhere('page.nameSingleEn IS NOT NULL AND page.nameSingleEn != :empty')
  1202.             ->andWhere('page.descriptionEn IS NOT NULL AND page.descriptionEn != :empty')
  1203.             ->orderBy('f.id''DESC')
  1204.             ->setMaxResults(1)
  1205.             ->setParameters([
  1206.                 'groupId' => FilterGroupEnum::REWARD,
  1207.                 'empty' => ''
  1208.             ]);
  1209.         $query $q->getQuery();
  1210.         $query->useQueryCache(true);
  1211.         $query->setQueryCacheLifetime(self::QUERY_CACHE_LIFETIME);
  1212.         try {
  1213.             return $query->getSingleResult();
  1214.         } catch (NoResultException NonUniqueResultException $e) {
  1215.             return null;
  1216.         }
  1217.     }
  1218.     /**
  1219.      * Получение списка наград для выпадающего списка
  1220.      * @return array
  1221.      */
  1222.     public function admGetAwardsForSelectMenu(): array
  1223.     {
  1224.         $q $this->createQueryBuilder('f');
  1225.         $q->select('f.id, f.name')
  1226.             ->leftJoin('f.groups''groups')
  1227.             ->andWhere("groups.altName = 'rewards'")
  1228.             ->andWhere("f.oldId != 1"// исключаем фильтр общий Премированные
  1229.         ;
  1230.         $res = [];
  1231.         $out $q->getQuery()->getArrayResult();
  1232.         foreach ($out as $i => $item) {
  1233.             $res[(string)$item['id']] = $item['name'];
  1234.         }
  1235.         return $res;
  1236.     }
  1237.     /**
  1238.      * Список выставок для БИ и админки
  1239.      * @return array
  1240.      */
  1241.     public function admGetExhibitionForSelectMenu(): array
  1242.     {
  1243.         $q $this->createQueryBuilder('f');
  1244.         $q->select('f.oldId id, f.name')
  1245.             ->leftJoin('f.groups''groups')
  1246.             ->andWhere("groups.altName = 'exhibition'");
  1247.         $res = [];
  1248.         $out $q->getQuery()->getArrayResult();
  1249.         foreach ($out as $i => $item) {
  1250.             $res[(string)$item['id']] = $item['name'];
  1251.         }
  1252.         return $res;
  1253.     }
  1254.     /**
  1255.      * @param $exhibition
  1256.      * @return array
  1257.      */
  1258.     public function admGetExhibitionForBI($exhibition): array
  1259.     {
  1260.         $q $this->createQueryBuilder('f');
  1261.         $q->select('f.id, f.name, f.iconUrl')
  1262.             ->leftJoin('f.groups''groups')
  1263.             ->leftJoin('f.param''param')
  1264.             ->andWhere("groups.altName = 'exhibition'")
  1265.             ->andWhere("f.oldId in (:exhibition)")
  1266.             ->setParameter('exhibition'$exhibition);
  1267.         $res = [];
  1268.         $out $q->getQuery()->getArrayResult();
  1269.         foreach ($out as $i => $item) {
  1270.             $link $item['iconUrl'];
  1271.             $res[(string)$item['id']] = (!empty($link)) ? $item['name'] . '(<a href="' $link '" target="_blank" rel="noopener noreferrer">' $link '</a>)' $item['name'];
  1272.         }
  1273.         return $res;
  1274.     }
  1275.     public function admGetAwardsForBi($awards): array
  1276.     {
  1277.         $q $this->createQueryBuilder('f');
  1278.         $q->select('f.id, f.name, f.iconUrl')
  1279.             ->leftJoin('f.groups''groups')
  1280.             ->andWhere("groups.altName = 'rewards'")
  1281.             ->andWhere("f.oldId != 1"// исключаем фильтр общий Премированные
  1282.             ->andWhere("f.id in (:awards)")
  1283.             ->setParameter('awards'$awards);
  1284.         $res = [];
  1285.         $out $q->getQuery()->getArrayResult();
  1286.         foreach ($out as $i => $item) {
  1287.             $link $item['iconUrl'];
  1288.             $res[(string)$item['id']] = (!empty($link)) ? $item['name'] . '(<a href="' $link '" target="_blank" rel="noopener noreferrer">' $link '</a>)' $item['name'];
  1289.         }
  1290.         return $res;
  1291.     }
  1292.     public function admGetForJsTree(): array
  1293.     {
  1294.         $q $this->createQueryBuilder('f');
  1295.         $q->select('f.id, f.name, groups.id gr_id, groups.altName gr_name')
  1296.             ->leftJoin('f.groups''groups')
  1297.             ->leftJoin('f.param''param')
  1298.             ->andWhere("groups.id != 411")// исключаем дизайнеров
  1299.             ->andWhere("groups.id != 408")// исключаем Размер
  1300.             //->andWhere("groups.id != 412")// исключаем top
  1301.             ->andWhere("groups.id != 415")// исключаем page
  1302.             ->andWhere("groups.id != 416")// исключаем БМ
  1303.             ->andWhere("groups.id != 407")// исключаем Сортировка
  1304.             ->andWhere("groups.id != 399")// исключаем распродажа
  1305.             ->andWhere("param.isEnabled = true")
  1306.             ->andWhere("param.showMenuAdvanced = true")
  1307.             ->orderBy('gr_name''ASC')
  1308.             ->addOrderBy('f.name''ASC')
  1309.             ->andWhere("groups.id != 406"// исключаем бренды
  1310.             //->andWhere("groups.id = 397") // временно, что бы был один
  1311.         ;
  1312.         $items $q->getQuery()->getArrayResult();
  1313.         $res = [];
  1314.         foreach ($items as $item) {
  1315.             $res[$item['gr_id']][] = $item;
  1316.         }
  1317.         return $res;
  1318.     }
  1319.     public function getSortListCataloge($locale null)
  1320.     {
  1321.         $locale $locale ?: App::getCurLocale();
  1322.         $localeUc ucfirst($locale);
  1323.         $q $this->createQueryBuilder('f')
  1324.             ->select("f.oldId as id, page.nameSingle$localeUc as nameSingle, page.nameMenu$localeUc as nameMenu")
  1325.             ->leftJoin('f.page''page')
  1326.             ->leftJoin('f.groups''gr')
  1327.             ->andWhere('gr.id = 407')
  1328.             ->orderBy('f.sort''ASC');
  1329.         $r $q->getQuery()
  1330.             ->useQueryCache(true);
  1331.         $items $r->getArrayResult();
  1332.         $res = [];
  1333.         foreach ($items as $item) {
  1334.             $res[$item['id']] = $item;
  1335.         }
  1336.         return $res;
  1337.     }
  1338.     public function getSameSingleByLeft($locale null$alias '')
  1339.     {
  1340.         $locale $locale ?: App::getCurLocale();
  1341.         $localeUc ucfirst($locale);
  1342.         $q $this->createQueryBuilder('f')
  1343.             ->select(" page.nameSingle$localeUc as nameSingle")
  1344.             ->leftJoin('f.page''page')
  1345.             ->leftJoin('f.groups''gr')
  1346.             ->andWhere('f.leftMenu = :alias')
  1347.             ->setParameter('alias'$alias)
  1348.             ->orderBy('f.sort''ASC');
  1349.         $r $q->getQuery()
  1350.             ->useQueryCache(true);
  1351.         $items $r->getSingleScalarResult();
  1352.         return $items;
  1353.     }
  1354.     public function getAwards(array $id)
  1355.     {
  1356.         $localeUc ucfirst(App::getCurLocale());
  1357.         if (count($id) == 0) {
  1358.             return [];
  1359.         }
  1360.         if (is_array($id)) {
  1361.             $id implode(', '$id);
  1362.             $id "($id)";
  1363.         }
  1364.         $q $this->createQueryBuilder('f')
  1365.             ->select("f.id, f.icon, f.iconUrl, page.nameSingle$localeUc")
  1366.             ->leftJoin('f.page''page')
  1367.             //            ->andWhere('f.icon IS NOT NULL') решили выводить данные https://te.remote.team/#/discus/649252D6-AAD4-D219-FD67-BBF3CDCA1062/
  1368.             ->andWhere("f.id IN $id");
  1369.         $r $q->getQuery()->useQueryCache(true);
  1370.         $items $r->getArrayResult();
  1371.         $res = [];
  1372.         foreach ($items as $item) {
  1373.             $res[$item['id']] = [
  1374.                 'id' => $item['id'],
  1375.                 'icon' => PathHelper::pathGenerate('filter'$item),
  1376.                 'title' => $item["nameSingle$localeUc"],
  1377.                 'url' => $item['iconUrl'],
  1378.             ];
  1379.         }
  1380.         return $res;
  1381.     }
  1382.     /**
  1383.      * Получаем выставки по oldId
  1384.      * @param array $id
  1385.      * @return array
  1386.      * @throws Exception
  1387.      */
  1388.     public function getExhibitions(array $id): array
  1389.     {
  1390.         $lcVo = new LocaleVo();
  1391.         $lc $lcVo->getCode();
  1392.         $lcUc ucfirst($lc);
  1393.         $lcFull $lcVo->getCodeFull();
  1394.         $id array_filter($id);
  1395.         if (count($id) == 0) {
  1396.             return [];
  1397.         }
  1398.         $id implode(', '$id);
  1399.         $id "($id)";
  1400.         $q $this->createQueryBuilder('f')
  1401.             ->select(
  1402.                 "f.id, f.oldId, f.iconUrl, tooltip.$lc as tooltipLc , page.nameMenu$lcUc, url.$lc as urlLocal"
  1403.             )
  1404.             ->leftJoin('f.page''page')
  1405.             ->leftJoin('f.url''url')
  1406.             ->leftJoin('f.param''param')
  1407.             ->leftJoin('f.tooltip''tooltip')
  1408.             ->andWhere('param.isEnabled = 1')
  1409.             ->andWhere('param.count > 0')
  1410.             ->andWhere("f.oldCommand = 'exhibition'")
  1411.             ->andWhere("f.oldId IN $id");
  1412.         $r $q->getQuery()->enableResultCache(TimeConstant::DAY);
  1413.         $router App::getRouter();
  1414.         $items $r->getArrayResult();
  1415.         $res = [];
  1416.         foreach ($items as $item) {
  1417.             $name $item["nameMenu$lcUc"];
  1418.             // показываем бирки только с возрастом не более 2-х лет
  1419.             $year intval(preg_replace('/\D/'''$name));
  1420.             $yearLimit intval(date("Y")) - 2;
  1421.             if ($year <= $yearLimit) {
  1422.                 continue;
  1423.             }
  1424.             $res[$item['id']] = [
  1425.                 'id' => $item['id'],
  1426.                 'sphinxId' => $item['oldId'],
  1427.                 'name' => $name,
  1428.                 'tooltip' => $item['tooltipLc'],
  1429.                 'urlRemote' => $item['iconUrl'],
  1430.                 'urlLocal' => $router->generate('app_catalog', ['key' => $item['urlLocal'], '_locale' => $lcFull]),
  1431.             ];
  1432.         }
  1433.         return $res;
  1434.     }
  1435.     /**
  1436.      * Получаем список url фильтров по языку для sitemap
  1437.      * @param $lang
  1438.      * @return array|null
  1439.      */
  1440.     public function getListUrlFiltersByLang($lang): ?array
  1441.     {
  1442.         $q $this->createQueryBuilder('f')
  1443.             ->select("u.$lang url, f.leftMenu, f.oldCommand, f.id")
  1444.             ->leftJoin('f.url''u')
  1445.             ->leftJoin('f.groups''g')
  1446.             ->leftJoin('f.param''p')
  1447.             ->andWhere('p.hide = 0')
  1448.             ->andWhere('p.count > 0')
  1449.             ->andWhere('g.id NOT IN (:groups)')
  1450.             ->setParameter('groups', [407416417])
  1451.             ->getQuery();
  1452.         $cacheName $this->buildCacheName('filter_getListUrlFiltersByLang'$lang);
  1453.         $q->useQueryCache(true)->enableResultCache((int)TimeConstant::DAY$cacheName);
  1454.         return $q->getArrayResult();
  1455.     }
  1456.     /**
  1457.      * Получение списка для проверки на наличие кириллических символов
  1458.      * @return array
  1459.      */
  1460.     public function getCollectionsAdmForCheckCyrillic(): array
  1461.     {
  1462.         $q $this->createQueryBuilder('f')
  1463.             ->select('f, page')
  1464.             ->leftJoin('f.page''page')
  1465.             ->leftJoin('f.param''param')
  1466.             ->andWhere("param.isEnabled = true");
  1467.         return $q->getQuery()->getArrayResult();
  1468.     }
  1469.     /**
  1470.      * Получение ID фильтра по ID бренда
  1471.      * @param $idBrand
  1472.      * @return mixed|null
  1473.      * @throws NonUniqueResultException
  1474.      */
  1475.     public function getIdFilterByIdBrand($idBrand)
  1476.     {
  1477.         $q $this
  1478.             ->createQueryBuilder('f')
  1479.             ->select('f.id')
  1480.             ->leftJoin('f.brand''brand')
  1481.             ->andWhere('brand.id = :idBrand')
  1482.             ->setParameter('idBrand'$idBrand)
  1483.             ->setMaxResults(1)
  1484.             ->getQuery();
  1485.         try {
  1486.             $id $q->getSingleResult();
  1487.             $id $id['id'];
  1488.         } catch (NoResultException $e) {
  1489.             return null;
  1490.         }
  1491.         return $id;
  1492.     }
  1493.     /**
  1494.      * Проставляем связи фильтра с коллекциями
  1495.      * @param int $fID
  1496.      * @param     $cIDs
  1497.      * @return bool
  1498.      * @throws Throwable
  1499.      */
  1500.     public function setCollections(int $fID$cIDs)
  1501.     {
  1502.         if (!$cIDs) {
  1503.             return false;
  1504.         }
  1505.         $conn $this->getEntityManager()->getConnection();
  1506.         $cIDs is_array($cIDs) ? $cIDs : [$cIDs];
  1507.         // находим коллекции, которых нет больше и удаляем их
  1508.         $cIDstr implode(','$cIDs);
  1509.         $conn->executeStatement(
  1510.             "DELETE FROM `collection_filters` WHERE `collection_id` NOT IN ($cIDstr) AND `filter_id` = '$fID';"
  1511.         );
  1512.         // проставляем связи для всех остальных записей
  1513.         // делаем порциями по почке запросов за раз
  1514.         $maxPortion 100;
  1515.         $sqlUpdate '';
  1516.         $cnt 0;
  1517.         foreach ($cIDs as $cID) {
  1518.             $sqlUpdate .= "INSERT INTO `collection_filters` (`collection_id`,`filter_id`)  VALUES  ('$cID', '$fID') ON DUPLICATE KEY UPDATE collection_id='$cID', filter_id='$fID';";
  1519.             $cnt++;
  1520.             if ($cnt == $maxPortion) {
  1521.                 $sth $conn->prepare($sqlUpdate);
  1522.                 $sth->execute();
  1523.                 $sth->closeCursor();
  1524.                 $cnt 0;
  1525.                 $sqlUpdate '';
  1526.             }
  1527.         }
  1528.         if ($sqlUpdate != '') {
  1529.             $sth $conn->prepare($sqlUpdate);
  1530.             $sth->execute();
  1531.             $sth->closeCursor();
  1532.         }
  1533.         return true;
  1534.     }
  1535.     /**
  1536.      * Получение фильтра для DTO выставки
  1537.      * @param $fids
  1538.      * @param $lc
  1539.      * @return array
  1540.      * @throws \Doctrine\DBAL\Exception
  1541.      */
  1542.     public function getForExhDTO($fids$lc)
  1543.     {
  1544.         if (!$fids) {
  1545.             return [];
  1546.         }
  1547.         $fidsStr implode(','$fids);
  1548.         $sql "SELECT
  1549.                 f.id,
  1550.                 f.alt_name AS `altName`,
  1551.                 f.old_command AS `nameSphinx`,
  1552.                 fp.name_menu_$lc AS `name`,
  1553.                 fp.name_many_$lc AS `nameMany`,
  1554.                 fp.name_single_$lc AS `nameFull`,
  1555.                 p.count AS `count`,
  1556.                 p.hex_code AS `hexCode`,
  1557.                 p.show_menu_advanced AS `showMenuAdvanced`,
  1558.                 p.show_menu AS `showMenu`,
  1559.                 g.alt_name AS `groupAltName`,
  1560.                 gname.$lc AS `groupName`,
  1561.                 c.id AS `countryId`,
  1562.                 c.old_id AS `countryOldId`,
  1563.                 cfp.name_menu_$lc AS `countryName`,
  1564.                 u.$lc AS `slug`
  1565.             FROM
  1566.                 filters f
  1567.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  1568.             LEFT JOIN filter_params p ON p.id = f.param_id
  1569.             LEFT JOIN filter_groups g ON g.id = f.group_id
  1570.             LEFT JOIN locale_text gname ON gname.filter_group_name = g.id
  1571.             LEFT JOIN filters c ON c.id = f.country_id
  1572.             LEFT JOIN filter_pages cfp ON cfp.id = c.page_id
  1573.             LEFT JOIN locale_url u ON u.filter_id = f.id
  1574.             WHERE f.id IN ($fidsStr) AND
  1575.             p.count > 0 AND
  1576.             g.alt_name != 'top' AND
  1577.             g.alt_name != 'release_year_collection' AND
  1578.             g.alt_name != 'price' AND
  1579.             g.alt_name != 'brand' AND
  1580.             f.alt_name != 'cataloge' AND
  1581.             g.alt_name != 'using' AND
  1582.             p.is_enable = 1
  1583.             ORDER BY f.sort, f.name";
  1584.         $memcache $this->cacheService->getMemcache();
  1585.         $memcacheKey md5($sql);
  1586.         $items $memcache->get($memcacheKey);
  1587.         if ($items) {
  1588.             return $items;
  1589.         }
  1590.         $items $this->getEntityManager()->getConnection()->fetchAllAssociative($sql);
  1591.         $memcache->set($memcacheKey$items);
  1592.         return $items;
  1593.     }
  1594.     /**
  1595.      * Получение имени для графика статистик в админке
  1596.      * @param array $fids
  1597.      * @param bool $isBrand
  1598.      * @return array
  1599.      */
  1600.     public function getNamesForStatChartAdmin(array $fidsbool $isBrand false)
  1601.     {
  1602.         $fidsStr implode(','$fids);
  1603.         if ($isBrand) {
  1604.             $where "WHERE f.brand IN ($fidsStr)";
  1605.         } else {
  1606.             $where "WHERE f.id IN ($fidsStr)";
  1607.         }
  1608.         $sql "SELECT
  1609.                 f.id,
  1610.                 f.brand,
  1611.                 fp.name_menu_ru AS `name`
  1612.             FROM
  1613.                 filters f
  1614.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  1615.             $where
  1616.             ORDER BY fp.name_menu_ru ASC";
  1617.         $sql preg_replace('/[\s\n\r]+/'' '$sql);
  1618.         $items $this->getEntityManager()->getConnection()->fetchAll($sql);
  1619.         $r = [];
  1620.         foreach ($items as $item) {
  1621.             $id $isBrand $item['brand'] : $item['id'];
  1622.             $r[$id] = [
  1623.                 'name' => $item['name'],
  1624.                 'data' => [],
  1625.             ];
  1626.         }
  1627.         return $r;
  1628.     }
  1629.     /**
  1630.      * @return array
  1631.      */
  1632.     public function admGetDesigners()
  1633.     {
  1634.         $q $this->createQueryBuilder('f');
  1635.         $q->select('f.id, f.name')
  1636.             ->leftJoin('f.groups''groups')
  1637.             ->andWhere("groups.altName = 'designer'")
  1638.             ->andWhere("f.oldId != 1")
  1639.             ->orderBy('f.name');
  1640.         $res = [];
  1641.         $out $q->getQuery()->getArrayResult();
  1642.         foreach ($out as $i => $item) {
  1643.             $res[$item['name']] = StrHelper::toLower($item['name']);
  1644.         }
  1645.         return $res;
  1646.     }
  1647.     public function admGetDesignersId()
  1648.     {
  1649.         $q $this->createQueryBuilder('f');
  1650.         $q->select('f.id, f.name')
  1651.             ->leftJoin('f.groups''groups')
  1652.             ->andWhere("groups.altName = 'designer'")
  1653.             ->andWhere("f.oldId != 1")
  1654.             ->orderBy('f.name');
  1655.         return $q->getQuery()->getArrayResult();
  1656.     }
  1657.     /**
  1658.      * Выборка фильтров для формирования свойств коллекции
  1659.      * @param $fids
  1660.      * @param null $lc
  1661.      * @return array
  1662.      */
  1663.     public function getForCollSettings($fids$lc null): array
  1664.     {
  1665.         $lc $lc ?: App::getCurLocale();
  1666.         $fidsStr implode(','$fids);
  1667.         $sql "SELECT
  1668.                 f.id,
  1669.                 f.rank AS `rank`,
  1670.                 f.alt_name AS `altName`,
  1671.                 f.old_command AS `sphinxName`,
  1672.                 f.old_id AS `sphinxId`,
  1673.                 fp.name_menu_$lc AS `name`,
  1674.                 fp.name_many_$lc AS `nameMany`,
  1675.                 fp.name_single_$lc AS `nameFull`,
  1676.                 p.count AS `count`,
  1677.                 g.id AS `group.id`,
  1678.                 g.alt_name AS `group.altName`,
  1679.                 gname.$lc AS `group.name`,
  1680.                 url.$lc AS `slug`
  1681.             FROM
  1682.                 filters f
  1683.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  1684.             LEFT JOIN filter_params p ON p.id = f.param_id
  1685.             LEFT JOIN filter_groups g ON g.id = f.group_id
  1686.             LEFT JOIN locale_text gname ON gname.filter_group_name = g.id
  1687.             LEFT JOIN locale_url url ON url.filter_id = f.id
  1688.             WHERE
  1689.                 f.id IN ($fidsStr) AND
  1690.                 p.is_enable = 1
  1691.             ORDER BY f.sort, f.name";
  1692.         $sql preg_replace('/[\s\n\r]+/'' '$sql);
  1693.         $memcache $this->cacheService->getMemcache();
  1694.         $memcacheKey md5($sql);
  1695.         $items $memcache->get($memcacheKey);
  1696.         if ($items) {
  1697.             return $items;
  1698.         }
  1699.         $items $this->getEntityManager()->getConnection()->fetchAll($sql);
  1700.         $memcache->set($memcacheKey$items);
  1701.         return $items;
  1702.     }
  1703.     /**
  1704.      * Получение данных для формирования имени фильтра в хистри расширенного поиска
  1705.      * @param array $fids
  1706.      * @return array
  1707.      */
  1708.     public function getForFilterNameHistorySearch(array $fids): array
  1709.     {
  1710.         $lc App::getCurLocale();
  1711.         $fids array_unique(array_map('intval'array_filter($fids'is_numeric')));
  1712.         if (empty($fids)) {
  1713.             return [];
  1714.         }
  1715.         $fidsStr implode(','$fids);
  1716.         $sql "SELECT
  1717.                 f.id AS `id`,
  1718.                 f.alt_name AS `altName`,
  1719.                 fpg.name_many_$lc AS `name`,
  1720.                 fpr.code AS `code`,
  1721.                 fg.alt_name AS `groupAltName`,
  1722.                 fg.left_menu AS `groupLeftMenu`
  1723.             FROM
  1724.                 filters f
  1725.             LEFT JOIN filter_groups fg ON fg.id = f.group_id
  1726.             LEFT JOIN filter_pages fpg ON fpg.id = f.page_id
  1727.             LEFT JOIN filter_params fpr ON fpr.id = f.param_id
  1728.             WHERE
  1729.                 f.id IN ($fidsStr)";
  1730.         $memcache $this->cacheService->getMemcache();
  1731.         $memcacheKey md5($sql);
  1732.         $items $memcache->get($memcacheKey);
  1733.         if ($items) {
  1734.             return $items;
  1735.         }
  1736.         $items $this->getEntityManager()->getConnection()->fetchAll($sql);
  1737.         $memcache->set($memcacheKey$items);
  1738.         return $items;
  1739.     }
  1740.     /**
  1741.      * Список для назначения родителя в админке
  1742.      * @param $gid
  1743.      * @param $fid
  1744.      * @return array
  1745.      * @throws \Doctrine\DBAL\Exception
  1746.      */
  1747.     public function admGetListForParent($gid$fid): array
  1748.     {
  1749.         $sql "SELECT
  1750.                 f.id as `id`,
  1751.                    f.name AS `name.ru`,
  1752.                    fp.name_menu_en AS `name.en`
  1753.             FROM
  1754.                 filters f
  1755.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  1756.             LEFT JOIN filter_params p ON p.id = f.param_id
  1757.             WHERE f.id != $fid AND f.group_id = $gid AND p.is_enable = 1
  1758.             ORDER BY `name.ru`";
  1759.         $items $this->getEntityManager()->getConnection()->fetchAllAssociative($sql);
  1760.         $rows = [];
  1761.         foreach ($items as $item) {
  1762.             $rows[$item['id']] = "{$item['name.ru']} ({$item['name.en']}) #{$item['id']}";
  1763.         }
  1764.         return $rows;
  1765.     }
  1766.     /**
  1767.      * @param string $leftMenu
  1768.      * @return string|null
  1769.      */
  1770.     public function getKeyByLeftMenu(string $leftMenu): ?string
  1771.     {
  1772.         $lc App::getCurLocale();
  1773.         $sql "SELECT
  1774.                    lurl.$lc AS `url`
  1775.             FROM
  1776.                 filters f
  1777.             LEFT JOIN locale_url lurl ON f.id = lurl.filter_id
  1778.             WHERE f.left_menu = '$leftMenu'
  1779.             LIMIT 1";
  1780.         $memcache $this->cacheService->getMemcache();
  1781.         $memcacheKey md5($sql);
  1782.         $items $memcache->get($memcacheKey);
  1783.         if ($items) {
  1784.             return $items;
  1785.         }
  1786.         try {
  1787.             $items $this->getEntityManager()
  1788.                 ->getConnection()
  1789.                 ->executeQuery($sql)
  1790.                 ->fetchOne() ?: null;
  1791.             $memcache->set($memcacheKey$items);
  1792.             return $items;
  1793.         } catch (Throwable $e) {
  1794.             return null;
  1795.         }
  1796.     }
  1797.     public function getListForTestCountTranslate()
  1798.     {
  1799.         $q $this->createQueryBuilder('f')
  1800.             ->select('f, g, p, descr, htmlShow')
  1801.             ->leftJoin('f.groups''g')
  1802.             ->leftJoin('f.page''p')
  1803.             ->leftJoin('f.htmlShow''htmlShow')
  1804.             ->leftJoin('f.nameForMetaDescr''descr')
  1805.             ->andWhere('g.id != 406')// фабрики
  1806.             ->andWhere('g.id != 411')// дизайнеры
  1807.             ->getQuery();
  1808.         return $q->getArrayResult();
  1809.     }
  1810.     /**
  1811.      * Получение списка ТОП фильтров, для формирования меню карусели на главной
  1812.      * @return array
  1813.      * @throws Exception
  1814.      * @see src/WebBundle/Resources/views/Home/_top-carousel.html.twig
  1815.      */
  1816.     public function getItemsForTopCollectionCarouselMenu(): array
  1817.     {
  1818.         $lc App::getCurLocale();
  1819.         $cacheKey "ItemsForTopCollectionCarouselMenu1.$lc";
  1820.         $redisCachePool App::getContainer()->get(RedisCachePool::class)->getPool();
  1821.         $cacheItem $redisCachePool->getItem($cacheKey);
  1822.         if ($cacheItem->isHit()) {
  1823.             return $cacheItem->get();
  1824.         }
  1825.         $translator App::getTranslator();
  1826.         $sql "SELECT
  1827.                lurl.$lc AS `url`,
  1828.                lurl.en AS `key`,
  1829.                f.alt_name AS `alt`,
  1830.                f.id AS `id`
  1831.         FROM
  1832.             filters f
  1833.         LEFT JOIN locale_url lurl ON f.id = lurl.filter_id
  1834.         WHERE f.id in (10592,10591)";
  1835.         $rows $this->getEntityManager()
  1836.             ->getConnection()
  1837.             ->executeQuery($sql)
  1838.             ->fetchAll();
  1839.         $items = [
  1840.             'top-all' => [
  1841.                 'title' => $translator->trans('main_top_all'),
  1842.                 'link' => App::generateUrl('app_catalog'),
  1843.                 'url-json' => App::generateUrl('app_last_collection', ['type' => 'top-all']),
  1844.                 'key' => 'top-all',
  1845.             ],
  1846.         ];
  1847.         if ($rows) {
  1848.             foreach ($rows as $row) {
  1849.                 $items[$row['key']] = [
  1850.                     'title' => $translator->trans("main_{$row['alt']}"),
  1851.                     'link' => App::generateUrl('app_catalog', ['key' => $row['url']]),
  1852.                     'url-json' => App::generateUrl('app_last_collection', ['type' => $row['key']]),
  1853.                     'key' => $row['key'],
  1854.                 ];
  1855.             }
  1856.             $cacheItem->set($items);
  1857.             $redisCachePool->save($cacheItem);
  1858.         }
  1859.         return $items;
  1860.     }
  1861.     /**
  1862.      * Выборка для отдачи списка дизайнеров в меню в каталоге
  1863.      * @param array $onlyIds
  1864.      * @return array
  1865.      * @throws \Doctrine\DBAL\Exception
  1866.      */
  1867.     public function getListDesignersForCataloge(array $onlyIds = []): array
  1868.     {
  1869.         if ($onlyIds) {
  1870.             $onlyIds implode("','"$onlyIds);
  1871.             $onlyIds " AND f.id IN ('$onlyIds')";
  1872.         } else {
  1873.             $onlyIds '';
  1874.         }
  1875.         $sql "SELECT
  1876.                 f.id,
  1877.                 f.rank AS `rank`,
  1878.                 f.old_command AS `oldCommand`,
  1879.                 f.old_id AS `oldId`,
  1880.                 fp.name_menu_en AS `name`,
  1881.                 p.count AS `cnt`,
  1882.                 url.en AS `slug`
  1883.             FROM
  1884.                 filters f
  1885.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  1886.             LEFT JOIN filter_params p ON p.id = f.param_id
  1887.             LEFT JOIN locale_url url ON url.filter_id = f.id
  1888.             WHERE p.count > 0 AND p.is_enable = 1 AND f.group_id = 411 $onlyIds
  1889.             ORDER BY f.name";
  1890.         $sql preg_replace('/[\s\n\r]+/'' '$sql);
  1891.         $memcache $this->cacheService->getMemcache();
  1892.         $memcacheKey md5($sql);
  1893.         $items $memcache->get($memcacheKey);
  1894.         if ($items) {
  1895.             return $items;
  1896.         }
  1897.         $items $this
  1898.             ->getEntityManager()
  1899.             ->getConnection()
  1900.             ->fetchAllAssociative($sql);
  1901.         $memcache->set($memcacheKey$items);
  1902.         return $items;
  1903.     }
  1904.     /**
  1905.      * @param string $lc
  1906.      * @param TranslatorInterface $translator
  1907.      * @return array
  1908.      */
  1909.     public function getListBrandsForMenu(string $lcTranslatorInterface $translator): array
  1910.     {
  1911.         $status BiConst::STATE_PUBLISHED ', ' BiConst::STATE_WORK_CONTINUED;
  1912.         $hideFactories HideFactoryCountriesHelper::length() > 0
  1913.             join(', 'HideFactoryCountriesHelper::codes())
  1914.             : 0;
  1915.         $sql "SELECT
  1916.                 b.id AS `id`,
  1917.                 url.$lc AS `slug`,
  1918.                 fp.name_menu_en AS `name`,
  1919.                 f.name AS `name2`,
  1920.                 f.id AS `filter_id`,
  1921.                 c.old_id AS `country.id`,
  1922.                 c.left_menu AS `country.alias`,
  1923.                 count(iia.idea_id) AS `totalIdeas`,
  1924.                 b.votes_submit AS `votesSubmit`,
  1925.                 b.votes_stars AS `votesStars`
  1926.             FROM
  1927.                 filters f
  1928.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  1929.             LEFT JOIN filter_params p ON p.id = f.param_id
  1930.             LEFT JOIN locale_url url ON url.filter_id = f.id
  1931.             LEFT JOIN factory b ON b.id = f.brand
  1932.             LEFT JOIN filters c ON c.id = f.country_id
  1933.             LEFT JOIN collection coll on b.id = coll.factory and coll.status = 1
  1934.             LEFT JOIN interior inte on coll.id = inte.collection
  1935.             LEFT JOIN idea_interior iia on inte.id = iia.interior_id
  1936.             WHERE f.brand IS NOT NULL
  1937.               AND f.id != '10639'
  1938.               AND p.is_enable = 1
  1939.               AND p.count >= 0
  1940.               AND b.status IN ($status)
  1941.               AND b.unid  IS NOT NULL
  1942.               AND b.id NOT IN ($hideFactories)
  1943.             group by f.id
  1944.             ORDER BY fp.name_menu_en";
  1945.         $memcache $this->cacheService->getMemcache();
  1946.         $memcacheKey md5($sql);
  1947.         $rows $memcache->get($memcacheKey);
  1948.         if ($rows) {
  1949.             return $rows;
  1950.         }
  1951.         $rows $this
  1952.             ->getEntityManager()
  1953.             ->getConnection()
  1954.             ->fetchAll($sql);
  1955.         foreach ($rows as $i => $row) {
  1956.             $row['id'] = intval($row['id']);
  1957.             $row['totalIdeas'] = intval($row['totalIdeas']);
  1958.             $row['votesSubmit'] = intval($row['votesSubmit']);
  1959.             $row['votesStars'] = intval($row['votesStars']);
  1960.             $row['country'] = [
  1961.                 'id' => intval($row['country.id']),
  1962.                 'alias' => trim($translator->trans($row['country.alias'])),
  1963.             ];
  1964.             unset($row['country.id']);
  1965.             unset($row['country.alias']);
  1966.             $rows[$i] = $row;
  1967.         }
  1968.         $memcache->set($memcacheKey$rows);
  1969.         return $rows;
  1970.     }
  1971.     /**
  1972.      * @param int $filterParamId
  1973.      * @param int $count
  1974.      * @return bool
  1975.      * @throws \Doctrine\DBAL\Exception
  1976.      */
  1977.     public function updateCountAndShow(int $filterParamIdint $count)
  1978.     {
  1979.         // исключил из обновы фильтр коммерческая плитка и размеры
  1980.         if (in_array($filterParamId, [1017110405104061040710408])) {
  1981.             return true;
  1982.         }
  1983.         $isEnabled $count 0;
  1984.         $sql "UPDATE `filter_params` SET `count` = '$count', `is_enable` = '$isEnabled' WHERE `id` = '$filterParamId';";
  1985.         $this->getEntityManager()->getConnection()->executeStatement($sql);
  1986.         return true;
  1987.     }
  1988.     /**
  1989.      * Выборка для простановки данных из шаблона переводов
  1990.      * @return FilterEntity[]
  1991.      */
  1992.     public function consoleGetListDesigners(): array
  1993.     {
  1994.         $q $this->createQueryBuilder('f');
  1995.         $q->select('f, groups, param, page')
  1996.             ->leftJoin('f.groups''groups')
  1997.             ->leftJoin('f.param''param')
  1998.             ->leftJoin('f.page''page')
  1999.             ->andWhere("f.parentKey = 'designer'");
  2000.         return $q->getQuery()->getResult();
  2001.     }
  2002.     /**
  2003.      * @deprecated todo на удаление - не используется
  2004.      */
  2005.     public function getDesigners()
  2006.     {
  2007.         $q $this->createQueryBuilder('f');
  2008.         $q
  2009.             ->andWhere("f.oldCommand =getDesigner")
  2010.             ->setParameter('getDesigner''getDesigner')
  2011.             ->orderBy('f.name');
  2012.         return $q->getQuery()->getArrayResult();
  2013.     }
  2014.     /**
  2015.      * Выборка для слайдера
  2016.      * @param string $lc
  2017.      * @param array $filters
  2018.      * @return array
  2019.      * @throws \Doctrine\DBAL\Exception
  2020.      */
  2021.     public function getArrListForSlider(string $lc, array $filters): array
  2022.     {
  2023.         $where = [];
  2024.         foreach ($filters as $group => $ides) {
  2025.             if ($ides[0] != null) {
  2026.                 if (is_int($ides[0])) {
  2027.                     $where[] = 'g.id = ' $group ' AND f.old_id = ' $ides[0] . ' AND f.old_command = "' $ides[1] . '"';
  2028.                 } elseif (is_array($ides[0])) {
  2029.                     $where[] = 'g.id = ' $group ' AND f.old_id IN (' join(
  2030.                         ',',
  2031.                         $ides[0]
  2032.                     ) . ') AND f.old_command = "' $ides[1] . '"';
  2033.                 }
  2034.             }
  2035.         }
  2036.         if (count($where) == 0) {
  2037.             return [];
  2038.         }
  2039.         $sql "SELECT
  2040.                 f.id,
  2041.                 f.alt_name AS `altName`,
  2042.                 fp.name_menu_$lc AS `name`,
  2043.                    u.$lc AS `url`,
  2044.                 p.count AS `count`,
  2045.                 g.id AS `group.id`,
  2046.                 f.old_command as `oldCommand`,
  2047.                 g.alt_name AS `group.altName`,
  2048.                 gname.$lc AS `group.name`
  2049.             FROM
  2050.                 filters f
  2051.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  2052.             LEFT JOIN filter_params p ON p.id = f.param_id
  2053.             LEFT JOIN filter_groups g ON g.id = f.group_id
  2054.             LEFT JOIN locale_text gname ON gname.filter_group_name = g.id
  2055.             LEFT JOIN locale_url u ON u.filter_id = f.id
  2056.             LEFT JOIN factory b ON b.id = f.brand
  2057.             WHERE (g.alt_name <> 'brand' AND p.show_menu_advanced = 1 OR g.alt_name = 'brand' AND b.status = 1) AND
  2058.             (p.count > 0 OR g.alt_name = 'brand' OR g.alt_name = 'reviews') AND
  2059.             p.is_enable = 1 AND p.hide != 1 AND p.hide_all != 1 AND f.id != '10639'
  2060.             ";
  2061.         if ($where != null) {
  2062.             $sql .= ' AND (' join(' OR '$where) . ')';
  2063.         }
  2064.         $memcache $this->cacheService->getMemcache();
  2065.         $memcacheKey md5($sql);
  2066.         $rows $memcache->get($memcacheKey);
  2067.         if ($rows) {
  2068.             return $rows;
  2069.         }
  2070.         $rows $this->getEntityManager()->getConnection()->fetchAllAssociative($sql);
  2071.         $memcache->set($memcacheKey$rows);
  2072.         return $rows;
  2073.     }
  2074.     public function getFiltersForSearchSphinx(array $keys$lc null)
  2075.     {
  2076.         $keys implode("','"$keys);
  2077.         $sql "SELECT
  2078.                 f.id,
  2079.                 f.old_command AS `oldCommand`,
  2080.                 f.old_id AS `oldId`
  2081.             FROM
  2082.                 filters f
  2083.             LEFT JOIN filter_params p ON p.id = f.param_id
  2084.             LEFT JOIN locale_url url ON url.filter_id = f.id
  2085.             WHERE p.count > 0 AND p.is_enable = 1 AND $lc IN ('$keys')
  2086.             ORDER BY f.name";
  2087.         $sql preg_replace('/[\s\n\r]+/'' '$sql);
  2088.         $memcache $this->cacheService->getMemcache();
  2089.         $memcacheKey md5($sql);
  2090.         $items $memcache->get($memcacheKey);
  2091.         if ($items) {
  2092.             return $items;
  2093.         }
  2094.         try {
  2095.             $items $this->getEntityManager()->getConnection()->fetchAllAssociative($sql);
  2096.         } catch (\Doctrine\DBAL\Exception $e) {
  2097.             return [];
  2098.         }
  2099.         $res = [];
  2100.         foreach ($items as $item) {
  2101.             if (empty($res[$item['oldCommand']])) {
  2102.                 $res[$item['oldCommand']] = [];
  2103.             }
  2104.             $res[$item['oldCommand']][] = $item['oldId'];
  2105.         }
  2106.         $memcache->set($memcacheKey$res);
  2107.         return $res;
  2108.     }
  2109.     /**
  2110.      * Получение списка фильтров для формирования ссылок под рекламу в гугле
  2111.      * @return array
  2112.      * @throws \Doctrine\DBAL\Exception
  2113.      */
  2114.     public function getListForGoogleAds()
  2115.     {
  2116.         //  -- группы ------------
  2117.         // Фактура 402
  2118.         // Стиль 400
  2119.         // Мотив рисунка 421
  2120.         // Цвет 395
  2121.         // Применение 394
  2122.         // Форма 413 (кроме прямоугольник 10507, квадрат 10845, неправильная форма 10510, Многоугольник 10509 )
  2123.         // Коэффициент антискольжения 422
  2124.         // Производство 396
  2125.         //  -- фильтры ------------
  2126.         // мозаика на сетке/бумаге 10114
  2127.         // фоновая плитка 10167
  2128.         // имитация мозаики 10677
  2129.         // раковина 10162
  2130.         // Виниловая плитка 10757
  2131.         // Назначение напольное 10170
  2132.         // Назначение настенное 10169
  2133.         // Поверхность 3D 10526
  2134.         // Поверхность состаренная 10613
  2135.         // Крупноформатная плитка 10617
  2136.         // Керамогранит утолщенный 10512
  2137.         // Керамогранит тонкий 10411
  2138.         $urlStrSql = [];
  2139.         $nameSingleStrSql = [];
  2140.         $nameManyStrSql = [];
  2141.         $nameGroupStrSql = [];
  2142.         $keyAdwords $titleAdwords $keyAdwCombiFirst $titleAdwCombiFirst $keyAdwCombiOther $titleAdwCombiOther = [];
  2143.         $locales LocaleHelper::getListAvailable();
  2144.         foreach ($locales as $lc) {
  2145.             $urlStrSql[] = "url.{$lc['code']} AS `url.{$lc['code']}`";
  2146.             $nameSingleStrSql[] = "page.name_single_{$lc['code']} AS `nameSingle.{$lc['code']}`";
  2147.             $nameManyStrSql[] = "page.name_many_{$lc['code']} AS `nameMany.{$lc['code']}`";
  2148.             $nameGroupStrSql[] = "fgname.{$lc['code']} AS `groupName.{$lc['code']}`";
  2149.             $keyAdwords[] = "keyAdw.{$lc['code']} AS `keyAdwords.{$lc['code']}`";
  2150.             $titleAdwords[] = "titleAdw.{$lc['code']} AS `titleAdwords.{$lc['code']}`";
  2151.             $keyAdwCombiFirst[] = "keyAdwCombiFirst.{$lc['code']} AS `keyAdwCombiFirst.{$lc['code']}`";
  2152.             $titleAdwCombiFirst[] = "titleAdwCombiFirst.{$lc['code']} AS `titleAdwCombiFirst.{$lc['code']}`";
  2153.             $keyAdwCombiOther[] = "keyAdwCombiOther.{$lc['code']} AS `keyAdwCombiOther.{$lc['code']}`";
  2154.             $titleAdwCombiOther[] = "titleAdwCombiOther.{$lc['code']} AS `titleAdwCombiOther.{$lc['code']}`";
  2155.         }
  2156.         $urlStrSql implode(', '$urlStrSql);
  2157.         $nameSingleStrSql implode(', '$nameSingleStrSql);
  2158.         $nameManyStrSql implode(', '$nameManyStrSql);
  2159.         $nameGroupStrSql implode(', '$nameGroupStrSql);
  2160.         $keyAdwords implode(', '$keyAdwords);
  2161.         $titleAdwords implode(', '$titleAdwords);
  2162.         $keyAdwCombiFirst implode(', '$keyAdwCombiFirst);
  2163.         $titleAdwCombiFirst implode(', '$titleAdwCombiFirst);
  2164.         $keyAdwCombiOther implode(', '$keyAdwCombiOther);
  2165.         $titleAdwCombiOther implode(', '$titleAdwCombiOther);
  2166.         $sql "SELECT
  2167.                 f.id,
  2168.                 fg.alt_name AS `groupAltName`,
  2169.                 page.name_single_ru AS `name.single.ru`,
  2170.                 page.name_many_ru AS `name.many.ru`,
  2171.                 f.group_id AS `groupId`,
  2172.                 f.old_command AS `oldCommand`,
  2173.                 f.old_id AS `oldId`,
  2174.                 $urlStrSql$nameSingleStrSql$nameManyStrSql$nameGroupStrSql$keyAdwords$titleAdwords$keyAdwCombiFirst$titleAdwCombiFirst$keyAdwCombiOther{$titleAdwCombiOther}
  2175.             FROM
  2176.                 filters f
  2177.             LEFT JOIN filter_params par ON par.id = f.param_id
  2178.             LEFT JOIN filter_pages page ON page.id = f.param_id
  2179.             LEFT JOIN locale_url url ON url.filter_id = f.id
  2180.             LEFT JOIN filter_groups fg ON fg.id = f.group_id
  2181.             LEFT JOIN locale_text fgname ON fg.id = fgname.filter_group_name
  2182.             LEFT JOIN locale_text keyAdw ON f.id = keyAdw.filter_key_adwords
  2183.             LEFT JOIN locale_text titleAdw ON f.id = titleAdw.filter_title_adwords
  2184.             LEFT JOIN locale_text keyAdwCombiFirst ON f.id = keyAdwCombiFirst.filter_key_adwords_combi_first
  2185.             LEFT JOIN locale_text titleAdwCombiFirst ON f.id = titleAdwCombiFirst.filter_title_adwords_combi_first
  2186.             LEFT JOIN locale_text keyAdwCombiOther ON f.id = keyAdwCombiOther.filter_key_adwords_combi_other
  2187.             LEFT JOIN locale_text titleAdwCombiOther ON f.id = titleAdwCombiOther.filter_title_adwords_combi_other
  2188.             WHERE par.is_enable = 1 AND par.count > 3
  2189.                 AND (
  2190.                     f.group_id IN (402,400,421,395,394,413,422,396) OR
  2191.                     f.id IN (10114,10677,10162,10757,10170,10169,10526,10613,10617,10512,10411)
  2192.                     )
  2193.                 AND (f.id NOT IN (10507,10845,10510,10509) )
  2194.             ";
  2195.         $sql preg_replace('/[\s\n\r]+/'' '$sql);
  2196.         $items $this->getEntityManager()->getConnection()->fetchAllAssociative($sql);
  2197.         $rows = [];
  2198.         foreach ($items as $item) {
  2199.             $fId $item['id'];
  2200.             $url = [];
  2201.             $nameSingle = [];
  2202.             $nameMany = [];
  2203.             $groupName = [];
  2204.             $keyAdwords $titleAdwords $keyAdwCombiFirst $titleAdwCombiFirst $keyAdwCombiOther $titleAdwCombiOther = [];
  2205.             foreach ($locales as $lc) {
  2206.                 $lcCode $lc['code'];
  2207.                 $url[$lcCode] = $item["url.$lcCode"];
  2208.                 $nameSingle[$lcCode] = $item["nameSingle.$lcCode"];
  2209.                 $nameMany[$lcCode] = $item["nameMany.$lcCode"];
  2210.                 $groupName[$lcCode] = $item["groupName.$lcCode"];
  2211.                 $keyAdwords[$lcCode] = trim($item["keyAdwords.$lcCode"]);
  2212.                 $titleAdwords[$lcCode] = trim($item["titleAdwords.$lcCode"]);
  2213.                 $keyAdwCombiFirst[$lcCode] = trim($item["keyAdwCombiFirst.$lcCode"]);
  2214.                 $titleAdwCombiFirst[$lcCode] = trim($item["titleAdwCombiFirst.$lcCode"]);
  2215.                 $keyAdwCombiOther[$lcCode] = trim($item["keyAdwCombiOther.$lcCode"]);
  2216.                 $titleAdwCombiOther[$lcCode] = trim($item["titleAdwCombiOther.$lcCode"]);
  2217.             }
  2218.             $adwCombiMulti $this->getAdwordsMulti($fId$locales);
  2219.             // Если специальных заголовков для первой комбинации нет, используем базовые Adwords
  2220.             if (!array_filter($titleAdwCombiFirst)) {
  2221.                 $titleAdwCombiFirst $titleAdwords;
  2222.             }
  2223.             $rows[$fId] = [
  2224.                 'id' => $fId,
  2225.                 'groupId' => $item['groupId'],
  2226.                 'groupAltName' => $item['groupAltName'],
  2227.                 'name.single.ru' => $item['name.single.ru'],
  2228.                 'oldCommand' => $item['oldCommand'],
  2229.                 'oldId' => $item['oldId'],
  2230.                 'url' => $url,
  2231.                 'nameSingle' => $nameSingle,
  2232.                 'nameMany' => $nameMany,
  2233.                 'groupName' => $groupName,
  2234.                 'adwords' => [
  2235.                     'keysOne' => $keyAdwords,
  2236.                     'titleOne' => $titleAdwords,
  2237.                     'keysCombiFirst' => $keyAdwCombiFirst,
  2238.                     'titleCombiFirst' => $titleAdwCombiFirst,
  2239.                     'keysCombiOther' => $keyAdwCombiOther,
  2240.                     'titleCombiOther' => $titleAdwCombiOther,
  2241.                     'keysCombiOtherMulti' => $adwCombiMulti['keysCombiOther'],
  2242.                     'titleCombiOtherMulti' => $adwCombiMulti['titleCombiOther'],
  2243.                     'keysOneMulti' => $adwCombiMulti['keysOne'],
  2244.                     'titleOneMulti' => $adwCombiMulti['titleOne'],
  2245.                 ],
  2246.             ];
  2247.         }
  2248.         return $rows;
  2249.     }
  2250.     /**
  2251.      * Возвращает набор ключевых слов и заголовков (CombiOther и обычные Adwords) для фильтра,
  2252.      * поддерживая множественные значения из locale_text.*_multi_id.
  2253.      */
  2254.     private function getAdwordsMulti(int $filterId, array $locales): array
  2255.     {
  2256.         $keys $titles $keysAdwords $titlesAdwords = [];
  2257.         foreach ($locales as $lc) {
  2258.             $keys[$lc['code']] = [];
  2259.             $titles[$lc['code']] = [];
  2260.             $keysAdwords[$lc['code']] = [];
  2261.             $titlesAdwords[$lc['code']] = [];
  2262.         }
  2263.         $conn $this->getEntityManager()->getConnection();
  2264.         $keysRows $conn->fetchAllAssociative(
  2265.             'SELECT * FROM locale_text WHERE filter_key_adwords_combi_multi_id = :id ORDER BY id ASC',
  2266.             ['id' => $filterId]
  2267.         );
  2268.         $titlesRows $conn->fetchAllAssociative(
  2269.             'SELECT * FROM locale_text WHERE filter_title_adwords_combi_multi_id = :id ORDER BY id ASC',
  2270.             ['id' => $filterId]
  2271.         );
  2272.         $keysAdwordsRows $conn->fetchAllAssociative(
  2273.             'SELECT * FROM locale_text WHERE filter_key_adwords_multi_id = :id ORDER BY id ASC',
  2274.             ['id' => $filterId]
  2275.         );
  2276.         $titlesAdwordsRows $conn->fetchAllAssociative(
  2277.             'SELECT * FROM locale_text WHERE filter_title_adwords_multi_id = :id ORDER BY id ASC',
  2278.             ['id' => $filterId]
  2279.         );
  2280.         foreach ($keysRows as $row) {
  2281.             foreach ($locales as $lc) {
  2282.                 $lcCode $lc['code'];
  2283.                 if (!empty($row[$lcCode])) {
  2284.                     $keys[$lcCode][] = trim($row[$lcCode]);
  2285.                 }
  2286.             }
  2287.         }
  2288.         foreach ($titlesRows as $row) {
  2289.             foreach ($locales as $lc) {
  2290.                 $lcCode $lc['code'];
  2291.                 if (!empty($row[$lcCode])) {
  2292.                     $titles[$lcCode][] = trim($row[$lcCode]);
  2293.                 }
  2294.             }
  2295.         }
  2296.         foreach ($keysAdwordsRows as $row) {
  2297.             foreach ($locales as $lc) {
  2298.                 $lcCode $lc['code'];
  2299.                 if (!empty($row[$lcCode])) {
  2300.                     $keysAdwords[$lcCode][] = trim($row[$lcCode]);
  2301.                 }
  2302.             }
  2303.         }
  2304.         foreach ($titlesAdwordsRows as $row) {
  2305.             foreach ($locales as $lc) {
  2306.                 $lcCode $lc['code'];
  2307.                 if (!empty($row[$lcCode])) {
  2308.                     $titlesAdwords[$lcCode][] = trim($row[$lcCode]);
  2309.                 }
  2310.             }
  2311.         }
  2312.         return [
  2313.             'keysCombiOther' => $keys,
  2314.             'titleCombiOther' => $titles,
  2315.             'keysOne' => $keysAdwords,
  2316.             'titleOne' => $titlesAdwords,
  2317.         ];
  2318.     }
  2319.     private function buildSQLSelectForFilterResponseDTO(string $lc): string
  2320.     {
  2321.         $lcs LocaleHelper::getListAvailable();
  2322.         $lcs array_column($lcs'code');
  2323.         $urlSelect = [];
  2324.         foreach ($lcs as $lc_) {
  2325.             $urlSelect[] = "url.$lc_ AS `slug.$lc_`";
  2326.         }
  2327.         $urlSelect implode(', '$urlSelect);
  2328.         return "SELECT
  2329.                 f.id,
  2330.                 f.rank AS `rank`,
  2331.                 f.alt_name AS `altName`,
  2332.                 f.old_command AS `sphinxName`,
  2333.                 f.old_id AS `sphinxId`,
  2334.                 htmlshow.$lc AS `isHtmlShow`,
  2335.                 fp.name_menu_$lc AS `nameMenu`,
  2336.                 fp.name_many_$lc AS `nameMany`,
  2337.                 fp.name_single_$lc AS `nameSingle`,
  2338.                 fp.html_$lc AS `html`,
  2339.                 fp.description_$lc AS `description`,
  2340.                 metadesc.$lc AS `metaDescriptionName`,
  2341.                 par.count AS `count`,
  2342.                 par.code AS `code`,
  2343.                 par.is_enable AS `isEnable`,
  2344.                 gr.id AS `groupId`,
  2345.                 gr.alt_name AS `groupAltName`,
  2346.                 gpname.$lc AS `groupName`,
  2347.                 url.$lc AS `slug`, $urlSelect,
  2348.                 b.id AS `brandId`,
  2349.                 b.status AS `brandStatus`,
  2350.                 b.stated_at AS `brandStatedAt`,
  2351.                 b.type AS `brandType`,
  2352.                 b.name AS `brandName`,
  2353.                 f.logo AS `brandLogo`,
  2354.                 f.logo_url AS `brandLogoUrl`,
  2355.                 b.sound AS `brandSound`,
  2356.                 b.video AS `brandVideo`,
  2357.                 cn.id AS `countryId`,
  2358.                 cnfp.name_single_$lc AS `countryName`,
  2359.                 cnurl.$lc AS `countrySlug`,
  2360.                 cnpar.code AS `countryCode`
  2361.             FROM
  2362.                 filters f
  2363.             LEFT JOIN filter_pages fp ON fp.id = f.page_id
  2364.             LEFT JOIN filter_params par ON par.id = f.param_id
  2365.             LEFT JOIN filter_groups gr ON gr.id = f.group_id
  2366.             LEFT JOIN locale_text gpname ON gpname.filter_group_name = gr.id
  2367.             LEFT JOIN locale_text metadesc ON metadesc.filter_name_for_meta_descr_id = f.id
  2368.             LEFT JOIN locale_url url ON url.filter_id = f.id
  2369.             LEFT JOIN locale_bool htmlshow ON htmlshow.filter_html_show_id = f.id
  2370.             LEFT JOIN factory b ON b.id = f.brand
  2371.             LEFT JOIN filters cn ON cn.id = f.country_id
  2372.             LEFT JOIN filter_pages cnfp ON cnfp.id = cn.page_id
  2373.             LEFT JOIN locale_url cnurl ON cnurl.filter_id = cn.id
  2374.             LEFT JOIN filter_params cnpar ON cnpar.id = cn.param_id
  2375.             ";
  2376.     }
  2377.     /**
  2378.      * $this->buildFilterResponseDTO($item);
  2379.      * @param array $data
  2380.      * @return FilterResponseDTO|null
  2381.      */
  2382.     private function buildFilterResponseDTO(array $data): ?FilterResponseDTO
  2383.     {
  2384.         if (!$data['slug']) {
  2385.             return null;
  2386.         }
  2387.         $lcs LocaleHelper::getListAvailable();
  2388.         $lcs array_column($lcs'code');
  2389.         $slugs = [];
  2390.         foreach ($lcs as $lc_) {
  2391.             $slugs[$lc_] = $data["slug.$lc_"];
  2392.         }
  2393.         $country = !$data['countryId']
  2394.             ? null
  2395.             : new FilterCountryResponseDTO(
  2396.                 (int)$data['countryId'],
  2397.                 $data['countryName'],
  2398.                 $data['countrySlug'],
  2399.                 $data['countryCode'],
  2400.             );
  2401.         $brand = !$data['brandId']
  2402.             ? null
  2403.             : new BrandResponseDTO(
  2404.                 (int)$data['brandId'],
  2405.                 (int)$data['brandStatus'],
  2406.                 $data['brandName'],
  2407.                 $data['nameSingle'],
  2408.                 $data['slug'],
  2409.                 $data['brandLogo'],
  2410.                 $data['brandLogoUrl'],
  2411.                 (int)$data['brandType'],
  2412.                 $data['brandStatedAt'],
  2413.                 $data['brandSound'],
  2414.                 $data['brandVideo'] ? json_decode($data['brandVideo']) : null,
  2415.                 $data['description'],
  2416.                 $country,
  2417.             );
  2418.         return new FilterResponseDTO(
  2419.             (int)$data['id'],
  2420.             $data['altName'],
  2421.             (int)$data['sphinxId'],
  2422.             $data['sphinxName'],
  2423.             $data['nameMenu'],
  2424.             $data['nameMany'],
  2425.             $data['nameSingle'],
  2426.             (bool)$data['isHtmlShow'],
  2427.             $data['metaDescriptionName'],
  2428.             $data['html'],
  2429.             $data['count'],
  2430.             $data['code'],
  2431.             (bool)$data['isEnable'],
  2432.             (int)$data['groupId'],
  2433.             $data['groupName'],
  2434.             $data['groupAltName'],
  2435.             $data['slug'],
  2436.             $slugs,
  2437.             $data['description'],
  2438.             $brand
  2439.         );
  2440.     }
  2441.     /**
  2442.      * @param string $sql
  2443.      * @param string $locale
  2444.      * @return FilterResponseDTO[]
  2445.      * @throws \Doctrine\DBAL\Driver\Exception
  2446.      * @throws \Doctrine\DBAL\Exception
  2447.      */
  2448.     private function getKeysBySql(string $sqlstring $locale): array
  2449.     {
  2450.         $memcache $this->cacheService->getMemcache();
  2451.         $memcacheKey md5($sql) . $locale;
  2452.         $rows $memcache->get($memcacheKey);
  2453.         if ($rows) {
  2454.             return $rows;
  2455.         }
  2456.         $items $this->getEntityManager()->getConnection()->fetchAllAssociative($sql);
  2457.         $ids array_column($items'id');
  2458.         $rows $this->getSortedByIds($ids$locale);
  2459.         $memcache->set($memcacheKey$rows);
  2460.         return $rows;
  2461.     }
  2462.     /**
  2463.      * Получает фильтры и соответствующие группы по идентификатору группы.
  2464.      *
  2465.      * @param int $groupId Идентификатор группы.
  2466.      * @return array Массив с данными фильтров и групп.
  2467.      */
  2468.     public function getFiltersByGroupId(int $groupId): array
  2469.     {
  2470.         $urlStrSql = [];
  2471.         $keyAdwords $titleAdwords $keyAdwCombiFirst $titleAdwCombiFirst $keyAdwCombiOther $titleAdwCombiOther = [];
  2472.         $locales LocaleHelper::getListAvailable();
  2473.         foreach ($locales as $lc) {
  2474.             $urlStrSql[] = "url.{$lc['code']} AS `url.{$lc['code']}`";
  2475.             $keyAdwords[] = "keyAdw.{$lc['code']} AS `keyAdwords.{$lc['code']}`";
  2476.             $titleAdwords[] = "titleAdw.{$lc['code']} AS `titleAdwords.{$lc['code']}`";
  2477.             $keyAdwCombiFirst[] = "keyAdwCombiFirst.{$lc['code']} AS `keyAdwCombiFirst.{$lc['code']}`";
  2478.             $titleAdwCombiFirst[] = "titleAdwCombiFirst.{$lc['code']} AS `titleAdwCombiFirst.{$lc['code']}`";
  2479.             $keyAdwCombiOther[] = "keyAdwCombiOther.{$lc['code']} AS `keyAdwCombiOther.{$lc['code']}`";
  2480.             $titleAdwCombiOther[] = "titleAdwCombiOther.{$lc['code']} AS `titleAdwCombiOther.{$lc['code']}`";
  2481.         }
  2482.         $urlStrSql implode(', '$urlStrSql);
  2483.         $keyAdwords implode(', '$keyAdwords);
  2484.         $titleAdwords implode(', '$titleAdwords);
  2485.         $keyAdwCombiFirst implode(', '$keyAdwCombiFirst);
  2486.         $titleAdwCombiFirst implode(', '$titleAdwCombiFirst);
  2487.         $keyAdwCombiOther implode(', '$keyAdwCombiOther);
  2488.         $titleAdwCombiOther implode(', '$titleAdwCombiOther);
  2489.         $sql "SELECT
  2490.                 f.id,
  2491.                 f.name AS name,
  2492.                 f.alt_name AS altName,
  2493.                 g.id AS groupId,
  2494.                 p.count AS count,
  2495.                 $urlStrSql,
  2496.                 $keyAdwords,
  2497.                 $titleAdwords,
  2498.                 $keyAdwCombiFirst,
  2499.                 $titleAdwCombiFirst,
  2500.                 $keyAdwCombiOther,
  2501.                 $titleAdwCombiOther
  2502.             FROM
  2503.                 filters f
  2504.             LEFT JOIN filter_groups g ON g.id = f.group_id
  2505.             LEFT JOIN filter_params p ON p.id = f.param_id
  2506.             LEFT JOIN locale_url url ON url.filter_id = f.id
  2507.             LEFT JOIN locale_text keyAdw ON keyAdw.filter_key_adwords = f.id
  2508.             LEFT JOIN locale_text titleAdw ON titleAdw.filter_title_adwords = f.id
  2509.             LEFT JOIN locale_text keyAdwCombiFirst ON keyAdwCombiFirst.filter_key_adwords_combi_first = f.id
  2510.             LEFT JOIN locale_text titleAdwCombiFirst ON titleAdwCombiFirst.filter_title_adwords_combi_first = f.id
  2511.             LEFT JOIN locale_text keyAdwCombiOther ON keyAdwCombiOther.filter_key_adwords_combi_other = f.id
  2512.             LEFT JOIN locale_text titleAdwCombiOther ON titleAdwCombiOther.filter_title_adwords_combi_other = f.id
  2513.             WHERE
  2514.                 g.id = :groupId
  2515.             ORDER BY
  2516.                 p.count DESC
  2517.                ";
  2518.         $items $this->getEntityManager()->getConnection()->fetchAllAssociative($sql, [
  2519.             'groupId' => $groupId
  2520.         ]);
  2521.         return $items;
  2522.     }
  2523.     /**
  2524.      * Retrieves old command search filters based on the provided IDs.
  2525.      *
  2526.      * @param array $ids List of filter IDs to search for.
  2527.      * @return array List of filters with oldCommand and oldId.
  2528.      */
  2529.     public function getOldCommandSearchFilters(array $ids): array
  2530.     {
  2531.         $qb $this->getEntityManager()->createQueryBuilder();
  2532.         $qb->select('filters.oldCommand as filter''filters.oldId as id')
  2533.             ->from(FilterEntity::class, 'filters')
  2534.             ->where($qb->expr()->in('filters.id'':ids'))
  2535.             ->setParameter('ids'$ids);
  2536.         return $qb->getQuery()->getResult();
  2537.     }
  2538. }