Index: trunk/core/kernel/db/db_tag_processor.php =================================================================== diff -u -N -r6703 -r6751 --- trunk/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 6703) +++ trunk/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 6751) @@ -137,6 +137,7 @@ $block_params['name'] = isset($options[$mode.'_block']) ? $options[$mode.'_block'] : $def_block; $block_params['field'] = $field; $block_params['sort_field'] = isset($options['sort_field']) ? $options['sort_field'] : $field; + $block_params['filter_field'] = isset($options['filter_field']) ? $options['filter_field'] : $field; $block_params = array_merge($std_params, $block_params, $options); $o.= $this->Application->ParseBlock($block_params, 1); } @@ -742,16 +743,10 @@ $object =& $this->getObject($params); $field = $params['field']; $saved_value = $object->GetDBField($field); - - $custom_filters = $this->Application->RecallVar( $this->getPrefixSpecial().'_custom_filters'); - if ($custom_filters) { - $custom_filters = unserialize($custom_filters); - $append = getArrayValue($params, 'type') ? '_'.$params['type'] : ''; - $object->SetDBField($field, $custom_filters[$field.$append]); - } - else { - $object->SetDBField($field, ''); - } + + $object->SetDBField($field, $this->SearchField($params)); + $custom_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_custom_filter'); + $ret = $this->PredefinedOptions($params); $object->SetDBField($field, $saved_value); return $ret; @@ -1419,9 +1414,14 @@ function SearchInputName($params) { $field = $this->SelectParam($params, 'field,name'); - $append = getArrayValue($params, 'type') ? '_'.$params['type'] : ''; - return 'custom_filters['.$this->getPrefixSpecial().']['.$field.$append.']'; + $ret = 'custom_filters['.$this->getPrefixSpecial().']['.$params['grid'].']['.$field.']['.$params['filter_type'].']'; + + if (isset($params['type'])) { + $ret .= '['.$params['type'].']'; + } + + return $ret; } /** @@ -1434,12 +1434,18 @@ { $field = $this->SelectParam($params, 'field,name'); - $custom_filters = $this->Application->RecallVar($this->getPrefixSpecial().'_custom_filters'); - $custom_filters = $custom_filters ? unserialize($custom_filters) : Array(); + $custom_filter = $this->Application->RecallVar($this->getPrefixSpecial().'_custom_filter'); + $custom_filter = $custom_filter ? unserialize($custom_filter) : Array(); - $append = getArrayValue($params, 'type'); - - return getArrayValue($custom_filters, $field.( $append ? '_'.$append : '') ); + if (isset($custom_filter[ $params['grid'] ][$field])) { + $ret = $custom_filter[ $params['grid'] ][$field][ $params['filter_type'] ]['submit_value']; + if (isset($params['type'])) { + $ret = $ret[ $params['type'] ]; + } + return $ret; + } + + return ''; } function SearchFormat($params) Index: trunk/core/kernel/db/dblist.php =================================================================== diff -u -N -r6428 -r6751 --- trunk/core/kernel/db/dblist.php (.../dblist.php) (revision 6428) +++ trunk/core/kernel/db/dblist.php (.../dblist.php) (revision 6751) @@ -1,29 +1,5 @@ OrderFields = Array(); - $this->WhereFilter[FLT_SYSTEM] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_AND); - $this->WhereFilter[FLT_NORMAL] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_OR); + + $filters = $this->getFilterStructure(); + + foreach ($filters as $filter_params) { + $filter =& $this->$filter_params['type']; + $filter[ $filter_params['class'] ] =& $this->Application->makeClass('kMultipleFilter', $filter_params['join_using']); + } - $this->WhereFilter[FLT_SEARCH] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_OR); - $this->WhereFilter[FLT_VIEW] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_AND); - - $this->HavingFilter[FLT_SYSTEM] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_AND); - $this->HavingFilter[FLT_NORMAL] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_OR); - - $this->HavingFilter[FLT_SEARCH] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_OR); - $this->HavingFilter[FLT_VIEW] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_AND); - - $this->AggregateFilter[FLT_SYSTEM] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_AND); - $this->AggregateFilter[FLT_NORMAL] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_OR); - $this->AggregateFilter[FLT_VIEW] =& $this->Application->makeClass('kMultipleFilter', FLT_TYPE_AND); - $this->PerPage = -1; } /** + * Returns information about all possible filter types + * + * @return Array + */ + function getFilterStructure() + { + $filters = Array ( + Array ('type' => 'WhereFilter', 'class' => FLT_SYSTEM, 'join_using' => FLT_TYPE_AND), + Array ('type' => 'WhereFilter', 'class' => FLT_NORMAL, 'join_using' => FLT_TYPE_OR), + Array ('type' => 'WhereFilter', 'class' => FLT_SEARCH, 'join_using' => FLT_TYPE_OR), + Array ('type' => 'WhereFilter', 'class' => FLT_VIEW, 'join_using' => FLT_TYPE_AND), + Array ('type' => 'WhereFilter', 'class' => FLT_CUSTOM, 'join_using' => FLT_TYPE_AND), + + Array ('type' => 'HavingFilter', 'class' => FLT_SYSTEM, 'join_using' => FLT_TYPE_AND), + Array ('type' => 'HavingFilter', 'class' => FLT_NORMAL, 'join_using' => FLT_TYPE_OR), + Array ('type' => 'HavingFilter', 'class' => FLT_SEARCH, 'join_using' => FLT_TYPE_OR), + Array ('type' => 'HavingFilter', 'class' => FLT_VIEW, 'join_using' => FLT_TYPE_AND), + Array ('type' => 'HavingFilter', 'class' => FLT_CUSTOM, 'join_using' => FLT_TYPE_AND), + + Array ('type' => 'AggregateFilter', 'class' => FLT_SYSTEM, 'join_using' => FLT_TYPE_AND), + Array ('type' => 'AggregateFilter', 'class' => FLT_NORMAL, 'join_using' => FLT_TYPE_OR), + Array ('type' => 'AggregateFilter', 'class' => FLT_VIEW, 'join_using' => FLT_TYPE_AND), + ); + + return $filters; + } + + /** * Adds new or replaces old filter with same name * * @param string $name filter name (for internal use) * @param string $clause where/having clause part (no OR/AND allowed) * @param int $filter_type is filter having filter or where filter - * @param int $filter_scope filter subtype: FLT_NORMAL,FLT_SYSTEM,FLT_SEARCH,FLT_VIEW + * @param int $filter_scope filter subtype: FLT_NORMAL,FLT_SYSTEM,FLT_SEARCH,FLT_VIEW,FLT_CUSTOM * @access public */ function addFilter($name, $clause, $filter_type = WHERE_FILTER, $filter_scope = FLT_SYSTEM) @@ -210,7 +206,7 @@ * * @param string $name filter name (for internal use) * @param int $filter_type is filter having filter or where filter - * @param int $filter_scope filter subtype: FLT_NORMAL,FLT_SYSTEM,FLT_SEARCH,FLT_VIEW + * @param int $filter_scope filter subtype: FLT_NORMAL,FLT_SYSTEM,FLT_SEARCH,FLT_VIEW,FLT_CUSTOM * @access public */ function removeFilter($name, $filter_type = WHERE_FILTER, $filter_scope = FLT_SYSTEM) @@ -228,32 +224,15 @@ /** * Clear list filters * - * @param bool $user clear user filters - * @param bool $system clear system filters */ - function clearFilters($user=true,$system=true,$search=true,$view=true) + function clearFilters() { - if ($system) { - $this->WhereFilter[FLT_SYSTEM]->clearFilters(); - $this->HavingFilter[FLT_SYSTEM]->clearFilters(); - $this->AggregateFilter[FLT_SYSTEM]->clearFilters(); - } - - if ($user) { - $this->WhereFilter[FLT_NORMAL]->clearFilters(); - $this->HavingFilter[FLT_NORMAL]->clearFilters(); - $this->AggregateFilter[FLT_NORMAL]->clearFilters(); - } - - if ($search) { - $this->WhereFilter[FLT_SEARCH]->clearFilters(); - $this->HavingFilter[FLT_SEARCH]->clearFilters(); - } - - if ($view) { - $this->WhereFilter[FLT_VIEW]->clearFilters(); - $this->HavingFilter[FLT_VIEW]->clearFilters(); - } + $filters = $this->getFilterStructure(); + + foreach ($filters as $filter_params) { + $filter =& $this->$filter_params['type']; + $filter[ $filter_params['class'] ]->clearFilters(); + } } /** @@ -458,12 +437,20 @@ if (!$system_filters_only) { $where->addFilter('view_where', $this->WhereFilter[FLT_VIEW] ); $search_w = $this->WhereFilter[FLT_SEARCH]->getSQL(); - if( $search_w || $for_counting ) // move search_having to search_where in case search_where isset or we are counting - { + if ($search_w || $for_counting) { // move search_having to search_where in case search_where isset or we are counting $search_h = $this->extractCalculatedFields( $this->HavingFilter[FLT_SEARCH]->getSQL() ); $search_w = ($search_w && $search_h) ? $search_w.' OR '.$search_h : $search_w.$search_h; $where->addFilter('search_where', $search_w ); } + + // CUSTOM + $search_w = $this->WhereFilter[FLT_CUSTOM]->getSQL(); + if ($search_w || $for_counting) { // move search_having to search_where in case search_where isset or we are counting + $search_h = $this->extractCalculatedFields( $this->HavingFilter[FLT_CUSTOM]->getSQL() ); + $search_w = ($search_w && $search_h) ? $search_w.' AND '.$search_h : $search_w.$search_h; + $where->addFilter('custom_where', $search_w ); + } + // CUSTOM } if( $for_counting ) // add system_having and view_having to where @@ -523,6 +510,7 @@ if (!$system_filters_only) { $having->addFilter('view_having', $this->HavingFilter[FLT_VIEW] ); + $having->addFilter('custom_having', $this->HavingFilter[FLT_CUSTOM] ); $search_w = $this->WhereFilter[FLT_SEARCH]->getSQL(); if (!$search_w) { $having->addFilter('search_having', $this->HavingFilter[FLT_SEARCH] ); Index: trunk/core/kernel/constants.php =================================================================== diff -u -N -r6656 -r6751 --- trunk/core/kernel/constants.php (.../constants.php) (revision 6656) +++ trunk/core/kernel/constants.php (.../constants.php) (revision 6751) @@ -1,13 +1,21 @@ 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 Index: trunk/core/admin_templates/img/toolbar/tool_search.gif =================================================================== diff -u -N Binary files differ Index: trunk/core/admin_templates/img/toolbar/tool_search_reset.gif =================================================================== diff -u -N Binary files differ Index: trunk/core/kernel/db/db_event_handler.php =================================================================== diff -u -N -r6647 -r6751 --- trunk/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 6647) +++ trunk/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 6751) @@ -653,8 +653,27 @@ } } - /** + * Adds filters found in session to object + * + * @param kEvent $event + * @param string $session_var variable name in session, where filter is stored + * @param string $filter_class filter class, e.g. FLT_SYSTEM, FLT_NORMAL, etc. + */ + function addStoredFilter(&$event, $session_var, $filter_class) + { + $filter_data = $this->Application->RecallVar($event->getPrefixSpecial().'_'.$session_var); + if ($filter_data) { + $object =& $event->getObject(); + $filter_data = unserialize($filter_data); + foreach ($filter_data as $filter_field => $filter_params) { + $filter_type = ($filter_params['type'] == 'having') ? HAVING_FILTER : WHERE_FILTER; + $object->addFilter($filter_field, $filter_params['value'], $filter_type, $filter_sub_type); + } + } + } + + /** * Add filters found in session * * @param kEvent $event @@ -663,16 +682,31 @@ { $object =& $event->getObject(); - $search_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_search_filter'); - if($search_filter) - { - $search_filter = unserialize($search_filter); - foreach($search_filter as $search_field => $filter_params) - { + // add search filter + $filter_data = $this->Application->RecallVar($event->getPrefixSpecial().'_search_filter'); + if ($filter_data) { + $filter_data = unserialize($filter_data); + foreach ($filter_data as $filter_field => $filter_params) { $filter_type = ($filter_params['type'] == 'having') ? HAVING_FILTER : WHERE_FILTER; - $object->addFilter($search_field, $filter_params['value'], $filter_type, FLT_SEARCH); + $object->addFilter($filter_field, $filter_params['value'], $filter_type, FLT_SEARCH); } } + + // add custom filter + $custom_filters = $this->Application->RecallVar($event->getPrefixSpecial().'_custom_filter'); + if ($custom_filters) { + $grid_name = $event->getEventParam('grid'); + $custom_filters = unserialize($custom_filters); + if (isset($custom_filters[$grid_name])) { + foreach ($custom_filters[$grid_name] as $field_name => $field_options) { + list ($filter_type, $field_options) = each($field_options); + if ($field_options['value']) { + $filter_type = ($field_options['sql_filter_type'] == 'having') ? HAVING_FILTER : WHERE_FILTER; + $object->addFilter($field_name, $field_options['value'], $filter_type, FLT_CUSTOM); + } + } + } + } $view_filter = $this->Application->RecallVar($event->getPrefixSpecial().'_view_filter'); if($view_filter) @@ -1465,41 +1499,6 @@ } /** - * 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; - } - - - /** * Ensures that popup will be closed automatically * and parent window will be refreshed with template * passed @@ -1532,6 +1531,7 @@ $this->Application->StoreVar('opener_stack', serialize($opener_stack)); } + /** * Create search filters based on search query * @@ -1541,192 +1541,9 @@ function OnSearch(&$event) { $event->setPseudoClass('_List'); - $object =& $event->getObject(); - - $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_filters = $this->Application->RecallVar( $event->getPrefixSpecial().'_custom_filters'); - $custom_filters = $custom_filters ? unserialize($custom_filters) : Array(); - - $submit_custom_filters = $this->Application->GetVar('custom_filters'); - - if ($submit_custom_filters) { - $submit_custom_filters = getArrayValue($submit_custom_filters, $event->getPrefixSpecial() ); - - if ($submit_custom_filters) { - foreach ($submit_custom_filters as $cf_name => $cf_value) { - if ($cf_value) { - $custom_filters[$cf_name] = $cf_value; - } - else { - unset($custom_filters[$cf_name]); - } - } - } - } - $this->Application->StoreVar($event->getPrefixSpecial().'_custom_filters', serialize($custom_filters) ); - - if( !$search_keyword && !count($custom_filters) ) - { - $this->OnSearchReset($event); - return true; - } - - $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(); + $search_helper =& $this->Application->recallObject('SearchHelper'); - $search_keywords = $search_helper->splitKeyword($search_keyword); - - foreach($search_fields as $search_field) - { - $filter_type = isset($object->VirtualFields[$search_field]) ? 'having' : 'where'; - $field_type = getArrayValue($object->Fields[$search_field],'type'); - if(!$field_type) $field_type = 'string'; // default LIKE filter for all fields without type - - $filter_value = ''; - - if (preg_match('/(.*)\.(.*)/', $search_field, $regs)) { - $table_name = '`'.$regs[1].'`.'; - $search_field = $regs[2]; - } - elseif ($filter_type == 'where') { - $table_name = '`'.$object->TableName.'`.'; - } - - $table_name = ($filter_type == 'where') ? $table_name : ''; - - // get field clause by formatter name and/or parameters - $formatter = getArrayValue($object->Fields[$search_field],'formatter'); - switch($formatter) - { - case 'kOptionsFormatter': - $search_keys = Array(); - - $field_value = getArrayValue($custom_filters, $search_field); - if ($field_value !== false) { - // if keyword passed through advanced search filter (e.g. on Visits lists section) - array_push($search_keys, $this->Conn->qstr($field_value)); - } - else { - // if keywords passed through simple search filter (on each grid) - $use_phrases = getArrayValue($object->Fields[$search_field], 'use_phrases'); - $field_options = $object->GetFieldOptions($search_field); - 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.'`'.$search_field.'` = 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.'`'.$search_field.'` IN ('.implode(',', $search_keys).')'; - } - - $field_processed = true; - break; - - case 'kDateFormatter': - $custom_filter = getArrayValue($object->Fields[$search_field], 'custom_filter'); - if(!$custom_filter) - { - $field_processed = false; - break; - } - - $filter_value = Array(); - - $field_value = getArrayValue($custom_filters, $search_field.'_datefrom'); - if($field_value) - { - $value = $this->processRangeField($event, $search_field, 'datefrom', $field_value, $formatter); - $filter_value[] = $table_name.'`'.$search_field.'` >= '.$value; - } - - $field_value = getArrayValue($custom_filters, $search_field.'_dateto'); - if($field_value) - { - $value = $this->processRangeField($event, $search_field, 'dateto', $field_value, $formatter); - $filter_value[] = $table_name.'`'.$search_field.'` <= '.$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.'`'.$search_field.'` 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.'`'.$search_field.'` - '.$this->Conn->qstr($keyword).') <= 0.0001'; - } - - if ($search_keys) { - $filter_value = '('.implode(') OR (', $search_keys).')'; - } - break; - - case 'string': - $filter_value = $search_helper->buildWhereClause($search_keyword, Array($table_name.'`'.$search_field.'`')); - break; - } - } - - if ($filter_value) { - $search_filter[$search_field] = Array('type' => $filter_type, 'value' => $filter_value); - } - } - - $this->Application->StoreVar($event->getPrefixSpecial().'_search_filter', serialize($search_filter) ); + $search_helper->performSearch($event); } /** @@ -1740,7 +1557,7 @@ $this->Application->RemoveVar($event->getPrefixSpecial().'_search_filter'); $this->Application->RemoveVar($event->getPrefixSpecial().'_search_keyword'); - $this->Application->RemoveVar($event->getPrefixSpecial().'_custom_filters'); + $this->Application->RemoveVar($event->getPrefixSpecial().'_custom_filter'); } /** Index: trunk/core/admin_templates/incs/form_blocks.tpl =================================================================== diff -u -N -r6703 -r6751 --- trunk/core/admin_templates/incs/form_blocks.tpl (.../form_blocks.tpl) (revision 6703) +++ trunk/core/admin_templates/incs/form_blocks.tpl (.../form_blocks.tpl) (revision 6751) @@ -293,7 +293,7 @@ - + ">