128 lines
4.1 KiB
PHP
128 lines
4.1 KiB
PHP
<?php
|
|
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
|
|
require_once __DIR__ . '/class/db-functions.php';
|
|
include dirname(__DIR__) . '/../extra/auth.php';
|
|
if (!Auth::check()) {
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Unauthorized']);
|
|
exit;
|
|
}
|
|
|
|
require_once __DIR__ . '/class/VisualLimsApiClient.class.php';
|
|
|
|
header('Content-Type: application/json');
|
|
ini_set('display_errors', '0');
|
|
error_reporting(E_ALL);
|
|
|
|
$fieldId = intval($_GET['field_id'] ?? 0);
|
|
$q = mb_strtolower(trim($_GET['q'] ?? ''));
|
|
$id = isset($_GET['id']) ? intval($_GET['id']) : null;
|
|
$rawLimit = intval($_GET['limit'] ?? 20);
|
|
$limit = $rawLimit <= 0 ? 0 : max(1, min(500, $rawLimit));
|
|
|
|
if (!$fieldId) {
|
|
echo json_encode(['results' => []]);
|
|
exit;
|
|
}
|
|
|
|
try {
|
|
$cacheDir = __DIR__ . '/cache';
|
|
$cacheFile = $cacheDir . '/customfield_' . $fieldId . '.json';
|
|
|
|
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < 3600)) {
|
|
$values = json_decode(file_get_contents($cacheFile), true);
|
|
} else {
|
|
$api = VisualLimsApiClient::getInstance();
|
|
$data = $api->get("CustomField($fieldId)?\$expand=CustomFieldsValues");
|
|
$values = $data['CustomFieldsValues'] ?? [];
|
|
if (!is_dir($cacheDir)) mkdir($cacheDir, 0777, true);
|
|
file_put_contents($cacheFile, json_encode($values));
|
|
}
|
|
|
|
// Lookup by ID
|
|
if ($id !== null) {
|
|
foreach ($values as $v) {
|
|
if ((int)($v['IdCustomFieldsValue'] ?? 0) === $id) {
|
|
echo json_encode(['results' => [['id' => $v['IdCustomFieldsValue'], 'text' => $v['Valore'] ?? '']]]);
|
|
exit;
|
|
}
|
|
}
|
|
echo json_encode(['results' => []]);
|
|
exit;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
$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) {
|
|
http_response_code(500);
|
|
echo json_encode(['error' => $e->getMessage()]);
|
|
}
|