diff --git a/public/userarea/search_matrici.php b/public/userarea/search_matrici.php index 50833800..785b4281 100644 --- a/public/userarea/search_matrici.php +++ b/public/userarea/search_matrici.php @@ -63,35 +63,66 @@ if (isset($_GET['macro_list'])) { exit; } -// Search (with optional MacroMatrice filter) - multi-term AND, position-independent -$results = []; - -// Spezza la query in termini separati (gestisce spazi multipli, rimuove vuoti) +// Search (with optional MacroMatrice filter) - multi-term AND, position-independent, ranked $terms = array_values(array_filter( preg_split('/\s+/u', $q, -1, PREG_SPLIT_NO_EMPTY) )); +// Nessun termine digitato: comportamento invariato (alfabetico, taglio al limite) +if (empty($terms)) { + $results = []; + foreach ($matrici as $m) { + if ($macro !== '' && ($m['MacroMatrice'] ?? '') !== $macro) continue; + $results[] = ['id' => $m['IdMatrice'], 'text' => $m['NomeMatrice'] ?? '']; + if (count($results) >= $limit) break; + } + echo json_encode(['results' => $results]); + exit; +} + +$firstTerm = $terms[0]; +$scored = []; + foreach ($matrici as $m) { $nome = $m['NomeMatrice'] ?? ''; if ($macro !== '' && ($m['MacroMatrice'] ?? '') !== $macro) continue; - if (empty($terms)) { - // Nessun termine digitato: mostra tutto fino al limite - $results[] = ['id' => $m['IdMatrice'], 'text' => $nome]; - } else { - $nomeLower = mb_strtolower($nome); - $matchAll = true; - foreach ($terms as $t) { - if (mb_strpos($nomeLower, $t) === false) { - $matchAll = false; - break; - } + $nomeLower = mb_strtolower($nome); + + // AND: tutti i termini devono essere presenti (in qualsiasi posizione) + $matchAll = true; + foreach ($terms as $t) { + if (mb_strpos($nomeLower, $t) === false) { + $matchAll = false; + break; } - if (!$matchAll) continue; - $results[] = ['id' => $m['IdMatrice'], 'text' => $nome]; + } + if (!$matchAll) continue; + + // Punteggio di pertinenza (più basso = più rilevante, per ordinamento crescente) + if ($nomeLower === $q) { + $score = 0; // match esatto + } elseif (mb_strpos($nomeLower, $firstTerm) === 0) { + $score = 1; // il nome inizia col primo termine + } elseif (preg_match('/(^|\s)' . preg_quote($firstTerm, '/') . '/u', $nomeLower)) { + $score = 2; // primo termine a inizio di una parola + } else { + $score = 3; // termine presente ma non a inizio parola } - if (count($results) >= $limit) break; + $scored[] = ['id' => $m['IdMatrice'], 'text' => $nome, '_s' => $score, '_n' => $nomeLower]; } +// Ordina per punteggio, poi alfabetico (stabile e prevedibile) +usort($scored, function ($a, $b) { + if ($a['_s'] !== $b['_s']) return $a['_s'] - $b['_s']; + return strcmp($a['_n'], $b['_n']); +}); + +// Taglia al limite DOPO l'ordinamento e rimuovi i campi interni +$results = array_map( + fn($r) => ['id' => $r['id'], 'text' => $r['text']], + array_slice($scored, 0, $limit) +); + echo json_encode(['results' => $results]);