$input['date_from']??$now->format('Y-m-01'),'date_to'=>$input['date_to']??$now->format('Y-m-t')]; foreach(['date_from','date_to'] as $k)$v[$k]=MembershipValidator::date($v[$k],$k); if($v['date_from']>$v['date_to'])CatalogValidator::invalid('date_to',__('The end date must be on or after the start date.','abece-booking')); $start=Time::day($v['date_from']);$end=Time::nextDay($v['date_to']); if(!$start||!$end||$end->getTimestamp()-$start->getTimestamp()>3660*86400)CatalogValidator::invalid('date_to',__('Choose a reporting period of at most ten years.','abece-booking')); $this->from=$start->getTimestamp();$this->to=$end->getTimestamp(); foreach(['sport_id','resource_id','membership_type_id'] as $k)$v[$k]=!isset($input[$k])||$input[$k]===''?null:CatalogValidator::integer($input[$k],$k,1,PHP_INT_MAX); foreach(['customer_type'=>['member','registered_non_member','external'],'payment_method'=>['credit','pay_on_site','bank_transfer','qr_payment','cash','manual'],'granularity'=>['auto','day','week','month'],'sort'=>['player_seconds','booking_count','final_amount','no_show','cancelled'],'direction'=>['asc','desc']] as $k=>$choices){$value=$input[$k]??null;if($value===null||$value==='')$value=['granularity'=>'auto','sort'=>'player_seconds','direction'=>'desc'][$k]??null;$v[$k]=$value===null||$value===''?null:CatalogValidator::choice($value,$k,$choices);} $v['search']=MembershipValidator::text($input['search']??'','search',100,true)??''; $v['page']=CatalogValidator::integer($input['page']??1,'page',1,PHP_INT_MAX); $v['per_page']=CatalogValidator::integer($input['per_page']??25,'per_page',1,100); $this->values=$v; } public function sqlFrom(): string {return Time::sql(Time::timestamp($this->from));} public function sqlTo(): string {return Time::sql(Time::timestamp($this->to));} public function granularity(): string {return $this->values['granularity']!=='auto'?$this->values['granularity']:($this->to-$this->from<=45*86400?'day':($this->to-$this->from<=550*86400?'week':'month'));} }