Skip to content

Commit 634f52d

Browse files
committed
feat: improve symbol matching
1 parent b8e3b56 commit 634f52d

1 file changed

Lines changed: 47 additions & 13 deletions

File tree

lib/Service/FetchCurrenciesService.php

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -180,24 +180,58 @@ private function safeProjectName(object $project): string {
180180

181181
/** Match the currency name from the known currencies. **/
182182
private function getCurrencyName(string $name): ?string {
183-
$name = strtolower($name);
184-
foreach ($this->symbols as $cur => $currency) {
185-
// e.g. usd
186-
$id = strtolower($cur);
187-
if (($name) === $id) {
183+
$original = trim($name);
184+
$lower = mb_strtolower($original, 'UTF-8');
185+
186+
// Prefer explicit 3-letter code tokens (e.g., "US Dollar (USD)")
187+
foreach ($this->symbols as $code => $currency) {
188+
$id = mb_strtolower((string)$code, 'UTF-8');
189+
if (preg_match('/\b' . preg_quote($id, '/') . '\b/u', $lower)) {
188190
return $id;
189191
}
192+
}
190193

191-
// e.g. $, $ USD
192-
$symbol = $currency['symbol'];
193-
if (str_contains($name, $symbol)) {
194-
return $id;
194+
// Symbol-based detection (avoid matching symbols attached to letters unless
195+
// those letters are part of the *symbol itself*, e.g., "R$")
196+
// Collect all codes hit by symbols, then resolve with preference.
197+
$hitsBySymbol = [];
198+
199+
foreach ($this->symbols as $code => $currency) {
200+
if (empty($currency['symbol'])) {
201+
continue;
195202
}
196203

197-
// e.g. US Dollar (USD)
198-
preg_match('/\b' . $id . '\b/', $name, $matches);
199-
if (count($matches) > 0) {
200-
return $id;
204+
$sym = (string)$currency['symbol'];
205+
$symQuoted = preg_quote($sym, '/');
206+
$hasLetters = preg_match('/\p{L}/u', $sym) === 1;
207+
208+
if ($hasLetters) {
209+
// Multi-char symbol that includes letters (e.g., "R$", "C$", "zł")
210+
$pattern = '/' . $symQuoted . '/u';
211+
} else {
212+
// Pure symbol (e.g., "$", "€", "₪") — require no letters adjacent
213+
// so "MN$" or "$U" won't match.
214+
$pattern = '/(?<!\p{L})' . $symQuoted . '(?!\p{L})/u';
215+
}
216+
217+
if (preg_match($pattern, $original)) {
218+
$hitsBySymbol[$sym] ??= [];
219+
$hitsBySymbol[$sym][] = mb_strtolower((string)$code, 'UTF-8');
220+
}
221+
}
222+
223+
if (!empty($hitsBySymbol)) {
224+
// Resolve ambiguity by symbol preference, else first hit
225+
foreach ($hitsBySymbol as $sym => $codes) {
226+
$preferred = $this->symbolPreference[$sym] ?? null;
227+
if ($preferred) {
228+
$preferredLower = mb_strtolower($preferred, 'UTF-8');
229+
if (in_array($preferredLower, $codes, true)) {
230+
return $preferredLower;
231+
}
232+
}
233+
// Fall back to first detected code for that symbol
234+
return $codes[0];
201235
}
202236
}
203237

0 commit comments

Comments
 (0)