5 use \Rsi\Fred\Controller;
7 class Record extends \Rsi\Fred\Controller\Provider{
15 protected function data($params){
17 if(!array_key_exists($key =
'data-' . md5(serialize($params)),$this->_cache)) $this->_cache[$key] = call_user_func(
$data,$params,$this->
id);
18 $data = $this->_cache[$key];
23 public function trans($column,$key,$value,$params =
null){
24 if(\Rsi::nothing($value))
return null;
25 foreach($this->
data($params) as $record)
if(array_key_exists($key,$record) && ($record[$key] == $value))
return $record[$column] ??
null;
29 public function exists($key,$value,$params =
null){
30 foreach($this->
data($params) as $record)
if(array_key_exists($key,$record) && ($record[$key] == $value))
return true;
35 $this->_controller->component(
'log')->debug(__CLASS__ .
"::filter(search,params,loose)",__FILE__,__LINE__,[
'id' => $this->_id] + compact(
'search',
'params',
'loose'));
37 foreach($this->
data($params) as $record){
39 foreach(
$search as $column => $values){
40 $value = \Rsi\Record::iget($record,$column);
41 foreach($values as $type => $ref){
42 if(array_key_exists($column,$this->
search)) $match = call_user_func($this->
search[$column],$value,$ref,$record);
45 $match = $value >= $ref;
48 $match = $value <= $ref;
51 foreach((is_array($ref) ? $ref : [$ref]) as $ref)
52 if(($ref && !($match = !strcasecmp($value,$ref))) || ((($ref ===
null) || ($ref ==
'null')) && !($match = ($value ===
null))))
break;
53 elseif(($ref ==
'""') && !($match = !strcmp($value,
'')))
break;
56 foreach((array)$ref as $date)
57 if(($date = \
Rsi\Fred\DateTime\Date::create($date)) && !($match = ($value >= (
string)$date) && ($value < (
string)$date->add())))
break;
60 foreach((array)$ref as $like)
if($like){
61 if(!preg_match(
'/^\\/.+\\/$/',$like)){
62 if($like ==
'null') $match = $value ===
null;
63 elseif($like ==
'""') $match = !strcmp($value,
'');
65 if($not = substr($like,0,1) ==
'-') $like = substr($like,1);
66 $mask = strtr(preg_quote($like,
'/'),[
'\\?' =>
'.',
'\\*' =>
'.*']);
67 if($loose) $mask =
"(?!$mask).+$mask";
68 $match = ($not xor preg_match(
"/^$mask/i",$value));
72 $match = preg_match($like .
'i',$value);
75 $this->_controller->component(
'log')->debug(
"Invalid reg-ex '$like': " . str_replace(
'preg_match(): Compilation failed: ',
'',$e->getMessage()),__FILE__,__LINE__);
84 if(!$match)
continue 2;
95 foreach(
$order as $column => &$type)
if(array_key_exists($column,$default)){
96 $type |= ($default[$column] & 0xf0);
97 unset($default[$column]);
104 foreach(
$order as $column => $type) $params = array_merge($params,[\
Rsi\Record::column($records,$column),$type & 0xf,$type >> 4]);
105 $params[] = &$records;
106 call_user_func_array(
'array_multisort',$params);
113 if(!array_key_exists($key =
'search-' . md5(serialize(compact(
'search',
'params'))),$this->_cache))
115 $records = $this->
sort($this->_cache[$key],
$order);
116 foreach(
$search as $values)
foreach($values as $type => $ref)
if($type == self::SEARCH_LIKE){
117 if(!array_key_exists($key .=
'-loose',$this->_cache)) $this->_cache[$key] = $this->
filter(
$search,$params,
true);
118 $records = array_merge($records,$this->
sort($this->_cache[$key],
$order));
123 return $limit ? array_slice($records,$offset,$limit) : $records;
127 $results = $counts = $averages = [];
129 foreach($totals as $column => &$types){
130 $results[$column] = $counts[$column] = [];
131 foreach(($types = is_array($types) ? $types : [$types]) as $type)
132 $results[$column][$type] = $counts[$column][$type] =
null;
136 foreach(($records = $this->
_search(
$search,
false,$params,
null,
null)) as $record){
137 foreach($totals as $column => $types)
foreach($types as $type){
138 $result = \Rsi\Record::iget($record,$column);
141 $results[$column][$type]++;
144 if(!array_key_exists($column,$averages)) $averages[$column] = \Rsi\Record::average(array_column($records,$column));
145 $result = pow($result - $averages[$column],2);
147 $counts[$column][$type]++;
149 $results[$column][$type] += $result;
152 if(($result !==
null) && (($results[$column][$type] ===
null) || ($result > $results[$column][$type])))
153 $results[$column][$type] = $result;
156 if(($result !==
null) && (($results[$column][$type] ===
null) || ($result < $results[$column][$type])))
157 $results[$column][$type] = $result;
160 if(!$results[$column][$type]) $results[$column][$type] = [];
161 if(!in_array($result,$results[$column][$type])) $results[$column][$type][] = $result;
164 if($result ===
null) $results[$column][$type]++;
167 if($result !==
null) $results[$column][$type]++;
173 foreach($totals as $column => $types)
foreach($types as $type){
174 if(is_array($results[$column][$type])) $results[$column][$type] = count($results[$column][$type]);
175 if($counts[$column][$type]) $results[$column][$type] /= $counts[$column][$type];
184 foreach(array_unique(\
Rsi\Record::column($this->
_search(
$search,
false,$params,
null,
null),$group)) as $value)
185 $result[$value] = \Rsi\Record::get($this->
_totals([$group => [self::SEARCH_EXACT => $value]] +
$search,[$column => [$total]],$params),[$column,$total]);
186 if(!$limit) return \Rsi\Record::sort($result,SORT_FLAG_CASE,
true);
187 $result = \Rsi\Record::sort($result,SORT_FLAG_CASE);
188 return $limit > 0 ? array_slice($result,0,$limit) : array_reverse(array_slice($result,$limit));