<?php
namespace WebBundle\Service;
use Doctrine\ORM\EntityManager;
use Exception;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Translation\Translator;
use WebBundle\Entity\ListMaterial;
use WebBundle\Entity\ListMeasure;
use WebBundle\Helper\App;
use WebBundle\Helper\CurrencyRateHelper;
use WebBundle\Helper\HideFactoryCountriesHelper;
use WebBundle\Helper\LocaleHelper;
use WebBundle\Helper\StrHelper;
use WebBundle\Repository\FilterRepository;
use WebBundle\Repository\ListMaterialRepository;
use WebBundle\Repository\ListMeasureRepository;
class SphinxSearcherService
{
private array $materials = [];
/** @required */
public ListMeasureRepository $listMeasureRepository;
/** @required */
public ListMaterialRepository $listMaterialRepository;
/** @var EntityManager */
private $em;
/** @var sphinxQLService $sphinxQL */
private $sphinxQL;
/** @var Translator $translator */
private $translator;
protected array $articlesId = [];
protected array $subFilters = [];
private FilterRepository $filterRepo;
/**
* @param ContainerInterface $container
* @param FilterRepository $filterRepository
* @throws Exception
*/
public function __construct(ContainerInterface $container, FilterRepository $filterRepository)
{
$this->filterRepo = $filterRepository;
$this->em = $container->get('doctrine');
$this->sphinxQL = $container->get('sphinx_ql');
$this->translator = $container->get('translator');
}
/**
* @param ?array $data - данные для выборки
* @param ?int $limit - если 0 то вывести все (интерьеры!!!!!!!!!!)
* @param ?bool $withSchema - если true, то в поиске подбирать артикулы со схематичным изображением
* @param ?bool $full
* @param ?bool $getCount
* @param ?bool $onlyCID
* @param ?bool $NoWithArticles
* @return array
* @throws Exception
*/
public function searchSphinx(
?array $data = [],
?int $limit = 0,
?bool $withSchema = false,
?bool $full = false,
?bool $getCount = false,
?bool $onlyCID = false, //для мантикоры
?bool $NoWithArticles = false //для мантикоры и для ускорения
): array {
$this->sphinxQL->clear();
if ($getCount) {
ini_set('memory_limit', '4048M');
} else {
ini_set('memory_limit', '2048M');
}
//App::debugExit($onlyCID,$NoWithArticles);
$dataReview = [];
$fields = [
//from Articule
'a_id',
'is_main',
'a_name',
'process',
'a_style',
'file',
'fs_x',
'fs_y',
'border_grey',
'f_name',
'c_name',
'publish_date',
'country',
'country_code',
'type',
//from collection
'coll',
'c_header',
'c_name',
'f_url',
'c_url',
'c_id',
'c_status',
'sliding',
'author',
'c_name',
'rating_month',
'c_header',
'c_release_year',
'c_url',
'f_name',
'f_id',
'f_url',
'c_material',
'prc_count',
'prc_vote',
'measure',
//from other
'attr_data',
'type_filter',
'c_exhibition',
'c_awards',
'c_designer_ids',
'c_accessible',
'c_express_sample',
'a_head', //для интерьера
'styleida',//для интерьера
];
//поиск по этим фильтрам выводит интерьер по умолчанию
$allowedKeys = [
'expressSample',
'getAwards',
'reviews',
'getCountry',
'factory',
'c_id'
];
$isValidFromMainInterior = empty(array_diff_key($data['searchFilter'], array_flip($allowedKeys)));
if (isset($data['searchFilter']['getTopMonth'])) {
$fields[] = 'c_pop30';
$fields[] = 'c_last_pop30';
} elseif (isset($data['searchFilter']['getTopWeek'])) {
$fields[] = 'c_pop7';
$fields[] = 'c_last_pop7';
}
$buildingMixtureOff = false;
// тут костыль для скольжения https://te.remote.team/#/discus/7AF53097-7533-5034-0808-93CF8BDB1E75/
// Не бывает матовой поверхности с коэффициентом противоскольжения (если и бывает, то это просто ошибка в свойствах артикула)
// todo излишнее так как sliding= '999.a.sliding
if (
!empty($data['searchFilter']['getSurfaces'])
&& !empty($data['searchFilter']['sliding'])
&& count($data['searchFilter']['sliding']) == 4
) {
$data['searchFilter']['getSurfaces'][] = 8;
unset($data['searchFilter']['sliding']);
}
// фильтр по антислипу sliding на самом деле getSurfaces
// todo лишнее
if (!empty($data['searchFilter']['sliding'])) {
foreach ($data['searchFilter']['sliding'] as $row) {
$data['searchFilter']['getSurfaces'][] = (int)('999' . $row);
}
unset($data['searchFilter']['sliding']);
}
// На основании вот этой просьбы https://te.remote.team/#/discus/4B853CC1-9B65-BD60-F896-352327BC5F2C/
if (!empty($data['searchFilter']['factory']) && count($data['searchFilter']) == 1) {
$withSchema = true;
}
if (!App::isRole('ROLE_TEST')) {
$this->sphinxQL->addWhere('c_test_access != 1');
$this->sphinxQL->addWhere('f_test_access != 1');
}
if (!empty($data['HideFactory'])) {
$this->sphinxQL->addWhere('f_id NOT IN (?)', $data['HideFactory']);
} elseif (HideFactoryCountriesHelper::length() > 0) {
$this->sphinxQL->addWhere('f_id NOT IN (?)', HideFactoryCountriesHelper::codes());
}
$country = App::getCurCountry();
$measure = !empty($data['measure']) ? $data['measure'] : LocaleHelper::getUserMeasure();
$priceFields = $this->getPriceFields(LocaleHelper::getCur(), $country, $measure);
// для автоматической простановки фильтров
$dataArticles = [
'getPrstatus' => 'pr_status', // код акции
'getTypes' => 'type', // код вида изделия
'getTypeUsings' => 'using', // код назначения
'getCountry' => 'country', // код страны
'getPrcateg' => 'pr_status', // код акции
'getMaterials' => 'material', // код материала
'getCostCategory' => $priceFields[3],//'a_price_cat', // код категории цены
'getEdgeType' => 'edge_type', // тип края
'offShade' => 'off_shade', // разнотон (моноколор)
'getStyles' => 'sid', // код стиля
'getSurfaces' => 'surface', // код типа
'getFacturas' => 'a_texture', // код фактуры
'getStone' => 'a_stone_texture', // код фактуры камня
//'getColors' => 'color', // код цветов
'shape' => 'shape', // код формы
'motive' => 'a_motive', // мотив рисунка
'motiv' => 'a_motiv', // мотив рисунка
'pei' => 'pei',
'exhibition' => 'c_exhibition',
];
//Добавим поля интерьера первые найденный тогда сфинкс вернет сразу пустую строку и не нужно будет делать проверку и цикл
$interiorFilds = [
'attr_data.i[0].i_name as i_name',
'attr_data.i[0].i_id as i_id',
'attr_data.i[0].i_rating as i_rating',
'attr_data.i[0].i_monochrome as i_monochrome',
'attr_data.i[0].i_status as i_status',
'attr_data.i[0].i_file as i_file',
'attr_data.i[0].i_wall_and_floor as i_wall_and_floor',
'attr_data.i[0].i_style as i_style',
'attr_data.i[0].i_texture as i_texture',
'attr_data.i[0].fsi_x as fsi_x',
'attr_data.i[0].fsi_y as fsi_y',
];
//поля которые перенесены в attr_data что позволило сократить таблицу до артикулов проверить
$mvaFields = [
'color',
'material',
'a_motive',
'a_texture',
'designer',
'edge_type',
'a_motiv',
'shape',
'shape_module',
'a_stone_texture',
'style',
'surface',
'texture',
'a_head',
'sid',
'styleida',
'styleid',
'sort',
'i_style',
'c_apply',
'apply_id',
'typecoll',
'i_rating',
'i_id',
'is_head',
'fsi_x',
'fsi_y',
'i_name_hash',
'i_file_hash',
'i_type',
'i_status',
'i_texture',
'i_monochrome',
'i_wall_and_floor',
'using',
'type',
'c_exhibition',
];
//вычитаем поля если они attr_data добавляются через $dataAttrFields
// $plusFields = array_diff($plusFields, $attrData);
if (!$getCount) {
$fields = array_unique(array_merge($interiorFilds, $fields, $priceFields));
} else {
if ($getCount) {
$fieldsGetCount = [
'coll',
'sid',
'surface',
'material',
'a_texture',
'a_stone_texture',
'color',
'shape',
'a_motive',
'a_motiv',
'typecoll',
'c_express_sample',
'c_awards',
'c_exhibition',
'size_x',
'size_y',
'tolsch',
'using',
'factory',
'u_id',
'c_id',
'thin_granite',
'size_big',
'glazed_granite',
'thick_granite',
'publish_period',
'c_release_year',
'reviews',
'dyed_in_mass',
'apply_id',
'c_designer_ids',
'monochrome',
'pr_status',
'type',
'country',
'edge_type',
'off_shade',
$priceFields[3] . ' as a_price_cat'
];
$fields = array_merge($fieldsGetCount);
}
}
// App::debugExit($fields);
if (empty($data['total_found'])) {
$this->sphinxQL->setFrom('article', $fields);
} else {
$this->sphinxQL->setFrom('article', 'coll'); //todo тут должна появиться новая таблица
}
$this->sphinxQL->addWhere('delivery_suspended <> 1');
if (!empty($data['searchFilter']['inside'])) {
$this->sphinxQL->addWhere($priceFields[0] . ' > 0.0');
$this->sphinxQL->addWhere('delivery <> 6');
} elseif (!empty($data['searchFilter']['discontinued'])) {
$this->sphinxQL->addWhere('ANY(typeColl) in (2) ');
} else {
//http://te2.remote.team/discus/42C71507-B112-C241-1D70-BB99E3BD2278?goto=true
//Снятая с производства коллекция не убирается из рекламы
// а при чем здесь выдача?
// if (!empty($data['ads'])) {
$this->sphinxQL->addWhere('ANY(typeColl) in (1)');
// }
if (!(!empty($data['searchFilter']['factory']) && count($data['searchFilter']) == 1)) {
$this->sphinxQL->addWhere($priceFields[0] . ' > 0.0');
$this->sphinxQL->addWhere('c_status = 1');
} else {
$this->sphinxQL->addWhere('c_status IN (1, 3)');
}
}
// принято решение, если выбран стиль, то отбираем сразу по фонам декорам панно
// https://te.remote.team/#/discus/85E0842C-BCDE-D6E6-7EA4-2DB50BB404EC/
if (
!empty($data['searchFilter']['getStyles']) &&
empty($data['searchFilter']['getTypes']) &&
empty($data['searchFilter']['inside'])
) {
$data['searchFilter']['getTypes'] = [1, 113, 106, 24, 122, 128]; //todo нужно перенести в индекс
}
$this->sphinxQL->addWhere('scheme = ?', 0);
// ставим фильтры
//переносим 3Д в И
if (
!empty($data['searchFilter']['getSurfaces'])
&& in_array(12, $data['searchFilter']['getSurfaces'])
) {
$this->sphinxQL->addWhere('ANY(surface) = ?', 12);
$data['searchFilter']['getSurfaces'] = array_diff($data['searchFilter']['getSurfaces'], [12]);
if (!empty($data['searchFilter']['getSurfaces'])) {
$this->sphinxQL->addWhere('ANY(surface) in(?)', $data['searchFilter']['getSurfaces']);
} else {
unset($data['searchFilter']['getSurfaces']);
$data['searchFilter']['getSurfaces_old'] = 1;
}
}
if (!empty($data['searchFilter'])) {
if (!empty($data['searchFilter']['expressSample'])) {
if (
!empty($data['searchFilter']['inside']) ||
count($data['searchFilter']) > 1 && empty($data['searchFilter']['factory']) ||
count($data['searchFilter']) > 2 && !empty($data['searchFilter']['factory'])
) {
$this->sphinxQL->addWhere("express_sample = 1");
} else {
$this->sphinxQL->addWhere("c_express_sample = 1");
}
}
// если getAwards, то просто проверяем наличие наград и все, без уточнений
if (!empty($data['searchFilter']['getAwards'])) {
$this->sphinxQL->addWhere("c_awards != '' ");
}
// отдельно фильтр для дизайнеров, с заготовкой под ID
if (!empty($data['searchFilter']['getDesigner'])) {
// 1 имя, 0 это Id
$designerName = '';
$designerId = $data['searchFilter']['getDesigner'][0];
// поставил LIKE поиск по имени дизайнера + поиск по ID
// $this->sphinxQL->addWhere('ANY(c_designer_ids) IN (?)', $designerId); only manticore
$this->sphinxQL->addWhere("MATCH('(@c_designer_ids \"[$designerId]\") {$designerName}')");
unset($data['searchFilter']['getDesigner']);
$data['searchFilter']['getDesigner_old'] = 1;
}
if (!empty($data['searchFilter']['size_x'])) {
$this->sphinxQL->addWhere(
'size_x >= ?',
str_replace(',', '.', $data['searchFilter']['size_x'][0] * 100)
);
$buildingMixtureOff = true;
}
if (!empty($data['searchFilter']['size_y'])) {
$this->sphinxQL->addWhere(
'size_y >= ?',
str_replace(',', '.', $data['searchFilter']['size_y'][0] * 100)
);
$buildingMixtureOff = true;
}
if (!empty($data['searchFilter']['tolsch'])) {
$this->sphinxQL->addWhere(
'tolsch >= ?',
str_replace(',', '.', $data['searchFilter']['tolsch'][0] * 100)
);
$buildingMixtureOff = true;
}
if (!empty($data['searchFilter']['size_x2'])) {
$this->sphinxQL->addWhere(
'size_x <= ?',
str_replace(',', '.', $data['searchFilter']['size_x2'][0] * 100)
);
if (empty($data['searchFilter']['size_x'])) {
$this->sphinxQL->addWhere('size_x > ?', 0);
}
$buildingMixtureOff = true;
}
if (!empty($data['searchFilter']['size_y2'])) {
$this->sphinxQL->addWhere(
'size_y <= ?',
str_replace(',', '.', $data['searchFilter']['size_y2'][0] * 100)
);
if (empty($data['searchFilter']['size_y'])) {
$this->sphinxQL->addWhere('size_y > ?', 0);
}
$buildingMixtureOff = true;
}
if (!empty($data['searchFilter']['tolsch2'])) {
$this->sphinxQL->addWhere(
'tolsch <= ?',
str_replace(',', '.', $data['searchFilter']['tolsch2'][0] * 100)
);
if (empty($data['searchFilter']['tolsch'])) {
$this->sphinxQL->addWhere('tolsch > ?', 0);
}
$buildingMixtureOff = true;
}
// специально для приложений
if (!empty($data['searchFilter']['prMinFrom'])) {
$this->sphinxQL->addWhere(
'pr_min <= ?',
str_replace(',', '.', $data['searchFilter']['prMinFrom'][0] * 100)
);
}
if (!empty($data['searchFilter']['prMinTo'])) {
$this->sphinxQL->addWhere(
'pr_min >= ?',
str_replace(',', '.', $data['searchFilter']['prMinTo'][0] * 100)
);
}
if (!empty($data['searchFilter']['shape'])) {
// Если в фильтре есть модуль (shape = 10)
if (in_array(10, $data['searchFilter']['shape'])) {
// Ищем по формам модулей (shape_module содержит формы модулей)
$shape = $data['searchFilter']['shape'];
unset($shape[array_search(10, $shape)]);
if (!empty($shape)) {
// Если есть другие формы, ищем их в формах модулей
$this->sphinxQL->addWhere('ANY(shape_module) in (?)', $shape);
} else {
// Если выбрана только форма 10 (модуль), показываем все модули
// shape_module не пустое означает что это модуль (любое значение > 0)
$this->sphinxQL->addWhere('ANY(shape_module) > 0');
}
} else {
// Если модуль не выбран, ищем по обычным формам (shape, исключая модули)
// Исключаем модули: shape не должен содержать 10
$this->sphinxQL->addWhere('ALL(shape) not in (?)', 10);
// Показываем только выбранные формы (квадрат, прямоугольник, неопределенная и т.д.)
$this->sphinxQL->addWhere('ANY(shape) in (?)', $data['searchFilter']['shape']);
$dataArticles['shape'] = 'shape'; // код цветов
}
}
if (!empty($data['searchFilter']['getColors']) && in_array(99, $data['searchFilter']['getColors'])) {
$this->sphinxQL->addWhere('ANY(color) in (?)', 99);
$colors = $data['searchFilter']['getColors'];
unset($colors[array_search(99, $colors)]);
if (!empty($colors)) {
$this->sphinxQL->addWhere('ANY(color) in (?)', $colors);
}
} else {
$dataArticles['getColors'] = 'color'; // код цветов
}
// если есть фильтры, то добавляем их к запросу
foreach ($data['searchFilter'] as $key => $row) {
if (!empty($dataArticles[$key])) {
// отключаем фильтр getPrcateg и ориентируемся на баланс
if (trim($key) == 'getPrcateg') {
continue;
}
//тут проставим $mvaFields чтобы искать в MVA any|all
if (in_array($dataArticles[$key], $mvaFields)) {
$dataArticles[$key] = ' ANY(' . $dataArticles[$key] . ')';
}
$this->sphinxQL->addWhere($dataArticles[$key] . ' IN (?)', $row);
}
}
// фильтр окрашен в массе
if (!empty($data['searchFilter']['dyedInMass'])) {
$this->sphinxQL->addWhere('dyed_in_mass = 1');
}
// !!! теперь если выбран фильтр применения показываем только интерьеры
// для применения работает немного иначе если более одного признака то идёт наследование от коллекции,
// но при этом надо не показывать интерьеры, которые не соответствуют применению
if (!empty($data['searchFilter']['getUsings'])) {
if (!empty($data['searchFilter']['getUsings'])) {
// вернул выборку по ID иначе показывает все из "применения" без фильтрации.
$this->sphinxQL->addWhere('ANY(apply_id) IN (?)', $data['searchFilter']['getUsings']);
}
$this->sphinxQL->addWhere('c_accessible <> 1');
}
// фильтр по фабрике
if (!empty($data['searchFilter']['factory'])) {
$this->sphinxQL->addWhere('factory = \'' . $data['searchFilter']['factory'][0] . '\'');
}
// фильтр по фабрике
if (!empty($data['searchFilter']['bm'])) {
$bmId = $data['searchFilter']['bm'];
$bmId = is_array($bmId) ? $bmId[0] : $bmId;
$this->sphinxQL->addWhere('u_id = ' . $bmId);
}
// фильтр по id коллекций
if (!empty($data['searchFilter']['c_id'])) {
$this->sphinxQL->addWhere('c_id IN (?)', $data['searchFilter']['c_id']);
unset($data['searchFilter']['c_id']);
}
}
// тонкий керамогранит
if (!empty($data['searchFilter']['getThinGranite'])) {
$this->sphinxQL->addWhere('thin_granite = ?', 1);
$buildingMixtureOff = true;
}
// фильтр большого размера плитки
if (!empty($data['searchFilter']['size_big'])) {
$this->sphinxQL->addWhere('size_big = ?', 1);
$buildingMixtureOff = true;
}
// глазурированный/неглазурированный керамогранит
if (!empty($data['searchFilter']['getGlazedGranit'])) {
$this->sphinxQL->addWhere('glazed_granite = ?', $data['searchFilter']['getGlazedGranit']);
}
if ($country == 'ru' || $buildingMixtureOff) {
$this->sphinxQL->addWhere('c_id != ?', 3245628);
}
// утолщенный керамогранит
if (!empty($data['searchFilter']['getThickGranite'])) {
$this->sphinxQL->addWhere('thick_granite = ?', $data['searchFilter']['getThickGranite']);
}
// Если новинки, то выводим только коллекции за месяц
//Семраш пишет не может сканировать страницу новинок
//https://te2.remote.team/discus/35DEFA01-C136-0EA2-DB72-E8999812EBFC
if (isset($data['searchFilter']['getTop'])) {
$this->sphinxQL->addWhere('ANY(publish_period) = ?', 4);
}
// выборки за период
if (isset($data['searchPeriod'])) {
$this->sphinxQL->addWhere('ANY(publish_period) = ?', $data['searchPeriod']);
}
$dateSort = 'publish_date DESC';
// фильтрация по году выпуска
if (!empty($data['searchFilter']['releaseYear'])) {
$years = [];
foreach ($data['searchFilter']['releaseYear'] as $year) {
if (strlen($year) > 4) {
$y = substr($year, 0, 4);
do {
$y--;
$years[] = $y;
} while ($y > 2013);
} elseif ($year == 999) {
$years[] = date('Y');
} else {
$years[] = $year;
}
}
if (count($years) > 0) {
$this->sphinxQL->addWhere('c_release_year IN (?)', $years);
}
}
// фильтрация по средней оценке отзывов
if (!empty($data['searchFilter']['reviews'])) {
$this->sphinxQL->addWhere('reviews IN (?)', $data['searchFilter']['reviews']);
if ($this->getSearchSortId() == 0) {
$data['searchSort'] = 6;
}
}
// учитываем сортировку в запросе
// App::debugExit($data);
if (isset($data['searchFilter']['getTopMonth'])) {
$searchSort = 'c_pop30 DESC';
} elseif (isset($data['searchFilter']['getTopWeek'])) {
$searchSort = 'c_pop7 DESC';
} else {
$searchSort = 'rating DESC';
}
if (!empty($data['searchFilter']['getCostCategory']) && $this->getSearchSortId() == 0) {
$searchSort = 'price_sort ASC';
}
if (!empty($data['searchFilter'][''])) {
unset($data['searchFilter']['']);
}
// определяем тип минимальной цены
$minTypeAll = false;
if (
(count($data['searchFilter']) == 0 || !empty($data['searchFilter']['factory'])
&& count($data['searchFilter']) == 1) && !$getCount
) {
$minTypeAll = true;
// Если нет фильтров ищем только по фонам мозаике декору
// Ага, а если ищем зеленный, то выводим красный :)
// $this->sphinxQL->addWhere('ANY(type) IN (?)', [1, 24, 113, 122, 27, 106, 64, 128, 0]);
}
// https://te.remote.team/#/discus/BDBD8973-1F54-3B16-99ED-8656AEFC1105/
// убрал совсем сортировку по полю price_euro
if (
!empty($data['searchFilter']['getTypes']) && !array_intersect(
(array)$data['searchFilter']['getTypes'],
[1, 24, 113, 122, 106]
)
) {
$sort = 'price_sort ASC';
} else {
$sort = $priceFields[4] . ' ASC';
}
$searchSortLimit = false;
if (!empty($data['searchSort'])) {
switch ($data['searchSort']) {
case 1:
$searchSort = 'c_pop7 DESC';
break;
case 2:
// по цене
$searchSort = false;
break;
case 3:
// по дате
$searchSort = 'publish_date DESC';
break;
case 4:
// по алфавиту
$searchSort = 'c_name ASC';
break;
case 5:
// по популярности за месяц
$searchSort = 'c_pop30 DESC';
break;
case 6:
// по отзывам
$searchSort = 'prc_star DESC';
$searchSortLimit = 'prc_count DESC';
break;
}
}
if (empty($data['total_found'])) {
if ($searchSort) {
$this->sphinxQL->setOrder($searchSort);
}
if ($searchSortLimit) {
$this->sphinxQL->setOrder($searchSortLimit);
}
$this->sphinxQL->setOrder('sort DESC');
$this->sphinxQL
->setOrder($sort) //цена в приоритете она создает коллекцию и минимальную ее цену
->setOrder('max_is_head DESC'); //сортирует только по строкам max_is_head"
if (!$searchSortLimit) {
$this->sphinxQL->setOrder($dateSort);
}
}
if (!empty($data['total_found'])) {
$this->sphinxQL->setLimit(1)
->setGroup('coll');
$rows = $this->sphinxQL->getQuery()->fetchAllAssociative();
$totalFound = $this->sphinxQL->getTotalFound();
return ['total_found' => $totalFound];
}
if (!empty($data['only_c_id'])) {
$this->sphinxQL->setLimit(200000)
->setGroup('c_id');
$rows = $this->sphinxQL->getQuery()->fetchAllAssociative();
return $rows;
}
$this->subFilters = $this->filterRepo->getFiltersSubRelation(false);
if (empty($data['limit'])) {
$this->sphinxQL->setLimit(SphinxQLService::MAX_MATCHES);
if (empty($data['searchFilter']['inside'])) {
$this->sphinxQL->setGroup('a_id');//, i_id, sid, styleid, styleida
}
} else {
$this->sphinxQL->setLimit($data['limit'])
->setGroup('coll');
}
if (!empty($data['real'])) {
$this->sphinxQL->setOption('max_matches=200000');
$this->sphinxQL->setLimit(200000);
}
$ed = [];
$listMeasure = $this->em->getRepository('WebBundle:ListMeasure')->findBy(['hide' => false]);
/** @var ListMeasure $row */
foreach ($listMeasure as $row) {
$ed[$row->getId()] = $row->getAlias() != null
? $this->translator->trans($row->getAlias())
: $row->getName();
}
//дополнительные свойства
$collections = ['i_names' => [], 'a_names' => []];
$num = 0;
if ($getCount) {
// $client = HttpClient::create();
// $response = $client->request('POST', 'http://go-service:8080/process', [
// 'json' => ['text' => 'hello world1', 'query'=> $this->sphinxQL->getSql()],
// ]);
//
// $calculate = $response->toArray();
$calculate = [];
// //Создаем привязку фильтра к нашим полям для подсчета
$aFiltersOnlyNoChilds = $this->filterRepo->getListForSynchCountFilters([]);
$realFilterProperty = [];
$newFiltersOnlyNoChild = [];
foreach ($aFiltersOnlyNoChilds as $fVal) {
$fRealId = $fVal['oldCommand'] == 'getDesigner' ? $fVal['id'] : $fVal['oldId'];
$realFilterProperty[$fVal['oldCommand']] [$fRealId] = $fVal;
$realFilterProperty[$fVal['oldCommand']] [$fRealId] ['oldId'] = $fRealId;
$realFilterProperty[$fVal['oldCommand']] [$fRealId] ['count'] = 0;
$realFilterProperty[$fVal['oldCommand']] [$fRealId] ['coll_array'] = []; //добавляем массив колеккций дабы отсекать у родителей дубли
$newFiltersOnlyNoChild[$fVal['id']] = $fVal;
$newFiltersOnlyNoChild[$fVal['id']]['coll_array'] = [];
}
$rows = $this->sphinxQL->getQuery()->fetchAllAssociative();
foreach ($rows as $row) {
if ($getCount) {
if (!empty($row['c_exhibition']) && $exhibitionDate = json_decode($row['c_exhibition'], true)) {
$row['c_exhibition'] = $exhibitionDate;
} else {
$row['c_exhibition'] = [];
}
if (
!empty($row['c_designer_ids']) && $c_designer_idsDate = json_decode(
$row['c_designer_ids'],
true
)
) {
$row['c_designer_ids'] = $c_designer_idsDate;
} else {
$row['c_designer_ids'] = [];
}
if (empty($calculate[$row['coll']])) {
//todo по факту эти поля нужно будет собрать из индекса который будет колеккцией пока у меня article2
$calculate[$row['coll']] = [
'getStyles' => [],
'getSurfaces' => [],
'getFacturas' => [],
'getMaterials' => [],
'getStone' => [],
'getColors' => [],
'shape' => [],
'motive' => [],
'motiv' => [],
'discontinued' => [],
'expressSample' => [],
'getAwards' => [],
'exhibition' => [],
'size_x' => [],
'size_y' => [],
'tolsch' => [],
'material' => [],
'getTypeUsings' => [],
'factory' => [],
'bm' => [],
'c_id' => [],
'getThinGranite' => [],
'size_big' => [],
'getGlazedGranit' => [],
'getThickGranite' => [],
'searchPeriod' => [],
'releaseYear' => [],
'reviews' => [],
'dyedInMass' => [],
'colorBody' => [],
'getUsings' => [],
'getDesigner' => [],
'monochrome' => [],
'getPrcateg' => [],
'getTypes' => [],
'getCountry' => [],
'a_price_cat' => [],
'getEdgeType' => [],
'offShade' => [],
'getCostCategory' => [],
];
}
//пробуем просто собрать данные;
$calculate[$row['coll']]['getCostCategory'] = array_merge(
$calculate[$row['coll']]['getCostCategory'],
[$row['a_price_cat']]
);
$calculate[$row['coll']]['getStyles'] = array_merge(
$calculate[$row['coll']]['getStyles'],
explode(',', $row['sid'])
);
$calculate[$row['coll']]['getSurfaces'] = array_merge(
$calculate[$row['coll']]['getSurfaces'],
explode(',', $row['surface'])
);
$calculate[$row['coll']]['getMaterials'] = array_merge(
$calculate[$row['coll']]['getMaterials'],
explode(',', $row['material'])
);
$calculate[$row['coll']]['getFacturas'] = array_merge(
$calculate[$row['coll']]['getFacturas'],
explode(',', $row['a_texture'])
);
$calculate[$row['coll']]['getStone'] = array_merge(
$calculate[$row['coll']]['getStone'],
explode(',', $row['a_stone_texture'])
);
$calculate[$row['coll']]['getColors'] = array_merge(
$calculate[$row['coll']]['getColors'],
explode(',', $row['color'])
);
$calculate[$row['coll']]['shape'] = array_merge(
$calculate[$row['coll']]['shape'],
explode(',', $row['shape'])
);
$calculate[$row['coll']]['motive'] = array_merge(
$calculate[$row['coll']]['motive'],
explode(',', $row['a_motive'])
);
$calculate[$row['coll']]['motiv'] = array_merge(
$calculate[$row['coll']]['motiv'],
explode(',', $row['a_motiv'])
);
$calculate[$row['coll']]['discontinued'] = array_merge(
$calculate[$row['coll']]['discontinued'],
explode(',', $row['typecoll'])
);
$calculate[$row['coll']]['expressSample'] = array_merge(
$calculate[$row['coll']]['expressSample'],
[$row['c_express_sample']]
);
$calculate[$row['coll']]['getAwards'] = array_merge(
$calculate[$row['coll']]['getAwards'],
[!empty($row['c_awards']) ? 1 : 2]
);
$calculate[$row['coll']]['exhibition'] = array_merge(
$calculate[$row['coll']]['exhibition'],
$row['c_exhibition']
);
$calculate[$row['coll']]['size_x'] = array_merge(
$calculate[$row['coll']]['size_x'],
[$row['size_x']]
);
$calculate[$row['coll']]['size_y'] = array_merge(
$calculate[$row['coll']]['size_y'],
[$row['size_y']]
);
$calculate[$row['coll']]['tolsch'] = array_merge(
$calculate[$row['coll']]['tolsch'],
[$row['tolsch']]
);
$calculate[$row['coll']]['material'] = array_merge(
$calculate[$row['coll']]['material'],
explode(',', $row['material'])
);
$calculate[$row['coll']]['getTypeUsings'] = array_merge(
$calculate[$row['coll']]['getTypeUsings'],
explode(',', $row['using'])
);
$calculate[$row['coll']]['factory'] = array_merge(
$calculate[$row['coll']]['factory'],
[$row['factory']]
);
$calculate[$row['coll']]['bm'] = array_merge($calculate[$row['coll']]['bm'], [$row['u_id']]);
$calculate[$row['coll']]['c_id'] = array_merge($calculate[$row['coll']]['c_id'], [$row['c_id']]);
$calculate[$row['coll']]['getThinGranite'] = array_merge(
$calculate[$row['coll']]['getThinGranite'],
[$row['thin_granite']]
);
$calculate[$row['coll']]['size_big'] = array_merge(
$calculate[$row['coll']]['size_big'],
[$row['size_big']]
);
$calculate[$row['coll']]['getGlazedGranit'] = array_merge(
$calculate[$row['coll']]['getGlazedGranit'],
[$row['glazed_granite']]
);
$calculate[$row['coll']]['getThickGranite'] = array_merge(
$calculate[$row['coll']]['getThickGranite'],
[$row['thick_granite']]
);
$calculate[$row['coll']]['searchPeriod'] = array_merge(
$calculate[$row['coll']]['searchPeriod'],
[$row['publish_period']]
);
$calculate[$row['coll']]['releaseYear'] = array_merge(
$calculate[$row['coll']]['releaseYear'],
[$row['c_release_year']]
);
$calculate[$row['coll']]['reviews'] = array_merge(
$calculate[$row['coll']]['reviews'],
explode(',', $row['reviews'])
);
$calculate[$row['coll']]['dyedInMass'] = array_merge(
$calculate[$row['coll']]['dyedInMass'],
[$row['dyed_in_mass']]
);
$calculate[$row['coll']]['getUsings'] = array_merge(
$calculate[$row['coll']]['getUsings'],
explode(',', $row['apply_id'])
);
$calculate[$row['coll']]['getDesigner'] = array_merge(
$calculate[$row['coll']]['getDesigner'],
$row['c_designer_ids']
);
$calculate[$row['coll']]['monochrome'] = array_merge(
$calculate[$row['coll']]['monochrome'],
explode(',', $row['monochrome'])
);
$calculate[$row['coll']]['getPrcateg'] = array_merge(
$calculate[$row['coll']]['getPrcateg'],
[$row['pr_status']]
);
$calculate[$row['coll']]['getTypes'] = array_merge(
$calculate[$row['coll']]['getTypes'],
explode(',', $row['type'])
);
$calculate[$row['coll']]['getCountry'] = array_merge(
$calculate[$row['coll']]['getCountry'],
[$row['country']]
);
$calculate[$row['coll']]['getEdgeType'] = array_merge(
$calculate[$row['coll']]['getEdgeType'],
explode(',', $row['edge_type'])
);
$calculate[$row['coll']]['offShade'] = array_merge(
$calculate[$row['coll']]['offShade'],
[$row['off_shade']]
);
//
//включаем если запрашивали
}
}
} else {
$rows = $this->sphinxQL->getQuery()->fetchAllAssociative();
foreach ($rows as $row) {
if (!empty($row['attr_data']) && $attDate = json_decode($row['attr_data'], true)) {
// удаляем интерьеры
unset($attDate['i_name']);
unset($attDate['i_id']);
unset($attDate['i_rating']);
unset($attDate['i_monochrome']);
unset($attDate['i_status']);
unset($attDate['i_file']);
unset($attDate['i_wall_and_floor']);
unset($attDate['i_style']);
unset($attDate['i_texture']);
unset($attDate['fsi_x']);
unset($attDate['fsi_y']);
$row = array_merge((array)$row, $attDate); //удалить главный интерьер из сфинкса
}
if (!empty($row['c_exhibition']) && $exhibitionDate = json_decode($row['c_exhibition'], true)) {
$row['c_exhibition'] = $exhibitionDate;
} else {
$row['c_exhibition'] = [];
}
if (!empty($row['c_awards']) && $c_awardsDate = json_decode($row['c_awards'], true)) {
$row['c_awards'] = $c_awardsDate;
} else {
$row['c_awards'] = [];
}
if (!empty($row['c_designer_ids']) && $c_designer_idsDate = json_decode($row['c_designer_ids'], true)) {
$row['c_designer_ids'] = $c_designer_idsDate;
} else {
$row['c_designer_ids'] = [];
}
// временно
//$row['apply_id'] = explode(',', $row['apply_id']);
if (!empty($data['offset'])) {
$num++;
if ($data['offset'] > ($num - 1)) {
continue;
}
}
if (!empty($row['c_accessible'])) {
$noInteriorFactory = true;
} else {
$noInteriorFactory = false;
}
if ($row['c_id'] == 3245628) {
$row['c_name'] = App::trans('left_menu_glue');
}
//создаем клон из строки, но с данными из Коллекций для блатного удаления и фильтрации
//обратить внимание при поиске по коллекциям возврщает полный результат и потом фильтрует возможно можно что-то перенести в sphinx или в where
$iRows = [];
if (!empty($row['i'])) {
if (!empty($data['searchFilter']['getUsings'])) {
$applyIds = $data['searchFilter']['getUsings'] ?? []; // Массив ID для фильтрации, например [2, 3]
$isSwimmingPoolFilter = in_array(8, $applyIds);
$filteredInteriors = array_filter($row['i'], function ($interior) use ($applyIds, $isSwimmingPoolFilter) {
// Если выбран фильтр бассейна (8), и артикул прошел фильтр ANY(apply_id)=8,
// показываем все интерьеры, даже если apply_id = null (бассейн добавляется через UNION для swimming_pool = 1)
if ($isSwimmingPoolFilter && empty($interior['apply_id'])) {
return true;
}
return !empty($interior['apply_id']) && in_array($interior['apply_id'], $applyIds);
});
// Переиндексация и обновление $row['i'], если есть результаты
if (!empty($filteredInteriors)) {
$row['i'] = array_values($filteredInteriors);
} else {
// Если все интерьеры отфильтрованы, очищаем массив
$row['i'] = [];
}
}
$row['i'] = array_values($row['i']);
// Заменяем значения $row значениями $row[i][n]
foreach ($row['i'] as $v) {
$iRows[] = array_merge($row, $v);
}
} else {
//если нет, то для дальнейшей проверки оставим старое значение
$iRows[] = $row;
}
foreach ($iRows as $intRow) {
$row = $intRow;
if (
!empty($row['apply_id']) &&
!empty($data['searchFilter']['getUsings']) &&
count($data['searchFilter']) > 1 &&
!(count(array_intersect([$row['apply_id']], $data['searchFilter']['getUsings'])) > 0)
) {
$applyShow = false;
} else {
$applyShow = true;
}
if ($row['process'] == 1) {
$row['i_file'] = str_replace(['.jpeg', '.jpg'], '.webp', $row['i_file']);
}
$noRestriction = $this->getNoRestriction($data['searchFilter'], $row, $oldTypeUsings ?? null);
// есть ограничение на показ интерьером, но выбран фильтр применения, пропускаем такой элемент
if (
!empty($data['searchFilter']['getUsings'])
&& !$noRestriction
) {
continue;
}
// базовая информация о коллекции
if (empty($collections[$row['coll']])) {
if ($row['c_status'] == 1) {
$dataReview[$row['coll']] = [
'name' => App::trans(
$row['c_header'] . '.short',
App::getCurLocale(),
[
'%collection%' => $row['c_name'],
]
),
'url' => App::generateUrl(
'app_collection',
[
'factoryUrl' => $row['f_url'],
'collectionUrl' => $row['c_url'],
]
),
];
}
if (isset($data['searchFilter']['getTopMonth'])) {
$arrow = $row['c_pop30'] > $row['c_last_pop30'] ? 'up' : 'down';
} elseif (isset($data['searchFilter']['getTopWeek'])) {
$arrow = $row['c_pop7'] > $row['c_last_pop7'] ? 'up' : 'down';
} else {
$arrow = false;
}
$collections[$row['coll']] = [
'c_id' => $row['c_id'],
'c_code' => $row['coll'],
'c_status' => $row['c_status'],
'c_name' => $row['c_name'],
'ratingMonth' => $row['rating_month'],
'arrow' => $arrow,
'c_header' => $row['c_header'],
'c_release_year' => $row['c_release_year'],
'c_url' => $row['c_url'],
'f_name' => $row['f_name'],
'f_url' => $row['f_id'] == 12 ? StrHelper::toLower($row['f_url']) : $row['f_url'],
];
// если не пустое, то там массив с ID фильтров, иконки которых надо получить будет
$collections[$row['coll']]['c_awards'] = $row['c_awards'];
// если не пустое, то там массив с sub ID фильтров выставок
$collections[$row['coll']]['c_exhibition'] = $row['c_exhibition'];
$collections[$row['coll']]['date'] = date('d.m.Y', $row['publish_date']);
$collections[$row['coll']]['country'] = $row['country'];
$collections[$row['coll']]['country_code'] = $row['country_code'];
$collections[$row['coll']]['type'] = $row['type'];
$collections[$row['coll']]['material'] = $this->mapMaterial(
array_unique(explode(',', $row['c_material'] ?? ''))
);
// вывел признак экспресс образца
$collections[$row['coll']]['hasExpressSample'] = !empty($row['c_express_sample']) && $row['c_express_sample'] == 1;
// добавил вывод prc_middle, что бы можно было проверить точность фильтрации
$prcCount = empty($row['prc_count']) ? null : $row['prc_count'];
$prcVote = empty($row['prc_vote']) ? null : $row['prc_vote'];
$prcMiddle = 0;
if ($prcCount && $prcVote) {
$prcMiddle = ($prcVote / $prcCount + 0.01 * $prcCount) * 100;
}
$collections[$row['coll']]['prc_count'] = $prcCount;
$collections[$row['coll']]['prc_vote'] = $prcVote;
$collections[$row['coll']]['prc_middle'] = $prcMiddle;
$collections[$row['coll']]['process'] = $row['process'] ?? 0;
$collections[$row['coll']]['alt'] = str_replace(
['\\', '"', '\''],
'',
join(', ', [$row['f_name'], $row['c_name'], $row['i_name']])
);
$collections[$row['coll']]['author'] = empty($row['author']) ? null : $row['author'];
$collections[$row['coll']]['sliding'] = empty($row['sliding']) ? [] : [$row['sliding']];
$collections[$row['coll']]['a_show'] = empty($data['searchFilter']['getUsings']) ? '1' : '0';
// цены по умолчанию
$collections[$row['coll']]['price'] = (float)(max($row[$priceFields[0]], 1));
$collections[$row['coll']]['pr_min'] = (float)(max($row[$priceFields[2]], 1));
$collections[$row['coll']]['price_mq'] = (float)(max($row[$priceFields[1]], 1));
$collections[$row['coll']][$priceFields[4]] = (float)(max($row[$priceFields[4]], 1));
$collections[$row['coll']]['measureId'] = $row['measure'];
if (!empty($collections[$row['coll']]['price_mq']) && $row[$priceFields[3]] > 0) {
$collections[$row['coll']]['price'] = $collections[$row['coll']]['price_mq'];
$collections[$row['coll']]['measureId'] = 1;
$row['measure'] = 1;
}
$collections[$row['coll']]['measureText'] = $row['measure'] == 1 && LocaleHelper::getUserMeasure() == 'ft' ? $ed[6] : $ed[$row['measure']];
//$collections[$row['coll']]['measureText'] = $ed[$row['measure']] == 'm²' && LocaleHelper::getUserMeasure() == 'ft' ? 'ft²' : $ed[$row['measure']];
if (in_array($country, ['ch', 'no', 'hk', 'sg'])) {
$collections[$row['coll']]['price'] = round(
$collections[$row['coll']]['price'] - $collections[$row['coll']]['price'] * 18 / 118,
2
);
$collections[$row['coll']]['pr_min'] = round(
$collections[$row['coll']]['pr_min'] - $collections[$row['coll']]['pr_min'] * 18 / 118,
2
);
$collections[$row['coll']]['price_mq'] = round(
$collections[$row['coll']]['price_mq'] - $collections[$row['coll']]['price_mq'] * 18 / 118,
2
);
}
// для Гонконга конвертируем из мальтийских цен по курсу
if ($country == 'hk') {
$collections[$row['coll']]['price'] = CurrencyRateHelper::convertPrice(
'HKD',
$collections[$row['coll']]['price']
);
$collections[$row['coll']]['pr_min'] = CurrencyRateHelper::convertPrice(
'HKD',
$collections[$row['coll']]['pr_min']
);
$collections[$row['coll']]['price_mq'] = CurrencyRateHelper::convertPrice(
'HKD',
$collections[$row['coll']]['price_mq']
);
$collections[$row['coll']][$priceFields[4]] = CurrencyRateHelper::convertPrice(
'HKD',
$collections[$row['coll']][$priceFields[4]]
);
}
// для Сингапура конвертируем из мальтийских цен по курсу
if ($country == 'sg') {
$collections[$row['coll']]['price'] = CurrencyRateHelper::convertPrice(
'SGD',
$collections[$row['coll']]['price']
);
$collections[$row['coll']]['pr_min'] = CurrencyRateHelper::convertPrice(
'SGD',
$collections[$row['coll']]['pr_min']
);
$collections[$row['coll']]['price_mq'] = CurrencyRateHelper::convertPrice(
'SGD',
$collections[$row['coll']]['price_mq']
);
$collections[$row['coll']][$priceFields[4]] = CurrencyRateHelper::convertPrice(
'SGD',
$collections[$row['coll']][$priceFields[4]]
);
}
// убираем копейки
$collections[$row['coll']]['price'] = round($collections[$row['coll']]['price']);
$collections[$row['coll']]['pr_min'] = round($collections[$row['coll']]['pr_min']);
$collections[$row['coll']]['price_mq'] = round($collections[$row['coll']]['price_mq']);
// минимальная цена по коллекции если, не установлены дополнительные фильтры
if ($minTypeAll) {
$collections[$row['coll']]['pr_min'] = round($collections[$row['coll']][$priceFields[4]]);
$collections[$row['coll']]['price_mq'] = round($collections[$row['coll']]['pr_min']);
$collections[$row['coll']]['price'] = round($collections[$row['coll']]['pr_min']);
} elseif (empty($collections[$row['coll']]['price_mq'])) {
$collections[$row['coll']]['price_mq'] = round($collections[$row['coll']]['price']);
}
// собираем коды ед.изм.
$collections[$row['coll']]['measure'] = $ed[$row['measure']] ?? (App::trans(
$measure == 'm' ? 'measure_mq' : 'measure_ft'
));
$collections['i_names'][$row['coll']] = [];
$collections[$row['coll']]['interiors'] = [];
$collections[$row['coll']]['articles'][] = $this->article($row);
$collections[$row['coll']]['slidingShow'] = 0;
if (
!empty($data['searchFilter']['getSurfaces'])
&& in_array(8, $data['searchFilter']['getSurfaces'])
) {
$collections[$row['coll']]['slidingShow'] = 1;
}
$collections['a_names'][$row['coll']][] = $row['a_name'];
if (
empty($data['searchFilter']['inside'])
&& !$noInteriorFactory
&& ((empty($data['searchFilter'])
|| count($data['searchFilter']) <= 2
&& !empty($data['searchFilter']['getAlsoCollViewed'])
|| count($data['searchFilter']) == 1
&& (!empty($data['searchFilter']['factory'])
|| !empty($data['searchFilter'][''])
)
) || $isValidFromMainInterior)
&& !empty($row['is_main'])
) { // специальная заглушка для главной картинки коллекции на случай если не выбраны фильтры
[
$mainInteriorId,
$mainInteriorName,
$mainInteriorFile,
$fileSizeX,
$fileSizeY,
$iRating,
] = explode('|', $row['is_main']);
if (!$fileSizeY == 0 && !empty($mainInteriorName)) {
$iName = $mainInteriorName;
$iFile = $mainInteriorFile;
if ($row['a_head'] || $isValidFromMainInterior || empty($data['searchFilter'])) {
$collections['i_names'][$row['coll']][] = $iName;
$collections[$row['coll']]['interiors_tmp'][] = [
'i_id' => $mainInteriorId,
'i_name' => $iName,
'i_file' => $iFile,
'i_rating' => $iRating,
'x' => $fileSizeX,
'y' => $fileSizeY,
];
}
}
}
if (
!$noInteriorFactory
&& !empty($row['i_name'])
&& isset($row['i_id']) && $row['i_id'] !== null
&& $noRestriction
&& $applyShow
&& !in_array($row['i_name'], $collections['i_names'][$row['coll']])
&& (empty($data['searchFilter']['getUsings'])
|| (!empty($row['apply_id']) && in_array($row['apply_id'], $data['searchFilter']['getUsings']))
|| (in_array(8, $data['searchFilter']['getUsings']) && empty($row['apply_id']))
)
) {
$iName = $row['i_name'];
$iFile = $row['i_file'];
if ($row['a_head']) {
$collections['i_names'][$row['coll']][] = $iName;
$collections[$row['coll']]['interiors'][] = [
'i_id' => $row['i_id'],
'i_name' => $iName,
'i_file' => $iFile,
'x' => $row['fsi_x'],
'y' => $row['fsi_y'],
'i_rating' => $row['i_rating'],
];
}
}
} else {
// если запрошена фильтрация по коллекции, то выводим все артикулы
if (!empty($_GET['debug']) || !empty($data['searchFilter']['inside']) && !$NoWithArticles) {
$collections[$row['coll']]['articles'][] = $this->article($row);
}
if (
!empty($row['author']) &&
is_array($collections[$row['coll']]['author']) &&
!in_array($row['author'], $collections[$row['coll']]['author'])
) {
$collections[$row['coll']]['author'] = $row['author'];
}
if (
!empty($row['sliding']) && !in_array(
$row['sliding'],
$collections[$row['coll']]['sliding']
)
) {
$collections[$row['coll']]['sliding'][] = $row['sliding'];
}
// собираем коды ед.изм.
$collections[$row['coll']]['measure'] = $ed[$row['measure']] ?? (App::trans(
$measure == 'm' ? 'measure_mq' : 'measure_ft'
));
if (
(!empty($data['searchFilter']['getPrcateg'])
&& (in_array(7, $data['searchFilter']['getPrcateg'])
|| in_array(6, $data['searchFilter']['getPrcateg'])
)
)
|| !empty($data['searchFilter']['coll']) || count(
$collections[$row['coll']]['articles']
) == 0
) {
/** см. выше для первого вхождения артикула в коллекцию */
if (
empty($data['searchFilter']['getStyles'])
|| (!empty($data['searchFilter']['getStyles'])
&& in_array($row['a_style'], $data['searchFilter']['getStyles'])
)
) {
if (!in_array($row['a_name'], $collections['a_names'][$row['coll']])) {
$collections[$row['coll']]['articles'][] = $this->article($row);
}
}
}
if (
!$noInteriorFactory
&& !empty($row['i_name'])
&& isset($row['i_id']) && $row['i_id'] !== null
&& $noRestriction
&& $applyShow
&& !in_array($row['i_name'], $collections['i_names'][$row['coll']])
&& (
empty($data['searchFilter']['getUsings'])
|| (!empty($row['apply_id']) && in_array($row['apply_id'], $data['searchFilter']['getUsings']))
|| (in_array(8, $data['searchFilter']['getUsings']) && empty($row['apply_id']))
)
) {
if ($row['a_head']) {
$collections['i_names'][$row['coll']][] = $row['i_name'];
$collections[$row['coll']]['interiors'][] = [
'i_id' => $row['i_id'],
'i_name' => $row['i_name'],
'i_file' => $row['i_file'],
'x' => $row['fsi_x'],
'y' => $row['fsi_y'],
'i_rating' => $row['i_rating'],
];
}
}
$collections['a_names'][$row['coll']][] = $row['a_name'];
}
}
}
}
unset($collections['i_names']);
unset($collections['a_names']);
foreach ($collections as $k => $v) {
if ($NoWithArticles && !empty($collections[$k]['interiors'])) {
unset($collections[$k]['articles']);
}
usort($collections[$k]['interiors'], function ($a, $b) {
return $b['i_rating'] <=> $a['i_rating']; // DESC; для ASC поменяйте a и b местами
});
if ($limit) {
$collections[$k]['interiors'] = array_slice($collections[$k]['interiors'], 0, $limit);
}
//Заглушку ставим только тогда когда у коллекции нет подходящих интерьеров https://te2.remote.team/discus/25909450-279B-15AB-A560-74C8D278134E?goto=true
if (empty($collections[$k]['interiors']) && !empty($collections[$k]['interiors_tmp'])) {
$collections[$k]['interiors'] = $collections[$k]['interiors_tmp'];
}
}
if (
!empty($data['searchFilter']['getPrcateg'])
&& (in_array(6, $data['searchFilter']['getPrcateg'])
|| in_array(7, $data['searchFilter']['getPrcateg'])
)
) {
$collections = $this->setIndexesForArticlesInCollections($collections);
}
$collections = array_values($collections);
if ($getCount) {
$fixfilter = $this->getCount($calculate, $realFilterProperty, $newFiltersOnlyNoChild);
if (!empty($fixfilter)) {
$res_enabledSize = $fixfilter;
} else {
$res_enabledSize = [];
}
$collections = [
'collections' => [],
'calculate' => $res_enabledSize,
];
}
if ($full) {
return [
'res' => $collections,
'codes' => $dataReview,
];
}
return $collections;
}
/**
* Подсчитывает Коллекции в свойстве
* @param array $calculate - Собраные значения
* @param array $realFilterProperty - фильтр связь ключей старые новые
* @return array - подсчет коллекций
* @throws Exception
*/
private function getCount(array $calculate, array $realFilterProperty = []): array
{
$oldId = 'id';
$res = [];
//перебераем массив с коллекциями не товарами
foreach ($calculate as $coll => $values) {
//перебираем их свойства
foreach ($values as $key => $value) {
//перебираем их значение
foreach (array_unique($value) as $v) {
//тут вся логика с фильтром
if (isset($realFilterProperty[$key][$v])) {
// $realFilterProperty[$key][$v]['count']++;
if (isset($res[$key][$realFilterProperty[$key][$v][$oldId]])) {
$res[$key][$realFilterProperty[$key][$v][$oldId]]++;
} else {
$res[$key][$realFilterProperty[$key][$v][$oldId]] = 1;
}
} else {
//если такого фильтра не существует нужно создать и присвоить его свойству первое вхождение
if (isset($res[$key][$v])) {
$res[$key][$v]++;
} else {
$res[$key][$v] = 1;
}
}
}
}
}
return $res;
}
/**
* @param $row
* @return array
* @throws Exception
*/
private function article($row): array
{
// сохраняем id артикула для выборки подробных данных артикулов подходящих под отбор
$this->articlesId[] = $row['a_id'];
return [
'a_id' => $row['a_id'],
'a_name' => $row['a_name'],
'file' => $row['process'] == 1 ? str_replace(['.jpeg', '.jpg'], '.webp', $row['file']) : $row['file'],
'a_x' => $row['fs_x'],
'a_y' => $row['fs_y'],
'b_g' => $row['border_grey'],
'alt' => str_replace(['\\', '"', '\''], '', join(', ', [$row['f_name'], $row['c_name'], $row['a_name']])),
];
}
/**
* @throws Exception
*/
private function mapMaterial(array $collectionMaterials = []): array
{
$listMaterialCollection = [];
foreach ($collectionMaterials as $materialId) {
if (!empty($this->getMaterials()[$materialId])) {
$listMaterialCollection[] = $this->getMaterials()[$materialId];
}
}
return $listMaterialCollection;
}
/**
* @return array
* @throws Exception
*/
private function getMaterials(): array
{
if (count($this->materials) == 0) {
$repoMaterialList = $this->listMaterialRepository;
$list = $repoMaterialList->getList(true);
/** @var ListMaterial $r */
foreach ($list as $r) {
$materials = App::trans('coll_preview_' . $r['alias']);
$position = strpos($materials, '_');
if ($position !== false) {
$materials = App::trans($r['alias']);
}
$this->materials[$r['id']] = $materials;
}
}
return $this->materials;
}
private function getPriceFields(string $currency, string $country, string $measure): array
{
if ($currency === 'EUR') {
switch ($country) {
case 'de':
return ['price_euro_de', 'price_mq_euro_de', 'pr_min_euro_de', 'a_price_cat_de', 'price_sort_de'];
case 'at':
return ['price_euro_at', 'price_mq_euro_at', 'pr_min_euro_at', 'a_price_cat_at', 'price_sort_at'];
case 'fi':
return ['price_euro_fi', 'price_mq_euro_fi', 'pr_min_euro_fi', 'a_price_cat_fi', 'price_sort_fi'];
case 'fr':
return ['price_euro_fr', 'price_mq_euro_fr', 'pr_min_euro_fr', 'a_price_cat_fr', 'price_sort_fr'];
case 'it':
return ['price_euro_it', 'price_mq_euro_it', 'pr_min_euro_it', 'a_price_cat_it', 'price_sort_it'];
case 'be':
return ['price_euro_be', 'price_mq_euro_be', 'pr_min_euro_be', 'a_price_cat_be', 'price_sort_be'];
case 'ie':
return ['price_euro_ie', 'price_mq_euro_ie', 'pr_min_euro_ie', 'a_price_cat_ie', 'price_sort_ie'];
case 'nl':
return ['price_euro_nl', 'price_mq_euro_nl', 'pr_min_euro_nl', 'a_price_cat_nl', 'price_sort_nl'];
case 'es':
return ['price_euro_es', 'price_mq_euro_es', 'pr_min_euro_es', 'a_price_cat_es', 'price_sort_es'];
case 'ru':
return ['price_rue', 'price_mq_rue', 'pr_min_rue', 'a_price_cat_rue', 'price_sort_rub'];
case 'gb':
return ['price_gbe', 'price_mq_gbe', 'pr_min_gbe', 'a_price_cat_gbe', 'price_sort_gbp'];
case 'ch':
return ['price_che', 'price_mq_che', 'pr_min_che', 'a_price_cat_che', 'price_sort_chf'];
case 'se':
return ['price_see', 'price_mq_see', 'pr_min_see', 'a_price_cat_see', 'price_sort_sek'];
case 'pl':
return ['price_ple', 'price_mq_ple', 'pr_min_ple', 'a_price_cat_ple', 'price_sort_pln'];
case 'us':
if ($measure === 'ft') {
return [
'price_fq_use',
'price_fq_use',
'pr_min_f_use',
'a_price_cat_fq_use',
'price_sort_fq_usd'
];
}
return ['price_use', 'price_mq_use', 'pr_min_use', 'a_price_cat_use', 'price_sort_usd'];
case 'ca':
if ($measure === 'ft') {
return ['price_cae', 'price_fq_cae', 'pr_min_cae', 'a_price_cat_fq_cae', 'price_sort_fq_cad'];
}
return ['price_cae', 'price_mq_cae', 'pr_min_cae', 'a_price_cat_cae', 'price_sort_cad'];
}
return ['price_euro', 'price_mq_euro', 'pr_min_euro', 'a_price_cat', 'price_sort'];
}
if ($country === 'ru' && $currency === 'RUB') {
return ['price_rub', 'price_mq_rub', 'pr_min_rub', 'a_price_cat_rub', 'price_sort_rub'];
}
if ($country === 'gb' && $currency === 'GBP') {
return ['price_gbp', 'price_mq_gbp', 'pr_min_gbp', 'a_price_cat_gbp', 'price_sort_gbp'];
}
if ($country === 'ch' && $currency === 'CHF') {
return ['price_chf', 'price_mq_chf', 'pr_min_chf', 'a_price_cat_chf', 'price_sort_chf'];
}
if ($country === 'se' && $currency === 'SEK') {
return ['price_sek', 'price_mq_sek', 'pr_min_sek', 'a_price_cat_sek', 'price_sort_sek'];
}
if ($country === 'dk' && $currency === 'DKK') {
return ['price_dkk', 'price_mq_dkk', 'pr_min_dkk', 'a_price_cat_dkk', 'price_sort_dkk'];
}
if ($country === 'no' && $currency === 'NOK') {
return ['price_nok', 'price_mq_nok', 'pr_min_nok', 'a_price_cat_nok', 'price_sort_nok'];
}
if ($country === 'pl' && $currency === 'PLN') {
return ['price_pln', 'price_mq_pln', 'pr_min_pln', 'a_price_cat_pln', 'price_sort_pln'];
}
if ($country === 'us' && $currency === 'USD') {
if ($measure === 'ft') {
return ['price_fq_usd', 'price_fq_usd', 'pr_min_f_usd', 'a_price_cat_fq_usd', 'price_sort_fq_usd'];
}
return ['price_usd', 'price_mq_usd', 'pr_min_usd', 'a_price_cat_usd', 'price_sort_usd'];
}
if ($country === 'ca' && $currency === 'CAD') {
if ($measure === 'ft') {
return ['price_cad', 'price_fq_cad', 'pr_min_cad', 'a_price_cat_fq_cad', 'price_sort_fq_cad'];
}
return ['price_cad', 'price_mq_cad', 'pr_min_cad', 'a_price_cat_cad', 'price_sort_cad'];
}
return ['price_euro', 'price_mq_euro', 'pr_min_euro', 'a_price_cat', 'price_sort'];
}
/**
* Ограничение на показ интерьеров
*
* @param array $searchFilter
* @param array $row
* @param array|null $oldTypeUsings
* @return bool
*/
private function getNoRestriction(array $searchFilter, array $row, ?array $oldTypeUsings): bool
{
$iTexture = array_filter(array_map('intval', explode(',', (string)($row['i_texture'] ?? ''))));
// В этой просьбе попросили исключить из ограничения фактуру по 17 кодом https://te.remote.team/#/discus/F4D2CA8B-BE66-7853-8FDC-2CFE011A151C/
$iTexture[] = 17;
// Если поиск по группе (например, 999) и интерьер содержит текстуру подгруппы,
// то считаем, что интерьер подходит и под группу.
if (!empty($searchFilter['getFacturas'])) {
$facturas = array_map('intval', (array)$searchFilter['getFacturas']);
if (in_array(999, $facturas, true)) {
$children = $this->subFilters['getFacturas'][999] ?? [];
if (!empty($children)) {
$children = array_map('intval', (array)$children);
if (count(array_intersect($iTexture, $children)) > 0) {
$iTexture[] = 999;
}
}
}
}
//внутри коллекции для интерьеров надо проверить, что привязаны заглавный артикулы
if (!empty($searchFilter['inside']) && empty($row['a_head'])) {
return true;
}
// ограничение на показ интерьера по признаку назначение
if (
!empty($oldTypeUsings)
&& (array_search(4, $oldTypeUsings)
&& !$row['i_wall_and_floor']
|| !in_array($row['i_type'], $oldTypeUsings)
)
) {
return false;
}
// ограничение на показ интерьера по признаку стиль
// внутри коллекции не используется это условие !!!!уже используется https://te2.remote.team/discus/C0B5DD6C-8487-9233-5238-08E2AF112A60?goto=true
// так же это ограничение не должно работать если стиль "ручная работа"
if (
isset($row['i_style'])
&& $row['i_style'] == 0
&& !empty($searchFilter['getStyles'])
&& !in_array(14, $searchFilter['getStyles'])
&& !in_array(14, [$row['a_style'], $row['styleida']])
) {
return false;
}
// если выбран фильтр монохром, но у интерьера нет монохромной фактуры - скрываем интерьер
if (
!empty($searchFilter['getColors'])
&& in_array(99, $searchFilter['getColors'])
&& !in_array(99, $iTexture)
) {
return false;
}
// ограничение на показ интерьеров при поиске по фактуре
if (
(
(empty($searchFilter['getTypes'])
|| !in_array($row['type'], $searchFilter['getTypes'])
)
&& (empty($searchFilter['getMaterials'])
|| !in_array(99, $searchFilter['getMaterials'])
|| $row['material'] != 99
)
)
&& empty($searchFilter['inside'])
) {
if (
!empty($searchFilter['getFacturas'])
&& count(array_intersect($iTexture, $searchFilter['getFacturas'])) == 0
) {
return true;
}
// ограничение подбора интерьеров по некоторым фильтрам
// исключаем случай, когда выбран фильтр монохром и у интерьера есть монохром https://te2.remote.team/discus/2C755E51-C93A-D6F6-21FE-641A6A4D1DF2
// if (
// !empty($searchFilter)
// && (!empty($searchFilter['getColors'])
// || !empty($searchFilter['getMaterials'])
// || !empty($searchFilter['getSurfaces'])
// )
// && empty($row['type_filter'])
// && !(
// !empty($searchFilter['getColors'])
// && in_array(99, $searchFilter['getColors'])
// && in_array(99, $iTexture)
// )
// ) {
// return false;
// }
return true;
}
if (empty($searchFilter['getFacturas'])) {
return true;
}
if (count(array_intersect($iTexture, $searchFilter['getFacturas'])) > 0) {
return true;
}
return false;
}
/**
* @param array $collections
* @return array
*/
private function setIndexesForArticlesInCollections(array $collections): array
{
$n = 0; // для простановки индексов артикулов
foreach ($collections as &$collection) {
unset($collection['interiors']);
if (!empty($collection['articles'])) {
foreach ($collection['articles'] as &$item) {
$item['num'] = $n;
$n++;
}
}
}
return $collections;
}
//нужно узнать не сортирует ли человек случайно чтобы отсортировать за него
/**
* @return int
* @throws Exception
*/
public function getSearchSortId()
{
$sort = App::getSession()->get('sort_catalog_tmp');
if ($sort == null) {
$sort = App::getRequest()->get('sort');
}
if ($sort == null) {
$sort = App::getRequest()->cookies->get('sort_catalog');
}
if ($sort == null) {
$sort = 0;
}
return $sort;
}
}