This commit is contained in:
Bellord
2026-07-07 19:10:50 +03:00
parent 19eaeb4f4e
commit 01d61b89fe
10 changed files with 837 additions and 0 deletions
+148
View File
@@ -0,0 +1,148 @@
<?php
namespace Ixrs\Catalog\Support;
class ElementList
{
public static function getGlobalFilter($iBlockId, $globalFilter)
{
$pFilter = [];
$af = app()->factory()->iBlock()->getEntityById($iBlockId);
$iBlockFactory = app()->factory()->main()->getIBlockFactory();
$iBlockEntity = $iBlockFactory->getEntityById($iBlockId);
$propertyFactory = $af->getPropertyFactory();
if($iBlockEntity->getCatalogEntity()->hasOffers()){
$offerAf = app()->factory()->iBlock()->getEntityById($iBlockEntity->getCatalogEntity()->getOfferBlockId());
$offerPropertyFactory = $offerAf->getPropertyFactory();
foreach ($globalFilter as $key => $values){
$res = \Ixrs\Catalog\Support\IBlock::getOperationFilter($key);
// $res = \CIBlock::MkOperationFilter($key);
if(!$res) {
continue;
}
$propertyId = $res['ID'];
$propertyEntity = $propertyFactory->getEntityById($propertyId);
if(!$propertyEntity){
continue;
}
$offerPropertyEntity = $offerPropertyFactory->getCollection([
'=CODE' => $propertyEntity->getCode(),
'=XML_ID' => $propertyEntity->getXmlId(),
'=PROPERTY_TYPE' => $propertyEntity->getBaseType(),
'=USER_TYPE' => $propertyEntity->getUserType(),
'=ACTIVE' => 'Y',
])->first();
if(!$offerPropertyEntity){
continue;
}
/**
* @var array $values
*/
$oKey = $res['PREFIX'] . 'PROPERTY_' . $offerPropertyEntity->getId();
$values = (array)$values;
$pFilter[$propertyId]['E'] = [];
$pFilter[$propertyId]['O'] = [];
foreach ($values as $value){
$oValue = $value;
if($propertyEntity->getBaseType() === 'L' && $propertyEntity->getValueFactory()){
$pve = $propertyEntity->getValueFactory()->getEntityById($oValue);
$x = $pve->get('XML_ID');
if($x){
$opve = $offerPropertyEntity->getValueFactory()->getCollection(['XML_ID' => $x])->first();
$oValue = $opve?->getId();
}
else {
$oValue = null;
}
}
if($oValue){
if(isset($globalFilter[$key])){
$globalFilter[$key] = collect($globalFilter[$key])->deleteValues([$value])->toArray();
}
$pFilter[$propertyId]['E'][$key][] = $value;
$pFilter[$propertyId]['O'][$oKey][] = $oValue;
if(isset($globalFilter['OFFERS'][$oKey])){
$globalFilter['OFFERS'][$oKey] =
collect($globalFilter['OFFERS'][$oKey])->deleteValues([$oValue])->toArray();
}
}
}
if($pFilter[$propertyId]['E'][$key] || $pFilter[$propertyId]['O'][$oKey]){
if($globalFilter[$key]){
$pFilter[$propertyId]['E'][$key] = array_merge($pFilter[$propertyId]['E'][$key], $globalFilter[$key]);
unset($globalFilter[$key]);
}
if($globalFilter['OFFERS'][$oKey]){
$pFilter[$propertyId]['O'][$oKey] = array_merge($pFilter[$propertyId]['O'][$oKey], $globalFilter['OFFERS'][$oKey]);
unset($globalFilter['OFFERS'][$oKey]);
}
}
if(!$globalFilter[$key]){
unset($globalFilter[$key]);
}
if(!$globalFilter['OFFERS'][$oKey]){
unset($globalFilter['OFFERS'][$oKey]);
}
}
}
/** inject */
$oFilter = [];
if($pFilter){
foreach ($pFilter as $ePId => $item) {
$data = [];
foreach ($item['E'] as $fKey => $values) {
foreach ($values as $value){
$data[] = [$fKey => $value];
}
}
foreach ($item['O'] as $fKey => $values) {
$oFilter[$fKey] = $values;
foreach ($values as $value){
$data[] = ['=ID' => \CIBlockElement::SubQuery(
'PROPERTY_'.$iBlockEntity->getCatalogEntity()->getSkuPropertyId(),
array_merge([
'IBLOCK_ID' => $iBlockEntity->getCatalogEntity()->getOfferBlockId(),
'ACTIVE_DATE' => 'Y',
'ACTIVE' => 'Y',
], [$fKey => $value])
)];
}
}
if($data){
$globalFilter[] = array_merge([
'LOGIC' => 'OR',
], $data);
}
}
//if(!is_array($this->storage['SUB_FILTER'])){
// $this->storage['SUB_FILTER'] = [];
//}
//foreach ($oFilter as $fKey => $values) {
// if(isset($this->storage['SUB_FILTER'][$fKey])){
// $this->storage['SUB_FILTER'][$fKey] =
// collect((array)$this->storage['SUB_FILTER'][$fKey])->merge($values)->unique()->toArray();
// }
// else {
// $this->storage['SUB_FILTER'][$fKey] = $values;
// }
//}
}
return $globalFilter;
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace Ixrs\Catalog\Support;
class IBlock
{
static array $operations = [
'!><' => 'NB', //not between
'!=' => 'NI', //not Identical
'!%' => 'NS', //not substring
'><' => 'B', //between
'>=' => 'GE', //greater or equal
'<=' => 'LE', //less or equal
'=' => 'I', //Identical
'%' => 'S', //substring
'?' => '?', //logical
'>' => 'G', //greater
'<' => 'L', //less
'!' => 'N', // not field LIKE val
'*' => 'FT', // partial full text match
'*=' => 'FTI', // identical full text match
'*%' => 'FTL', // partial full text match based on LIKE
];
public static function getOperationFilter($key)
{
$re = '/^(!><|!=|!%|><|>=|<=|=|%|\?|>|<|!|\*|\*=|\*%)?(PROPERTY_)(\d+)$/m';
$matches = [];
$r = preg_match($re, $key, $matches);
if($r){
return [
'FIELD' => mb_strtoupper($matches[2] . $matches[3]),
'OPERATION' => static::$operations[$matches[1]]??'',
'PREFIX' => $matches[1],
'ID' => $matches[3],
];
}
return [];
}
}
+385
View File
@@ -0,0 +1,385 @@
<?php
namespace Ixrs\Catalog\Support;
class SmartFilter
{
public static function getPreparedCombo($iBlockId, $combo)
{
//pre('getPreparedCombo');
$result = [];
$af = app()->factory()->iBlock()->getEntityById($iBlockId);
$iBlockFactory = app()->factory()->main()->getIBlockFactory();
$iBlockEntity = $iBlockFactory->getEntityById($iBlockId);
if(!$iBlockEntity->getCatalogEntity()->hasOffers()) {
return $combo;
}
$propertyFactory = $af->getPropertyFactory();
$offerAf = app()->factory()->iBlock()->getEntityById($iBlockEntity->getCatalogEntity()->getOfferBlockId());
$offerPropertyFactory = $offerAf->getPropertyFactory();
foreach ($combo as $i => $combination){
$result[] = $combination;
foreach ($combination as $propertyId => $value){
$propertyEntity = $propertyFactory->getEntityById($propertyId);
if(!$propertyEntity){
continue;
}
// $offerPropertyEntity = $offerPropertyFactory->getCollection([
// '=CODE' => $propertyEntity->getCode(),
// '=XML_ID' => $propertyEntity->getXmlId(),
// '=PROPERTY_TYPE' => $propertyEntity->getBaseType(),
// '=USER_TYPE' => $propertyEntity->getUserType(),
// '=ACTIVE' => 'Y',
// ])->first();
$offerPropertyEntity = $offerPropertyFactory->getEntityByCode($propertyEntity->getCode());
if(!$offerPropertyEntity){
continue;
}
if(!isset($combination[$offerPropertyEntity->getId()])){
continue;
}
if($combination[$offerPropertyEntity->getId()] === false){
continue;
}
$v = $combo[$i][$offerPropertyEntity->getId()];
unset($combo[$i][$offerPropertyEntity->getId()]);
$c = $combo[$i];
$c[$propertyId] = $v;
$result[] = $c;
}
}
return $result;
}
public static function getPreparedItems($iBlockId, $items, $filterName, $deleteOffersProps = true)
{
//pre('getPreparedItems ' . ($deleteOffersProps?'true':'false'));
$af = app()->factory()->iBlock()->getEntityById($iBlockId);
$iBlockFactory = app()->factory()->main()->getIBlockFactory();
$iBlockEntity = $iBlockFactory->getEntityById($iBlockId);
$propertyFactory = $af->getPropertyFactory();
if(!$iBlockEntity->getCatalogEntity()->hasOffers()) {
return $items;
}
$offerAf = app()->factory()->iBlock()->getEntityById($iBlockEntity->getCatalogEntity()->getOfferBlockId());
$offerPropertyFactory = $offerAf->getPropertyFactory();
foreach ($items as $propertyId => $property){
$propertyEntity = $propertyFactory->getEntityById($propertyId);
if(!$propertyEntity){
continue;
}
$offerPropertyEntity = $offerPropertyFactory->getEntityByCode($propertyEntity->getCode());
if(!$offerPropertyEntity){
continue;
}
if(!isset($items[$offerPropertyEntity->getId()])){
continue;
}
$oValues = $items[$offerPropertyEntity->getId()]['VALUES'];
$oValuesReserve = $oValues;
foreach ($oValuesReserve as &$oValue){
$oValue['IBLOCK_ID'] = $offerAf->getBlockId();
$oValue['PROPERTY_ID'] = $offerPropertyEntity->getId();
}
unset($oValue);
foreach ($oValues as $propertyValueId => $propertyValue){
$key = null;
foreach ($items[$propertyId]['VALUES'] as $propertyValueId2 => $propertyValueValue){
if($propertyValue['VALUE'] === $propertyValueValue['VALUE']){
$key = $propertyValueId2;
break;
}
}
if(is_null($key)){
continue;
}
unset($oValuesReserve[$propertyValueId]);
if($deleteOffersProps){
unset($items[$offerPropertyEntity->getId()]['VALUES'][$propertyValueId]);
if(!$items[$offerPropertyEntity->getId()]['VALUES']){
unset($items[$offerPropertyEntity->getId()]);
}
}
$items[$propertyId]['VALUES'][$key]['DISABLED'] ??= false;
$propertyValue['DISABLED'] ??= false;
$items[$propertyId]['VALUES'][$key]['DISABLED'] =
$items[$propertyId]['VALUES'][$key]['DISABLED'] && $propertyValue['DISABLED'];
$items[$propertyId]['VALUES'][$key]['CHECKED'] ??= false;
$propertyValue['CHECKED'] ??= false;
$items[$propertyId]['VALUES'][$key]['CHECKED'] =
$items[$propertyId]['VALUES'][$key]['CHECKED'] || $propertyValue['CHECKED'];
//if($items[$propertyId]['VALUES'][$key]['CONTROL_ID'] !== $propertyValue['CONTROL_ID']) {
// $items[$propertyId]['VALUES'][$key]['ELEMENT_COUNT'] += $propertyValue['ELEMENT_COUNT'];
//}
}
//foreach ($items[$propertyId]['VALUES'] as $propertyValueId => &$propertyValue){
// $propertyValue['CONTROL_NAME_ALT'] = $filterName . '_' . $propertyEntity->getId();
// $propertyValue['CONTROL_NAME'] = $propertyValue['CONTROL_NAME_ALT'] . '_' . $propertyValue['HTML_VALUE_ALT'];
// $propertyValue['CONTROL_ID'] = $propertyValue['CONTROL_NAME_ALT'] . '_' . $propertyValue['HTML_VALUE_ALT'];
//}
//unset($propertyValue);
if($deleteOffersProps) {
unset($items[$offerPropertyEntity->getId()]);
$items[$propertyId]['VALUES'] = $items[$propertyId]['VALUES'] + $oValuesReserve;
}
}
return $items;
}
public static function getPreparedFacetIndex($iBlockId, $items, $filterName, $deleteOffersProps = true)
{
//pre('getPreparedFacetIndex');
$af = app()->factory()->iBlock()->getEntityById($iBlockId);
$iBlockFactory = app()->factory()->main()->getIBlockFactory();
$iBlockEntity = $iBlockFactory->getEntityById($iBlockId);
$propertyFactory = $af->getPropertyFactory();
if(!$iBlockEntity->getCatalogEntity()->hasOffers()) {
return $items;
}
$offerAf = app()->factory()->iBlock()->getEntityById($iBlockEntity->getCatalogEntity()->getOfferBlockId());
$offerPropertyFactory = $offerAf->getPropertyFactory();
foreach ($items as $propertyId => $values){
$propertyEntity = $propertyFactory->getEntityById($propertyId);
if(!$propertyEntity){
continue;
}
$offerPropertyEntity = $offerPropertyFactory->getEntityByCode($propertyEntity->getCode());
if(!$offerPropertyEntity){
continue;
}
if(!isset($items[$offerPropertyEntity->getId()])){
continue;
}
$oValues = $items[$offerPropertyEntity->getId()];
$oValuesReserve = $oValues;
foreach ($oValues as $facetId => $propertyValue){
$key = null;
foreach ($items[$propertyId] as $facetId2 => $propertyValueValue){
if($propertyValue['VALUE'] === $propertyValueValue['VALUE']){
$key = $facetId2;
break;
}
}
if(is_null($key)){
continue;
}
unset($oValuesReserve[$facetId]);
if($deleteOffersProps){
unset($items[$offerPropertyEntity->getId()][$facetId]);
if(!$items[$offerPropertyEntity->getId()]){
unset($items[$offerPropertyEntity->getId()]);
}
}
$items[$propertyId][$key]['DISABLED'] ??= false;
$propertyValue['DISABLED'] ??= false;
$items[$propertyId][$key]['DISABLED'] =
$items[$propertyId][$key]['DISABLED'] && $propertyValue['DISABLED'];
$items[$propertyId][$key]['CHECKED'] ??= false;
$propertyValue['CHECKED'] ??= false;
$items[$propertyId][$key]['CHECKED'] =
$items[$propertyId][$key]['CHECKED'] || $propertyValue['CHECKED'];
if($items[$propertyId][$key]['CONTROL_ID'] !== $propertyValue['CONTROL_ID']) {
$items[$propertyId][$key]['ELEMENT_COUNT'] += $propertyValue['ELEMENT_COUNT'];
}
}
//foreach ($items[$propertyId] as $facetId => &$propertyValue){
// $propertyValue['CONTROL_NAME_ALT'] = $filterName . '_' . $propertyEntity->getId();
// $propertyValue['CONTROL_NAME'] = $propertyValue['CONTROL_NAME_ALT'] . '_' . $propertyValue['HTML_VALUE_ALT'];
// $propertyValue['CONTROL_ID'] = $propertyValue['CONTROL_NAME_ALT'] . '_' . $propertyValue['HTML_VALUE_ALT'];
//}
//unset($propertyValue);
//if($deleteOffersProps) {
//$items[$propertyId] = $items[$propertyId] + $oValuesReserve;
//}
}
return $items;
}
/**
* property id to offer property id
*
* @param $iBlockId
* @param $propertyId
* @return int|string|null
*/
public static function getOfferPropertyId($iBlockId, $propertyId)
{
$af = app()->factory()->iBlock()->getEntityById($iBlockId);
$iBlockFactory = app()->factory()->main()->getIBlockFactory();
$iBlockEntity = $iBlockFactory->getEntityById($iBlockId);
$propertyFactory = $af->getPropertyFactory();
if(!$iBlockEntity->getCatalogEntity()->hasOffers()) {
return null;
}
$propertyEntity = $propertyFactory->getEntityById($propertyId);
if(!$propertyEntity){
return null;
}
$offerAf = app()->factory()->iBlock()->getEntityById($iBlockEntity->getCatalogEntity()->getOfferBlockId());
$offerPropertyFactory = $offerAf->getPropertyFactory();
$offerPropertyEntity = $offerPropertyFactory->getEntityByCode($propertyEntity->getCode());
return $offerPropertyEntity?->getId();
}
/**
* @param $iBlockId
* @param $propertyId
* @param int|string $propertyValueIndex модет быть id или xmlId
* @return void|null
*/
public static function getOfferPropertyValueIndex($iBlockId, $propertyId, $propertyValueIndex)
{
$af = app()->factory()->iBlock()->getEntityById($iBlockId);
$iBlockFactory = app()->factory()->main()->getIBlockFactory();
$iBlockEntity = $iBlockFactory->getEntityById($iBlockId);
$propertyFactory = $af->getPropertyFactory();
$propertyEntity =$propertyFactory->getEntityById($propertyId);
if($iBlockEntity->getCatalogEntity()->hasOffers()) {
$offerAf = app()->factory()->iBlock()->getEntityById($iBlockEntity->getCatalogEntity()->getOfferBlockId());
$offerPropertyFactory = $offerAf->getPropertyFactory();
$offerPropertyEntity = $offerPropertyFactory->getEntityByCode($propertyEntity->getCode());
if (!$offerPropertyEntity) {
return null;
}
if($propertyEntity->getBaseType() === 'L' && $propertyEntity->getValueFactory()){
$pve = $propertyEntity->getValueFactory()->getEntityById($propertyValueIndex);
$xmlId = $pve?->getXmlId();
if($xmlId){
$opve = $offerPropertyEntity->getValueFactory()->getEntityByXmlId($xmlId);
return $opve?->getId();
}
return null;
}
return $propertyValueIndex;
}
}
/**
* @param $iBlockId
* @param $propertyId
* @param int|string $propertyValueIndex модет быть id или xmlId
* @return void|null
*/
public static function getPropertyValueIndex($iBlockId, $oPropertyId, $oPropertyValueIndex)
{
$af = app()->factory()->iBlock()->getEntityById($iBlockId);
$iBlockFactory = app()->factory()->main()->getIBlockFactory();
$iBlockEntity = $iBlockFactory->getEntityById($iBlockId);
$propertyFactory = $af->getPropertyFactory();
if(!$iBlockEntity->getCatalogEntity()->hasOffers()) {
return null;
}
$offerAf = app()->factory()->iBlock()->getEntityById($iBlockEntity->getCatalogEntity()->getOfferBlockId());
$offerPropertyFactory = $offerAf->getPropertyFactory();
$offerPropertyEntity = $offerPropertyFactory->getEntityById($oPropertyId);
if(!$offerPropertyEntity){
return null;
}
//pre("{$offerPropertyEntity->getId()} {$offerPropertyEntity->getCode()} {$oPropertyValueIndex}");
$propertyEntity = $propertyFactory->getEntityByCode($offerPropertyEntity->getCode());
if (!$propertyEntity) {
return null;
}
if($offerPropertyEntity->getBaseType() === 'L' && $offerPropertyEntity->getValueFactory()){
$pve = $offerPropertyEntity->getValueFactory()->getEntityById($oPropertyValueIndex);
$xmlId = $pve?->getXmlId();
if($xmlId){
$opve = $propertyEntity->getValueFactory()->getEntityByXmlId($xmlId);
return $opve?->getId();
}
return null;
}
return $oPropertyValueIndex;
}
/**
* offer property id to property id
*
* @param $iBlockId
* @param $offerPropertyId
* @return int|string|null
*/
public static function getPropertyId($iBlockId, $offerPropertyId)
{
$af = app()->factory()->iBlock()->getEntityById($iBlockId);
$iBlockFactory = app()->factory()->main()->getIBlockFactory();
$iBlockEntity = $iBlockFactory->getEntityById($iBlockId);
$propertyFactory = $af->getPropertyFactory();
if(!$iBlockEntity->getCatalogEntity()->hasOffers()) {
return null;
}
$offerAf = app()->factory()->iBlock()->getEntityById($iBlockEntity->getCatalogEntity()->getOfferBlockId());
$offerPropertyFactory = $offerAf->getPropertyFactory();
$offerPropertyEntity = $offerPropertyFactory->getEntityById($offerPropertyId);
if(!$offerPropertyEntity){
return null;
}
$propertyEntity = $propertyFactory->getEntityByCode($offerPropertyEntity->getCode());
return $propertyEntity?->getId();
}
}
+58
View File
@@ -0,0 +1,58 @@
<?php
return [
0 =>
[
876 => 'Акция',
877 => 'SHIKstudio',
878 => false,
1247 => 'Россия',
1250 => false,
906 => false,
1251 => false,
1252 => false,
1255 => false,
1256 => false,
1257 => false,
1258 => false,
1259 => false,
1260 => false,
1261 => false,
1262 => false,
1263 => false,
1264 => false,
1265 => false,
1266 => false,
1267 => false,
1269 => false,
1489 => false,
1 => false,
],
1 =>
[
876 => 'Акция',
877 => 'SHIKstudio',
878 => 'Y',
1247 => 'Россия',
1250 => false,
906 => false,
1251 => false,
1252 => false,
1255 => false,
1256 => false,
1257 => false,
1258 => false,
1259 => false,
1260 => false,
1261 => false,
1262 => false,
1263 => false,
1264 => false,
1265 => false,
1266 => false,
1267 => false,
1269 => false,
1489 => false,
1 => false,
],
// ...
];
+38
View File
@@ -0,0 +1,38 @@
<?php
return [
876 => // property id
[
394 => // FACET_VALUE
[
'CONTROL_ID' => 'MAX_SMART_FILTER_876_4133288916',
'CONTROL_NAME' => 'MAX_SMART_FILTER_876_4133288916',
'CONTROL_NAME_ALT' => 'MAX_SMART_FILTER_876',
'HTML_VALUE_ALT' => 4133288916,
'HTML_VALUE' => 'Y',
'VALUE' => 'Новинка',
'SORT' => 300,
'UPPER' => 'НОВИНКА',
'FLAG' => true,
'URL_ID' => 'new',
'FACET_VALUE' => '394',
'ELEMENT_COUNT' => '207',
],
395 =>
[
'CONTROL_ID' => 'MAX_SMART_FILTER_876_2170276674',
'CONTROL_NAME' => 'MAX_SMART_FILTER_876_2170276674',
'CONTROL_NAME_ALT' => 'MAX_SMART_FILTER_876',
'HTML_VALUE_ALT' => 2170276674,
'HTML_VALUE' => 'Y',
'VALUE' => 'Акция',
'SORT' => 400,
'UPPER' => 'АКЦИЯ',
'FLAG' => true,
'URL_ID' => 'stock',
'FACET_VALUE' => '395',
'ELEMENT_COUNT' => '56',
],
],
// 877 => ...
];