diff --git a/web/includes/Filter.php b/web/includes/Filter.php index c15d8ba6a..e9dd0a132 100644 --- a/web/includes/Filter.php +++ b/web/includes/Filter.php @@ -39,7 +39,7 @@ class Filter extends ZM_Object { public function Query() { if ( func_num_args( ) ) { - $this->{'Query'} = func_get_arg(0);; + $this->{'Query'} = func_get_arg(0); $this->{'Query_json'} = jsonEncode($this->{'Query'}); } if ( !property_exists($this, 'Query') ) { @@ -57,6 +57,297 @@ class Filter extends ZM_Object { return $this->{'Query'}; } + public function parse( $querySep='&') { + + $filter = $this->Query(); + Warning(print_r($filter, true)); + + $query = ''; + $sql = ''; + $fields = ''; + + $validQueryConjunctionTypes = getFilterQueryConjunctionTypes(); + $StorageArea = NULL; + + # It is not possible to pass an empty array in the url, so we have to deal with there not being a terms field. + $terms = (is_array($filter['terms'])) ? $filter['terms'] : array(); + + if ( count($terms) ) { + for ( $i = 0; $i < count($terms); $i++ ) { + + $term = $terms[$i]; + + if ( isset($term['cnj']) && array_key_exists($term['cnj'], $validQueryConjunctionTypes) ) { + $query .= $querySep.urlencode("filter[Query][terms][$i][cnj]").'='.urlencode($term['cnj']); + $sql .= ' '.$term['cnj'].' '; + $fields .= "\n"; + } + if ( isset($term['obr']) && (string)(int)$term['obr'] == $term['obr'] ) { + $query .= $querySep.urlencode("filter[Query][terms][$i][obr]").'='.urlencode($term['obr']); + $sql .= ' '.str_repeat('(', $term['obr']).' '; + $fields .= "\n"; + } + if ( isset($term['attr']) ) { + $query .= $querySep.urlencode("filter[Query][terms][$i][attr]").'='.urlencode($term['attr']); + $fields .= "\n"; + switch ( $term['attr'] ) { + case 'AlarmedZoneId': + $term['op'] = 'EXISTS'; + break; + case 'MonitorName': + $sql .= 'M.Name'; + break; + case 'ServerId': + case 'MonitorServerId': + $sql .= 'M.ServerId'; + break; + case 'StorageServerId': + $sql .= 'S.ServerId'; + break; + case 'FilterServerId': + $sql .= ZM_SERVER_ID; + break; + # Unspecified start or end, so assume start, this is to support legacy filters + case 'DateTime': + $sql .= 'E.StartTime'; + break; + case 'Date': + $sql .= 'to_days(E.StartTime)'; + break; + case 'Time': + $sql .= 'extract(hour_second FROM E.StartTime)'; + break; + case 'Weekday': + $sql .= 'weekday(E.StartTime)'; + break; + # Starting Time + case 'StartDateTime': + $sql .= 'E.StartTime'; + break; + case 'FramesEventId': + $sql .= 'F.EventId'; + break; + case 'StartDate': + $sql .= 'to_days(E.StartTime)'; + break; + case 'StartTime': + $sql .= 'extract(hour_second FROM E.StartTime)'; + break; + case 'StartWeekday': + $sql .= 'weekday(E.StartTime)'; + break; + # Ending Time + case 'EndDateTime': + $sql .= 'E.EndTime'; + break; + case 'EndDate': + $sql .= 'to_days(E.EndTime)'; + break; + case 'EndTime': + $sql .= 'extract(hour_second FROM E.EndTime)'; + break; + case 'EndWeekday': + $sql .= 'weekday(E.EndTime)'; + break; + case 'Id': + case 'Name': + case 'DiskSpace': + case 'MonitorId': + case 'StorageId': + case 'SecondaryStorageId': + case 'Length': + case 'Frames': + case 'AlarmFrames': + case 'TotScore': + case 'AvgScore': + case 'MaxScore': + case 'Cause': + case 'Notes': + case 'StateId': + case 'Archived': + $sql .= 'E.'.$term['attr']; + break; + case 'DiskPercent': + // Need to specify a storage area, so need to look through other terms looking for a storage area, else we default to ZM_EVENTS_PATH + if ( ! $StorageArea ) { + for ( $j = 0; $j < count($terms); $j++ ) { + if ( + isset($terms[$j]['attr']) + and + ($terms[$j]['attr'] == 'StorageId') + and + isset($terms[$j]['val']) + ) { + $StorageArea = ZM\Storage::find_one(array('Id'=>$terms[$j]['val'])); + break; + } + } // end foreach remaining term + if ( ! $StorageArea ) $StorageArea = new ZM\Storage(); + } // end no StorageArea found yet + + $sql .= getDiskPercent($StorageArea->Path()); + break; + case 'DiskBlocks': + // Need to specify a storage area, so need to look through other terms looking for a storage area, else we default to ZM_EVENTS_PATH + if ( ! $StorageArea ) { + for ( $j = $i; $j < count($terms); $j++ ) { + if ( + isset($terms[$j]['attr']) + and + ($terms[$j]['attr'] == 'StorageId') + and + isset($terms[$j]['val']) + ) { + $StorageArea = ZM\Storage::find_one(array('Id'=>$terms[$j]['val'])); + } + } // end foreach remaining term + } // end no StorageArea found yet + $sql .= getDiskBlocks( $StorageArea ); + break; + case 'SystemLoad': + $sql .= getLoad(); + break; + } + $valueList = array(); + foreach ( preg_split('/["\'\s]*?,["\'\s]*?/', preg_replace('/^["\']+?(.+)["\']+?$/', '$1', $term['val'])) as $value ) { + switch ( $term['attr'] ) { + + case 'AlarmedZoneId': + $value = '(SELECT * FROM Stats WHERE EventId=E.Id AND ZoneId='.$value.')'; + break; + case 'MonitorName': + case 'Name': + case 'Cause': + case 'Notes': + if ( $term['op'] == 'LIKE' || $term['op'] == 'NOT LIKE' ) { + $value = '%'.$value.'%'; + } + $value = dbEscape($value); + break; + case 'MonitorServerId': + case 'FilterServerId': + case 'StorageServerId': + case 'ServerId': + if ( $value == 'ZM_SERVER_ID' ) { + $value = ZM_SERVER_ID; + } else if ( $value == 'NULL' ) { + + } else { + $value = dbEscape($value); + } + break; + case 'StorageId': + $StorageArea = ZM\Storage::find_one(array('Id'=>$value)); + if ( $value != 'NULL' ) + $value = dbEscape($value); + break; + case 'DateTime': + case 'StartDateTime': + case 'EndDateTime': + if ( $value != 'NULL' ) + $value = '\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\''; + break; + case 'Date': + case 'StartDate': + case 'EndDate': + if ( $value == 'CURDATE()' or $value == 'NOW()' ) { + $value = 'to_days('.$value.')'; + } else if ( $value != 'NULL' ) { + $value = 'to_days(\''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')'; + } + break; + case 'Time': + case 'StartTime': + case 'EndTime': + if ( $value != 'NULL' ) + $value = 'extract(hour_second from \''.strftime(STRF_FMT_DATETIME_DB, strtotime($value)).'\')'; + break; + default : + if ( $value != 'NULL' ) + $value = dbEscape($value); + break; + } + $valueList[] = $value; + } // end foreach value + + switch ( $term['op'] ) { + case '=' : + case '!=' : + case '>=' : + case '>' : + case '<' : + case '<=' : + case 'LIKE' : + case 'NOT LIKE': + $sql .= ' '.$term['op'].' '. $value; + break; + case '=~' : + $sql .= ' regexp '.$value; + break; + case '!~' : + $sql .= ' not regexp '.$value; + break; + case '=[]' : + case 'IN' : + $sql .= ' IN ('.join(',', $valueList).')'; + break; + case '![]' : + $sql .= ' not in ('.join(',', $valueList).')'; + break; + case 'EXISTS' : + $sql .= ' EXISTS ' .$value; + break; + case 'IS' : + if ( $value == 'Odd' ) { + $sql .= ' % 2 = 1'; + } else if ( $value == 'Even' ) { + $sql .= ' % 2 = 0'; + } else { + $sql .= " IS $value"; + } + break; + case 'IS NOT' : + $sql .= " IS NOT $value"; + break; + default: + ZM\Warning('Invalid operator in filter: ' . print_r($term['op'], true)); + } // end switch op + + $query .= $querySep.urlencode("filter[Query][terms][$i][op]").'='.urlencode($term['op']); + $fields .= "\n"; + if ( isset($term['val']) ) { + $query .= $querySep.urlencode("filter[Query][terms][$i][val]").'='.urlencode($term['val']); + $fields .= "\n"; + } + } // end if isset($term['attr']) + if ( isset($term['cbr']) && (string)(int)$term['cbr'] == $term['cbr'] ) { + $query .= $querySep.urlencode("filter[Query][terms][$i][cbr]").'='.urlencode($term['cbr']); + $sql .= ' '.str_repeat(')', $term['cbr']); + $fields .= "\n"; + } + } // end foreach term + if ( $sql ) + $sql = ' AND ( '.$sql.' )'; + } else { + $query = $querySep; + #.urlencode('filter[Query][terms]=[]'); + } // end if terms + $this->{'query'} = $query; + $this->{'sql'} = $sql; + $this->{'fields'} = $fields; + + #if ( 0 ) { + #// ICON I feel like these should be here, but not yet + #if ( isset($filter['Query']['sort_field']) ) { + #$sql .= ' ORDER BY ' . $filter['Query']['sort_field'] . ( + #( $filter['Query']['sort_asc'] ? ' ASC' : ' DESC' ) ); + #} + #if ( $filter['Query']['limit'] ) { + #$sql .= ' LIMIT ' . validInt($filter['Query']['limit']); + #} + #} + } // end function parse($querySep='&') + public static function find( $parameters = array(), $options = array() ) { return ZM_Object::_find(get_class(), $parameters, $options); } @@ -104,6 +395,27 @@ class Filter extends ZM_Object { #return $this->defaults{'sort_asc'}; } + public function fields() { + if ( !property_exists($this, 'fields') ) { + $this->parse(); + } + return $this->{'fields'}; + } + + public function sql() { + if ( !property_exists($this, 'sql') ) { + $this->sql(); + } + return $this->{'sql'}; + } + + public function query_string() { + if ( !property_exists($this, 'query') ) { + $this->query(); + } + return $this->{'query'}; + } + public function limit( ) { if ( func_num_args( ) ) { $Query = $this->Query();