To achieve search/sort by "relevance," I looked at Mindstellar (available on GitHub), which, starting with version 5.0.0, stated in its changelog that, among other changes, it had included this feature. What I did was adapt the code in model/Search.php and helpers/hSearch.php (to include the option). Specifically, in the code within model/Search.php, I changed this section to:
/**
* Establish the order of the search
*
* @access public
* @since unknown
* @param string $o_c column
* @param string $o_d direction
* @param string $table
*/
public function order($o_c = '', $o_d = 'DESC', $table = null)
{
// LÓGICA DE RELEVANCIA MEJORADA:
// 1. Si la columna de orden es 'relevance', la forzamos a ser descendente (la mayor puntuación es la más relevante).
if ($o_c === 'relevance') {
$o_d = 'DESC';
// 2. Si no se ha especificado un orden ('') o el orden es el de defecto ('dt_pub_date')
// y hay un patrón de búsqueda, forzamos 'relevance'.
} elseif ($o_c === '') {
if ($this->withPattern) {
$o_c = 'relevance'; // Usar relevancia si hay patrón de búsqueda
} else {
$o_c = 'dt_pub_date'; // Usar fecha de publicación si no hay patrón
}
}
// FIN DE LA LÓGICA DE RELEVANCIA
// Lógica original de OsclassPoint para establecer la columna
if ($table == '') {
$this->order_column = $o_c;
} elseif ($table != '') {
// Nota: Adaptado para usar el prefijo de Osclass y la lógica de Mindstellar.
if ($table === DB_TABLE_PREFIX . 't_user') {
$this->order_column = sprintf("ISNULL(%s.$o_c), %s.$o_c", $table, $table);
} else {
$this->order_column = sprintf("$table.$o_c");
}
}
$this->order_direction = $o_d;
}
and this:
/**
* Return an array with columns allowed for sorting
*
* @return array
*/
public static function getAllowedColumnsForSorting($extended = false) {
$data = array('i_price', 'dt_pub_date', 'relevance');
if($extended === true) {
$data[] = 'dt_expiration';
$data[] = 'i_rating';
}
return osc_apply_filter('search_list_columns', $data);
}
I also modified this part as follows:
if($this->withPattern) {
// Unir la tabla de descripciones (ya existe en OsclassPoint)
$this->dao->join(DB_TABLE_PREFIX.'t_item_description as d','d.fk_i_item_id = '.DB_TABLE_PREFIX.'t_item.pk_i_id','LEFT');
// ********** INYECCIÓN DE LÓGICA DE RELEVANCIA **********
// 1. Si se ordenó por relevancia, añadimos el SELECT y HAVING
if ($this->order_column === 'relevance') {
// SELECT: Añadir la columna de puntuación 'relevance' (Mindstellar)
$this->dao->select(sprintf(
"MATCH(d.s_title, d.s_description) AGAINST('%s') as relevance",
$this->sPattern
));
// HAVING: Filtra los resultados con puntuación cero (Mindstellar)
$this->dao->having(sprintf("relevance > %s", 0));
}
// ********** FIN DE INYECCIÓN DE LÓGICA DE RELEVANCIA **********
$search_pattern_cond = '';
// 2. Lógica de WHERE de OsclassPoint (Mantenida)
if($this->sPattern != '') {
if(osc_search_pattern_method() == '') {
// Si la columna de orden es 'relevance', ya no necesitamos un WHERE adicional,
// ya que el HAVING lo hace. De lo contrario, usamos BOOLEAN MODE.
if ($this->order_column !== 'relevance') {
$search_pattern_cond = sprintf("MATCH(d.s_title, d.s_description) AGAINST('%s' IN BOOLEAN MODE)", $this->sPattern);
}
} else if(osc_search_pattern_method() == 'nlp') {
// Si el modo es NLP, no ordenamos, solo filtramos
$search_pattern_cond = sprintf("MATCH(d.s_title, d.s_description) AGAINST('%s' IN NATURAL LANGUAGE MODE)", $this->sPattern);
} else if(osc_search_pattern_method() == 'like') {
$search_pattern_cond = sprintf("lower(concat(d.s_title, d.s_description)) like '%%%s%%'", strtolower(trim((string)$this->sPattern)));
}
}
$search_pattern_cond = osc_apply_filter('search_cond_pattern', $search_pattern_cond, $this->sPattern);
if($search_pattern_cond != '') {
$this->dao->where($search_pattern_cond);
}
if(osc_search_pattern_current_locale_only()) {
if(empty($this->locale_code)) {
if(OC_ADMIN) {
$this->locale_code[osc_current_admin_locale()] = osc_current_admin_locale();
} else {
$this->locale_code[osc_current_user_locale()] = osc_current_user_locale();
}
}
$this->dao->where(sprintf("(d.fk_c_locale_code LIKE '%s')", implode("' d.fk_c_locale_code LIKE '", $this->locale_code)));
}
}
and in the helpers/hSearch.php file, I modified it as follows:
/**
* Gets available search orders
*
* @return array
*/
function osc_list_orders() {
$default_orders = array();
// Si hay patrón de búsqueda, añadimos relevance como primera opción
if (osc_search_pattern() !== '') {
$default_orders[__('Relevance')] = array(
'sOrder' => 'relevance',
'iOrderType' => 'desc'
);
// *** TRUCO IMPORTANTE ***
// Si el usuario no eligió un orden (GET vacío), fijamos relevance como orden activo
if (Params::getParam('sOrder') === '') {
Params::setParam('sOrder', 'relevance');
Params::setParam('iOrderType', 'desc');
}
}
// Lógica original de OsclassPoint
$default_orders[__('Newly listed')] = array(
'sOrder' => 'dt_pub_date',
'iOrderType' => 'desc'
);
if (osc_price_enabled_at_items()) {
$default_orders[__('Lower price first')] = array('sOrder' => 'i_price', 'iOrderType' => 'asc');
$default_orders[__('Higher price first')] = array('sOrder' => 'i_price', 'iOrderType' => 'desc');
}
return osc_apply_filter('search_list_orders', $default_orders);
}
What I (personally) would like to do is (having already achieved the search/sort by "Relevance" (which works perfectly)) have the search logic look something like this: Relevance (First place) Relevance + Most recent (Second place) Relevance + Price: Cheapest (Third place) Relevance + Price: Most expensive (Fourth place) etc...