Your IP : 18.191.97.62


Current Path : /var/www/u0635749/data/www/hobbyclick.ru/public/local/components/aip/filter/
Upload File :
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();
	}	
}
?>