24 private array $propertyFilter;
32 $this->dictionary = $this->facet->getDictionary();
33 $this->storage = $this->facet->getStorage();
43 return $this->facet->isValid();
66 if (array_key_exists(
"FACET_OPTIONS",
$filter))
68 if (is_array(
$filter[
"FACET_OPTIONS"]))
70 $this->options =
$filter[
"FACET_OPTIONS"];
72 unset(
$filter[
"FACET_OPTIONS"]);
75 $this->distinct =
false;
82 || ($this->options && !isset(
$filter[
"SECTION_ID"]))
90 if (isset(
$filter[
"INCLUDE_SUBSECTIONS"]) &&
$filter[
"INCLUDE_SUBSECTIONS"] ===
"Y")
92 $subsectionsCondition =
"";
97 $subsectionsCondition =
"INCLUDE_SUBSECTIONS=1";
98 if (array_key_exists(
"INCLUDE_SUBSECTIONS",
$filter))
102 $hasAdditionalFilters =
false;
103 $this->fillWhere($where, $hasAdditionalFilters, $toUnset,
$filter);
111 "VALUES" =>
array(0),
117 &&
$filter[
"=ID"]->arFilter[
"IBLOCK_ID"] == $this->facet->getSkuIblockId()
118 &&
$filter[
"=ID"]->strField ===
"PROPERTY_".$this->facet->getSkuPropertyId()
121 $hasAdditionalFilters =
false;
122 $this->fillWhere($where, $hasAdditionalFilters, $toUnset,
$filter[
"=ID"]->arFilter);
123 if (!$hasAdditionalFilters)
132 $this->facet->setSectionId(
$filter[
"SECTION_ID"]);
135 if (isset($this->options[
"CURRENCY_CONVERSION"]) && $this->options[
"CURRENCY_CONVERSION"])
137 $this->facet->enableCurrencyConversion(
138 $this->options[
"CURRENCY_CONVERSION"][
"TO"] ??
'',
139 $this->options[
"CURRENCY_CONVERSION"][
"FROM"] ??
''
144 if (
count($where) == 1 && $distinctSelectCapable)
146 $this->distinct =
true;
147 $fcJoin =
"INNER JOIN ".$this->storage->getTableName().
" FC on FC.ELEMENT_ID = BE.ID";
148 foreach ($where as $facetFilter)
150 $sqlWhere = $this->facet->whereToSql($facetFilter,
"FC", $subsectionsCondition);
152 $sqlSearch[] = $sqlWhere;
160 foreach ($where as $facetFilter)
163 $subJoin .=
"FROM ".$this->storage->getTableName().
" FC$i\n";
165 $subJoin .=
"INNER JOIN ".$this->storage->getTableName().
" FC$i ON FC$i.ELEMENT_ID = FC0.ELEMENT_ID\n";
167 $sqlWhere = $this->facet->whereToSql($facetFilter,
"FC$i", $subsectionsCondition);
171 $subWhere .=
"\nAND ".$sqlWhere;
173 $subWhere .= $sqlWhere;
181 SELECT ".($distinctSelectCapable?
"DISTINCT":
"").
" FC0.ELEMENT_ID
185 ) FC on FC.ELEMENT_ID = BE.ID
190 $condition =
array();
191 foreach ($where as $facetFilter)
193 $sqlWhere = $this->facet->whereToSql($facetFilter,
"FC0", $subsectionsCondition);
195 $condition[] = $sqlWhere;
199 SELECT FC0.ELEMENT_ID
200 FROM ".$this->storage->getTableName().
" FC0
201 WHERE FC0.SECTION_ID = ".
$filter[
"SECTION_ID"].
"
203 (".implode(
")OR(", $condition).
")
205 GROUP BY FC0.ELEMENT_ID
206 HAVING count(DISTINCT FC0.FACET_ID) = ".
count($condition).
"
207 ) FC on FC.ELEMENT_ID = BE.ID
211 foreach ($toUnset as $command)
213 unset($command[0][$command[1]]);
234 private function fillWhere(&$where, &$hasAdditionalFilters, &$toUnset, &
$filter)
236 $countUnset =
count($toUnset);
238 $propertyCodeMap =
null;
240 $usePriceFilter = isset($this->options[
'PRICE_FILTER']) && $this->options[
'PRICE_FILTER'];
242 foreach (
$filter as $filterKey => $filterValue)
244 if (preg_match(
"/^(=)PROPERTY\$/i", $filterKey, $keyDetails) && is_array($filterValue))
246 if ($properties ===
null)
247 $properties = $this->getFilterProperty();
248 if ($propertyCodeMap ===
null)
250 $propertyCodeMap = $this->getPropertyCodeMap();
253 foreach ($filterValue as $propertyId => $value)
255 $propertyId = $propertyCodeMap[$propertyId] ??
null;
258 || !isset($properties[$propertyId])
263 $facetId = $this->storage->propertyIdToFacetId($propertyId);
270 "TYPE" => $properties[$propertyId],
271 "OP" => $keyDetails[1],
272 "FACET_ID" => $facetId,
273 "VALUES" => $sqlValues,
280 elseif (preg_match(
"/^(=)PROPERTY_(\\d+)\$/i", $filterKey, $keyDetails))
282 if ($properties ===
null)
283 $properties = $this->getFilterProperty();
284 if ($propertyCodeMap ===
null)
286 $propertyCodeMap = $this->getPropertyCodeMap();
289 $propertyId = $propertyCodeMap[$keyDetails[2]] ??
null;
292 || !isset($properties[$propertyId])
298 $facetId = $this->storage->propertyIdToFacetId($propertyId);
305 "TYPE" => $properties[$propertyId],
306 "OP" => $keyDetails[1],
307 "FACET_ID" => $facetId,
308 "VALUES" => $sqlValues,
314 elseif (preg_match(
"/^(>=|<=)PROPERTY\$/i", $filterKey, $keyDetails) && is_array($filterValue))
316 if ($properties ===
null)
317 $properties = $this->getFilterProperty();
318 if ($propertyCodeMap ===
null)
320 $propertyCodeMap = $this->getPropertyCodeMap();
323 foreach ($filterValue as $propertyId => $value)
325 $propertyId = $propertyCodeMap[$propertyId] ??
null;
328 || !isset($properties[$propertyId])
333 $facetId = $this->storage->propertyIdToFacetId($propertyId);
336 if (is_array($value))
337 $doubleValue = doubleval(current($value));
339 $doubleValue = doubleval($value);
342 "OP" => $keyDetails[1],
343 "FACET_ID" => $facetId,
344 "VALUES" =>
array($doubleValue),
350 if (is_array($value))
351 $timestamp =
MakeTimeStamp(current($value),
"YYYY-MM-DD HH:MI:SS");
356 "OP" => $keyDetails[1],
357 "FACET_ID" => $facetId,
358 "VALUES" =>
array($timestamp),
364 elseif (preg_match(
"/^(><)PROPERTY\$/i", $filterKey, $keyDetails) && is_array($filterValue))
366 if ($properties ===
null)
367 $properties = $this->getFilterProperty();
368 if ($propertyCodeMap ===
null)
370 $propertyCodeMap = $this->getPropertyCodeMap();
373 foreach ($filterValue as $propertyId => $value)
375 $propertyId = $propertyCodeMap[$propertyId] ??
null;
378 || !isset($properties[$propertyId])
383 $facetId = $this->storage->propertyIdToFacetId($propertyId);
386 if (is_array($value) &&
count($value) == 2)
388 $doubleMinValue = doubleval(current($value));
389 $doubleMaxValue = doubleval(end($value));
392 "OP" => $keyDetails[1],
393 "FACET_ID" => $facetId,
394 "VALUES" =>
array($doubleMinValue, $doubleMaxValue),
401 if (is_array($value) &&
count($value) == 2)
403 $timestamp1 =
MakeTimeStamp(current($value),
"YYYY-MM-DD HH:MI:SS");
404 $timestamp2 =
MakeTimeStamp(end($value),
"YYYY-MM-DD HH:MI:SS");
407 "OP" => $keyDetails[1],
408 "FACET_ID" => $facetId,
409 "VALUES" =>
array($timestamp1, $timestamp2),
418 && preg_match(
"/^(>=|<=)(?:CATALOG_|)PRICE_(\\d+)\$/i", $filterKey, $keyDetails)
419 && !is_array($filterValue)
422 $priceId = $keyDetails[2];
424 $facetId = $this->storage->priceIdToFacetId($priceId);
425 $doubleValue = doubleval($value);
428 "OP" => $keyDetails[1],
429 "FACET_ID" => $facetId,
430 "VALUES" =>
array($doubleValue),
436 && preg_match(
"/^(><)(?:CATALOG_|)PRICE_(\\d+)\$/i", $filterKey, $keyDetails)
437 && is_array($filterValue)
440 $priceId = $keyDetails[2];
442 $facetId = $this->storage->priceIdToFacetId($priceId);
443 $doubleValueMin = doubleval($value[0]);
444 $doubleValueMax = doubleval($value[1]);
447 "OP" => $keyDetails[1],
448 "FACET_ID" => $facetId,
449 "VALUES" =>
array($doubleValueMin, $doubleValueMax),
455 && is_numeric($filterKey)
456 && is_array($filterValue) &&
count($filterValue) === 3
457 && isset($filterValue[
"LOGIC"]) && $filterValue[
"LOGIC"] ===
"OR"
458 && isset($filterValue[
"=ID"]) && is_object($filterValue[
"=ID"])
459 && preg_match(
"/^(>=|<=)(?:CATALOG_|)PRICE_(\\d+)\$/i", key($filterValue[0][0]), $keyDetails)
460 && !is_array(current($filterValue[0][0]))
463 $priceId = $keyDetails[2];
464 $value = current($filterValue[0][0]);
465 $facetId = $this->storage->priceIdToFacetId($priceId);
466 $doubleValue = doubleval($value);
469 "OP" => $keyDetails[1],
470 "FACET_ID" => $facetId,
471 "VALUES" =>
array($doubleValue),
474 $toUnset[] =
array(&
$filter,
"CATALOG_SHOP_QUANTITY_".$priceId);
478 && is_numeric($filterKey)
479 && is_array($filterValue) &&
count($filterValue) === 3
480 && isset($filterValue[
"LOGIC"]) && $filterValue[
"LOGIC"] ===
"OR"
481 && isset($filterValue[
"=ID"]) && is_object($filterValue[
"=ID"])
482 && preg_match(
"/^(><)(?:CATALOG_|)PRICE_(\\d+)\$/i", key($filterValue[0][0]), $keyDetails)
483 && is_array(current($filterValue[0][0]))
486 $priceId = $keyDetails[2];
487 $value = current($filterValue[0][0]);
488 $facetId = $this->storage->priceIdToFacetId($priceId);
489 $doubleValueMin = doubleval($value[0]);
490 $doubleValueMax = doubleval($value[1]);
493 "OP" => $keyDetails[1],
494 "FACET_ID" => $facetId,
495 "VALUES" =>
array($doubleValueMin, $doubleValueMax),
498 $toUnset[] =
array(&
$filter,
"CATALOG_SHOP_QUANTITY_".$priceId);
501 $filterKey !==
"IBLOCK_ID"
502 && $filterKey !==
"ACTIVE"
503 && $filterKey !==
"ACTIVE_DATE"
506 $hasAdditionalFilters =
true;
509 if ($hasAdditionalFilters)
511 while (
count($toUnset) > $countUnset)
530 if (is_array($value))
532 foreach ($value as
$val)
538 $result[] = $this->dictionary->getStringId(
$val,
false);
547 elseif ((
string)$value <>
'')
551 $result[] = $this->dictionary->getStringId($value,
false);
569 private function getFilterProperty():
array
572 if (!isset($this->propertyFilter))
574 $this->propertyFilter = [];
575 $propertyList = \Bitrix\Iblock\SectionPropertyTable::getList([
578 'PROPERTY_TYPE' =>
'PROPERTY.PROPERTY_TYPE',
579 'USER_TYPE' =>
'PROPERTY.USER_TYPE',
583 $this->facet->getIblockId(),
584 $this->facet->getSkuIblockId(),
586 '=SMART_FILTER' =>
'Y',
589 while ($link = $propertyList->fetch())
610 return $this->propertyFilter;
613 private function getPropertyCodeMap():
array
617 $iterator = \Bitrix\Iblock\PropertyTable::getList([
623 '=IBLOCK_ID' => $this->facet->getIblockId(),
628 $id = (int)$row[
'ID'];
630 $row[
'CODE'] = (string)$row[
'CODE'];
631 if ($row[
'CODE'] !==
'')
638 $skuIblockId = $this->facet->getSkuIblockId();
639 if ($skuIblockId > 0)
641 $iterator = \Bitrix\Iblock\PropertyTable::getList([
646 '=IBLOCK_ID' => $skuIblockId,
651 $id = (int)$row[
'ID'];