File manager - Edit - /var/www/html/portalHomolog/app/Helpers/MobiangraBuscaLinhasHelper.php
Back
<?php namespace App\Helpers; use App\Models\Mobiangra\MobiangraLinha; use Illuminate\Support\Collection; /** * Busca tolerante de linhas MobiAngra (acentos e pequenos erros de digitação). */ class MobiangraBuscaLinhasHelper { public static function normalizar(string $texto): string { $texto = mb_strtolower(trim($texto), 'UTF-8'); if ($texto === '') { return ''; } $ascii = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $texto); if ($ascii !== false) { $texto = $ascii; } $texto = preg_replace('/[^a-z0-9\s\-\/]/', ' ', $texto) ?? $texto; return trim(preg_replace('/\s+/', ' ', $texto) ?? $texto); } /** * @param array<int, string|null> $campos */ public static function corresponde(?string $termo, array $campos): bool { $termo = trim((string) $termo); if ($termo === '') { return true; } $tokens = array_filter(explode(' ', self::normalizar($termo))); if ($tokens === []) { return true; } $haystack = self::normalizar(implode(' ', array_filter(array_map( static fn ($c) => $c !== null ? (string) $c : '', $campos )))); if ($haystack === '') { return false; } foreach ($tokens as $token) { if (! self::tokenCorresponde($haystack, $token)) { return false; } } return true; } private static function tokenCorresponde(string $haystack, string $token): bool { if ($token === '') { return true; } if (str_contains($haystack, $token)) { return true; } $maxDist = self::maxEditDistance(mb_strlen($token)); if ($maxDist === 0) { return false; } foreach (explode(' ', $haystack) as $parte) { if ($parte === '' || mb_strlen($parte) < 2) { continue; } if (str_contains($parte, $token) || str_contains($token, $parte)) { return true; } if (abs(mb_strlen($parte) - mb_strlen($token)) <= $maxDist && self::levenshtein($parte, $token) <= $maxDist) { return true; } } if (mb_strlen($token) >= 6 && abs(mb_strlen($haystack) - mb_strlen($token)) <= $maxDist + 2) { return self::levenshtein($haystack, $token) <= $maxDist; } return false; } private static function maxEditDistance(int $len): int { return match (true) { $len <= 3 => 0, $len <= 5 => 1, $len <= 8 => 2, default => 3, }; } private static function levenshtein(string $a, string $b): int { $m = mb_strlen($a); $n = mb_strlen($b); if ($m === 0) { return $n; } if ($n === 0) { return $m; } $dp = range(0, $n); for ($i = 1; $i <= $m; $i++) { $prev = $dp[0]; $dp[0] = $i; $charA = mb_substr($a, $i - 1, 1); for ($j = 1; $j <= $n; $j++) { $tmp = $dp[$j]; $cost = $charA === mb_substr($b, $j - 1, 1) ? 0 : 1; $dp[$j] = min($dp[$j] + 1, $dp[$j - 1] + 1, $prev + $cost); $prev = $tmp; } } return $dp[$n]; } /** * Resolve índice da linha em uma coleção pelo termo (?linha= na URL). * * @param Collection<int, MobiangraLinha>|array<int, MobiangraLinha> $linhas */ public static function indicePorTermo(Collection|array $linhas, ?string $termo): ?int { $termo = trim((string) $termo); if ($termo === '') { return null; } $lista = $linhas instanceof Collection ? $linhas->values() : array_values($linhas); foreach ($lista as $idx => $linha) { if (strcasecmp($linha->codigo, $termo) === 0) { return (int) $idx; } } foreach ($lista as $idx => $linha) { if (self::corresponde($termo, [ $linha->codigo, $linha->nome, $linha->nome_completo, ])) { return (int) $idx; } } return null; } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings