Index: trunk/core/units/general/helpers/search_helper.php =================================================================== diff -u -N -r4228 -r6751 --- trunk/core/units/general/helpers/search_helper.php (.../search_helper.php) (revision 4228) +++ trunk/core/units/general/helpers/search_helper.php (.../search_helper.php) (revision 6751) @@ -82,6 +82,377 @@ return $where_clause; } + /** + * Returns additional information about search field + * + * @param kDBList $object + * @param string $field_name + * @return Array + */ + function getFieldInformation(&$object, $field_name) + { + $sql_filter_type = isset($object->VirtualFields[$field_name]) ? 'having' : 'where'; + $field_type = isset($object->Fields[$field_name]['type']) ? $object->Fields[$field_name]['type'] : 'string'; + + if (preg_match('/(.*)\.(.*)/', $field_name, $regs)) { + $table_name = '`'.$regs[1].'`.'; // field from external table + $field_name = $regs[2]; + } + elseif ($sql_filter_type == 'where') { + $table_name = '`'.$object->TableName.'`.'; // field from local table + } + + $table_name = ($sql_filter_type == 'where') ? $table_name : ''; + return Array ('field_name' => $field_name, 'field_type' => $field_type, 'table_name' => $table_name, 'sql_filter_type' => $sql_filter_type); + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function performSearch(&$event) + { + $object =& $event->getObject(); + + // process search keyword + $search_keyword = $this->Application->GetVar( $event->getPrefixSpecial(true).'_search_keyword'); + $this->Application->StoreVar( $event->getPrefixSpecial().'_search_keyword', $search_keyword); + $search_keyword = str_replace('*', '%', $search_keyword); + + $custom_filter = $this->processCustomFilters($event); + + if(!$search_keyword && $custom_filter === false) { + $this->OnSearchReset($event); + return true; + } + + if ($search_keyword) { + $this->processAutomaticFilters($event, $search_keyword, $custom_filter); + } + } + + + function processAutomaticFilters(&$event, $search_keyword, $custom_filter) + { + $grid_name = $this->Application->GetVar('grid_name'); + $grids = $this->Application->getUnitOption($event->Prefix, 'Grids'); + $search_fields = array_keys($grids[$grid_name]['Fields']); + + $search_filter = Array(); + $object =& $event->getObject(); + + foreach ($search_fields as $search_field) { + $custom_keyword = isset($custom_filter[$search_field]) ? $custom_filter[$search_field]['submit_value'] : false; + + $filter_data = $this->getSearchClause($object, $search_field, $search_keyword, $custom_keyword); + + if ($filter_data) { + $search_filter[$search_field] = $filter_data; + } + } + $this->Application->StoreVar($event->getPrefixSpecial().'_search_filter', serialize($search_filter) ); + } + + /** + * Returns search clause for any particular field + * + * @param kDBList $object + * @param string $search_field + * @param string $search_keyword what we are searching (false, when building custom filter clause) + * @param string $custom_filter all custom filter + * @return Array + */ + function getSearchClause(&$object, $field_name, $search_keyword, $custom_keyword) + { + $search_keywords = $this->splitKeyword($search_keyword); + + extract( $this->getFieldInformation($object, $field_name) ); // see getFieldInformation for more details + + $filter_value = ''; + + // get field clause by formatter name and/or parameters + $formatter = getArrayValue($object->Fields[$field_name], 'formatter'); + switch ($formatter) { + case 'kOptionsFormatter': + $search_keys = Array(); + + if ($custom_keyword !== false) { + // if keyword passed through advanced search filter (e.g. on Visits lists section) + array_push($search_keys, $this->Conn->qstr($custom_keyword)); + } + else { + // if keywords passed through simple search filter (on each grid) + $use_phrases = getArrayValue($object->Fields[$field_name], 'use_phrases'); + $field_options = $object->GetFieldOptions($field_name); + foreach ($field_options['options'] as $key => $val) { + foreach ($search_keywords as $keyword => $sign) { + $pattern = '#'.$keyword.'#i'; + if (!preg_match($pattern, $use_phrases ? $this->Application->Phrase($val) : $val)) { + if ($sign == '+') { + $filter_value = $table_name.'`'.$field_name.'` = NULL'; + break; + } + else { + continue; + } + } + + if ($sign == '+' || $sign == '') { + $search_keys[$key] = $this->Conn->qstr($key); + } + elseif($sign == '-') { + // if same value if found as exclusive too, then remove from search result + unset($search_keys[$key]); + } + } + } + } + + if ($search_keys) { + $filter_value = $table_name.'`'.$field_name.'` IN ('.implode(',', $search_keys).')'; + } + + $field_processed = true; + break; + + case 'kDateFormatter': + $field_processed = true; + break; + + /*case 'kDateFormatter': // move to Custom Filters (by Alex) + $filter_value = Array(); + if ($field_name === false) { + $field_value = getArrayValue($custom_filter, $field_name.'_datefrom', 'submit_value'); + if ($field_value) { + $value = $this->processRangeField($event, $field_name, 'datefrom', $field_value, $formatter); + $filter_value[] = $table_name.'`'.$field_name.'` >= '.$value; + } + + $field_value = getArrayValue($custom_filter, $field_name.'_dateto', 'submit_value'); + if ($field_value) { + $value = $this->processRangeField($event, $field_name, 'dateto', $field_value, $formatter); + $filter_value[] = $table_name.'`'.$field_name.'` <= '.$value; + } + + $filter_value = $filter_value ? '('.implode(') AND (', $filter_value).')' : ''; + } + + $field_processed = true; + break;*/ + + default: + $field_processed = false; + break; + } + + // if not already processed by formatter, then get clause by field type + if (!$field_processed && $search_keywords) { + switch($field_type) + { + case 'int': + case 'integer': + case 'numeric': + $search_keys = Array(); + foreach ($search_keywords as $keyword => $sign) { + if (!is_numeric($keyword) || ($sign == '-')) continue; + $search_keys[] = $this->Conn->qstr($keyword); + } + + if ($search_keys) { + $filter_value = $table_name.'`'.$field_name.'` IN ('.implode(',', $search_keys).')'; + } + break; + + case 'double': + case 'float': + case 'real': + $search_keys = Array(); + foreach ($search_keywords as $keyword => $sign) { + $keyword = str_replace(',', '.', $keyword); + if (!is_numeric($keyword) || ($sign == '-')) continue; + $search_keys[] = 'ABS('.$table_name.'`'.$field_name.'` - '.$this->Conn->qstr($keyword).') <= 0.0001'; + } + + if ($search_keys) { + $filter_value = '('.implode(') OR (', $search_keys).')'; + } + break; + + case 'string': + $filter_value = $this->buildWhereClause($search_keyword, Array($table_name.'`'.$field_name.'`')); + break; + } + } + + if ($filter_value) { + return Array('type' => $sql_filter_type, 'value' => $filter_value); + } + + return false; + } + + /** + * Processes custom filters from submit + * + * @param KEvent $event + * @return bool + */ + function processCustomFilters(&$event) + { + $grid_name = $this->Application->GetVar('grid_name'); + + // update "custom filter" with values from submit: begin + $custom_filters = $this->Application->RecallVar($event->getPrefixSpecial().'_custom_filter'); + if ($custom_filters) { + $custom_filters = unserialize($custom_filters); + $custom_filter = isset($custom_filters[$grid_name]) ? $custom_filters[$grid_name] : Array (); + } + else { + $custom_filter = Array (); + } + + // submit format custom_filters[prefix_special][field] + $submit_filters = $this->Application->GetVar('custom_filters'); + if ($submit_filters) { + $submit_filters = getArrayValue($submit_filters, $event->getPrefixSpecial(), $grid_name); + if ($submit_filters) { + foreach ($submit_filters as $field_name => $field_options) { + list ($filter_type, $field_value) = each($field_options); + $is_empty = is_array($field_value) ? !implode('', $field_value) : !$field_value; + if ($is_empty) { + if (isset($custom_filter[$field_name])) { + // use isset, because non-existing key will cause "php notice"! + unset($custom_filter[$field_name][$filter_type]); // remove filter + + if (!$custom_filter[$field_name]) { + // if no filters left for field, then delete record at all + unset($custom_filter[$field_name]); + } + } + } + else { + $custom_filter[$field_name][$filter_type]['submit_value'] = $field_value; + } + } + } + } + + if ($custom_filter) { + $custom_filters[$grid_name] = $custom_filter; + } + else { + unset($custom_filters[$grid_name]); + } + // update "custom filter" with values from submit: end + + if (!$custom_filter) { + // in case when no filters specified, there are nothing to process + $this->Application->StoreVar($event->getPrefixSpecial().'_custom_filter', serialize($custom_filters) ); + return false; + } + + $object =& $event->getObject(); // don't recall it each time in getCustomFilterSearchClause + foreach ($custom_filter as $field_name => $field_options) { + list ($filter_type, $field_options) = each($field_options); + $field_options = $this->getCustomFilterSearchClause($object, $field_name, $filter_type, $field_options); + if ($field_options['value']) { + $custom_filter[$field_name][$filter_type] = $field_options; + } + } + + $custom_filters[$grid_name] = $custom_filter; + $this->Application->StoreVar($event->getPrefixSpecial().'_custom_filter', serialize($custom_filters) ); + return $custom_filter; + } + + function getCustomFilterSearchClause(&$object, $field_name, $filter_type, $field_options) + { + extract( $this->getFieldInformation($object, $field_name) ); // see getFieldInformation for more details + + $filter_value = ''; + + switch ($filter_type) { + case 'range': + $from = $field_options['submit_value']['from'] ? $this->Conn->qstr($field_options['submit_value']['from']) : false; + $to = $field_options['submit_value']['to'] ? $this->Conn->qstr($field_options['submit_value']['to']) : false; + + if ($from !== false && $to !== false) { + // add range filter + $filter_value = $table_name.'`'.$field_name.'` >= '.$from.' AND '.$table_name.'`'.$field_name.'` <= '.$to; + } + elseif ($from !== false && $to === false) { + // add equals filter on $from + $filter_value = $table_name.'`'.$field_name.'` = '.$from; + } + elseif ($from === false && $to !== false) { + // add equals filter on $to + $filter_value = $table_name.'`'.$field_name.'` = '.$to; + } + break; + + case 'date_range': + break; + + case 'equals': + case 'options': + $field_value = $field_options['submit_value'] ? $this->Conn->qstr($field_options['submit_value']) : false; + if ($field_value) { + $filter_value = $table_name.'`'.$field_name.'` = '.$field_value; + } + break; + + case 'like': + $filter_value = $this->buildWhereClause($field_options['submit_value'], Array($table_name.'`'.$field_name.'`')); + break; + + default: + break; + } + + $field_options['sql_filter_type'] = $sql_filter_type; + $field_options['value'] = $filter_value; + + return $field_options; + } + + /** + * Enter description here... + * + * @param kEvent $event + * @param string $search_field + * @param string $type + * @param string $value + * @param string $formatter_class + */ + function processRangeField(&$event, $search_field, $type, $value, $formatter_class) + { + $field = $search_field.'_'.$type; + $lang_current =& $this->Application->recallObject('lang.current'); + + $object =& $event->getObject(); + $dt_separator = getArrayValue( $object->GetFieldOptions($search_field), 'date_time_separator' ); + if(!$dt_separator) $dt_separator = ' '; + + $time = ($type == 'datefrom') ? adodb_mktime(0,0,0) : adodb_mktime(23,59,59); + $time = adodb_date( $lang_current->GetDBField('InputTimeFormat'), $time); + $full_value = $value.$dt_separator.$time; + + $formatter =& $this->Application->recallObject($formatter_class); + + $value_ts = $formatter->Parse($full_value, $search_field, $object); + $pseudo = getArrayValue($object->FieldErrors, $search_field, 'pseudo'); + if($pseudo) + { + $this->Application->StoreVar($event->getPrefixSpecial().'_'.$field.'_error', $pseudo); + return -1; + } + return $value_ts; + } + + + + } ?> \ No newline at end of file