diff --git a/public/userarea/gridRenderer.js b/public/userarea/gridRenderer.js index 582082f..bffa0fa 100644 --- a/public/userarea/gridRenderer.js +++ b/public/userarea/gridRenderer.js @@ -392,7 +392,6 @@ allowClear: true, width: "100%", minimumInputLength: 0, - sorter: sortSelect2ResultsByStart, ajax: { url: "search_customfield_values.php", dataType: "json", diff --git a/public/userarea/search_customfield_values.php b/public/userarea/search_customfield_values.php index 6e4205a..35f95d4 100644 --- a/public/userarea/search_customfield_values.php +++ b/public/userarea/search_customfield_values.php @@ -51,18 +51,74 @@ try { exit; } - // Search by query - $results = []; - foreach ($values as $v) { - $text = $v['Valore'] ?? ''; - if ($q === '' || mb_strpos(mb_strtolower($text), $q) !== false) { - $results[] = ['id' => $v['IdCustomFieldsValue'], 'text' => $text]; - if ($limit > 0 && count($results) >= $limit) break; + // Search — multi-term AND, position-independent, ranked + $terms = array_values(array_filter( + preg_split('/\s+/u', $q, -1, PREG_SPLIT_NO_EMPTY) + )); + + // Nessun termine digitato: alfabetico, taglio al limite + if (empty($terms)) { + $all = []; + foreach ($values as $v) { + $all[] = ['id' => $v['IdCustomFieldsValue'], 'text' => $v['Valore'] ?? '']; } + usort($all, fn($a, $b) => strcasecmp($a['text'], $b['text'])); + if ($limit > 0) $all = array_slice($all, 0, $limit); + echo json_encode(['results' => $all]); + exit; } - // Sort alphabetically - usort($results, fn($a, $b) => strcasecmp($a['text'], $b['text'])); + $firstTerm = $terms[0]; + $scored = []; + + foreach ($values as $v) { + $text = $v['Valore'] ?? ''; + $textLower = mb_strtolower($text); + + // AND: tutti i termini devono essere presenti, in qualsiasi posizione + $matchAll = true; + foreach ($terms as $t) { + if (mb_strpos($textLower, $t) === false) { + $matchAll = false; + break; + } + } + if (!$matchAll) continue; + + // Punteggio di pertinenza (più basso = più rilevante) + if ($textLower === $q) { + $score = 0; // match esatto + } elseif (mb_strpos($textLower, $firstTerm) === 0) { + $score = 1; // inizia col primo termine + } elseif (preg_match('/(^|\s)' . preg_quote($firstTerm, '/') . '/u', $textLower)) { + $score = 2; // primo termine a inizio di una parola + } else { + $score = 3; // presente ma non a inizio parola + } + + $scored[] = [ + 'id' => $v['IdCustomFieldsValue'], + 'text' => $text, + '_s' => $score, + '_n' => $textLower + ]; + } + + // Ordina per punteggio, poi alfabetico + usort($scored, function ($a, $b) { + if ($a['_s'] !== $b['_s']) return $a['_s'] - $b['_s']; + return strcmp($a['_n'], $b['_n']); + }); + + // Taglia DOPO l'ordinamento e rimuovi i campi interni + if ($limit > 0) { + $scored = array_slice($scored, 0, $limit); + } + + $results = array_map( + fn($r) => ['id' => $r['id'], 'text' => $r['text']], + $scored + ); echo json_encode(['results' => $results]); } catch (Exception $e) {