Lines 100.00% 8 / 8
Functions and Methods 100.00% 1 / 1
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
ClosestNameFinder 100.00% 8 / 8 100.00% 1 / 1 3 100.00% 1 / 1
 findClosestName 100.00% 8 / 8 100.00% 1 / 1 3
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Support\Text;
6
7/** @internal */
8final readonly class ClosestNameFinder
9{
10    private const int MINIMUM_ALLOWED_DISTANCE = 2;
11
12    private const int CHARACTERS_PER_ALLOWED_EDIT = 3;
13
14    /** @param iterable<string> $candidates */
15    public function findClosestName(string $name, iterable $candidates): ?string
16    {
17        $closest = null;
18        $shortestDistance = max(self::MINIMUM_ALLOWED_DISTANCE, intdiv(\strlen($name), self::CHARACTERS_PER_ALLOWED_EDIT)) + 1;
19
20        foreach ($candidates as $candidate) {
21            $distance = levenshtein($name, $candidate);
22
23            if ($distance < $shortestDistance) {
24                $closest = $candidate;
25                $shortestDistance = $distance;
26            }
27        }
28
29        return $closest;
30    }
31}