Index: trunk/kernel/units/general/cat_event_handler.php =================================================================== diff -u -r2596 -r2826 --- trunk/kernel/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 2596) +++ trunk/kernel/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 2826) @@ -181,6 +181,724 @@ break; } */ } + + /** + * Adds calculates fields for item statuses + * + * @param kCatDBItem $object + * @param kEvent $event + */ + function PrepareObject(&$object, &$event) + { + + $property_mappings = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings'); + + $new_days_var = getArrayValue($property_mappings, 'NewDays'); + if($new_days_var) + { + $object->addCalculatedField('IsNew', ' IF(%1$s.NewItem = 2, + IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '. + $this->Application->ConfigValue($new_days_var). + '*3600*24), 1, 0), + %1$s.NewItem + )'); + } + + $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 = $this->Conn->GetOne($sql); + if($hot_limit === false) $hot_limit = $this->CalculateHotLimit($event); + $object->addCalculatedField('IsHot', ' IF(%1$s.HotItem = 2, + IF(%1$s.Hits >= '.$hot_limit.', 1, 0), + %1$s.HotItem + )'); + } + + $votes2pop_var = getArrayValue($property_mappings, 'VotesToPop'); + $rating2pop_var = getArrayValue($property_mappings, 'RatingToPop'); + + if($votes2pop_var && $rating2pop_var) + { + $object->addCalculatedField('IsPop', ' IF(%1$s.PopItem = 2, + IF(%1$s.CachedVotesQty >= '. + $this->Application->ConfigValue($votes2pop_var). + ' AND %1$s.CachedRating >= '. + $this->Application->ConfigValue($rating2pop_var). + ', 1, 0), + %1$s.PopItem)'); + } + } + + function CalculateHotLimit(&$event) + { + $property_mappings = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings'); + $hot_count_var = getArrayValue($property_mappings, 'HotCount'); + $hot_limit_var = getArrayValue($property_mappings, 'HotLimit'); + + if($hot_count_var && $hot_limit_var) + { + $last_hot = $this->Application->ConfigValue($hot_count_var) - 1; + $sql = 'SELECT Hits FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' + ORDER BY Hits DESC + LIMIT '.$last_hot.', 1'; + $res = $this->Conn->GetCol($sql); + $hot_limit = (double)array_shift($res); + $this->Conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache VALUES ("'.$hot_limit_var.'", "'.$hot_limit.'", '.mktime().')'); + return $hot_limit; + } + return 0; + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnBeforeItemUpdate(&$event) + { + $object =& $event->getObject(); + if( $this->Application->IsAdmin() && ($this->Application->GetVar('Hits_original') !== false) && + floor($this->Application->GetVar('Hits_original')) != $object->GetDBField('Hits') ) + { + $sql = 'SELECT MAX(Hits) FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' + WHERE FLOOR(Hits) = '.$object->GetDBField('Hits'); + $hits = ( $res = $this->Conn->GetOne($sql) ) ? $res + 0.000001 : $object->GetDBField('Hits'); + $object->SetDBField('Hits', $hits); + } + } + + function OnAfterItemUpdate(&$event) + { + $this->CalculateHotLimit($event); + } + + /** + * Makes simple search for products + * based on keywords string + * + * @param kEvent $event + * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!! + */ + function OnSimpleSearch(&$event) + { + if($this->Application->GetVar('INPORTAL_ON') && !($this->Application->GetVar('Action') == 'm_simple_search')) + { + return; + } + + $event->redirect = false; + $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetVar('sid').'_'.TABLE_PREFIX.'Search'; + + $keywords = trim($this->Application->GetVar('keywords')); + if( !$this->Application->GetVar('INPORTAL_ON') ) + { + $keywords = unhtmlentities($keywords); + } + + $query_object =& $this->Application->recallObject('HTTPQuery'); + $sql = 'SHOW TABLES LIKE "'.$search_table.'"'; + + if(!isset($query_object->Get['keywords']) && + !isset($query_object->Post['keywords']) && + $this->Conn->Query($sql)) + { + return; // used when navigating by pages or changing sorting in search results + } + if(!$keywords || strlen($keywords) < $this->Application->ConfigValue('Search_MinKeyword_Length')) + { + $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); + $this->Application->SetVar('keywords_too_short', 1); + return; // if no or too short keyword entered, doing nothing + } + + $this->Application->StoreVar('keywords', $keywords); + + $keywords = strtr($keywords, Array('%' => '\\%', '_' => '\\_')); + + $event->setPseudoClass('_List'); + $object =& $event->getObject(); + $this->Application->SetVar($event->getPrefixSpecial().'_Page', 1); + $lang = $this->Application->GetVar('m_lang'); + $product_table = $this->Application->getUnitOption('p', 'TableName'); + + $sql = ' SELECT * FROM '.$this->Application->getUnitOption('confs', 'TableName').' + WHERE ModuleName="In-Commerce" + AND SimpleSearch=1'; + $search_config = $this->Conn->Query($sql, 'FieldName'); + $field_list = array_keys($search_config); + + $join_clauses = Array(); + + // field processing + $weight_sum = 0; + foreach($field_list as $key => $field) + { + $options = $object->getFieldOptions($field); + $local_table = TABLE_PREFIX.$search_config[$field]['TableName']; + $weight_sum += $search_config[$field]['Priority']; // counting weight sum; used when making relevance clause + + // processing multilingual fields + if($options['formatter'] == 'kMultiLanguage') + { + $field_list[$key] = 'l'.$lang.'_'.$field; + } + + // processing fields from other tables + if($foreign_field = $search_config[$field]['ForeignField']) + { + $exploded = explode(':', $foreign_field, 2); + if($exploded[0] == 'CALC') + { + unset($field_list[$key]); + continue; // ignoring having type clauses in simple search + /*$user_object =& $this->Application->recallObject('u'); + $user_groups = $user_object->GetDBField('PortalUserId') ? + implode(',', $this->Conn->GetCol(' SELECT GroupId + FROM '.TABLE_PREFIX.'UserGroup + WHERE PortalUserId='.$user_object->GetDBField('PortalUserId'))) : 0; + $having_list[$key] = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]); + $join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $search_config[$field]['JoinClause']); + $join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause); + $join_clause = ' LEFT JOIN '.$join_clause; + $join_clauses[] = $join_clause;*/ + } + else + { + $exploded = explode('.', $foreign_field); + $foreign_table = TABLE_PREFIX.$exploded[0]; + + $alias_counter++; + $alias = 't'.$alias_counter; + + $field_list[$key] = $alias.'.'.$exploded[1]; + $join_clause = str_replace('{ForeignTable}', $alias, $search_config[$field]['JoinClause']); + $join_clause = str_replace('{LocalTable}', $product_table, $join_clause); + if($search_config[$field]['CustomFieldId']) + { + $join_clause .= ' AND '.$alias.'.CustomFieldId='.$search_config[$field]['CustomFieldId']; + } + $join_clauses[] = ' LEFT JOIN '.$foreign_table.' '.$alias.' + ON '.$join_clause; + } + } + else + { + // processing fields from local table + $field_list[$key] = $local_table.'.'.$field_list[$key]; + } + } + + // keyword string processing + $normal_keywords = Array(); + $plus_keywords = Array(); + $minus_keywords = Array(); + + for($i = 0; $i < strlen($keywords); $i++) + { + if(substr($keywords, $i, 1) == ' ') continue; + $extra_skip = 0; + switch(substr($keywords, $i, 1)) + { + case '+': + if(substr($keywords, $i + 1, 1) == '"') + { + $keyword_start = $i + 2; + $keyword_end = strpos($keywords, '"', $i + 2); + $extra_skip = 2; + } + else + { + $keyword_start = $i + 1; + $keyword_end = strpos($keywords, ' ', $i + 1); + $extra_skip = 0; + } + $target_array =& $plus_keywords; + break; + case '-': + if(substr($keywords, $i + 1, 1) == '"') + { + $keyword_start = $i + 2; + $keyword_end = strpos($keywords, '"', $i + 2); + $extra_skip = 2; + } + else + { + $keyword_start = $i + 1; + $keyword_end = strpos($keywords, ' ', $i + 1); + $extra_skip = 0; + } + $target_array =& $minus_keywords; + break; + case '"': + $keyword_start = $i + 1; + $keyword_end = strpos($keywords, '"', $i + 1); + $extra_skip = 1; + $target_array =& $normal_keywords; + break; + default: + $keyword_start = $i; + $keyword_end = strpos($keywords, ' ', $i + 1); + $target_array =& $normal_keywords; + } + + if($keyword_end === false) + { + $keyword_end = strlen($keywords); + } + $keyword_length = $keyword_end - $keyword_start; + $keyword = substr($keywords, $keyword_start, $keyword_length); + + if(strlen($keyword) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) + { + $target_array[] = addcslashes($keyword, '"'); + } + + $i += $keyword_length + $extra_skip; + } + + // preparing conditions + $normal_conditions = Array(); + $plus_conditions = Array(); + $minus_conditions = Array(); + foreach($normal_keywords as $keyword) + { + $normal_conditions[] = implode(' LIKE "%'.$keyword.'%" OR ', $field_list).' LIKE "%'.$keyword.'%"'; + } + foreach($plus_keywords as $keyword) + { + $plus_conditions[] = implode(' LIKE "%'.$keyword.'%" OR ', $field_list).' LIKE "%'.$keyword.'%"'; + } + foreach($minus_keywords as $keyword) + { + foreach($field_list as $field) + { + $condition[] = $field.' NOT LIKE "%'.$keyword.'%" OR '.$field.' IS NULL'; + } + $minus_conditions[] = '('.implode(') AND (', $condition).')'; + } + + // building where clause + if($normal_conditions) + { + $where_clause = '('.implode(') OR (', $normal_conditions).')'; + } + else + { + $where_clause = '1'; + } + if($plus_conditions) + { + $where_clause = '('.$where_clause.') AND ('.implode(') AND (', $plus_conditions).')'; + } + if($minus_conditions) + { + $where_clause = '('.$where_clause.') AND ('.implode(') AND (', $minus_conditions).')'; + } + $where_clause = $where_clause.' AND '.$product_table.'.Status=1'; + + if($this->Application->GetVar('Action') == 'm_simple_subsearch') // subsearch, In-portal + { + if( $event->getEventParam('ResultIds') ) + { + $where_clause .= ' AND '.$product_table.'.ResourceId IN ('.implode(',', $event->specificParams['ResultIds']).')'; + } + } + if( $event->MasterEvent && $event->MasterEvent->Name == 'OnListBuild' ) // subsearch, k4 + { + if( $event->MasterEvent->getEventParam('ResultIds') ) + { + $where_clause .= ' AND '.$product_table.'.ResourceId IN ('.implode(',', $event->MasterEvent->getEventParam('ResultIds')).')'; + } + } + + // building having clause + + + // making relevance clause + $positive_words = array_merge($normal_keywords, $plus_keywords); + $this->Application->StoreVar('highlight_keywords', serialize($positive_words)); + $revelance_parts = Array(); + reset($search_config); + foreach($field_list as $field) + { + $config_elem = each($search_config); + $weight = $search_config[$field]['Priority']; + $revelance_parts[] = 'IF('.$field.' LIKE "%'.implode(' ', $positive_words).'%", '.$weight_sum.', 0)'; + foreach($positive_words as $keyword) + { + $revelance_parts[] = 'IF('.$field.' LIKE "%'.$keyword.'%", '.$config_elem['value']['Priority'].', 0)'; + } + } + $rel_keywords = $this->Application->ConfigValue('SearchRel_DefaultKeyword_products') / 100; + $rel_pop = $this->Application->ConfigValue('SearchRel_DefaultPop_products') / 100; + $rel_rating = $this->Application->ConfigValue('SearchRel_DefaultRating_products') / 100; + $relevance_clause = '('.implode(' + ', $revelance_parts).') / '.$weight_sum.' * '.$rel_keywords; + $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop; + $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating; + + // building final search query + if( !$this->Application->GetVar('INPORTAL_ON') ) + { + $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); // erase old search table if clean k4 event + } + + if($this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"')) + { + $select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) '; + } + else + { + $select_intro = 'CREATE TABLE '.$search_table.' AS '; + } + + $sql = $select_intro.' SELECT '.$relevance_clause.' AS Relevance, + '.$product_table.'.ProductId AS ItemId, + '.$product_table.'.ResourceId, + 11 AS ItemType, + '.$product_table.'.EditorsPick AS EdPick + FROM '.$object->TableName.' + '.implode(' ', $join_clauses).' + WHERE '.$where_clause.' + GROUP BY '.$product_table.'.ProductId'; + + $res = $this->Conn->Query($sql); + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnSubSearch(&$event) + { + $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetVar('sid').'_'.TABLE_PREFIX.'Search'; + $sql = 'SHOW TABLES LIKE "'.$search_table.'"'; + if($this->Conn->Query($sql)) + { + $sql = 'SELECT DISTINCT ResourceId FROM '.$search_table; + $ids = $this->Conn->GetCol($sql); + } + $event->setEventParam('ResultIds', $ids); + $event->CallSubEvent('OnSimpleSearch'); + } + + /** + * Enter description here... + * + * @param kEvent $event + * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!! + */ + function OnAdvancedSearch(&$event) + { + $query_object =& $this->Application->recallObject('HTTPQuery'); + if(!isset($query_object->Post['andor'])) + { + return; // used when navigating by pages or changing sorting in search results + } + + $this->Application->RemoveVar('keywords'); + $this->Application->RemoveVar('Search_Keywords'); + + $sql = ' SELECT * FROM '.$this->Application->getUnitOption('confs', 'TableName').' + WHERE ModuleName="In-Commerce" + AND AdvancedSearch=1'; + $search_config = $this->Conn->Query($sql); + $lang = $this->Application->GetVar('m_lang'); + $object =& $event->getObject(); + $object->SetPage(1); + $user_object =& $this->Application->recallObject('u'); + $product_table = $this->Application->getUnitOption('p', 'TableName'); + + $keywords = $this->Application->GetVar('value'); + $verbs = $this->Application->GetVar('verb'); + $glues = $this->Application->GetVar('andor'); + + $and_conditions = Array(); + $or_conditions = Array(); + $and_having_conditions = Array(); + $or_having_conditions = Array(); + $join_clauses = Array(); + $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; + $weight_sum = 0; + // processing fields and preparing conditions + foreach($search_config as $record) + { + $field = $record['FieldName']; + $join_clause = ''; + $condition_mode = 'WHERE'; + + // field processing + + $options = $object->getFieldOptions($field); + $local_table = TABLE_PREFIX.$record['TableName']; + $weight_sum += $record['Priority']; // counting weight sum; used when making relevance clause + + // processing multilingual fields + if($options['formatter'] == 'kMultiLanguage') + { + $field_name = 'l'.$lang.'_'.$field; + } + else + { + $field_name = $field; + } + + // processing fields from other tables + if($foreign_field = $record['ForeignField']) + { + $exploded = explode(':', $foreign_field, 2); + if($exploded[0] == 'CALC') + { + $user_groups = $user_object->GetDBField('PortalUserId') ? + implode(',', $this->Conn->GetCol(' SELECT GroupId + FROM '.TABLE_PREFIX.'UserGroup + WHERE PortalUserId='.$user_object->GetDBField('PortalUserId'))) : 0; + $field_name = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]); + $join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $record['JoinClause']); + $join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause); + $join_clause = ' LEFT JOIN '.$join_clause; + + $condition_mode = 'HAVING'; + } + else + { + $exploded = explode('.', $foreign_field); + $foreign_table = TABLE_PREFIX.$exploded[0]; + + $alias_counter++; + $alias = 't'.$alias_counter; + + $field_name = $alias.'.'.$exploded[1]; + $join_clause = str_replace('{ForeignTable}', $alias, $record['JoinClause']); + $join_clause = str_replace('{LocalTable}', $product_table, $join_clause); + + if($record['CustomFieldId']) + { + $join_clause .= ' AND '.$alias.'.CustomFieldId='.$record['CustomFieldId']; + } + $join_clause = ' LEFT JOIN '.$foreign_table.' '.$alias.' + ON '.$join_clause; + } + } + else + { + // processing fields from local table + $field_name = $local_table.'.'.$field_name; + } + + $condition = ''; + switch($record['FieldType']) + { + case 'text': + if( !$this->Application->GetVar('INPORTAL_ON') ) + { + $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 = 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 = mktime() - $time_mapping[$keywords[$field]]; + } + $condition = $field_name.' > '.$min_time; + } + break; + } + + 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') + { + $and_conditions[] = $condition; + } + else + { + $and_having_conditions[] = $condition; + } + } + else // or + { + if($condition_mode == 'WHERE') + { + $or_conditions[] = $condition; + } + else + { + $or_having_conditions[] = $condition; + } + } + } + } + + $this->Application->StoreVar('highlight_keywords', serialize($highlight_keywords)); + + // making relevance clause + if($relevance_parts) + { + $rel_keywords = $this->Application->ConfigValue('SearchRel_DefaultKeyword_products') / 100; + $rel_pop = $this->Application->ConfigValue('SearchRel_DefaultPop_products') / 100; + $rel_rating = $this->Application->ConfigValue('SearchRel_DefaultRating_products') / 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; + } + else + { + $relevance_clause = '0'; + } + + // building having clause + if($or_having_conditions) + { + $and_having_conditions[] = '('.implode(' OR ', $or_having_conditions).')'; + } + $having_clause = implode(' AND ', $and_having_conditions); + $having_clause = $having_clause ? ' HAVING '.$having_clause : ''; + + // building where clause + if($or_conditions) + { + $and_conditions[] = '('.implode(' OR ', $or_conditions).')'; + } +// $and_conditions[] = $product_table.'.Status = 1'; + $where_clause = implode(' AND ', $and_conditions); + if(!$where_clause) + { + if($having_clause) + { + $where_clause = '1'; + } + else + { + $where_clause = '0'; + $this->Application->SetVar('adv_search_error', 1); + } + } + $where_clause .= ' AND '.$product_table.'.Status = 1'; + + // building final search query + $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetVar('sid').'_'.TABLE_PREFIX.'Search'; + + $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); + + $sql = ' CREATE TABLE '.$search_table.' + SELECT '.$relevance_clause.' AS Relevance, + '.$product_table.'.ProductId AS ItemId, + '.$product_table.'.ResourceId AS ResourceId, + 11 AS ItemType, + '.$product_table.'.EditorsPick AS EdPick + FROM '.$product_table.' + '.implode(' ', $join_clauses).' + WHERE '.$where_clause.' + GROUP BY '.$product_table.'.ProductId'. + $having_clause; + + $res = $this->Conn->Query($sql); + } } ?> \ No newline at end of file Index: trunk/core/units/general/cat_event_handler.php =================================================================== diff -u -r2596 -r2826 --- trunk/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 2596) +++ trunk/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 2826) @@ -181,6 +181,724 @@ break; } */ } + + /** + * Adds calculates fields for item statuses + * + * @param kCatDBItem $object + * @param kEvent $event + */ + function PrepareObject(&$object, &$event) + { + + $property_mappings = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings'); + + $new_days_var = getArrayValue($property_mappings, 'NewDays'); + if($new_days_var) + { + $object->addCalculatedField('IsNew', ' IF(%1$s.NewItem = 2, + IF(%1$s.CreatedOn >= (UNIX_TIMESTAMP() - '. + $this->Application->ConfigValue($new_days_var). + '*3600*24), 1, 0), + %1$s.NewItem + )'); + } + + $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 = $this->Conn->GetOne($sql); + if($hot_limit === false) $hot_limit = $this->CalculateHotLimit($event); + $object->addCalculatedField('IsHot', ' IF(%1$s.HotItem = 2, + IF(%1$s.Hits >= '.$hot_limit.', 1, 0), + %1$s.HotItem + )'); + } + + $votes2pop_var = getArrayValue($property_mappings, 'VotesToPop'); + $rating2pop_var = getArrayValue($property_mappings, 'RatingToPop'); + + if($votes2pop_var && $rating2pop_var) + { + $object->addCalculatedField('IsPop', ' IF(%1$s.PopItem = 2, + IF(%1$s.CachedVotesQty >= '. + $this->Application->ConfigValue($votes2pop_var). + ' AND %1$s.CachedRating >= '. + $this->Application->ConfigValue($rating2pop_var). + ', 1, 0), + %1$s.PopItem)'); + } + } + + function CalculateHotLimit(&$event) + { + $property_mappings = $this->Application->getUnitOption($event->Prefix, 'ItemPropertyMappings'); + $hot_count_var = getArrayValue($property_mappings, 'HotCount'); + $hot_limit_var = getArrayValue($property_mappings, 'HotLimit'); + + if($hot_count_var && $hot_limit_var) + { + $last_hot = $this->Application->ConfigValue($hot_count_var) - 1; + $sql = 'SELECT Hits FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' + ORDER BY Hits DESC + LIMIT '.$last_hot.', 1'; + $res = $this->Conn->GetCol($sql); + $hot_limit = (double)array_shift($res); + $this->Conn->Query('REPLACE INTO '.TABLE_PREFIX.'Cache VALUES ("'.$hot_limit_var.'", "'.$hot_limit.'", '.mktime().')'); + return $hot_limit; + } + return 0; + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnBeforeItemUpdate(&$event) + { + $object =& $event->getObject(); + if( $this->Application->IsAdmin() && ($this->Application->GetVar('Hits_original') !== false) && + floor($this->Application->GetVar('Hits_original')) != $object->GetDBField('Hits') ) + { + $sql = 'SELECT MAX(Hits) FROM '.$this->Application->getUnitOption($event->Prefix, 'TableName').' + WHERE FLOOR(Hits) = '.$object->GetDBField('Hits'); + $hits = ( $res = $this->Conn->GetOne($sql) ) ? $res + 0.000001 : $object->GetDBField('Hits'); + $object->SetDBField('Hits', $hits); + } + } + + function OnAfterItemUpdate(&$event) + { + $this->CalculateHotLimit($event); + } + + /** + * Makes simple search for products + * based on keywords string + * + * @param kEvent $event + * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!! + */ + function OnSimpleSearch(&$event) + { + if($this->Application->GetVar('INPORTAL_ON') && !($this->Application->GetVar('Action') == 'm_simple_search')) + { + return; + } + + $event->redirect = false; + $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetVar('sid').'_'.TABLE_PREFIX.'Search'; + + $keywords = trim($this->Application->GetVar('keywords')); + if( !$this->Application->GetVar('INPORTAL_ON') ) + { + $keywords = unhtmlentities($keywords); + } + + $query_object =& $this->Application->recallObject('HTTPQuery'); + $sql = 'SHOW TABLES LIKE "'.$search_table.'"'; + + if(!isset($query_object->Get['keywords']) && + !isset($query_object->Post['keywords']) && + $this->Conn->Query($sql)) + { + return; // used when navigating by pages or changing sorting in search results + } + if(!$keywords || strlen($keywords) < $this->Application->ConfigValue('Search_MinKeyword_Length')) + { + $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); + $this->Application->SetVar('keywords_too_short', 1); + return; // if no or too short keyword entered, doing nothing + } + + $this->Application->StoreVar('keywords', $keywords); + + $keywords = strtr($keywords, Array('%' => '\\%', '_' => '\\_')); + + $event->setPseudoClass('_List'); + $object =& $event->getObject(); + $this->Application->SetVar($event->getPrefixSpecial().'_Page', 1); + $lang = $this->Application->GetVar('m_lang'); + $product_table = $this->Application->getUnitOption('p', 'TableName'); + + $sql = ' SELECT * FROM '.$this->Application->getUnitOption('confs', 'TableName').' + WHERE ModuleName="In-Commerce" + AND SimpleSearch=1'; + $search_config = $this->Conn->Query($sql, 'FieldName'); + $field_list = array_keys($search_config); + + $join_clauses = Array(); + + // field processing + $weight_sum = 0; + foreach($field_list as $key => $field) + { + $options = $object->getFieldOptions($field); + $local_table = TABLE_PREFIX.$search_config[$field]['TableName']; + $weight_sum += $search_config[$field]['Priority']; // counting weight sum; used when making relevance clause + + // processing multilingual fields + if($options['formatter'] == 'kMultiLanguage') + { + $field_list[$key] = 'l'.$lang.'_'.$field; + } + + // processing fields from other tables + if($foreign_field = $search_config[$field]['ForeignField']) + { + $exploded = explode(':', $foreign_field, 2); + if($exploded[0] == 'CALC') + { + unset($field_list[$key]); + continue; // ignoring having type clauses in simple search + /*$user_object =& $this->Application->recallObject('u'); + $user_groups = $user_object->GetDBField('PortalUserId') ? + implode(',', $this->Conn->GetCol(' SELECT GroupId + FROM '.TABLE_PREFIX.'UserGroup + WHERE PortalUserId='.$user_object->GetDBField('PortalUserId'))) : 0; + $having_list[$key] = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]); + $join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $search_config[$field]['JoinClause']); + $join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause); + $join_clause = ' LEFT JOIN '.$join_clause; + $join_clauses[] = $join_clause;*/ + } + else + { + $exploded = explode('.', $foreign_field); + $foreign_table = TABLE_PREFIX.$exploded[0]; + + $alias_counter++; + $alias = 't'.$alias_counter; + + $field_list[$key] = $alias.'.'.$exploded[1]; + $join_clause = str_replace('{ForeignTable}', $alias, $search_config[$field]['JoinClause']); + $join_clause = str_replace('{LocalTable}', $product_table, $join_clause); + if($search_config[$field]['CustomFieldId']) + { + $join_clause .= ' AND '.$alias.'.CustomFieldId='.$search_config[$field]['CustomFieldId']; + } + $join_clauses[] = ' LEFT JOIN '.$foreign_table.' '.$alias.' + ON '.$join_clause; + } + } + else + { + // processing fields from local table + $field_list[$key] = $local_table.'.'.$field_list[$key]; + } + } + + // keyword string processing + $normal_keywords = Array(); + $plus_keywords = Array(); + $minus_keywords = Array(); + + for($i = 0; $i < strlen($keywords); $i++) + { + if(substr($keywords, $i, 1) == ' ') continue; + $extra_skip = 0; + switch(substr($keywords, $i, 1)) + { + case '+': + if(substr($keywords, $i + 1, 1) == '"') + { + $keyword_start = $i + 2; + $keyword_end = strpos($keywords, '"', $i + 2); + $extra_skip = 2; + } + else + { + $keyword_start = $i + 1; + $keyword_end = strpos($keywords, ' ', $i + 1); + $extra_skip = 0; + } + $target_array =& $plus_keywords; + break; + case '-': + if(substr($keywords, $i + 1, 1) == '"') + { + $keyword_start = $i + 2; + $keyword_end = strpos($keywords, '"', $i + 2); + $extra_skip = 2; + } + else + { + $keyword_start = $i + 1; + $keyword_end = strpos($keywords, ' ', $i + 1); + $extra_skip = 0; + } + $target_array =& $minus_keywords; + break; + case '"': + $keyword_start = $i + 1; + $keyword_end = strpos($keywords, '"', $i + 1); + $extra_skip = 1; + $target_array =& $normal_keywords; + break; + default: + $keyword_start = $i; + $keyword_end = strpos($keywords, ' ', $i + 1); + $target_array =& $normal_keywords; + } + + if($keyword_end === false) + { + $keyword_end = strlen($keywords); + } + $keyword_length = $keyword_end - $keyword_start; + $keyword = substr($keywords, $keyword_start, $keyword_length); + + if(strlen($keyword) >= $this->Application->ConfigValue('Search_MinKeyword_Length')) + { + $target_array[] = addcslashes($keyword, '"'); + } + + $i += $keyword_length + $extra_skip; + } + + // preparing conditions + $normal_conditions = Array(); + $plus_conditions = Array(); + $minus_conditions = Array(); + foreach($normal_keywords as $keyword) + { + $normal_conditions[] = implode(' LIKE "%'.$keyword.'%" OR ', $field_list).' LIKE "%'.$keyword.'%"'; + } + foreach($plus_keywords as $keyword) + { + $plus_conditions[] = implode(' LIKE "%'.$keyword.'%" OR ', $field_list).' LIKE "%'.$keyword.'%"'; + } + foreach($minus_keywords as $keyword) + { + foreach($field_list as $field) + { + $condition[] = $field.' NOT LIKE "%'.$keyword.'%" OR '.$field.' IS NULL'; + } + $minus_conditions[] = '('.implode(') AND (', $condition).')'; + } + + // building where clause + if($normal_conditions) + { + $where_clause = '('.implode(') OR (', $normal_conditions).')'; + } + else + { + $where_clause = '1'; + } + if($plus_conditions) + { + $where_clause = '('.$where_clause.') AND ('.implode(') AND (', $plus_conditions).')'; + } + if($minus_conditions) + { + $where_clause = '('.$where_clause.') AND ('.implode(') AND (', $minus_conditions).')'; + } + $where_clause = $where_clause.' AND '.$product_table.'.Status=1'; + + if($this->Application->GetVar('Action') == 'm_simple_subsearch') // subsearch, In-portal + { + if( $event->getEventParam('ResultIds') ) + { + $where_clause .= ' AND '.$product_table.'.ResourceId IN ('.implode(',', $event->specificParams['ResultIds']).')'; + } + } + if( $event->MasterEvent && $event->MasterEvent->Name == 'OnListBuild' ) // subsearch, k4 + { + if( $event->MasterEvent->getEventParam('ResultIds') ) + { + $where_clause .= ' AND '.$product_table.'.ResourceId IN ('.implode(',', $event->MasterEvent->getEventParam('ResultIds')).')'; + } + } + + // building having clause + + + // making relevance clause + $positive_words = array_merge($normal_keywords, $plus_keywords); + $this->Application->StoreVar('highlight_keywords', serialize($positive_words)); + $revelance_parts = Array(); + reset($search_config); + foreach($field_list as $field) + { + $config_elem = each($search_config); + $weight = $search_config[$field]['Priority']; + $revelance_parts[] = 'IF('.$field.' LIKE "%'.implode(' ', $positive_words).'%", '.$weight_sum.', 0)'; + foreach($positive_words as $keyword) + { + $revelance_parts[] = 'IF('.$field.' LIKE "%'.$keyword.'%", '.$config_elem['value']['Priority'].', 0)'; + } + } + $rel_keywords = $this->Application->ConfigValue('SearchRel_DefaultKeyword_products') / 100; + $rel_pop = $this->Application->ConfigValue('SearchRel_DefaultPop_products') / 100; + $rel_rating = $this->Application->ConfigValue('SearchRel_DefaultRating_products') / 100; + $relevance_clause = '('.implode(' + ', $revelance_parts).') / '.$weight_sum.' * '.$rel_keywords; + $relevance_clause .= ' + (Hits + 1) / (MAX(Hits) + 1) * '.$rel_pop; + $relevance_clause .= ' + (CachedRating + 1) / (MAX(CachedRating) + 1) * '.$rel_rating; + + // building final search query + if( !$this->Application->GetVar('INPORTAL_ON') ) + { + $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); // erase old search table if clean k4 event + } + + if($this->Conn->Query('SHOW TABLES LIKE "'.$search_table.'"')) + { + $select_intro = 'INSERT INTO '.$search_table.' (Relevance, ItemId, ResourceId, ItemType, EdPick) '; + } + else + { + $select_intro = 'CREATE TABLE '.$search_table.' AS '; + } + + $sql = $select_intro.' SELECT '.$relevance_clause.' AS Relevance, + '.$product_table.'.ProductId AS ItemId, + '.$product_table.'.ResourceId, + 11 AS ItemType, + '.$product_table.'.EditorsPick AS EdPick + FROM '.$object->TableName.' + '.implode(' ', $join_clauses).' + WHERE '.$where_clause.' + GROUP BY '.$product_table.'.ProductId'; + + $res = $this->Conn->Query($sql); + } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnSubSearch(&$event) + { + $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetVar('sid').'_'.TABLE_PREFIX.'Search'; + $sql = 'SHOW TABLES LIKE "'.$search_table.'"'; + if($this->Conn->Query($sql)) + { + $sql = 'SELECT DISTINCT ResourceId FROM '.$search_table; + $ids = $this->Conn->GetCol($sql); + } + $event->setEventParam('ResultIds', $ids); + $event->CallSubEvent('OnSimpleSearch'); + } + + /** + * Enter description here... + * + * @param kEvent $event + * @todo Change all hardcoded Products table & In-Commerce module usage to dynamic usage from item config !!! + */ + function OnAdvancedSearch(&$event) + { + $query_object =& $this->Application->recallObject('HTTPQuery'); + if(!isset($query_object->Post['andor'])) + { + return; // used when navigating by pages or changing sorting in search results + } + + $this->Application->RemoveVar('keywords'); + $this->Application->RemoveVar('Search_Keywords'); + + $sql = ' SELECT * FROM '.$this->Application->getUnitOption('confs', 'TableName').' + WHERE ModuleName="In-Commerce" + AND AdvancedSearch=1'; + $search_config = $this->Conn->Query($sql); + $lang = $this->Application->GetVar('m_lang'); + $object =& $event->getObject(); + $object->SetPage(1); + $user_object =& $this->Application->recallObject('u'); + $product_table = $this->Application->getUnitOption('p', 'TableName'); + + $keywords = $this->Application->GetVar('value'); + $verbs = $this->Application->GetVar('verb'); + $glues = $this->Application->GetVar('andor'); + + $and_conditions = Array(); + $or_conditions = Array(); + $and_having_conditions = Array(); + $or_having_conditions = Array(); + $join_clauses = Array(); + $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; + $weight_sum = 0; + // processing fields and preparing conditions + foreach($search_config as $record) + { + $field = $record['FieldName']; + $join_clause = ''; + $condition_mode = 'WHERE'; + + // field processing + + $options = $object->getFieldOptions($field); + $local_table = TABLE_PREFIX.$record['TableName']; + $weight_sum += $record['Priority']; // counting weight sum; used when making relevance clause + + // processing multilingual fields + if($options['formatter'] == 'kMultiLanguage') + { + $field_name = 'l'.$lang.'_'.$field; + } + else + { + $field_name = $field; + } + + // processing fields from other tables + if($foreign_field = $record['ForeignField']) + { + $exploded = explode(':', $foreign_field, 2); + if($exploded[0] == 'CALC') + { + $user_groups = $user_object->GetDBField('PortalUserId') ? + implode(',', $this->Conn->GetCol(' SELECT GroupId + FROM '.TABLE_PREFIX.'UserGroup + WHERE PortalUserId='.$user_object->GetDBField('PortalUserId'))) : 0; + $field_name = str_replace('{PREFIX}', TABLE_PREFIX, $exploded[1]); + $join_clause = str_replace('{PREFIX}', TABLE_PREFIX, $record['JoinClause']); + $join_clause = str_replace('{USER_GROUPS}', $user_groups, $join_clause); + $join_clause = ' LEFT JOIN '.$join_clause; + + $condition_mode = 'HAVING'; + } + else + { + $exploded = explode('.', $foreign_field); + $foreign_table = TABLE_PREFIX.$exploded[0]; + + $alias_counter++; + $alias = 't'.$alias_counter; + + $field_name = $alias.'.'.$exploded[1]; + $join_clause = str_replace('{ForeignTable}', $alias, $record['JoinClause']); + $join_clause = str_replace('{LocalTable}', $product_table, $join_clause); + + if($record['CustomFieldId']) + { + $join_clause .= ' AND '.$alias.'.CustomFieldId='.$record['CustomFieldId']; + } + $join_clause = ' LEFT JOIN '.$foreign_table.' '.$alias.' + ON '.$join_clause; + } + } + else + { + // processing fields from local table + $field_name = $local_table.'.'.$field_name; + } + + $condition = ''; + switch($record['FieldType']) + { + case 'text': + if( !$this->Application->GetVar('INPORTAL_ON') ) + { + $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 = 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 = mktime() - $time_mapping[$keywords[$field]]; + } + $condition = $field_name.' > '.$min_time; + } + break; + } + + 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') + { + $and_conditions[] = $condition; + } + else + { + $and_having_conditions[] = $condition; + } + } + else // or + { + if($condition_mode == 'WHERE') + { + $or_conditions[] = $condition; + } + else + { + $or_having_conditions[] = $condition; + } + } + } + } + + $this->Application->StoreVar('highlight_keywords', serialize($highlight_keywords)); + + // making relevance clause + if($relevance_parts) + { + $rel_keywords = $this->Application->ConfigValue('SearchRel_DefaultKeyword_products') / 100; + $rel_pop = $this->Application->ConfigValue('SearchRel_DefaultPop_products') / 100; + $rel_rating = $this->Application->ConfigValue('SearchRel_DefaultRating_products') / 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; + } + else + { + $relevance_clause = '0'; + } + + // building having clause + if($or_having_conditions) + { + $and_having_conditions[] = '('.implode(' OR ', $or_having_conditions).')'; + } + $having_clause = implode(' AND ', $and_having_conditions); + $having_clause = $having_clause ? ' HAVING '.$having_clause : ''; + + // building where clause + if($or_conditions) + { + $and_conditions[] = '('.implode(' OR ', $or_conditions).')'; + } +// $and_conditions[] = $product_table.'.Status = 1'; + $where_clause = implode(' AND ', $and_conditions); + if(!$where_clause) + { + if($having_clause) + { + $where_clause = '1'; + } + else + { + $where_clause = '0'; + $this->Application->SetVar('adv_search_error', 1); + } + } + $where_clause .= ' AND '.$product_table.'.Status = 1'; + + // building final search query + $search_table = TABLE_PREFIX.'ses_'.$this->Application->GetVar('sid').'_'.TABLE_PREFIX.'Search'; + + $this->Conn->Query('DROP TABLE IF EXISTS '.$search_table); + + $sql = ' CREATE TABLE '.$search_table.' + SELECT '.$relevance_clause.' AS Relevance, + '.$product_table.'.ProductId AS ItemId, + '.$product_table.'.ResourceId AS ResourceId, + 11 AS ItemType, + '.$product_table.'.EditorsPick AS EdPick + FROM '.$product_table.' + '.implode(' ', $join_clauses).' + WHERE '.$where_clause.' + GROUP BY '.$product_table.'.ProductId'. + $having_clause; + + $res = $this->Conn->Query($sql); + } } ?> \ No newline at end of file Index: trunk/admin/install/langpacks/english.lang =================================================================== diff -u -r2690 -r2826 --- trunk/admin/install/langpacks/english.lang (.../english.lang) (revision 2690) +++ trunk/admin/install/langpacks/english.lang (.../english.lang) (revision 2826) @@ -457,7 +457,6 @@ QWRtaW4gZ3JvdXA= TWVzc2FnZXMgZnJvbSBTaXRlIEFkbWluIGFyZSBmcm9t QWR2YW5jZWQgU2VhcmNo - QWZmaWxpYXRlIFN0b3JhZ2UgTWV0aG9k QWxsb3cgcGFzc3dvcmQgcmVzZXQgYWZ0ZXI= QWxsIHRlbXBsYXRlcw== QWx0IHZhbHVl @@ -1135,7 +1134,6 @@ QWRkaW5nIFN0eWxlc2hlZXQ= QWRkIE1vZHVsZQ== QWR2YW5jZWQgVmlldw== - QWZmaWxpYXRlIFBheW1lbnQgVHlwZXM= QmFja3Vw QmFzZSBTdHlsZXM= QmxvY2sgU3R5bGVz @@ -1688,6 +1686,7 @@ TG9naW4gTmFtZQ== TG9naW4= TG9nIE91dA== + TG9nb3V0IG9mIHlvdXIgYWNjb3VudA== TG9nIG91dCBvZiB0aGUgc3lzdGVt TWFpbGluZyBMaXN0 TWFy @@ -1944,6 +1943,7 @@ UmVwbGllcw== UmVwbHk= UmVxdWlyZWQgRmllbGQ= + UmVzZXQ= QXJlIHlvdSBzdXJlIHlvdSB3YW50IHRvIHJlc2V0IHRoZSBwYXNzd29yZD8= UGxlYXNlIGNvbmZpcm0gdGhhdCB5b3Ugd2FudCB0byByZXNldCB5b3VyIHBhc3N3b3JkLg== UmV2aWV3cw== @@ -2073,41 +2073,41 @@ dGVzdCAy + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBtb2RpZmllZAoKQSBjYXRlZ29yeSAiPGlucDptX2NhdGVnb3J5X2ZpZWxkIF9GaWVsZD0iTmFtZSIgX1N0cmlwSFRNTD0iMSIvPiIgaGFzIGJlZW4gbW9kaWZpZWQu + + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVXNlciB2YWxpZGF0ZWQKClVzZXIgIjxpbnA6dG91c2VyIF9GaWVsZD0iVXNlck5hbWUiIC8+IiBoYXMgYmVlbiB2YWxpZGF0ZWQu + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQ2hlY2sgb3V0IHRoaXMgc2l0ZQoKSGksDQoNClRoaXMgbWVzc2FnZSBoYXMgYmVlbiBzZW50IHRvIHlvdSBmcm9tIG9uZSBvZiB5b3VyIGZyaWVuZHMuDQpDaGVjayBvdXQgdGhpcyBzaXRlOiA8YSBocmVmPSI8aW5wOm1fdGhlbWVfdXJsIF9wYWdlPSJjdXJyZW50Ii8+Ij48aW5wOm1fcGFnZV90aXRsZSAvPjwvYT4h + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogWW91IGhhdmUgYmVlbiB1bnN1YnNjcmliZWQKCllvdSBoYXZlIHN1Y2Nlc3NmdWxseSB1bnN1YnNyaWJlZCBmcm9tIDxpbnA6bV9wYWdlX3RpdGxlIC8+IG1haWxpbmcgbGlzdC4= + WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IEEgY2F0ZWdvcnkgaGFzIGJlZW4gZGVsZXRlZAoKQSBjYXRlZ29yeSAiPGlucDptX2NhdGVnb3J5X2ZpZWxkIF9GaWVsZD0iTmFtZSIgX1N0cmlwSFRNTD0iMSIvPiIgaGFzIGJlZW4gZGVsZXRlZC4= + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogWW91IGhhdmUgYmVlbiBhcHByb3ZlZAoKV2VsY29tZSB0byBJbi1wb3J0YWwhDQpZb3VyIHVzZXIgcmVnaXN0cmF0aW9uIGhhcyBiZWVuIGFwcHJvdmVkLiBZb3VyIHVzZXIgbmFtZSBpcyAiPGlucDp0b3VzZXIgX0ZpZWxkPSJVc2VyTmFtZSIgLz4iLg== + WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IE1lbWJlcnNoaXAgZXhwaXJhdGlvbiBub3RpY2UKCk1lbWJlcnNoaXAgZXhwaXJhdGlvbiBub3RpY2U= WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogTG9zdCBwYXNzd29yZAoKWW91ciBsb3N0IHBhc3N3b3JkIGhhcyBiZWVuIHJlc2V0LiBZb3VyIG5ldyBwYXNzd29yZCBpczogIjxpbnA6dG91c2VyIF9GaWVsZD0iUGFzc3dvcmQiIC8+Ii4= - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQ2F0ZWdvcnkgYWRkZWQgKHBlbmRpbmcpCgpBIGNhdGVnb3J5ICI8aW5wOm1fY2F0ZWdvcnlfZmllbGQgX0ZpZWxkPSJOYW1lIiBfU3RyaXBIVE1MPSIxIi8+IiBoYXMgYmVlbiBhZGRlZCwgcGVuZGluZyB5b3VyIGNvbmZpcm1hdGlvbi4gIFBsZWFzZSByZXZpZXcgdGhlIGNhdGVnb3J5IGFuZCBhcHByb3ZlIG9yIGRlbnkgaXQu - WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IE1lbWJlcnNoaXAgZXhwaXJlZAoKTWVtYmVyc2hpcCBleHBpcmVk - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVGhlIHNpdGUgaGFzIGJlZW4gc3VnZ2VzdGVkCgpBIHZpc2l0b3Igc3VnZ2VzdGVkIHlvdXIgc2l0ZSB0byBhIGZyaWVuZC4= + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVXNlciBkZW5pZWQKClVzZXIgIjxpbnA6dG91c2VyIF9GaWVsZD0iVXNlck5hbWUiIC8+IiBoYXMgYmVlbiBkZW5pZWQu WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IFVzZXIgcmVnaXN0ZXJlZAoKQSBuZXcgdXNlciAiPGlucDp0b3VzZXIgX0ZpZWxkPSJMb2dpbiIgLz4iIGhhcyByZWdpc3RlcmVkIGFuZCBpcyBwZW5kaW5nIGFkbWluaXN0cmF0aXZlIGFwcHJvdmFsLg== + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQ2F0ZWdvcnkgYWRkZWQgKHBlbmRpbmcpCgpBIGNhdGVnb3J5ICI8aW5wOm1fY2F0ZWdvcnlfZmllbGQgX0ZpZWxkPSJOYW1lIiBfU3RyaXBIVE1MPSIxIi8+IiBoYXMgYmVlbiBhZGRlZCwgcGVuZGluZyB5b3VyIGNvbmZpcm1hdGlvbi4gIFBsZWFzZSByZXZpZXcgdGhlIGNhdGVnb3J5IGFuZCBhcHByb3ZlIG9yIGRlbnkgaXQu WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IE5ldyB1c2VyIGhhcyBiZWVuIGFkZGVkCgpBIG5ldyB1c2VyICI8aW5wOnRvdXNlciBfRmllbGQ9IkxvZ2luIiAvPiIgaGFzIGJlZW4gYWRkZWQu WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSB1c2VyIGhhcyBzdWJzY3JpYmVkCgpBIHVzZXIgaGFzIHN1YnNjcmliZWQgdG8gPGlucDptX3BhZ2VfdGl0bGUgLz4gbWFpbGluZyBsaXN0Lg== - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVXNlciBkZW5pZWQKClVzZXIgIjxpbnA6dG91c2VyIF9GaWVsZD0iVXNlck5hbWUiIC8+IiBoYXMgYmVlbiBkZW5pZWQu - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogTG9zdCBwYXNzd29yZAoKWW91ciBsb3N0IHBhc3N3b3JkIGhhcyBiZWVuIHJlc2V0LiBZb3VyIG5ldyBwYXNzd29yZCBpczogIjxpbnA6dG91c2VyIF9GaWVsZD0iUGFzc3dvcmQiIC8+Ii4= + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVGhlIHNpdGUgaGFzIGJlZW4gc3VnZ2VzdGVkCgpBIHZpc2l0b3Igc3VnZ2VzdGVkIHlvdXIgc2l0ZSB0byBhIGZyaWVuZC4= + WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IE1lbWJlcnNoaXAgZXhwaXJlZAoKTWVtYmVyc2hpcCBleHBpcmVk WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IE1lbWJlcnNoaXAgZXhwaXJlZAoKTWVtYmVyc2hpcCBleHBpcmVk + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogTG9zdCBwYXNzd29yZAoKWW91ciBsb3N0IHBhc3N3b3JkIGhhcyBiZWVuIHJlc2V0LiBZb3VyIG5ldyBwYXNzd29yZCBpczogIjxpbnA6dG91c2VyIF9GaWVsZD0iUGFzc3dvcmQiIC8+Ii4= + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBkZW5pZWQKCkEgY2F0ZWdvcnkgIjxpbnA6bV9jYXRlZ29yeV9maWVsZCBfRmllbGQ9Ik5hbWUiIF9TdHJpcEhUTUw9IjEiLz4iIGhhcyBiZWVuIGRlbmllZC4= WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IE1lbWJlcnNoaXAgZXhwaXJhdGlvbiBub3RpY2UKCk1lbWJlcnNoaXAgZXhwaXJhdGlvbiBub3RpY2U= WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogSW4tcG9ydGFsIHJlZ2lzdHJhdGlvbgoKV2VsY29tZSB0byBJbi1wb3J0YWwhDQpZb3VyIHVzZXIgcmVnaXN0cmF0aW9uIGhhcyBiZWVuIGFwcHJvdmVkLiBZb3VyIHVzZXIgbmFtZSBpcyAiPGlucDp0b3VzZXIgX0ZpZWxkPSJVc2VyTmFtZSIgLz4iIGFuZCB5b3VyIHBhc3N3b3JkIGlzICI8aW5wOnRvdXNlciBfRmllbGQ9InBhc3N3b3JkIiAvPiIuDQo= - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBkZW5pZWQKCkEgY2F0ZWdvcnkgIjxpbnA6bV9jYXRlZ29yeV9maWVsZCBfRmllbGQ9Ik5hbWUiIF9TdHJpcEhUTUw9IjEiLz4iIGhhcyBiZWVuIGRlbmllZC4= - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBhcHByb3ZlZAoKWW91ciBzdWdnZXN0ZWQgY2F0ZWdvcnkgIjxpbnA6bV9jYXRlZ29yeV9maWVsZCBfRmllbGQ9Ik5hbWUiIF9TdHJpcEhUTUw9IjEiLz4iIGhhcyBiZWVuIGFwcHJvdmVkLg== WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBhcHByb3ZlZAoKQSBjYXRlZ29yeSAiPGlucDptX2NhdGVnb3J5X2ZpZWxkIF9GaWVsZD0iTmFtZSIgX1N0cmlwSFRNTD0iMSIvPiIgaGFzIGJlZW4gYXBwcm92ZWQu WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBtb2RpZmllZAoKWW91ciBzdWdnZXN0ZWQgY2F0ZWdvcnkgIjxpbnA6bV9jYXRlZ29yeV9maWVsZCBfRmllbGQ9Ik5hbWUiIF9TdHJpcEhUTUw9IjEiLz4iIGhhcyBiZWVuIG1vZGlmaWVkLg== - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVXNlciB1bnN1YnNyaWJlZAoKQSB1c2VyIGhhcyB1bnN1YnNjcmliZWQu + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBhcHByb3ZlZAoKWW91ciBzdWdnZXN0ZWQgY2F0ZWdvcnkgIjxpbnA6bV9jYXRlZ29yeV9maWVsZCBfRmllbGQ9Ik5hbWUiIF9TdHJpcEhUTUw9IjEiLz4iIGhhcyBiZWVuIGFwcHJvdmVkLg== WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQWNjZXNzIGRlbmllZAoKWW91ciByZWdpc3RyYXRpb24gdG8gPGlucDptX3BhZ2VfdGl0bGUgLz4gaGFzIGJlZW4gZGVuaWVkLg== - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBkZWxldGVkCgpBIGNhdGVnb3J5ICI8aW5wOm1fY2F0ZWdvcnlfZmllbGQgX0ZpZWxkPSJOYW1lIiBfU3RyaXBIVE1MPSIxIi8+IiBoYXMgYmVlbiBkZWxldGVkLg== WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBkZW5pZWQKCllvdXIgY2F0ZWdvcnkgc3VnZ2VzdGlvbiAiPGlucDptX2NhdGVnb3J5X2ZpZWxkIF9GaWVsZD0iTmFtZSIgX1N0cmlwSFRNTD0iMSIvPiIgaGFzIGJlZW4gZGVuaWVkLg== + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBkZWxldGVkCgpBIGNhdGVnb3J5ICI8aW5wOm1fY2F0ZWdvcnlfZmllbGQgX0ZpZWxkPSJOYW1lIiBfU3RyaXBIVE1MPSIxIi8+IiBoYXMgYmVlbiBkZWxldGVkLg== + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVXNlciB1bnN1YnNyaWJlZAoKQSB1c2VyIGhhcyB1bnN1YnNjcmliZWQu WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogSW4tcG9ydGFsIHJlZ2lzdHJhdGlvbgoKRGVhciA8aW5wOnRvdXNlciBfRmllbGQ9IkZpcnN0TmFtZSIgLz4gPGlucDp0b3VzZXIgX0ZpZWxkPSJMYXN0TmFtZSIgLz4sDQoNClRoYW5rIHlvdSBmb3IgcmVnaXN0ZXJpbmcgb24gPGlucDptX3BhZ2VfdGl0bGUgLz4uIFlvdXIgcmVnaXN0cmF0aW9uIGlzIG5vdyBhY3RpdmUu - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogUGFzc3dvcmQgcmVzZXQgY29uZmlybWF0aW9uCgpIZWxsbywNCg0KSXQgc2VlbXMgdGhhdCB5b3UgaGF2ZSByZXF1ZXN0ZWQgYSBwYXNzd29yZCByZXNldCBmb3IgeW91ciBJbi1wb3J0YWwgYWNjb3VudC4gSWYgeW91IHdvdWxkIGxpa2UgdG8gcHJvY2VlZCBhbmQgY2hhbmdlIHRoZSBwYXNzd29yZCwgcGxlYXNlIGNsaWNrIG9uIHRoZSBsaW5rIGJlbG93Og0KPGlucDptX2NvbmZpcm1fcGFzc3dvcmRfbGluayAvPg0KDQpZb3Ugd2lsbCByZWNlaXZlIGEgc2Vjb25kIGVtYWlsIHdpdGggeW91ciBuZXcgcGFzc3dvcmQgc2hvcnRseS4NCg0KSWYgeW91IGJlbGlldmUgeW91IGhhdmUgcmVjZWl2ZWQgdGhpcyBlbWFpbCBpbiBlcnJvciwgcGxlYXNlIGlnbm9yZSB0aGlzIGVtYWlsLiBZb3VyIHBhc3N3b3JkIHdpbGwgbm90IGJlIGNoYW5nZWQgdW5sZXNzIHlvdSBoYXZlIGNsaWNrZWQgb24gdGhlIGFib3ZlIGxpbmsuDQo= U3ViamVjdDogQ2F0ZWdvcnkgYWRkZWQKCllvdXIgc3VnZ2VzdGVkIGNhdGVnb3J5ICI8aW5wOm1fY2F0ZWdvcnlfZmllbGQgX0ZpZWxkPSJOYW1lIiBfU3RyaXBIVE1MPSIxIi8+IiBoYXMgYmVlbiBhZGRlZC4= + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogUGFzc3dvcmQgcmVzZXQgY29uZmlybWF0aW9uCgpIZWxsbywNCg0KSXQgc2VlbXMgdGhhdCB5b3UgaGF2ZSByZXF1ZXN0ZWQgYSBwYXNzd29yZCByZXNldCBmb3IgeW91ciBJbi1wb3J0YWwgYWNjb3VudC4gSWYgeW91IHdvdWxkIGxpa2UgdG8gcHJvY2VlZCBhbmQgY2hhbmdlIHRoZSBwYXNzd29yZCwgcGxlYXNlIGNsaWNrIG9uIHRoZSBsaW5rIGJlbG93Og0KPGlucDptX2NvbmZpcm1fcGFzc3dvcmRfbGluayAvPg0KDQpZb3Ugd2lsbCByZWNlaXZlIGEgc2Vjb25kIGVtYWlsIHdpdGggeW91ciBuZXcgcGFzc3dvcmQgc2hvcnRseS4NCg0KSWYgeW91IGJlbGlldmUgeW91IGhhdmUgcmVjZWl2ZWQgdGhpcyBlbWFpbCBpbiBlcnJvciwgcGxlYXNlIGlnbm9yZSB0aGlzIGVtYWlsLiBZb3VyIHBhc3N3b3JkIHdpbGwgbm90IGJlIGNoYW5nZWQgdW5sZXNzIHlvdSBoYXZlIGNsaWNrZWQgb24gdGhlIGFib3ZlIGxpbmsuDQo= WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IEluLVBvcnRhbCBSZWdpc3RyYXRpb24KCkRlYXIgPGlucDp0b3VzZXIgX0ZpZWxkPSJGaXJzdE5hbWUiIC8+IDxpbnA6dG91c2VyIF9GaWVsZD0iTGFzdE5hbWUiIC8+LA0KDQpUaGFuayB5b3UgZm9yIHJlZ2lzdGVyaW5nIG9uIDxpbnA6bV9wYWdlX3RpdGxlIC8+LiBZb3VyIHJlZ2lzdHJhdGlvbiB3aWxsIGJlIGFjdGl2ZSBhZnRlciBhcHByb3ZhbC4= - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogU3Vic2NyaXB0aW9uIGNvbmZpcm1hdGlvbgoKWW91IGhhdmUgc3Vic2NyaWJlZCB0byA8aW5wOm1fcGFnZV90aXRsZSAvPiBtYWlsaW5nIGxpc3Qu WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBhZGRlZAoKQSBjYXRlZ29yeSAiPGlucDptX2NhdGVnb3J5X2ZpZWxkIF9GaWVsZD0iTmFtZSIgX1N0cmlwSFRNTD0iMSIvPiIgaGFzIGJlZW4gYWRkZWQu WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVXNlciBhcHByb3ZlZAoKVXNlciAiPGlucDp0b3VzZXIgX0ZpZWxkPSJVc2VyTmFtZSIgLz4iIGhhcyBiZWVuIGFwcHJvdmVkLg== - WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IEEgY2F0ZWdvcnkgaGFzIGJlZW4gZGVsZXRlZAoKQSBjYXRlZ29yeSAiPGlucDptX2NhdGVnb3J5X2ZpZWxkIF9GaWVsZD0iTmFtZSIgX1N0cmlwSFRNTD0iMSIvPiIgaGFzIGJlZW4gZGVsZXRlZC4= - WC1Qcmlvcml0eTogMQpYLU1TTWFpbC1Qcmlvcml0eTogSGlnaApYLU1haWxlcjogSW4tUG9ydGFsClN1YmplY3Q6IE1lbWJlcnNoaXAgZXhwaXJhdGlvbiBub3RpY2UKCk1lbWJlcnNoaXAgZXhwaXJhdGlvbiBub3RpY2U= - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogVXNlciB2YWxpZGF0ZWQKClVzZXIgIjxpbnA6dG91c2VyIF9GaWVsZD0iVXNlck5hbWUiIC8+IiBoYXMgYmVlbiB2YWxpZGF0ZWQu - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogWW91IGhhdmUgYmVlbiBhcHByb3ZlZAoKV2VsY29tZSB0byBJbi1wb3J0YWwhDQpZb3VyIHVzZXIgcmVnaXN0cmF0aW9uIGhhcyBiZWVuIGFwcHJvdmVkLiBZb3VyIHVzZXIgbmFtZSBpcyAiPGlucDp0b3VzZXIgX0ZpZWxkPSJVc2VyTmFtZSIgLz4iLg== - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQSBjYXRlZ29yeSBoYXMgYmVlbiBtb2RpZmllZAoKQSBjYXRlZ29yeSAiPGlucDptX2NhdGVnb3J5X2ZpZWxkIF9GaWVsZD0iTmFtZSIgX1N0cmlwSFRNTD0iMSIvPiIgaGFzIGJlZW4gbW9kaWZpZWQu - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogWW91IGhhdmUgYmVlbiB1bnN1YnNjcmliZWQKCllvdSBoYXZlIHN1Y2Nlc3NmdWxseSB1bnN1YnNyaWJlZCBmcm9tIDxpbnA6bV9wYWdlX3RpdGxlIC8+IG1haWxpbmcgbGlzdC4= - - WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogQ2hlY2sgb3V0IHRoaXMgc2l0ZQoKSGksDQoNClRoaXMgbWVzc2FnZSBoYXMgYmVlbiBzZW50IHRvIHlvdSBmcm9tIG9uZSBvZiB5b3VyIGZyaWVuZHMuDQpDaGVjayBvdXQgdGhpcyBzaXRlOiA8YSBocmVmPSI8aW5wOm1fdGhlbWVfdXJsIF9wYWdlPSJjdXJyZW50Ii8+Ij48aW5wOm1fcGFnZV90aXRsZSAvPjwvYT4h + WC1Qcmlvcml0eTogMQ0KWC1NU01haWwtUHJpb3JpdHk6IEhpZ2gNClgtTWFpbGVyOiBJbi1Qb3J0YWwKU3ViamVjdDogU3Vic2NyaXB0aW9uIGNvbmZpcm1hdGlvbgoKWW91IGhhdmUgc3Vic2NyaWJlZCB0byA8aW5wOm1fcGFnZV90aXRsZSAvPiBtYWlsaW5nIGxpc3Qu \ No newline at end of file Index: trunk/admin/install/inportal_remove.sql =================================================================== diff -u -r2618 -r2826 --- trunk/admin/install/inportal_remove.sql (.../inportal_remove.sql) (revision 2618) +++ trunk/admin/install/inportal_remove.sql (.../inportal_remove.sql) (revision 2826) @@ -8,6 +8,8 @@ # -------------------------------------------------------- DROP TABLE AffiliatePlansItems # -------------------------------------------------------- +DROP TABLE AffiliatePaymentTypes +# -------------------------------------------------------- DROP TABLE Affiliates # -------------------------------------------------------- DROP TABLE Currencies @@ -84,6 +86,10 @@ # -------------------------------------------------------- DROP TABLE News # -------------------------------------------------------- +DROP TABLE Pages +# -------------------------------------------------------- +DROP TABLE PageContent +# -------------------------------------------------------- DROP TABLE BanRules # -------------------------------------------------------- DROP TABLE Cache