Current Path : /var/www/u0635749/data/www/hobbyclick.ru/public/local/components/aip/filter/ |
Current File : /var/www/u0635749/data/www/hobbyclick.ru/public/local/components/aip/filter/class.php |
<?php if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); CModule::IncludeModule('iblock'); CModule::IncludeModule("catalog"); CModule::IncludeModule('highloadblock'); use Bitrix\Main\Engine\ActionFilter; use Bitrix\Main\Engine\Contract\Controllerable; CJSCore::Init(array("fx", "ajax")); class AipFilter extends CBitrixComponent implements Controllerable{ public $ajax=false; public $aItemsAll=array();//все варианты текущей категории public $aFilterValues=array();//варианты для html public $aFilterVals=array();//по этим фильтруем public $aUrl=false;//если здесь нет, берем текущий урл public $aUrlParams=[//откуда берем значения в aItemsAll 'rayon'=>['OFFERS', 'HALL', 'PROPERTY_AREA_CITY_VALUE'],//эти фильтруем в массиве 'metro'=>['OFFERS', 'HALL', 'PROPERTY_METRO_VALUE'],//эти фильтруем в массиве 'level'=>['OFFER', 'PROPERTY_LEVEL_VALUE'],//все остальные в бд 'sex'=>['OFFER', 'PROPERTY_SEX_VALUE'], 'motiv'=>'PROPERTY_FILTER_MOTIV', 'proishozhd'=>'PROPERTY_FILTER_REGION', 'nagruzka'=>'PROPERTY_FILTER_STRESS', 'vozrast'=>[], 'times'=>['DATE_1', 'DATE_2', 'DATE_3', 'DATE_4', 'DATE_5', 'DATE_6', 'DATE_0']//эти фильтруем в массиве ]; public function refrashAction($data=array()){//ajax - формируем урл фильтра $this->ajax=true; $this->arParams=json_decode($data['param'], true); $this->aUrl=array('-'); foreach($this->aUrlParams as $name=>$v){ foreach($data as $pname=>$pv){ if(is_array($pv))continue; $pv=addslashes($pv); if(addslashes($pname)==$name and !empty($pv)){ $this->aUrl[]=$name; $this->aUrl[]=$pv; } } } $this->aUrl=array_merge($this->aUrl, $this->getTimesUrl($data));//для times формируем урл тут ob_start(); $this->executeComponent(); $html=ob_get_contents(); ob_end_clean(); return array($html, $this->arResult['COUNT'], $this->arResult['ACTION']); } public function setFilterVals(){// читаем фильтр по урлу $aUrl=$this->aUrl; $this->aFilterVals=array(); $fl404=false; $_pi=count(explode('/', $this->arParams['BASE_URL'])); if(count($aUrl)<=$_pi)return false; $_aUrl=array_slice($aUrl, $_pi, count($aUrl)); $_aUrl=array_values($_aUrl); for($i=0;$i<count($_aUrl);$i=$i+2){ $v=addslashes($_aUrl[$i+1]); $n=addslashes($_aUrl[$i]); if($this->getTimesDataFromUrl($n, $v))continue; if(isset($this->aUrlParams[$n]) and !empty($v))$this->aFilterVals[$n]=$v; else $fl404=true; } if($fl404 and count($this->aFilterVals)>0)\Bitrix\Iblock\Component\Tools::process404('', true, true, true); } public function getTimesDataFromUrl($n, $v){ $ret=false; foreach($this->aUrlParams['times'] as $f){ if($n==$f and !empty($v)){ $this->aFilterVals['times'][$n]=$v; $ret=true; break; } } return $ret; } public function getTimesUrl(&$data){ $ret=array(); //var_dump('<pre>',$data);die(); if(isset($data['times']) and is_array($data['times'])){ foreach($data['times'] as $f=>$row){ $from=trim(addslashes($row['from'])); $to=trim(addslashes($row['to'])); $v=$from.'-'.$to; if(!isset($row['day']) and empty($from) and empty($to))continue; elseif(!isset($row['day']))$row['day']=$f; if(isset($row['day']) and empty($from) and empty($to))$v='day'; $ret[]=$f;$ret[]=$v; } } return $ret; } public function getChecked($f, $v){ if(isset($this->aFilterVals[$f]) and ($this->aFilterVals[$f]==$v))return 'Y'; return 'N'; } public function setMetroVals(){ $ret=array(); foreach($this->getItemsAll() as $item){ foreach($item['OFFERS'] as $sku){ foreach($sku['HALL']['METRO_HL'] as $row){ $ret[$row['UF_NAME']]=array('VALUE'=>$row['UF_XML_ID'], 'DISPLAY_VALUE'=>$row['UF_NAME'], 'CHECKED'=>$this->getChecked('metro', $row['UF_XML_ID'])); } } } ksort($ret); $this->aFilterValues['metro']=array( 'PROP_PARAMS'=>[ 'ID'=>'metro', 'CODE'=>'metro', 'NAME'=>'Метро', ], 'VALUES'=>$ret ); } public function setRayonVals(){ $ret=array(); foreach($this->getItemsAll() as $item){ foreach($item['OFFERS'] as $sku){ foreach($sku['HALL']['RAYON_HL'] as $row){ $ret[$row['UF_XML_ID']]=array('VALUE'=>$row['UF_XML_ID'], 'DISPLAY_VALUE'=>$row['UF_NAME'], 'CHECKED'=>$this->getChecked('rayon', $row['UF_XML_ID'])); } } } $this->aFilterValues['rayon']=array( 'PROP_PARAMS'=>[ 'ID'=>'rayon', 'CODE'=>'rayon', 'NAME'=>'Район', ], 'VALUES'=>$ret ); } public function getEnumVal($field, $id=null){ if(!isset($this->aEnumSpr[$field])){ $this->aEnumSpr[$field]=array(); $prop=str_replace('_VALUE', '', $field); $prop=str_replace('PROPERTY_', '', $prop); $property_enums = CIBlockPropertyEnum::GetList(Array("DEF"=>"DESC", "SORT"=>"ASC"), Array("IBLOCK_ID"=>$this->arParams['IBLOCK_ID'], 'CODE'=>$prop)); while($enum_fields=$property_enums->GetNext()){ $this->aEnumSpr[$field][$enum_fields['ID']]=array('ID'=>$enum_fields['ID'], 'VALUE'=>$enum_fields['VALUE'], 'XML_ID'=>$enum_fields['XML_ID']); } } if(empty($id))return $this->aEnumSpr[$field]; return $this->aEnumSpr[$field][$id]; } public function setItemHtmlVals($name, $title, $prop){ $ret=array(); foreach($this->getItemsAll() as $item){ if(empty($item['OFFERS']))continue; foreach($item[$prop] as $id=>$row){ $aEnum=$this->getEnumVal($prop, $id); $ret[$aEnum['ID']]=array('VALUE'=>$aEnum['ID'], 'DISPLAY_VALUE'=>$aEnum['VALUE'], 'CHECKED'=>$this->getChecked($name, $aEnum['ID'])); } } $this->aFilterValues[$name]=array( 'PROP_PARAMS'=>[ 'ID'=>$name, 'CODE'=>$name, 'NAME'=>$title, ], 'VALUES'=>$ret ); } public function setSkuVals($name, $title, $prop){ $ret=array(); foreach($this->getItemsAll() as $item){ if(isset($item['OFFERS'])){ foreach($item['OFFERS'] as $sku){ $av=$sku[$prop]; if(is_array($av)){ foreach($av as $k=>$v)$ret[$k]=array('VALUE'=>$k, 'DISPLAY_VALUE'=>$v, 'CHECKED'=>$this->getChecked($name, $k)); }else{ $enum_valueField=str_replace('_VALUE', '_ENUM_ID', $prop); if(isset($sku[$enum_valueField])){ $k=$sku[$enum_valueField]; $v=$av; $ret[$k]=array('VALUE'=>$k, 'DISPLAY_VALUE'=>$v, 'CHECKED'=>$this->getChecked($name, $k)); } } } } } $this->aFilterValues[$name]=array( 'PROP_PARAMS'=>[ 'ID'=>$name, 'CODE'=>$name, 'NAME'=>$title, ], 'VALUES'=>$ret ); } public function getCheckedTimes($prop, $v, $i=null){ $ret='N'; //var_dump('<pre>',$this->aFilterVals['times']);//die(); if(!isset($this->aFilterVals['times']))return $ret; foreach($this->aFilterVals['times'] as $_prop=>$_v){ if($_prop!=$prop)continue; if($v=='day'){$ret='Y';break;} $a_v=explode('-', $_v); if(!isset($a_v[$i]))return $ret; if($a_v[$i]==$v[$i]){$ret='Y';break;} } return $ret; } private function setTimesValsGetAll($prop){ $ret=array('FROM'=>array(), 'TO'=>array()); $rfrom=array(); $rto=array(); foreach($this->getItemsAll() as $item){ if(isset($item['OFFERS'])){ foreach($item['OFFERS'] as $sku){ if(isset($sku['PROPERTY_'.$prop.'_VALUE']) and is_array($sku['PROPERTY_'.$prop.'_VALUE'])){ foreach($sku['PROPERTY_'.$prop.'_VALUE'] as $row){ $ap=explode('-', $row); $rfrom[$ap[0]]=array('VALUE'=>$ap[0], 'DISPLAY_VALUE'=>$ap[0], 'CHECKED'=>$this->getCheckedTimes($prop, $ap, 0)); $rto[$ap[1]]=array('VALUE'=>$ap[1], 'DISPLAY_VALUE'=>$ap[1], 'CHECKED'=>$this->getCheckedTimes($prop, $ap, 1)); } } } } } uksort($rfrom, function($a, $b){ $a=intval(explode(':', $a)[0]); $b=intval(explode(':', $b)[0]); if($a==$b)return 0; return($a<$b)?-1:1; }); uksort($rto, function($a, $b){ $a=intval(explode(':', $a)[0]); $b=intval(explode(':', $b)[0]); if($a==$b)return 0; return($a<$b)?-1:1; }); $ret['FROM']=$rfrom; $ret['TO']=$rto; return $ret; } public function setTimesVals(){ $ret=array(); $aData=array('1'=>'Пн', '2'=>'Вт', '3'=>'Ср', '4'=>'Чт', '5'=>'Пт', '6'=>'Сб', '0'=>'Вс'); $fl=false; foreach($aData as $k=>$name){ $field='DATE_'.$k; $ad=$this->setTimesValsGetAll($field); if(!$fl and (count($ad['FROM'])>0 or count($ad['TO'])>0))$fl=true; $ret[]=array('CHECKED'=>$this->getCheckedTimes($field, 'day'), 'CODE'=>$field, 'DAY'=>$field, 'NAME'=>$name, 'FROM'=>$ad['FROM'], 'TO'=>$ad['TO']); } if(!$fl)$ret=false; $this->aFilterValues[$name]=array( 'CHECKED'=>'Y', 'PROP_PARAMS'=>[ 'ID'=>'times', 'CODE'=>'times', 'NAME'=>'Выбрать время', ], 'VALUES'=>$ret ); } public function setVozrastVal(){ $ret=array(); // foreach($this->getItemsAll() as $item){ // if(isset($item['OFFERS'])){ // foreach($item['OFFERS'] as $sku){ // $v=intval($sku['PROPERTY_GODOT_VALUE']).'-'.intval($sku['PROPERTY_GODDO_VALUE']); // $dv='от '.intval($sku['PROPERTY_GODOT_VALUE']).' до '.intval($sku['PROPERTY_GODDO_VALUE']); // $ret[$v]=array('VALUE'=>$v, 'DISPLAY_VALUE'=>$dv, 'CHECKED'=>$this->getChecked('vozrast', $v)); // } // } // } // uksort($ret, function($a, $b){ // $a=intval(explode('-', $a)[0]); // $b=intval(explode('-', $b)[0]); // if($a==$b)return 0; // return($a<$b)?-1:1; // }); for($i=1;$i<80;$i++)$ret[$i]=array('VALUE'=>$i, 'DISPLAY_VALUE'=>$i, 'CHECKED'=>$this->getChecked('vozrast', $i)); $this->aFilterValues['vozrast']=array( 'PROP_PARAMS'=>[ 'ID'=>'vozrast', 'CODE'=>'vozrast', 'NAME'=>'Возраст', ], 'VALUES'=>$ret ); } public function getArFilter(){ global $arrFilter; $offerId=array(); $hallId=array(); foreach($this->getItemsAll() as $item){ if(isset($item['OFFERS'])){ foreach($item['OFFERS'] as $sku){ $offerId[]=$sku['ID']; $hallId[]=$sku['HALL']['ID']; } } } if(empty($offerId)){ $offerId=-1; $hallId=-1; }else $hallId=array_unique($hallId); $arrFilter=[ 'OFFER'=>$offerId, 'HALL'=>array('=ID'=>$hallId) ]; } public function configureActions(){ return [ 'refrash' => [ '-prefilters' => [ ActionFilter\Authentication::class, ], ], ]; } private function comareTimesFilterVal($val, $filterVal){ if($filterVal=='day' and count($val)>0)return true;//если весь день foreach($val as $v){ if($v==$filterVal)return true;//полное совпадение (начало-конец) $av=explode('-', $v); $afv=explode('-', $filterVal); if(empty($afv[1]) and $av[0]==$afv[0])return true; if(empty($afv[0]) and $av[1]==$afv[1])return true; } return false; } public function removeItems(){//убираем ненужные из итога $allCount=0; foreach($this->aItemsAll as $k=>$item){ if(isset($item['OFFERS']) and is_array($item['OFFERS'])){ foreach($item['OFFERS'] as $kSku=>$sku){ foreach($this->aFilterVals as $name=>$val){ if($name=='times' and is_array($val)){//только для поля Время $fl=false; foreach($val as $field=>$sTime){ $fieldSku='PROPERTY_'.$field.'_VALUE'; if(isset($sku[$fieldSku]) and is_array($sku[$fieldSku])){ if($this->comareTimesFilterVal($sku[$fieldSku], $val[$field]))$fl=true; } } if(!$fl)unset($this->aItemsAll[$k]['OFFERS'][$kSku]); }elseif(isset($this->aUrlParams[$name]) and $aFields=$this->aUrlParams[$name] and is_array($aFields) and $aFields[0]=='OFFERS'){ $aVal=$sku; $fl=false; for($i=1;$i<=count($aFields)-1;$i++){ if(isset($aVal[$aFields[$i]])){ if($i==count($aFields)-1){ if(is_array($aVal[$aFields[$i]])){//ежели вход массив foreach($aVal[$aFields[$i]] as $_v){ if($val==$_v){ $fl=true;break; } } }elseif($aVal[$aFields[$i]]==$val){ $fl=true;break; } } $aVal=$aVal[$aFields[$i]]; }else break; } if(!$fl){ unset($this->aItemsAll[$k]['OFFERS'][$kSku]); }else{ $allCount++; } } } } } } return $allCount; } public function getItemsAll(){ return $this->aItemsAll; } public function getFromHL($aID, $HLBLOCK_ID){ if(!isset($this->hldata[$HLBLOCK_ID])){ $hlblock=\Bitrix\Highloadblock\HighloadBlockTable::getById($HLBLOCK_ID)->fetch(); $entity=\Bitrix\Highloadblock\HighloadBlockTable::compileEntity($hlblock); $entityDataClass=$entity->getDataClass(); $result=$entityDataClass::getList(array( "select"=>array("*"), "order"=>array("ID"=>"DESC"), "filter"=>Array(), )); $this->hldata[$HLBLOCK_ID]=array(); while($arRow=$result->Fetch())$this->hldata[$HLBLOCK_ID][]=$arRow; } if(!is_array($aID))$aID=array($aID); $ret=array(); foreach($this->hldata[$HLBLOCK_ID] as $row){ foreach($aID as $id)if($row['UF_XML_ID']==$id)$ret[]=$row; } return $ret; } public function getHall($ID){ if(!isset($this->aHall)){ $this->aHall=array(); $rhalls=CIBlockElement::GetList( Array("NAME" => "ASC"), Array( "IBLOCK_ID"=>15, 'ID'=>$aHall ), false, false, ['ID', 'NAME', 'PROPERTY_AREA_CITY', 'PROPERTY_METRO', 'CODE'] ); while($ar_fields=$rhalls->GetNext()){ $ar_fields['METRO_HL']=$this->getFromHL($ar_fields['PROPERTY_METRO_VALUE'], '4'); $ar_fields['RAYON_HL']=$this->getFromHL($ar_fields['PROPERTY_AREA_CITY_VALUE'], '5'); $this->aHall[$ar_fields['ID']]=$ar_fields; } } if(isset($this->aHall[$ID]))return $this->aHall[$ID]; else return false; } public function getArFilterQuery(){ $ret=array(); foreach($this->aFilterVals as $name=>$val){ if(isset($this->aUrlParams[$name]) and !is_array($this->aUrlParams[$name]))$ret[$this->aUrlParams[$name]]=array('ID'=>$val); } if(isset($this->arParams['ID']))$ret['ID']=$this->arParams['ID']; return $ret; } public function getFilterVozrast(){ $ret=array(); if(isset($this->aFilterVals['vozrast'])){ // $av=explode('-', $this->aFilterVals['vozrast']); // if(count($av)==2){ // $ret=array( // "LOGIC"=>'AND', // array('<=PROPERTY_godot'=>intval($av[0])), // array('>=PROPERTY_goddo'=>intval($av[1])) // ); // } $ret=array( "LOGIC"=>'AND', array('<=PROPERTY_godot'=>intval($this->aFilterVals['vozrast'])), array('>=PROPERTY_goddo'=>intval($this->aFilterVals['vozrast'])) ); } return $ret; } public function getFilterSKU($name, $prop){ $ret=array(); if(isset($this->aFilterVals[$name])){ $ret=array( "LOGIC"=>'AND', array('='.$prop=>addslashes($this->aFilterVals[$name])), ); } return $ret; } public function setItemsAll(){ $elements=[]; //item в SECTiON $arFilterQuery=Array( "IBLOCK_ID"=>$this->arParams['IBLOCK_ID'], 'SECTION_ID'=>$this->arParams['SECTION_ID'] ); $arFilterQuery=array_merge($arFilterQuery, $this->getArFilterQuery()); $re=CIBlockElement::GetList( Array("NAME" => "ASC"), $arFilterQuery, false, false, ['ID', 'NAME', 'PROPERTY_FILTER_MOTIV', 'PROPERTY_FILTER_REGION', 'PROPERTY_FILTER_STRESS']//todo: сюда добавляем из aUrlParams ); while($ar_fields=$re->GetNext())$elements[]=$ar_fields; //SKU $aProductID=array_column($elements, 'ID'); $aFilterSku=array( 'ACTIVE'=>'Y', 'PROPERTY_CITY_DOMEN'=>'1243',//город ); $aFilterSku=array_merge($aFilterSku, $this->getFilterVozrast(), $this->getFilterSKU('sex', 'PROPERTY_sex'), $this->getFilterSKU('level', 'PROPERTY_level')); $_arSKU=CCatalogSKU::getOffersList( $aProductID, 0, $aFilterSku, array('ID', 'NAME', 'CODE', 'PROPERTY_HALL', 'PROPERTY_godot', 'PROPERTY_goddo', 'PROPERTY_level', 'PROPERTY_sex', 'PROPERTY_DATE_1', 'PROPERTY_DATE_2', 'PROPERTY_DATE_3', 'PROPERTY_DATE_4', 'PROPERTY_DATE_5', 'PROPERTY_DATE_6', 'PROPERTY_DATE_0'), array() ); foreach($_arSKU as $id=>$itemsSKU){ foreach($elements as $k=>$item){ if(!isset($elements[$k]['OFFERS']))$elements[$k]['OFFERS']=array(); if($item['ID']==$id){ foreach($itemsSKU as $sku){ $sku['HALL']=$this->getHall($sku['PROPERTY_HALL_VALUE']); $elements[$k]['OFFERS'][]=$sku; } } } } $this->aItemsAll=$elements; unset($elements); } public function getCountSku(){ $ret=0; foreach($this->getItemsAll() as $item){ foreach($item['OFFERS'] as $sku)$ret++; } return $ret; } public function executeComponent(){ //var_dump('<pre>',$this->arParams);die(); if($this->aUrl===false){ $this->aUrl=explode('?', $_SERVER['REQUEST_URI']); $this->aUrl=explode('/', $this->aUrl[0]); $this->aUrl=array_diff($this->aUrl, array('')); $this->aUrl=array_values($this->aUrl); } $this->setFilterVals(); $this->setItemsAll(); $c=$this->removeItems(); $this->getArFilter(); //html $this->setVozrastVal();//sku $this->setMetroVals();//halls $this->setRayonVals();//halls //$this->setItemHtmlVals('motiv', 'Мотив', 'PROPERTY_FILTER_MOTIV_VALUE'); //$this->setItemHtmlVals('proishozhd', 'Происхождение', 'PROPERTY_FILTER_REGION_VALUE'); $this->setItemHtmlVals('nagruzka', 'Нагрузка', 'PROPERTY_FILTER_STRESS_VALUE');//item $this->setSkuVals('sex', 'Пол', 'PROPERTY_SEX_VALUE');//item $this->setSkuVals('level', 'Уровень', 'PROPERTY_LEVEL_VALUE');//item $this->setTimesVals();//item /// $aurl=$this->aUrl; unset($aurl[0]); $this->arResult=[ 'AJAX'=>$this->ajax, 'URL'=>'/'.$this->arParams['BASE_URL'].'/', 'ACTION'=>'/'.$this->arParams['BASE_URL'].'/'.implode('/', $aurl), 'ITEMS'=>$this->aFilterValues, 'COUNT'=>$this->getCountSku() ]; // if(isset($_COOKIE['active_view']) and $_COOKIE['active_view']=='#schedule-1')$this->arParams['ACTIVE_TAB']=1; else $this->arParams['ACTIVE_TAB']=1; $this->includeComponentTemplate(); } } ?>