Index: branches/RC/core/units/general/cat_event_handler.php =================================================================== diff -u -r9363 -r9398 --- branches/RC/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 9363) +++ branches/RC/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 9398) @@ -1072,15 +1072,19 @@ $this->Application->RemoveVar('keywords'); $this->Application->RemoveVar('Search_Keywords'); - $sql = ' SELECT * FROM '.$this->Application->getUnitOption('confs', 'TableName').' - WHERE ModuleName="In-Commerce" - AND AdvancedSearch=1'; + $module_name = $this->Application->findModule('Var', $event->Prefix, 'Name'); + + $sql = 'SELECT * + FROM '.$this->Application->getUnitOption('confs', 'TableName').' + WHERE (ModuleName = '.$this->Conn->qstr($module_name).') AND (AdvancedSearch = 1)'; $search_config = $this->Conn->Query($sql); + $lang = $this->Application->GetVar('m_lang'); $object =& $event->getObject(); $object->SetPage(1); - $product_table = $this->Application->getUnitOption('p', 'TableName'); + $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName'); + $search_keywords = $this->Application->GetVar('value'); // will not be changed $keywords = $this->Application->GetVar('value'); // will be changed down there @@ -1095,25 +1099,19 @@ $highlight_keywords = Array(); $relevance_parts = Array(); - $condition_patterns = Array( 'any' => '%s LIKE %s', - 'contains' => '%s LIKE %s', - 'notcontains' => '(NOT (%1$s LIKE %2$s) OR %1$s IS NULL)', - 'is' => '%s = %s', - 'isnot' => '(%1$s != %2$s OR %1$s IS NULL)'); - $alias_counter = 0; $custom_fields = $this->Application->getUnitOption($event->Prefix, 'CustomFields'); if ($custom_fields) { $custom_table = $this->Application->getUnitOption($event->Prefix.'-cdata', 'TableName'); - $join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$product_table.'.ResourceId = custom_data.ResourceId'; + $join_clauses[] = ' LEFT JOIN '.$custom_table.' custom_data ON '.$items_table.'.ResourceId = custom_data.ResourceId'; } $search_log = ''; $weight_sum = 0; + // processing fields and preparing conditions - foreach($search_config as $record) - { + foreach ($search_config as $record) { $field = $record['FieldName']; $join_clause = ''; $condition_mode = 'WHERE'; @@ -1158,7 +1156,7 @@ $field_name = $alias.'.'.$exploded[1]; $join_clause = str_replace('{ForeignTable}', $alias, $record['JoinClause']); - $join_clause = str_replace('{LocalTable}', $product_table, $join_clause); + $join_clause = str_replace('{LocalTable}', $items_table, $join_clause); if($record['CustomFieldId']) { @@ -1179,142 +1177,33 @@ $field_name = $local_table.'.'.$field_name; } - $condition = ''; - switch($record['FieldType']) - { - case 'select': - $keywords[$field] = unhtmlentities( $keywords[$field] ); - $condition = sprintf($condition_patterns['is'], $field_name, $this->Conn->qstr( $keywords[$field] )); - break; - - case 'text': - $keywords[$field] = unhtmlentities( $keywords[$field] ); - - if(strlen($keywords[$field]) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) - { - $highlight_keywords[] = $keywords[$field]; - if( in_array($verbs[$field], Array('any', 'contains', 'notcontains')) ) - { - $keywords[$field] = '%'.strtr($keywords[$field], Array('%' => '\\%', '_' => '\\_')).'%'; - } - $condition = sprintf( $condition_patterns[$verbs[$field]], - $field_name, - $this->Conn->qstr( $keywords[$field] )); - } - break; - - case 'boolean': - if($keywords[$field] != -1) - { - $property_mappings = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings'); - switch($field) - { - case 'HotItem': - $hot_limit_var = getArrayValue($property_mappings, 'HotLimit'); - if($hot_limit_var) - { - $sql = 'SELECT Data FROM '.TABLE_PREFIX.'Cache WHERE VarName="'.$hot_limit_var.'"'; - $hot_limit = (int)$this->Conn->GetOne($sql); - $condition = 'IF('.$product_table.'.HotItem = 2, - IF('.$product_table.'.Hits >= '. - $hot_limit. - ', 1, 0), '.$product_table.'.HotItem) = '.$keywords[$field]; - } - break; - case 'PopItem': - $votes2pop_var = getArrayValue($property_mappings, 'VotesToPop'); - $rating2pop_var = getArrayValue($property_mappings, 'RatingToPop'); - if($votes2pop_var && $rating2pop_var) - { - $condition = 'IF('.$product_table.'.PopItem = 2, IF('.$product_table.'.CachedVotesQty >= '. - $this->Application->ConfigValue($votes2pop_var). - ' AND '.$product_table.'.CachedRating >= '. - $this->Application->ConfigValue($rating2pop_var). - ', 1, 0), '.$product_table.'.PopItem) = '.$keywords[$field]; - } - break; - case 'NewItem': - $new_days_var = getArrayValue($property_mappings, 'NewDays'); - if($new_days_var) - { - $condition = 'IF('.$product_table.'.NewItem = 2, - IF('.$product_table.'.CreatedOn >= (UNIX_TIMESTAMP() - '. - $this->Application->ConfigValue($new_days_var). - '*3600*24), 1, 0), '.$product_table.'.NewItem) = '.$keywords[$field]; - } - break; - case 'EditorsPick': - $condition = $product_table.'.EditorsPick = '.$keywords[$field]; - break; - } - } - break; - - case 'range': - $range_conditions = Array(); - if($keywords[$field.'_from'] && !preg_match("/[^0-9]/i", $keywords[$field.'_from'])) - { - $range_conditions[] = $field_name.' >= '.$keywords[$field.'_from']; - } - if($keywords[$field.'_to'] && !preg_match("/[^0-9]/i", $keywords[$field.'_to'])) - { - $range_conditions[] = $field_name.' <= '.$keywords[$field.'_to']; - } - if($range_conditions) - { - $condition = implode(' AND ', $range_conditions); - } - break; - - case 'date': - if($keywords[$field]) - { - if( in_array($keywords[$field], Array('today', 'yesterday')) ) - { - $current_time = getdate(); - $day_begin = adodb_mktime(0, 0, 0, $current_time['mon'], $current_time['mday'], $current_time['year']); - $time_mapping = Array('today' => $day_begin, 'yesterday' => ($day_begin - 86400)); - $min_time = $time_mapping[$keywords[$field]]; - } - else - { - $time_mapping = Array( 'last_week' => 604800, 'last_month' => 2628000, - 'last_3_months' => 7884000, 'last_6_months' => 15768000, - 'last_year' => 31536000 - ); - $min_time = adodb_mktime() - $time_mapping[$keywords[$field]]; - } - $condition = $field_name.' > '.$min_time; - } - break; + $condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords); + if ($record['CustomFieldId'] && strlen($condition)) { + // search in primary value of custom field + value in current language + $field_name = $local_table.'.'.'l'.$this->Application->GetDefaultLanguageId().'_cust_'.array_search($field, $custom_fields); + $primary_condition = $this->getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, $highlight_keywords); + $condition = '('.$condition.' OR '.$primary_condition.')'; } - if($condition) - { - if($join_clause) - { + if ($condition) { + if ($join_clause) { $join_clauses[] = $join_clause; } + $relevance_parts[] = 'IF('.$condition.', '.$record['Priority'].', 0)'; - if($glues[$field] == 1) // and - { - if($condition_mode == 'WHERE') - { + if ($glues[$field] == 1) { // and + if ($condition_mode == 'WHERE') { $and_conditions[] = $condition; } - else - { + else { $and_having_conditions[] = $condition; } } - else // or - { - if($condition_mode == 'WHERE') - { + else { // or + if ($condition_mode == 'WHERE') { $or_conditions[] = $condition; } - else - { + else { $or_having_conditions[] = $condition; } } @@ -1325,18 +1214,21 @@ } } - $search_log = implode('
', $search_log); - $search_log = preg_replace('/(.*) '.preg_quote($this->Application->Phrase('lu_and'), '/').'|'.preg_quote($this->Application->Phrase('lu_or'), '/').'$/is', '\\1', $search_log); - $this->saveToSearchLog($search_log, 1); // advanced search + if ($search_log) { + $search_log = implode('
', $search_log); + $search_log = preg_replace('/(.*) '.preg_quote($this->Application->Phrase('lu_and'), '/').'|'.preg_quote($this->Application->Phrase('lu_or'), '/').'$/is', '\\1', $search_log); + $this->saveToSearchLog($search_log, 1); // advanced search + } $this->Application->StoreVar('highlight_keywords', serialize($highlight_keywords)); // making relevance clause if($relevance_parts) { - $rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_products') / 100; - $rel_pop = $this->Application->ConfigValue('SearchRel_Pop_products') / 100; - $rel_rating = $this->Application->ConfigValue('SearchRel_Rating_products') / 100; + $conf_postfix = $this->Application->getUnitOption($event->Prefix, 'SearchConfigPostfix'); + $rel_keywords = $this->Application->ConfigValue('SearchRel_Keyword_'.$conf_postfix) / 100; + $rel_pop = $this->Application->ConfigValue('SearchRel_Pop_'.$conf_postfix) / 100; + $rel_rating = $this->Application->ConfigValue('SearchRel_Rating_'.$conf_postfix) / 100; $relevance_clause = '('.implode(' + ', $relevance_parts).') / '.$weight_sum.' * '.$rel_keywords; $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop; $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating; @@ -1359,7 +1251,7 @@ { $and_conditions[] = '('.implode(' OR ', $or_conditions).')'; } -// $and_conditions[] = $product_table.'.Status = 1'; +// $and_conditions[] = $items_table.'.Status = 1'; $where_clause = implode(' AND ', $and_conditions); if(!$where_clause) { @@ -1373,29 +1265,163 @@ $this->Application->SetVar('adv_search_error', 1); } } - $where_clause .= ' AND '.$product_table.'.Status = 1'; + $where_clause .= ' AND '.$items_table.'.Status = 1'; // building final search query $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetSID().'_'.TABLE_PREFIX.'Search'; $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); + $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); + $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); + $pick_field = isset($fields['EditorsPick']) ? $items_table.'.EditorsPick' : '0'; + $sql = ' CREATE TABLE '.$search_table.' SELECT '.$relevance_clause.' AS Relevance, - '.$product_table.'.ProductId AS ItemId, - '.$product_table.'.ResourceId AS ResourceId, + '.$items_table.'.'.$id_field.' AS ItemId, + '.$items_table.'.ResourceId AS ResourceId, 11 AS ItemType, - '.$product_table.'.EditorsPick AS EdPick - FROM '.$product_table.' + '.$pick_field.' AS EdPick + FROM '.$items_table.' '.implode(' ', $join_clauses).' WHERE '.$where_clause.' - GROUP BY '.$product_table.'.ProductId'. + GROUP BY '.$items_table.'.'.$id_field. $having_clause; $res = $this->Conn->Query($sql); } + function getAdvancedSearchCondition($field_name, $record, $keywords, $verbs, &$highlight_keywords) + { + $field = $record['FieldName']; + $condition_patterns = Array ( + 'any' => '%s LIKE %s', + 'contains' => '%s LIKE %s', + 'notcontains' => '(NOT (%1$s LIKE %2$s) OR %1$s IS NULL)', + 'is' => '%s = %s', + 'isnot' => '(%1$s != %2$s OR %1$s IS NULL)' + ); + + $condition = ''; + switch ($record['FieldType']) { + case 'select': + $keywords[$field] = unhtmlentities( $keywords[$field] ); + if ($keywords[$field]) { + $condition = sprintf($condition_patterns['is'], $field_name, $this->Conn->qstr( $keywords[$field] )); + } + break; + + case 'multiselect': + $keywords[$field] = unhtmlentities( $keywords[$field] ); + if ($keywords[$field]) { + $condition = Array (); + $values = explode('|', substr($keywords[$field], 1, -1)); + foreach ($values as $selected_value) { + $condition[] = sprintf($condition_patterns['contains'], $field_name, $this->Conn->qstr('%|'.$selected_value.'|%')); + } + $condition = '('.implode(' OR ', $condition).')'; + } + break; + + case 'text': + $keywords[$field] = unhtmlentities( $keywords[$field] ); + + if (strlen($keywords[$field]) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) { + $highlight_keywords[] = $keywords[$field]; + if (in_array($verbs[$field], Array('any', 'contains', 'notcontains'))) { + $keywords[$field] = '%'.strtr($keywords[$field], Array('%' => '\\%', '_' => '\\_')).'%'; + } + $condition = sprintf($condition_patterns[$verbs[$field]], $field_name, $this->Conn->qstr( $keywords[$field] )); + } + break; + + case 'boolean': + if ($keywords[$field] != -1) { + $property_mappings = $this->Application->getUnitOption($this->Prefix, 'ItemPropertyMappings'); + $items_table = $this->Application->getUnitOption($event->Prefix, 'TableName'); + + switch ($field) { + case 'HotItem': + $hot_limit_var = getArrayValue($property_mappings, 'HotLimit'); + if ($hot_limit_var) { + $sql = 'SELECT Data + FROM '.TABLE_PREFIX.'Cache + WHERE VarName = "'.$hot_limit_var.'"'; + $hot_limit = (int)$this->Conn->GetOne($sql); + + $condition = 'IF('.$items_table.'.HotItem = 2, + IF('.$items_table.'.Hits >= '. + $hot_limit. + ', 1, 0), '.$items_table.'.HotItem) = '.$keywords[$field]; + } + break; + + case 'PopItem': + $votes2pop_var = getArrayValue($property_mappings, 'VotesToPop'); + $rating2pop_var = getArrayValue($property_mappings, 'RatingToPop'); + if ($votes2pop_var && $rating2pop_var) { + $condition = 'IF('.$items_table.'.PopItem = 2, IF('.$items_table.'.CachedVotesQty >= '. + $this->Application->ConfigValue($votes2pop_var). + ' AND '.$items_table.'.CachedRating >= '. + $this->Application->ConfigValue($rating2pop_var). + ', 1, 0), '.$items_table.'.PopItem) = '.$keywords[$field]; + } + break; + + case 'NewItem': + $new_days_var = getArrayValue($property_mappings, 'NewDays'); + if ($new_days_var) { + $condition = 'IF('.$items_table.'.NewItem = 2, + IF('.$items_table.'.CreatedOn >= (UNIX_TIMESTAMP() - '. + $this->Application->ConfigValue($new_days_var). + '*3600*24), 1, 0), '.$items_table.'.NewItem) = '.$keywords[$field]; + } + break; + + case 'EditorsPick': + $condition = $items_table.'.EditorsPick = '.$keywords[$field]; + break; + } + } + break; + + case 'range': + $range_conditions = Array(); + if ($keywords[$field.'_from'] && !preg_match("/[^0-9]/i", $keywords[$field.'_from'])) { + $range_conditions[] = $field_name.' >= '.$keywords[$field.'_from']; + } + if ($keywords[$field.'_to'] && !preg_match("/[^0-9]/i", $keywords[$field.'_to'])) { + $range_conditions[] = $field_name.' <= '.$keywords[$field.'_to']; + } + if ($range_conditions) { + $condition = implode(' AND ', $range_conditions); + } + break; + + case 'date': + if ($keywords[$field]) { + if (in_array($keywords[$field], Array('today', 'yesterday'))) { + $current_time = getdate(); + $day_begin = adodb_mktime(0, 0, 0, $current_time['mon'], $current_time['mday'], $current_time['year']); + $time_mapping = Array('today' => $day_begin, 'yesterday' => ($day_begin - 86400)); + $min_time = $time_mapping[$keywords[$field]]; + } + else { + $time_mapping = Array ( + 'last_week' => 604800, 'last_month' => 2628000, 'last_3_months' => 7884000, + 'last_6_months' => 15768000, 'last_year' => 31536000, + ); + $min_time = adodb_mktime() - $time_mapping[$keywords[$field]]; + } + $condition = $field_name.' > '.$min_time; + } + break; + } + + return $condition; + } + function getHuman($type, $search_data) { $type = ucfirst(strtolower($type)); @@ -1430,7 +1456,7 @@ $ret = $this->Application->Phrase($values[$value]); break; - case 'text': + default: $ret = $value; break;