public static function search($search, $categories) { if (!$categories) { return; } $token_length = self::get_token_length(); $limit = Base_SearchCommon::get_recordset_limit_records(); $tabs_priority = DB::GetAssoc('SELECT id,search_priority FROM recordbrowser_table_properties WHERE search_include>0'); $categories = array_intersect($categories, array_keys($tabs_priority)); $categories = array_map(create_function('$a', 'return DB::qstr($a);'), $categories); $texts = array_filter(preg_split('/[^\\p{L}0-9]/u', mb_strtolower($search))); $total_results = array(); $total_max_score = 0; foreach ($texts as $text) { //for each word $len = mb_strlen($text); if ($len < $token_length) { continue; } //if word is less then token lenght - ignore it $results = array(); $max_score = $len - $token_length + 1; $total_max_score += $len; for ($i = 0; $i <= $len - $token_length; $i++) { $word = mb_substr($text, $i, $token_length); $ret = DB::Execute('SELECT m.tab_id,m.record_id,m.field_id,m.position FROM recordbrowser_words_index w INNER JOIN recordbrowser_words_map m ON w.id=m.word_id WHERE w.word=%s AND m.tab_id IN (' . implode(',', $categories) . ')', array($word)); while ($row = $ret->FetchRow()) { $score = 1; for ($k = 1; $k <= $token_length + 1; $k++) { if (isset($results[$row['tab_id']][$row['record_id']][$row['field_id']][$row['position'] - $k])) { $score += $results[$row['tab_id']][$row['record_id']][$row['field_id']][$row['position'] - $k]; break; } } $results[$row['tab_id']][$row['record_id']][$row['field_id']][$row['position']] = min($max_score, $score); } } foreach ($results as $tab_id => $records) { foreach ($records as $record => $fields) { //get max score for each field... if max score is 50% or more equal save it foreach ($fields as $field => $scores) { $max_score_local = max($scores); if ($max_score_local > $max_score / 2) { $results[$tab_id][$record][$field] = $max_score_local; } else { unset($results[$tab_id][$record][$field]); } } //if some fields was saved if ($results[$tab_id][$record]) { $max = 0; //get max score of all fields where the "word" was found $max_fields = array(); //get field names with maximal score foreach ($results[$tab_id][$record] as $field => $score) { if ($max < $score) { $max = $score; $max_fields = array($field); } elseif ($max == $score) { $max_fields[] = $field; } } $max += $token_length - 1; if (!isset($total_results[$tab_id . '#' . $record])) { $total_results[$tab_id . '#' . $record] = array('score' => 0, 'fields' => array(), 'fields_score' => array(), 'priority' => $tabs_priority[$tab_id]); } $total_results[$tab_id . '#' . $record]['score'] += $max; $total_results[$tab_id . '#' . $record]['fields_score'][] = $max; $total_results[$tab_id . '#' . $record]['fields'][] = $max_fields; } else { unset($results[$tab_id][$record]); } } } unset($results); } if ($total_max_score == 0) { Epesi::alert(__('Displaying only partial results - please enter at least one word of 3 or more letters')); return; } //sort with score... if score is the same sort with qty of fields where the "word" was found uasort($total_results, create_function('$a,$b', 'return $a["score"]>$b["score"]?-1:($a["score"]<$b["score"]?1:($a["priority"]>$b["priority"]?-1:($a["priority"]<$b["priority"]?1:($a["fields"]>$b["fields"]?-1:1))));')); $tabs = DB::GetAssoc('SELECT id,tab FROM recordbrowser_table_properties WHERE search_include>0'); $ret = array(); $cols_cache = array(); $count = 0; foreach ($total_results as $rec => $score) { list($tab_id, $id) = explode('#', $rec, 2); $tab = $tabs[$tab_id]; $record = self::get_record($tab, $id); //get fields names translations if (!isset($cols_cache[$tab])) { $table_rows = self::init($tab); $cols_cache[$tab] = array(); foreach ($table_rows as $col) { $cols_cache[$tab][$col['pkey']] = array('name' => $col['name'], 'id' => $col['id']); } } //get access $has_access = self::get_access($tab, 'view', $record); if (!$has_access) { continue; } //no access at all //if there are fields that should not be visible, remove them from results list and recalculate score foreach ($score['fields'] as $fields_group => $fields) { foreach ($fields as $field_pos => $field_id) { if (isset($cols_cache[$tab][$field_id])) { $field = $cols_cache[$tab][$field_id]['id']; } else { $field = ''; } if (!isset($has_access[$field]) || !$has_access[$field]) { unset($score['fields'][$fields_group][$field_pos]); } } if (empty($score['fields'][$fields_group])) { $score['score'] -= $score['fields_score'][$fields_group]; unset($score['fields'][$fields_group]); unset($score['fields_score'][$fields_group]); } } if (!$score['fields']) { continue; } $fields = array(); foreach ($score['fields'] as $fields_group) { foreach ($fields_group as $field) { $fields[] = _V($cols_cache[$tab][$field]['name']); } } //create link with default label $ret[] = self::create_default_linked_label($tab, $id) . ' <span style="color: red">' . round($score['score'] * 100 / $total_max_score) . '%</span> (' . implode(', ', $fields) . ')'; $count++; if ($count >= $limit) { break; } } return $ret; }
public static function search($word, $types) { if(!$types) return; $r = null; $limit = Base_SearchCommon::get_recordset_limit_records(); $ret = array(); foreach($types as $type) { if($type=='files') { $r = DB::SelectLimit('SELECT ua.id,uaf.original,ual.func,ual.args,ual.local,ua.f_title FROM utils_attachment_data_1 ua INNER JOIN utils_attachment_local AS ual ON ual.attachment=ua.id INNER JOIN utils_attachment_file AS uaf ON uaf.attach_id=ua.id WHERE ua.active=1 AND '. ' uaf.original '.DB::like().' '.DB::Concat(DB::qstr('%'),'%s',DB::qstr('%')).' AND uaf.deleted=0', $limit, -1, array($word)); } elseif($type=='downloads') { if(strlen($word)==32) { $query = 'SELECT ua.id,uaf.original,ual.func,ual.args,ual.local,ua.f_title FROM utils_attachment_file uaf INNER JOIN utils_attachment_download uad ON uad.attach_file_id=uaf.id INNER JOIN utils_attachment_data_1 ua ON uaf.attach_id=ua.id INNER JOIN utils_attachment_local AS ual ON ual.attachment=ua.id WHERE uad.token='.DB::qstr($word); $r = DB::Execute($query); } else { $query = parse_url($word,PHP_URL_QUERY); if($query) { $vars = array(); parse_str($query,$vars); if($vars && isset($vars['id']) && isset($vars['token'])) { $query = 'SELECT ua.id,uaf.original,ual.func,ual.args,ual.local,ua.f_title FROM utils_attachment_file uaf INNER JOIN utils_attachment_download uad ON uad.attach_file_id=uaf.id INNER JOIN utils_attachment_data_1 ua ON uaf.attach_id=ua.id INNER JOIN utils_attachment_local AS ual ON ual.attachment=ua.id WHERE uad.id='.DB::qstr($vars['id']).' AND uad.token='.DB::qstr($vars['token']); $r = DB::Execute($query); } } } } if($r) { while($row = $r->FetchRow()) { if(!self::get_access($row['id'])) continue; $func = unserialize($row['func']); $record = $func ? call_user_func_array($func, unserialize($row['args'])) : ''; if(!$record) continue; $title = $row['original'].' - '.self::description_callback(Utils_RecordBrowserCommon::get_record('utils_attachment',$row['id'])); $title = Utils_RecordBrowserCommon::record_link_open_tag('utils_attachment', $row['id']) . __('Files').': ' . $title . Utils_RecordBrowserCommon::record_link_close_tag(); $ret[$row['id'].'#'.$row['local']] = $title . " ($record)"; } } } return $ret; }