Index: trunk/kernel/units/languages/languages_event_handler.php =================================================================== --- trunk/kernel/units/languages/languages_event_handler.php (revision 2914) +++ trunk/kernel/units/languages/languages_event_handler.php (revision 2915) @@ -1,366 +1,366 @@ <?php class LanguagesEventHandler extends InpDBEventHandler { /** * Updates table structure on new language adding/removing language * * @param kEvent $event */ function OnReflectMultiLingualFields($event) { $table_name = $this->Application->getUnitOption($event->Prefix,'TableName'); $languages_count = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$table_name); $languages_count = $languages_count + 5 - ( $languages_count % 5 ? ($languages_count % 5) : 5 ); $sqls = Array(); $unit_config_reader =& $this->Application->recallObject('kUnitConfigReader'); foreach($unit_config_reader->configData as $prefix => $config_data) { $table_name = getArrayValue($config_data,'TableName'); $fields = getArrayValue($config_data,'Fields'); if(!($table_name && $fields) ) continue; foreach($fields as $field_name => $field_options) { if( isset($field_options['formatter']) && $field_options['formatter'] == 'kMultiLanguage' ) { $describe = $this->Conn->Query('DESCRIBE '.$table_name.' \'l%_'.$field_name.'\''); $field_mask = 'l%s_'.$field_name.' '.$describe[0]['Type']; $create_count = $languages_count - count($describe); - if($create_count) + if($create_count > 0) { $sqls[] = 'ALTER TABLE '.$table_name.( $this->generateAlterSQL($field_mask, count($describe) + 1, $create_count) ); } } } } if($sqls) $this->Conn->Query( implode("\n",$sqls) ); } /** * Shows only enabled languages on front * * @param kEvent $event */ function SetCustomQuery(&$event) { if($event->Special == 'enabled') { $object =& $event->getObject(); $object->addFilter('enabled_filter', '%1$s.Enabled = 1'); } } /** * Returns ALTER statement part for adding required fields to table * * @param string $field_mask sql mask for creating field with correct definition (type & size) * @param int $start_index add new fields starting from this index * @param int $create_count create this much new multilingual field translations * @return string */ function generateAlterSQL($field_mask, $start_index, $create_count) { $i_count = $start_index + $create_count; $ret = ''; while($start_index < $i_count) { list($prev_field,$type) = explode(' ', sprintf($field_mask, $start_index-1) ); $ret .= ' ADD COLUMN '.sprintf($field_mask,$start_index).' AFTER '.$prev_field.', '; $start_index++; } return preg_replace('/, $/',';',$ret); } /** * Copy labels from another language * * @param kEvent $event */ function OnCopyLabels(&$event) { $object =& $event->getObject(); $from_lang_id = $object->GetDBField('CopyFromLanguage'); if( ($event->MasterEvent->status == erSUCCESS) && $object->GetDBField('CopyLabels') == 1 && ($from_lang_id > 0) ) { $lang_id = $object->GetID(); // 1. phrases import $phrases_live = $this->Application->getUnitOption('phrases','TableName'); $phrases_temp = kTempTablesHandler::GetTempName($phrases_live); $sql = 'INSERT INTO '.$phrases_temp.' SELECT Phrase, Translation, PhraseType, 0-PhraseId, '.$lang_id.', '.time().', "", Module FROM '.$phrases_live.' WHERE LanguageId='.$from_lang_id; $this->Conn->Query($sql); // 2. events import $em_table_live = $this->Application->getUnitOption('emailmessages','TableName'); $em_table_temp = kTempTablesHandler::GetTempName($em_table_live); $sql = 'SELECT * FROM '.$em_table_live.' WHERE LanguageId = '.$from_lang_id; $email_messages = $this->Conn->Query($sql); if($email_messages) { $id = $this->Conn->GetOne('SELECT MIN(EmailMessageId) FROM '.$em_table_live); if($id > 0) $id = 0; $id--; $sqls = Array(); foreach($email_messages as $email_message) { $sqls[] = $id.','.$this->Conn->qstr($email_message['Template']).','.$this->Conn->qstr($email_message['MessageType']).','.$lang_id.','.$email_message['EventId']; $id--; } $sql = 'INSERT INTO '.$em_table_temp.'(EmailMessageId,Template,MessageType,LanguageId,EventId) VALUES ('.implode('),(',$sqls).')'; $this->Conn->Query($sql); } $object->SetDBField('CopyLabels', 0); } } /** * Prepare temp tables for creating new item * but does not create it. Actual create is * done in OnPreSaveCreated * * @param kEvent $event */ function OnPreCreate(&$event) { parent::OnPreCreate($event); $object =& $event->getObject(); $object->SetDBField('CopyLabels', 1); $live_table = kTempTablesHandler::GetLiveName($object->TableName); $primary_lang_id = $this->Conn->GetOne('SELECT '.$object->IDField.' FROM '.$live_table.' WHERE PrimaryLang = 1'); $object->SetDBField('CopyFromLanguage', $primary_lang_id); } function OnChangeLanguage(&$event) { $this->Application->SetVar('m_lang', $this->Application->GetVar('language')); $this->Application->LinkVar('language', 'm_lang'); } /** * Parse language XML file into temp tables and redirect to progress bar screen * * @param kEvent $event */ function OnImportLanguage(&$event) { $items_info = $this->Application->GetVar('phrases_import'); if($items_info) { list($id,$field_values) = each($items_info); $filename = getArrayValue($field_values, 'LangFile', 'tmp_name'); if( filesize($filename) ) { $modules = getArrayValue($field_values,'Module'); $lang_xml =& $this->Application->recallObject('LangXML'); $lang_xml->Parse($filename, $field_values['PhraseType'], $modules, $field_values['ImportOverwrite']); $event->redirect = 'dummy'; $event->SetRedirectParams( Array('lang_event' => 'OnImportProgress', 'pass' => 'all,lang', 'mode'=>$field_values['ImportOverwrite']) ); } else { $object =& $this->Application->recallObject('phrases.import'); $object->SetError('LangFile', 'la_empty_file', 'la_EmptyFile'); $event->redirect = false; } } } /** * Copies imported from xml file from temp table to live table * * @param kEvent $event */ function OnImportProgress(&$event) { define('IMPORT_BY', 300); // import this much records per step $template_name = 'regional/languages_import_step2'; $import_mode = (int)$this->Application->GetVar('mode'); // 1 - overwrite existing phrases, 0 - don't overwrite existing phrases $import_source = (int)$this->Application->GetVar('source'); $import_steps = Array(0 => 'lang', 1 => 'phrases', 2 => 'emailmessages', 3 => 'finish'); $key_fields = Array(0 => 'PackName', 1 => 'Phrase', 2 => 'EventId'); // by what field should we search record match $import_titles = Array(0 => 'la_ImportingLanguages', 1 => 'la_ImportingPhrases', 2 => 'la_ImportingEmailEvents', 3 => 'la_Done'); // --- BEFORE --- $import_prefix = $import_steps[$import_source]; $import_start = (int)$this->Application->GetVar('start'); $id_field = $this->Application->getUnitOption($import_prefix,'IDField'); $dst_table = $this->Application->getUnitOption($import_prefix,'TableName'); $src_table = kTempTablesHandler::GetTempName($dst_table); $import_total = $this->Application->GetVar('total'); if(!$import_total) $import_total = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$src_table); // --- AFTER --- if($import_start == $import_total) { $import_source++; $import_prefix = $import_steps[$import_source]; if($import_prefix == 'finish') { $event->SetRedirectParam('opener','u'); return true; } $import_start = 0; $id_field = $this->Application->getUnitOption($import_prefix,'IDField'); $dst_table = $this->Application->getUnitOption($import_prefix,'TableName'); $src_table = kTempTablesHandler::GetTempName($dst_table); $import_total = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$src_table); } $done_percent = ($import_start * 100) / $import_total; $block_params = Array( 'name' => $template_name, 'title' => $import_titles[$import_source], 'percent_done' => $done_percent, 'percent_left' => 100 - $done_percent); $this->Application->InitParser(); $this->Application->setUnitOption('phrases','AutoLoad',false); echo $this->Application->ParseBlock($block_params); flush(); $sql = 'SELECT * FROM %s LIMIT %s,%s'; $rows = $this->Conn->Query( sprintf($sql,$src_table,$import_start,IMPORT_BY) ); $values_sql = ''; // if found and mode = 1 (overwrite) $search_sql = 'SELECT '.$id_field.' FROM '.$dst_table.' WHERE '.$key_fields[$import_source].' = %s AND LanguageId = %s'; $update_sql = 'UPDATE '.$dst_table.' SET %s WHERE '.$id_field.' = %s'; foreach($rows as $row) { $tmp_sql = sprintf($search_sql, $this->Conn->qstr($row[ $key_fields[$import_source] ]), $row['LanguageId'] ); $tmp_id = $this->Conn->GetOne($tmp_sql); if($tmp_id > 0 && $import_mode == 1) { // update $update_fields = ''; foreach($row as $field_name => $field_value) { if($field_name == $id_field) continue; $update_fields .= '`'.$field_name.'` = '.$this->Conn->qstr($field_value).','; } $update_fields = preg_replace('/(.*),$/', '\\1', $update_fields); $this->Conn->Query( sprintf($update_sql, $update_fields, $tmp_id) ); } elseif(!$tmp_id) { $values_sql .= '('; foreach($row as $field_value) { $values_sql .= $this->Conn->qstr($field_value).','; } $values_sql = preg_replace('/(.*),$/', '\\1', $values_sql).'),'; } } if($values_sql) { $fields_sql = ''; $fields = array_keys( $this->Application->getUnitOption($import_prefix,'Fields') ); foreach($fields as $field_name) { $fields_sql .= '`'.$field_name.'`,'; } $fields_sql = preg_replace('/(.*),$/', '\\1', $fields_sql); $values_sql = preg_replace('/(.*),$/', '\\1', $values_sql); $sql = sprintf('INSERT INTO %s (%s) VALUES %s', $dst_table, $fields_sql, $values_sql); $this->Conn->Query($sql); } $event->setRedirectParams( Array('lang_event' => 'OnImportProgress', 'pass' => 'all,lang', 'start' => $import_start += count($rows), 'total' => $import_total, 'source' => $import_source, 'mode' => $import_mode) ); } /** * Stores ids of selected languages and redirects to export language step 1 * * @param kEvent $event */ function OnExportLanguage(&$event) { $this->Application->setUnitOption('phrases','AutoLoad',false); $this->StoreSelectedIDs($event); $this->Application->StoreVar('export_language_ids', implode(',', $this->getSelectedIDs($event)) ); $event->setRedirectParams( Array('m_opener'=>'d','phrases.export_event'=>'OnNew','pass'=>'all,phrases.export') ); $event->redirect = 'regional/languages_export'; } /** * Saves selected languages to xml file passed * * @param kEvent $event */ function OnExportProgress(&$event) { $this->Application->setUnitOption('phrases','AutoLoad',false); $object =& $this->Application->recallObject('phrases.export'); $items_info = $this->Application->GetVar('phrases_export'); if($items_info) { list($id,$field_values) = each($items_info); $lang_ids = explode(',', $this->Application->RecallVar('export_language_ids') ); if( !getArrayValue($field_values,'LangFile') ) { $object->SetError('LangFile', 'required'); $event->redirect = false; return false; } if( !is_writable(EXPORT_PATH) ) { $object->SetError('LangFile', 'write_error', 'la_ExportFolderNotWritable'); $event->redirect = false; return false; } $field_values['LangFile'] .= '.lang'; $filename = EXPORT_PATH.'/'.$field_values['LangFile']; $lang_xml =& $this->Application->recallObject('LangXML'); $lang_xml->Create($filename, $field_values['PhraseType'], $lang_ids, $field_values['Module']); } $event->redirect = 'regional/languages_export_step2'; $event->SetRedirectParam('export_file', $field_values['LangFile']); } /** * Returns to previous template in opener stack * * @param kEvent $event */ function OnGoBack(&$event) { $event->redirect_params['opener'] = 'u'; } } ?> \ No newline at end of file Property changes on: trunk/kernel/units/languages/languages_event_handler.php ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.9 \ No newline at end of property +1.10 \ No newline at end of property Index: trunk/kernel/units/general/cat_event_handler.php =================================================================== --- trunk/kernel/units/general/cat_event_handler.php (revision 2914) +++ trunk/kernel/units/general/cat_event_handler.php (revision 2915) @@ -1,904 +1,951 @@ <?php $application =& kApplication::Instance(); $application->Factory->includeClassFile('kDBEventHandler'); class kCatDBEventHandler extends InpDBEventHandler { function OnCopy(&$event) { $object = $event->getObject(); $this->StoreSelectedIDs($event); $ids = $this->getSelectedIDs($event); $this->Application->StoreVar($event->getPrefixSpecial().'_clipboard', implode(',', $ids)); $this->Application->StoreVar($event->getPrefixSpecial().'_clipboard_mode', 'copy'); $this->Application->StoreVar('ClipBoard', 'COPY-0.'.$object->TableName.'.ResourceId=0'); $event->redirect_params = Array('opener' => 's', 'pass_events'=>true); //do not go up - STAY } function OnCut(&$event) { $object = $event->getObject(); $this->StoreSelectedIDs($event); $ids = $this->getSelectedIDs($event); $this->Application->StoreVar($event->getPrefixSpecial().'_clipboard', implode(',', $ids)); $this->Application->StoreVar($event->getPrefixSpecial().'_clipboard_mode', 'cut'); $this->Application->StoreVar('ClipBoard', 'CUT-0.'.$object->TableName.'.ResourceId=0'); $event->redirect_params = Array('opener' => 's', 'pass_events'=>true); //do not go up - STAY } function OnPaste(&$event) { $ids = $this->Application->RecallVar($event->getPrefixSpecial().'_clipboard'); if ($ids == '') { $event->redirect = false; return; } //recalling by different name, because we may get kDBList, if we recall just by prefix $object =& $this->Application->recallObject($event->getPrefixSpecial().'.item', $event->Prefix); $this->prepareObject($object, $event); if ($this->Application->RecallVar($event->getPrefixSpecial().'_clipboard_mode') == 'copy') { $ids_arr = explode(',', $ids); $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); if($ids_arr) { $temp->CloneItems($event->Prefix, $event->Special, $ids_arr); } } else { // mode == cut $ids_arr = explode(',', $ids); foreach ($ids_arr as $id) { $object->Load($id); $object->MoveToCat(); } } $event->status = erSUCCESS; } /** * Occurs when pasting category * * @param kEvent $event */ function OnCatPaste(&$event) { $inp_clipboard = $this->Application->RecallVar('ClipBoard'); $inp_clipboard = explode('-', $inp_clipboard, 2); if($inp_clipboard[0] == 'COPY') { $saved_cat_id = $this->Application->GetVar('m_cat_id'); $cat_ids = $event->getEventParam('cat_ids'); $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); $table = $this->Application->getUnitOption($event->Prefix, 'TableName'); $ids_sql = 'SELECT '.$id_field.' FROM '.$table.' WHERE ResourceId IN (%s)'; $resource_ids_sql = 'SELECT ItemResourceId FROM '.TABLE_PREFIX.'CategoryItems WHERE CategoryId = %s AND PrimaryCat = 1'; $this->Application->setUnitOption($event->Prefix,'AutoLoad', false); $object =& $this->Application->recallObject($event->Prefix.'.item', $event->Prefix); foreach($cat_ids as $source_cat => $dest_cat) { $item_resource_ids = $this->Conn->GetCol( sprintf($resource_ids_sql, $source_cat) ); if(!$item_resource_ids) continue; $this->Application->SetVar('m_cat_id', $dest_cat); $item_ids = $this->Conn->GetCol( sprintf($ids_sql, implode(',', $item_resource_ids) ) ); $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); if($item_ids) $temp->CloneItems($event->Prefix, $event->Special, $item_ids); } $this->Application->setUnitOption($event->Prefix,'AutoLoad', true); $this->Application->SetVar('m_cat_id', $saved_cat_id); } } /** + * Enter description here... + * + * @param kEvent $event + */ + function OnPreSaveAndOpenTranslator(&$event) + { + $this->Application->SetVar('allow_translation', true); + $object =& $event->getObject(); + $this->RemoveRequiredFields($object); + $event->CallSubEvent('OnPreSave'); + if ($event->status == erSUCCESS) { +// $url = $this->Application->HREF($t, '', Array('pass'=>'all', $event->getPrefixSpecial(true).'_id' => $object->GetId())); +// $field = $this->Application->GetVar('translator_field'); + $cf_id = $this->Application->GetVar('translator_cf_id'); + if($cf_id) + { + $cv =& $this->Application->recallObject('cv.-item', null, Array('skip_autoload' => true) ); + $load_params = Array('CustomFieldId' => $cf_id, 'ResourceId'=> $object->GetDBField('ResourceId') ); + if( !$cv->Load($load_params) ) + { + $cv->SetFieldsFromHash($load_params); + $cv->Create(); + } + $this->Application->SetVar('cv_id', $cv->getID() ); + } + + $event->redirect = $this->Application->GetVar('translator_t'); + $event->redirect_params = Array('pass'=>'all,trans,'.$this->Application->GetVar('translator_prefixes'), + $event->getPrefixSpecial(true).'_id' => $object->GetId(), + 'trans_event'=>'OnLoad', + 'trans_prefix'=> $this->Application->GetVar('translator_prefixes'), + 'trans_field'=>$this->Application->GetVar('translator_field'), + ); + + // 1. SAVE LAST TEMPLATE TO SESSION + $last_template = $this->Application->RecallVar('last_template'); + preg_match('/index4\.php\|'.$this->Application->GetSID().'-(.*):/U', $last_template, $rets); + $this->Application->StoreVar('return_template', $rets[1]); + + //$after_script = "openTranslator('".$event->getPrefixSpecial()."', '".$field."', '".$url."', '".$wnd_name."')"; + } + +// $this->Application->SetVar('after_script', $after_script); +// $event->redirect = false; + } + + /** * Apply scope clause * * @param kEvent $event */ function SetCustomQuery(&$event) { $object =& $event->getObject(); if ($event->Special != 'showall') { if ( $event->getEventParam('parent_cat_id') ) { $parent_cat_id = $event->getEventParam('parent_cat_id'); } else { $parent_cat_id = $this->Application->GetVar('c_id'); if (!$parent_cat_id) { $parent_cat_id = $this->Application->GetVar('m_cat_id'); } if (!$parent_cat_id) { $parent_cat_id = 0; } } if ((string) $parent_cat_id != 'any') { if ($event->getEventParam('recursive')) { $current_path = $this->Conn->GetOne('SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId='.$parent_cat_id); $subcats = $this->Conn->GetCol('SELECT CategoryId FROM '.TABLE_PREFIX.'Category WHERE ParentPath LIKE "'.$current_path.'%" '); $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId IN ('.implode(', ', $subcats).')'); } else { $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId = '.$parent_cat_id ); } } } else { $object->addFilter('primary_filter', 'PrimaryCat = 1'); } $view_perm = 1; $object->addFilter('perm_filter', 'perm.PermId = '.$view_perm); if (!defined('ADMIN')) { $groups = explode(',',$this->Application->RecallVar('UserGroups')); foreach ($groups as $group) { $view_filters[] = 'FIND_IN_SET('.$group.', perm.acl) || ((NOT FIND_IN_SET('.$group.',perm.dacl)) AND perm.acl=\'\')'; } $view_filter = implode(' OR ', $view_filters); $object->addFilter('perm_filter2', $view_filter); } if (!defined('ADMIN')) { $object->addFilter('status_filter', $object->TableName.'.Status = 1'); } /*$list_type = $event->getEventParam('ListType'); switch($list_type) { case 'favorites': $fav_table = $this->Application->getUnitOption('fav','TableName'); $user_id =& $this->Application->GetVar('u_id'); $sql = 'SELECT DISTINCT f.ResourceId FROM '.$fav_table.' f LEFT JOIN '.$object->TableName.' p ON p.ResourceId = f.ResourceId WHERE f.PortalUserId = '.$user_id; $ids = $this->Conn->GetCol($sql); if(!$ids) $ids = Array(-1); $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.PrimaryCat = 1'); $object->addFilter('favorites_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')'); break; case 'search': $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetVar('sid').'_'.TABLE_PREFIX.'Search'; $sql = ' SELECT DISTINCT ResourceId FROM '.$search_results_table.' WHERE ItemType=11'; $ids = $this->Conn->GetCol($sql); if(!$ids) $ids = Array(-1); $object->addFilter('search_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')'); 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 Property changes on: trunk/kernel/units/general/cat_event_handler.php ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.9 \ No newline at end of property +1.10 \ No newline at end of property Index: trunk/admin/help/manual.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: trunk/admin/help/manual.pdf ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.17 \ No newline at end of property +1.18 \ No newline at end of property Index: trunk/core/units/languages/languages_event_handler.php =================================================================== --- trunk/core/units/languages/languages_event_handler.php (revision 2914) +++ trunk/core/units/languages/languages_event_handler.php (revision 2915) @@ -1,366 +1,366 @@ <?php class LanguagesEventHandler extends InpDBEventHandler { /** * Updates table structure on new language adding/removing language * * @param kEvent $event */ function OnReflectMultiLingualFields($event) { $table_name = $this->Application->getUnitOption($event->Prefix,'TableName'); $languages_count = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$table_name); $languages_count = $languages_count + 5 - ( $languages_count % 5 ? ($languages_count % 5) : 5 ); $sqls = Array(); $unit_config_reader =& $this->Application->recallObject('kUnitConfigReader'); foreach($unit_config_reader->configData as $prefix => $config_data) { $table_name = getArrayValue($config_data,'TableName'); $fields = getArrayValue($config_data,'Fields'); if(!($table_name && $fields) ) continue; foreach($fields as $field_name => $field_options) { if( isset($field_options['formatter']) && $field_options['formatter'] == 'kMultiLanguage' ) { $describe = $this->Conn->Query('DESCRIBE '.$table_name.' \'l%_'.$field_name.'\''); $field_mask = 'l%s_'.$field_name.' '.$describe[0]['Type']; $create_count = $languages_count - count($describe); - if($create_count) + if($create_count > 0) { $sqls[] = 'ALTER TABLE '.$table_name.( $this->generateAlterSQL($field_mask, count($describe) + 1, $create_count) ); } } } } if($sqls) $this->Conn->Query( implode("\n",$sqls) ); } /** * Shows only enabled languages on front * * @param kEvent $event */ function SetCustomQuery(&$event) { if($event->Special == 'enabled') { $object =& $event->getObject(); $object->addFilter('enabled_filter', '%1$s.Enabled = 1'); } } /** * Returns ALTER statement part for adding required fields to table * * @param string $field_mask sql mask for creating field with correct definition (type & size) * @param int $start_index add new fields starting from this index * @param int $create_count create this much new multilingual field translations * @return string */ function generateAlterSQL($field_mask, $start_index, $create_count) { $i_count = $start_index + $create_count; $ret = ''; while($start_index < $i_count) { list($prev_field,$type) = explode(' ', sprintf($field_mask, $start_index-1) ); $ret .= ' ADD COLUMN '.sprintf($field_mask,$start_index).' AFTER '.$prev_field.', '; $start_index++; } return preg_replace('/, $/',';',$ret); } /** * Copy labels from another language * * @param kEvent $event */ function OnCopyLabels(&$event) { $object =& $event->getObject(); $from_lang_id = $object->GetDBField('CopyFromLanguage'); if( ($event->MasterEvent->status == erSUCCESS) && $object->GetDBField('CopyLabels') == 1 && ($from_lang_id > 0) ) { $lang_id = $object->GetID(); // 1. phrases import $phrases_live = $this->Application->getUnitOption('phrases','TableName'); $phrases_temp = kTempTablesHandler::GetTempName($phrases_live); $sql = 'INSERT INTO '.$phrases_temp.' SELECT Phrase, Translation, PhraseType, 0-PhraseId, '.$lang_id.', '.time().', "", Module FROM '.$phrases_live.' WHERE LanguageId='.$from_lang_id; $this->Conn->Query($sql); // 2. events import $em_table_live = $this->Application->getUnitOption('emailmessages','TableName'); $em_table_temp = kTempTablesHandler::GetTempName($em_table_live); $sql = 'SELECT * FROM '.$em_table_live.' WHERE LanguageId = '.$from_lang_id; $email_messages = $this->Conn->Query($sql); if($email_messages) { $id = $this->Conn->GetOne('SELECT MIN(EmailMessageId) FROM '.$em_table_live); if($id > 0) $id = 0; $id--; $sqls = Array(); foreach($email_messages as $email_message) { $sqls[] = $id.','.$this->Conn->qstr($email_message['Template']).','.$this->Conn->qstr($email_message['MessageType']).','.$lang_id.','.$email_message['EventId']; $id--; } $sql = 'INSERT INTO '.$em_table_temp.'(EmailMessageId,Template,MessageType,LanguageId,EventId) VALUES ('.implode('),(',$sqls).')'; $this->Conn->Query($sql); } $object->SetDBField('CopyLabels', 0); } } /** * Prepare temp tables for creating new item * but does not create it. Actual create is * done in OnPreSaveCreated * * @param kEvent $event */ function OnPreCreate(&$event) { parent::OnPreCreate($event); $object =& $event->getObject(); $object->SetDBField('CopyLabels', 1); $live_table = kTempTablesHandler::GetLiveName($object->TableName); $primary_lang_id = $this->Conn->GetOne('SELECT '.$object->IDField.' FROM '.$live_table.' WHERE PrimaryLang = 1'); $object->SetDBField('CopyFromLanguage', $primary_lang_id); } function OnChangeLanguage(&$event) { $this->Application->SetVar('m_lang', $this->Application->GetVar('language')); $this->Application->LinkVar('language', 'm_lang'); } /** * Parse language XML file into temp tables and redirect to progress bar screen * * @param kEvent $event */ function OnImportLanguage(&$event) { $items_info = $this->Application->GetVar('phrases_import'); if($items_info) { list($id,$field_values) = each($items_info); $filename = getArrayValue($field_values, 'LangFile', 'tmp_name'); if( filesize($filename) ) { $modules = getArrayValue($field_values,'Module'); $lang_xml =& $this->Application->recallObject('LangXML'); $lang_xml->Parse($filename, $field_values['PhraseType'], $modules, $field_values['ImportOverwrite']); $event->redirect = 'dummy'; $event->SetRedirectParams( Array('lang_event' => 'OnImportProgress', 'pass' => 'all,lang', 'mode'=>$field_values['ImportOverwrite']) ); } else { $object =& $this->Application->recallObject('phrases.import'); $object->SetError('LangFile', 'la_empty_file', 'la_EmptyFile'); $event->redirect = false; } } } /** * Copies imported from xml file from temp table to live table * * @param kEvent $event */ function OnImportProgress(&$event) { define('IMPORT_BY', 300); // import this much records per step $template_name = 'regional/languages_import_step2'; $import_mode = (int)$this->Application->GetVar('mode'); // 1 - overwrite existing phrases, 0 - don't overwrite existing phrases $import_source = (int)$this->Application->GetVar('source'); $import_steps = Array(0 => 'lang', 1 => 'phrases', 2 => 'emailmessages', 3 => 'finish'); $key_fields = Array(0 => 'PackName', 1 => 'Phrase', 2 => 'EventId'); // by what field should we search record match $import_titles = Array(0 => 'la_ImportingLanguages', 1 => 'la_ImportingPhrases', 2 => 'la_ImportingEmailEvents', 3 => 'la_Done'); // --- BEFORE --- $import_prefix = $import_steps[$import_source]; $import_start = (int)$this->Application->GetVar('start'); $id_field = $this->Application->getUnitOption($import_prefix,'IDField'); $dst_table = $this->Application->getUnitOption($import_prefix,'TableName'); $src_table = kTempTablesHandler::GetTempName($dst_table); $import_total = $this->Application->GetVar('total'); if(!$import_total) $import_total = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$src_table); // --- AFTER --- if($import_start == $import_total) { $import_source++; $import_prefix = $import_steps[$import_source]; if($import_prefix == 'finish') { $event->SetRedirectParam('opener','u'); return true; } $import_start = 0; $id_field = $this->Application->getUnitOption($import_prefix,'IDField'); $dst_table = $this->Application->getUnitOption($import_prefix,'TableName'); $src_table = kTempTablesHandler::GetTempName($dst_table); $import_total = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$src_table); } $done_percent = ($import_start * 100) / $import_total; $block_params = Array( 'name' => $template_name, 'title' => $import_titles[$import_source], 'percent_done' => $done_percent, 'percent_left' => 100 - $done_percent); $this->Application->InitParser(); $this->Application->setUnitOption('phrases','AutoLoad',false); echo $this->Application->ParseBlock($block_params); flush(); $sql = 'SELECT * FROM %s LIMIT %s,%s'; $rows = $this->Conn->Query( sprintf($sql,$src_table,$import_start,IMPORT_BY) ); $values_sql = ''; // if found and mode = 1 (overwrite) $search_sql = 'SELECT '.$id_field.' FROM '.$dst_table.' WHERE '.$key_fields[$import_source].' = %s AND LanguageId = %s'; $update_sql = 'UPDATE '.$dst_table.' SET %s WHERE '.$id_field.' = %s'; foreach($rows as $row) { $tmp_sql = sprintf($search_sql, $this->Conn->qstr($row[ $key_fields[$import_source] ]), $row['LanguageId'] ); $tmp_id = $this->Conn->GetOne($tmp_sql); if($tmp_id > 0 && $import_mode == 1) { // update $update_fields = ''; foreach($row as $field_name => $field_value) { if($field_name == $id_field) continue; $update_fields .= '`'.$field_name.'` = '.$this->Conn->qstr($field_value).','; } $update_fields = preg_replace('/(.*),$/', '\\1', $update_fields); $this->Conn->Query( sprintf($update_sql, $update_fields, $tmp_id) ); } elseif(!$tmp_id) { $values_sql .= '('; foreach($row as $field_value) { $values_sql .= $this->Conn->qstr($field_value).','; } $values_sql = preg_replace('/(.*),$/', '\\1', $values_sql).'),'; } } if($values_sql) { $fields_sql = ''; $fields = array_keys( $this->Application->getUnitOption($import_prefix,'Fields') ); foreach($fields as $field_name) { $fields_sql .= '`'.$field_name.'`,'; } $fields_sql = preg_replace('/(.*),$/', '\\1', $fields_sql); $values_sql = preg_replace('/(.*),$/', '\\1', $values_sql); $sql = sprintf('INSERT INTO %s (%s) VALUES %s', $dst_table, $fields_sql, $values_sql); $this->Conn->Query($sql); } $event->setRedirectParams( Array('lang_event' => 'OnImportProgress', 'pass' => 'all,lang', 'start' => $import_start += count($rows), 'total' => $import_total, 'source' => $import_source, 'mode' => $import_mode) ); } /** * Stores ids of selected languages and redirects to export language step 1 * * @param kEvent $event */ function OnExportLanguage(&$event) { $this->Application->setUnitOption('phrases','AutoLoad',false); $this->StoreSelectedIDs($event); $this->Application->StoreVar('export_language_ids', implode(',', $this->getSelectedIDs($event)) ); $event->setRedirectParams( Array('m_opener'=>'d','phrases.export_event'=>'OnNew','pass'=>'all,phrases.export') ); $event->redirect = 'regional/languages_export'; } /** * Saves selected languages to xml file passed * * @param kEvent $event */ function OnExportProgress(&$event) { $this->Application->setUnitOption('phrases','AutoLoad',false); $object =& $this->Application->recallObject('phrases.export'); $items_info = $this->Application->GetVar('phrases_export'); if($items_info) { list($id,$field_values) = each($items_info); $lang_ids = explode(',', $this->Application->RecallVar('export_language_ids') ); if( !getArrayValue($field_values,'LangFile') ) { $object->SetError('LangFile', 'required'); $event->redirect = false; return false; } if( !is_writable(EXPORT_PATH) ) { $object->SetError('LangFile', 'write_error', 'la_ExportFolderNotWritable'); $event->redirect = false; return false; } $field_values['LangFile'] .= '.lang'; $filename = EXPORT_PATH.'/'.$field_values['LangFile']; $lang_xml =& $this->Application->recallObject('LangXML'); $lang_xml->Create($filename, $field_values['PhraseType'], $lang_ids, $field_values['Module']); } $event->redirect = 'regional/languages_export_step2'; $event->SetRedirectParam('export_file', $field_values['LangFile']); } /** * Returns to previous template in opener stack * * @param kEvent $event */ function OnGoBack(&$event) { $event->redirect_params['opener'] = 'u'; } } ?> \ No newline at end of file Property changes on: trunk/core/units/languages/languages_event_handler.php ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.9 \ No newline at end of property +1.10 \ No newline at end of property Index: trunk/core/units/general/cat_event_handler.php =================================================================== --- trunk/core/units/general/cat_event_handler.php (revision 2914) +++ trunk/core/units/general/cat_event_handler.php (revision 2915) @@ -1,904 +1,951 @@ <?php $application =& kApplication::Instance(); $application->Factory->includeClassFile('kDBEventHandler'); class kCatDBEventHandler extends InpDBEventHandler { function OnCopy(&$event) { $object = $event->getObject(); $this->StoreSelectedIDs($event); $ids = $this->getSelectedIDs($event); $this->Application->StoreVar($event->getPrefixSpecial().'_clipboard', implode(',', $ids)); $this->Application->StoreVar($event->getPrefixSpecial().'_clipboard_mode', 'copy'); $this->Application->StoreVar('ClipBoard', 'COPY-0.'.$object->TableName.'.ResourceId=0'); $event->redirect_params = Array('opener' => 's', 'pass_events'=>true); //do not go up - STAY } function OnCut(&$event) { $object = $event->getObject(); $this->StoreSelectedIDs($event); $ids = $this->getSelectedIDs($event); $this->Application->StoreVar($event->getPrefixSpecial().'_clipboard', implode(',', $ids)); $this->Application->StoreVar($event->getPrefixSpecial().'_clipboard_mode', 'cut'); $this->Application->StoreVar('ClipBoard', 'CUT-0.'.$object->TableName.'.ResourceId=0'); $event->redirect_params = Array('opener' => 's', 'pass_events'=>true); //do not go up - STAY } function OnPaste(&$event) { $ids = $this->Application->RecallVar($event->getPrefixSpecial().'_clipboard'); if ($ids == '') { $event->redirect = false; return; } //recalling by different name, because we may get kDBList, if we recall just by prefix $object =& $this->Application->recallObject($event->getPrefixSpecial().'.item', $event->Prefix); $this->prepareObject($object, $event); if ($this->Application->RecallVar($event->getPrefixSpecial().'_clipboard_mode') == 'copy') { $ids_arr = explode(',', $ids); $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); if($ids_arr) { $temp->CloneItems($event->Prefix, $event->Special, $ids_arr); } } else { // mode == cut $ids_arr = explode(',', $ids); foreach ($ids_arr as $id) { $object->Load($id); $object->MoveToCat(); } } $event->status = erSUCCESS; } /** * Occurs when pasting category * * @param kEvent $event */ function OnCatPaste(&$event) { $inp_clipboard = $this->Application->RecallVar('ClipBoard'); $inp_clipboard = explode('-', $inp_clipboard, 2); if($inp_clipboard[0] == 'COPY') { $saved_cat_id = $this->Application->GetVar('m_cat_id'); $cat_ids = $event->getEventParam('cat_ids'); $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); $table = $this->Application->getUnitOption($event->Prefix, 'TableName'); $ids_sql = 'SELECT '.$id_field.' FROM '.$table.' WHERE ResourceId IN (%s)'; $resource_ids_sql = 'SELECT ItemResourceId FROM '.TABLE_PREFIX.'CategoryItems WHERE CategoryId = %s AND PrimaryCat = 1'; $this->Application->setUnitOption($event->Prefix,'AutoLoad', false); $object =& $this->Application->recallObject($event->Prefix.'.item', $event->Prefix); foreach($cat_ids as $source_cat => $dest_cat) { $item_resource_ids = $this->Conn->GetCol( sprintf($resource_ids_sql, $source_cat) ); if(!$item_resource_ids) continue; $this->Application->SetVar('m_cat_id', $dest_cat); $item_ids = $this->Conn->GetCol( sprintf($ids_sql, implode(',', $item_resource_ids) ) ); $temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler'); if($item_ids) $temp->CloneItems($event->Prefix, $event->Special, $item_ids); } $this->Application->setUnitOption($event->Prefix,'AutoLoad', true); $this->Application->SetVar('m_cat_id', $saved_cat_id); } } /** + * Enter description here... + * + * @param kEvent $event + */ + function OnPreSaveAndOpenTranslator(&$event) + { + $this->Application->SetVar('allow_translation', true); + $object =& $event->getObject(); + $this->RemoveRequiredFields($object); + $event->CallSubEvent('OnPreSave'); + if ($event->status == erSUCCESS) { +// $url = $this->Application->HREF($t, '', Array('pass'=>'all', $event->getPrefixSpecial(true).'_id' => $object->GetId())); +// $field = $this->Application->GetVar('translator_field'); + $cf_id = $this->Application->GetVar('translator_cf_id'); + if($cf_id) + { + $cv =& $this->Application->recallObject('cv.-item', null, Array('skip_autoload' => true) ); + $load_params = Array('CustomFieldId' => $cf_id, 'ResourceId'=> $object->GetDBField('ResourceId') ); + if( !$cv->Load($load_params) ) + { + $cv->SetFieldsFromHash($load_params); + $cv->Create(); + } + $this->Application->SetVar('cv_id', $cv->getID() ); + } + + $event->redirect = $this->Application->GetVar('translator_t'); + $event->redirect_params = Array('pass'=>'all,trans,'.$this->Application->GetVar('translator_prefixes'), + $event->getPrefixSpecial(true).'_id' => $object->GetId(), + 'trans_event'=>'OnLoad', + 'trans_prefix'=> $this->Application->GetVar('translator_prefixes'), + 'trans_field'=>$this->Application->GetVar('translator_field'), + ); + + // 1. SAVE LAST TEMPLATE TO SESSION + $last_template = $this->Application->RecallVar('last_template'); + preg_match('/index4\.php\|'.$this->Application->GetSID().'-(.*):/U', $last_template, $rets); + $this->Application->StoreVar('return_template', $rets[1]); + + //$after_script = "openTranslator('".$event->getPrefixSpecial()."', '".$field."', '".$url."', '".$wnd_name."')"; + } + +// $this->Application->SetVar('after_script', $after_script); +// $event->redirect = false; + } + + /** * Apply scope clause * * @param kEvent $event */ function SetCustomQuery(&$event) { $object =& $event->getObject(); if ($event->Special != 'showall') { if ( $event->getEventParam('parent_cat_id') ) { $parent_cat_id = $event->getEventParam('parent_cat_id'); } else { $parent_cat_id = $this->Application->GetVar('c_id'); if (!$parent_cat_id) { $parent_cat_id = $this->Application->GetVar('m_cat_id'); } if (!$parent_cat_id) { $parent_cat_id = 0; } } if ((string) $parent_cat_id != 'any') { if ($event->getEventParam('recursive')) { $current_path = $this->Conn->GetOne('SELECT ParentPath FROM '.TABLE_PREFIX.'Category WHERE CategoryId='.$parent_cat_id); $subcats = $this->Conn->GetCol('SELECT CategoryId FROM '.TABLE_PREFIX.'Category WHERE ParentPath LIKE "'.$current_path.'%" '); $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId IN ('.implode(', ', $subcats).')'); } else { $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.CategoryId = '.$parent_cat_id ); } } } else { $object->addFilter('primary_filter', 'PrimaryCat = 1'); } $view_perm = 1; $object->addFilter('perm_filter', 'perm.PermId = '.$view_perm); if (!defined('ADMIN')) { $groups = explode(',',$this->Application->RecallVar('UserGroups')); foreach ($groups as $group) { $view_filters[] = 'FIND_IN_SET('.$group.', perm.acl) || ((NOT FIND_IN_SET('.$group.',perm.dacl)) AND perm.acl=\'\')'; } $view_filter = implode(' OR ', $view_filters); $object->addFilter('perm_filter2', $view_filter); } if (!defined('ADMIN')) { $object->addFilter('status_filter', $object->TableName.'.Status = 1'); } /*$list_type = $event->getEventParam('ListType'); switch($list_type) { case 'favorites': $fav_table = $this->Application->getUnitOption('fav','TableName'); $user_id =& $this->Application->GetVar('u_id'); $sql = 'SELECT DISTINCT f.ResourceId FROM '.$fav_table.' f LEFT JOIN '.$object->TableName.' p ON p.ResourceId = f.ResourceId WHERE f.PortalUserId = '.$user_id; $ids = $this->Conn->GetCol($sql); if(!$ids) $ids = Array(-1); $object->addFilter('category_filter', TABLE_PREFIX.'CategoryItems.PrimaryCat = 1'); $object->addFilter('favorites_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')'); break; case 'search': $search_results_table = TABLE_PREFIX.'ses_'.$this->Application->GetVar('sid').'_'.TABLE_PREFIX.'Search'; $sql = ' SELECT DISTINCT ResourceId FROM '.$search_results_table.' WHERE ItemType=11'; $ids = $this->Conn->GetCol($sql); if(!$ids) $ids = Array(-1); $object->addFilter('search_filter', '%1$s.`ResourceId` IN ('.implode(',',$ids).')'); 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 Property changes on: trunk/core/units/general/cat_event_handler.php ___________________________________________________________________ Modified: cvs2svn:cvs-rev ## -1 +1 ## -1.9 \ No newline at end of property +1.10 \ No newline at end of property