summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Elements/DemographicDataType.php2
-rw-r--r--app/Elements/HierarchicalRelationship.php2
-rw-r--r--app/Elements/LanguageId.php2
-rw-r--r--app/Elements/SourceMediaType.php2
-rw-r--r--app/Elements/TempleCode.php2
-rw-r--r--app/Functions/FunctionsEdit.php3
-rw-r--r--app/Functions/FunctionsPrint.php8
-rw-r--r--app/GedcomRecord.php2
-rw-r--r--app/GedcomTag.php264
-rw-r--r--app/Http/RequestHandlers/TreePreferencesPage.php76
-rw-r--r--app/Http/RequestHandlers/TreePrivacyPage.php4
-rw-r--r--app/I18N.php20
-rw-r--r--app/Module/ChartsBlockModule.php2
-rw-r--r--app/Module/ColorsTheme.php2
-rw-r--r--app/Module/FamilyTreeStatisticsModule.php2
-rw-r--r--app/Module/ModuleThemeTrait.php2
-rw-r--r--app/Module/TopSurnamesModule.php2
-rw-r--r--app/Services/ModuleService.php22
-rw-r--r--app/Statistics/Repository/IndividualRepository.php2
-rw-r--r--phpstan-baseline.neon7
-rw-r--r--tests/app/I18NTest.php18
21 files changed, 122 insertions, 324 deletions
diff --git a/app/Elements/DemographicDataType.php b/app/Elements/DemographicDataType.php
index d1fe599aa3..5e52c725b2 100644
--- a/app/Elements/DemographicDataType.php
+++ b/app/Elements/DemographicDataType.php
@@ -56,7 +56,7 @@ class DemographicDataType extends AbstractElement
'CITI' => /* I18N: Type of demographic data */ I18N::translate('citizen'),
];
- uasort($values, [I18N::class, 'strcasecmp']);
+ uasort($values, I18N::comparator());
return $values;
}
diff --git a/app/Elements/HierarchicalRelationship.php b/app/Elements/HierarchicalRelationship.php
index 644ffed319..9b4aa646e6 100644
--- a/app/Elements/HierarchicalRelationship.php
+++ b/app/Elements/HierarchicalRelationship.php
@@ -59,7 +59,7 @@ class HierarchicalRelationship extends AbstractElement
'CULT' => /* I18N: Type of location hierarchy */ I18N::translate('cultural'),
];
- uasort($values, [I18N::class, 'strcasecmp']);
+ uasort($values, I18N::comparator());
return $values;
}
diff --git a/app/Elements/LanguageId.php b/app/Elements/LanguageId.php
index 1942c6c7c8..543cdcdfe1 100644
--- a/app/Elements/LanguageId.php
+++ b/app/Elements/LanguageId.php
@@ -214,7 +214,7 @@ class LanguageId extends AbstractElement
'Yiddish' => (new LocaleYi())->endonym(),
];
- uasort($values, [I18N::class, 'strcasecmp']);
+ uasort($values, I18N::comparator());
return $values;
}
diff --git a/app/Elements/SourceMediaType.php b/app/Elements/SourceMediaType.php
index 909494293c..571442905a 100644
--- a/app/Elements/SourceMediaType.php
+++ b/app/Elements/SourceMediaType.php
@@ -77,7 +77,7 @@ class SourceMediaType extends AbstractElement
'video' => /* I18N: Type of media object */ I18N::translate('Video'),
];
- uasort($values, '\Fisharebest\Webtrees\I18N::strcasecmp');
+ uasort($values, I18N::comparator());
return $values;
}
diff --git a/app/Elements/TempleCode.php b/app/Elements/TempleCode.php
index 8ac67d4f76..b8f0530add 100644
--- a/app/Elements/TempleCode.php
+++ b/app/Elements/TempleCode.php
@@ -207,7 +207,7 @@ class TempleCode extends AbstractElement
'WINTE' => /* I18N: Location of an LDS church temple */ I18N::translate('Winter Quarters, Nebraska, United States'),
];
- uasort($values, [I18N::class, 'strcasecmp']);
+ uasort($values, I18N::comparator());
$values = ['' => I18N::translate('No temple - living ordinance')] + $values;
return $values;
diff --git a/app/Functions/FunctionsEdit.php b/app/Functions/FunctionsEdit.php
index 18efd70eff..fc7484a437 100644
--- a/app/Functions/FunctionsEdit.php
+++ b/app/Functions/FunctionsEdit.php
@@ -23,6 +23,7 @@ use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\Census\Census;
use Fisharebest\Webtrees\Config;
use Fisharebest\Webtrees\Date;
+use Fisharebest\Webtrees\Elements\PafUid;
use Fisharebest\Webtrees\Fact;
use Fisharebest\Webtrees\Family;
use Fisharebest\Webtrees\Gedcom;
@@ -641,7 +642,7 @@ class FunctionsEdit
} else {
self::$tags[0] = $fact;
if ($fact === '_UID') {
- $fact .= ' ' . GedcomTag::createUid();
+ $fact .= ' ' . (new PafUid(''))->default($tree);
}
// These new level 1 tags need to be turned into links
if (in_array($fact, ['ALIA', 'ASSO'], true)) {
diff --git a/app/Functions/FunctionsPrint.php b/app/Functions/FunctionsPrint.php
index d24e341401..aa1ba2db7d 100644
--- a/app/Functions/FunctionsPrint.php
+++ b/app/Functions/FunctionsPrint.php
@@ -26,7 +26,6 @@ use Fisharebest\Webtrees\Family;
use Fisharebest\Webtrees\Filter;
use Fisharebest\Webtrees\Gedcom;
use Fisharebest\Webtrees\GedcomRecord;
-use Fisharebest\Webtrees\GedcomTag;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Individual;
use Fisharebest\Webtrees\Media;
@@ -561,12 +560,11 @@ class FunctionsPrint
$addfacts = array_merge(self::checkFactUnique($uniquefacts, $usedfacts), $addfacts);
$quickfacts = array_intersect($quickfacts, $addfacts);
$translated_addfacts = [];
+
foreach ($addfacts as $addfact) {
- $translated_addfacts[$addfact] = GedcomTag::getLabel($record->tag() . ':' . $addfact);
+ $translated_addfacts[$addfact] = Registry::elementFactory()->make($record->tag() . ':' . $addfact)->label();
}
- uasort($translated_addfacts, static function (string $x, string $y): int {
- return I18N::strcasecmp(I18N::translate($x), I18N::translate($y));
- });
+ uasort($translated_addfacts, I18N::comparator());
echo view('edit/add-fact-row', [
'add_facts' => $translated_addfacts,
diff --git a/app/GedcomRecord.php b/app/GedcomRecord.php
index 4a8b71f717..8a9d92c57b 100644
--- a/app/GedcomRecord.php
+++ b/app/GedcomRecord.php
@@ -135,7 +135,7 @@ class GedcomRecord
return static function (GedcomRecord $x, GedcomRecord $y): int {
if ($x->canShowName()) {
if ($y->canShowName()) {
- return I18N::strcasecmp($x->sortName(), $y->sortName());
+ return I18N::comparator()($x->sortName(), $y->sortName());
}
return -1; // only $y is private
diff --git a/app/GedcomTag.php b/app/GedcomTag.php
index 9a81b02662..2a69a53647 100644
--- a/app/GedcomTag.php
+++ b/app/GedcomTag.php
@@ -1283,268 +1283,4 @@ class GedcomTag
I18N::translate('<span class="label">%1$s:</span> <span class="field" dir="auto">%2$s</span>', self::getLabel($tag), $value) .
'</' . $element . '>';
}
-
- /**
- * Get a list of facts, for use in the "fact picker" edit control
- *
- * @param string $fact_type
- *
- * @return array<string>
- */
- public static function getPicklistFacts(string $fact_type): array
- {
- switch ($fact_type) {
- case Individual::RECORD_TYPE:
- $tags = [
- // Facts, attributes for individuals (no links to FAMs)
- 'RESN',
- 'NAME',
- 'SEX',
- 'BIRT',
- 'CHR',
- 'DEAT',
- 'BURI',
- 'CREM',
- 'ADOP',
- 'BAPM',
- 'BARM',
- 'BASM',
- 'BLES',
- 'CHRA',
- 'CONF',
- 'FCOM',
- 'ORDN',
- 'NATU',
- 'EMIG',
- 'IMMI',
- 'CENS',
- 'PROB',
- 'WILL',
- 'GRAD',
- 'RETI',
- 'EVEN',
- 'CAST',
- 'DSCR',
- 'EDUC',
- 'IDNO',
- 'NATI',
- 'NCHI',
- 'NMR',
- 'OCCU',
- 'PROP',
- 'RELI',
- 'RESI',
- 'SSN',
- 'TITL',
- 'FACT',
- 'BAPL',
- 'CONL',
- 'ENDL',
- 'SLGC',
- 'SUBM',
- 'ASSO',
- 'ALIA',
- 'ANCI',
- 'DESI',
- 'RFN',
- 'AFN',
- 'REFN',
- 'RIN',
- 'CHAN',
- 'NOTE',
- 'SHARED_NOTE',
- 'SOUR',
- 'OBJE',
- // non standard tags
- '_BRTM',
- '_DEG',
- '_DNA',
- '_EYEC',
- '_FNRL',
- '_HAIR',
- '_HEIG',
- '_HNM',
- '_HOL',
- '_INTE',
- '_MDCL',
- '_MEDC',
- '_MILI',
- '_MILT',
- '_NAME',
- '_NAMS',
- '_NLIV',
- '_NMAR',
- '_PRMN',
- '_TODO',
- '_UID',
- '_WEIG',
- '_YART',
- ];
- break;
-
- case Family::RECORD_TYPE:
- $tags = [
- // Facts for families, left out HUSB, WIFE & CHIL links
- 'RESN',
- 'ANUL',
- 'CENS',
- 'DIV',
- 'DIVF',
- 'ENGA',
- 'MARB',
- 'MARC',
- 'MARR',
- 'MARL',
- 'MARS',
- 'RESI',
- 'EVEN',
- 'NCHI',
- 'SUBM',
- 'SLGS',
- 'REFN',
- 'RIN',
- 'CHAN',
- 'NOTE',
- 'SHARED_NOTE',
- 'SOUR',
- 'OBJE',
- // non standard tags
- '_NMR',
- 'MARR_CIVIL',
- 'MARR_RELIGIOUS',
- 'MARR_PARTNERS',
- 'MARR_UNKNOWN',
- '_COML',
- '_MBON',
- '_MARI',
- '_SEPR',
- '_TODO',
- ];
- break;
-
- case Source::RECORD_TYPE:
- $tags = [
- // Facts for sources
- 'DATA',
- 'AUTH',
- 'TITL',
- 'ABBR',
- 'PUBL',
- 'TEXT',
- 'REPO',
- 'REFN',
- 'RIN',
- 'CHAN',
- 'NOTE',
- 'SHARED_NOTE',
- 'OBJE',
- 'RESN',
- ];
- break;
-
- case Repository::RECORD_TYPE:
- $tags = [
- // Facts for repositories
- 'NAME',
- 'ADDR',
- 'PHON',
- 'EMAIL',
- 'FAX',
- 'WWW',
- 'NOTE',
- 'SHARED_NOTE',
- 'REFN',
- 'RIN',
- 'CHAN',
- 'RESN',
- ];
- break;
-
- case 'PLAC':
- $tags = [
- // Facts for places
- 'FONE',
- 'ROMN',
- // non standard tags
- '_GOV',
- '_HEB',
- ];
- break;
-
- case 'NAME':
- $tags = [
- // Facts subordinate to NAME
- 'FONE',
- 'ROMN',
- // non standard tags
- '_HEB',
- '_AKA',
- '_MARNM',
- ];
- break;
-
- default:
- $tags = [];
- break;
- }
-
- $facts = [];
- foreach ($tags as $tag) {
- $facts[$tag] = self::getLabel($tag);
- }
- uasort($facts, '\Fisharebest\Webtrees\I18N::strcasecmp');
-
- return $facts;
- }
-
- /**
- * Translate the value for 1 FILE/2 FORM/3 TYPE
- *
- * @param string $type
- *
- * @return string
- */
- public static function getFileFormTypeValue(string $type): string
- {
- $element = Registry::elementFactory()->make('OBJE:FILE:FORM:TYPE');
-
- return $element->values()[$type] ?? $type;
- }
-
- /**
- * A list of all possible values for 1 FILE/2 FORM/3 TYPE
- *
- * @return array<string>
- */
- public static function getFileFormTypes(): array
- {
- $element = Registry::elementFactory()->make('OBJE:FILE:FORM:TYPE');
-
- return array_filter($element->values());
- }
-
- /**
- * Generate a value for a new _UID field.
- * Instead of RFC4122-compatible UUIDs, generate ones that
- * are compatible with PAF, Legacy, RootsMagic, etc.
- * In these, the string is upper-cased, dashes are removed,
- * and a two-byte checksum is added.
- *
- * @return string
- */
- public static function createUid(): string
- {
- $uid = str_replace('-', '', Uuid::uuid4()->toString());
-
- $checksum_a = 0; // a sum of the bytes
- $checksum_b = 0; // a sum of the incremental values of $checksum_a
-
- // Compute checksums
- for ($i = 0; $i < 32; $i += 2) {
- $checksum_a += hexdec(substr($uid, $i, 2));
- $checksum_b += $checksum_a & 0xff;
- }
-
- return strtoupper($uid . substr(dechex($checksum_a), -2) . substr(dechex($checksum_b), -2));
- }
}
diff --git a/app/Http/RequestHandlers/TreePreferencesPage.php b/app/Http/RequestHandlers/TreePreferencesPage.php
index 5f929b0e39..520a6d6d12 100644
--- a/app/Http/RequestHandlers/TreePreferencesPage.php
+++ b/app/Http/RequestHandlers/TreePreferencesPage.php
@@ -22,7 +22,6 @@ namespace Fisharebest\Webtrees\Http\RequestHandlers;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\Contracts\UserInterface;
use Fisharebest\Webtrees\Date;
-use Fisharebest\Webtrees\GedcomTag;
use Fisharebest\Webtrees\Http\ViewResponseTrait;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Module\ModuleThemeInterface;
@@ -32,6 +31,7 @@ use Fisharebest\Webtrees\Services\TreeService;
use Fisharebest\Webtrees\Services\UserService;
use Fisharebest\Webtrees\SurnameTradition;
use Fisharebest\Webtrees\Tree;
+use Illuminate\Support\Collection;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
@@ -51,6 +51,39 @@ class TreePreferencesPage implements RequestHandlerInterface
{
use ViewResponseTrait;
+ private const ALL_FAM_FACTS = [
+ 'RESN', 'ANUL', 'CENS', 'DIV', 'DIVF', 'ENGA', 'MARB', 'MARC', 'MARR', 'MARL', 'MARS', 'RESI', 'EVEN',
+ 'NCHI', 'SUBM', 'SLGS', 'REFN', 'RIN', 'CHAN', 'NOTE', 'SHARED_NOTE', 'SOUR', 'OBJE',
+ '_NMR', '_COML', '_MBON', '_MARI', '_SEPR', '_TODO',
+ ];
+
+ private const ALL_INDI_FACTS = [
+ 'RESN', 'NAME', 'SEX', 'BIRT', 'CHR', 'DEAT', 'BURI', 'CREM', 'ADOP', 'BAPM', 'BARM', 'BASM',
+ 'BLES', 'CHRA', 'CONF', 'FCOM', 'ORDN', 'NATU', 'EMIG', 'IMMI', 'CENS', 'PROB', 'WILL',
+ 'GRAD', 'RETI', 'EVEN', 'CAST', 'DSCR', 'EDUC', 'IDNO', 'NATI', 'NCHI', 'NMR', 'OCCU', 'PROP',
+ 'RELI', 'RESI', 'SSN', 'TITL', 'FACT', 'BAPL', 'CONL', 'ENDL', 'SLGC', 'SUBM', 'ASSO',
+ 'ALIA', 'ANCI', 'DESI', 'RFN', 'AFN', 'REFN', 'RIN', 'CHAN', 'NOTE', 'SHARED_NOTE', 'SOUR', 'OBJE',
+ '_BRTM', '_DEG', '_DNA', '_EYEC', '_FNRL', '_HAIR', '_HEIG', '_HNM', '_HOL', '_INTE', '_MDCL',
+ '_MEDC', '_MILI', '_MILT', '_NAME', '_NAMS', '_NLIV', '_NMAR', '_PRMN', '_TODO', '_UID', '_WEIG', '_YART',
+ ];
+
+ private const ALL_NAME_FACTS = [
+ 'FONE', 'ROMN', '_HEB', '_AKA', '_MARNM',
+ ];
+
+ private const ALL_PLAC_FACTS = [
+ 'FONE', 'ROMN', '_GOV', '_HEB',
+ ];
+
+ private const ALL_REPO_FACTS = [
+ 'NAME', 'ADDR', 'PHON', 'EMAIL', 'FAX', 'WWW', 'NOTE', 'SHARED_NOTE', 'REFN', 'RIN', 'CHAN', 'RESN',
+ ];
+
+ private const ALL_SOUR_FACTS = [
+ 'DATA', 'AUTH', 'TITL', 'ABBR', 'PUBL', 'TEXT', 'REPO', 'REFN', 'RIN',
+ 'CHAN', 'NOTE', 'SHARED_NOTE', 'OBJE', 'RESN',
+ ];
+
/** @var ModuleService */
private $module_service;
@@ -163,12 +196,41 @@ class TreePreferencesPage implements RequestHandlerInterface
return Auth::isMember($tree, $user);
});
- $all_fam_facts = GedcomTag::getPicklistFacts('FAM');
- $all_indi_facts = GedcomTag::getPicklistFacts('INDI');
- $all_name_facts = GedcomTag::getPicklistFacts('NAME');
- $all_plac_facts = GedcomTag::getPicklistFacts('PLAC');
- $all_repo_facts = GedcomTag::getPicklistFacts('REPO');
- $all_sour_facts = GedcomTag::getPicklistFacts('SOUR');
+ $all_fam_facts = Collection::make(self::ALL_FAM_FACTS)
+ ->mapWithKeys(static function (string $tag): array {
+ return [$tag => Registry::elementFactory()->make('FAM:' . $tag)->label()];
+ })
+ ->sort(I18N::comparator());
+
+ $all_indi_facts = Collection::make(self::ALL_INDI_FACTS)
+ ->mapWithKeys(static function (string $tag): array {
+ return [$tag => Registry::elementFactory()->make('INDI:' . $tag)->label()];
+ })
+ ->sort(I18N::comparator());
+
+ $all_name_facts = Collection::make(self::ALL_NAME_FACTS)
+ ->mapWithKeys(static function (string $tag): array {
+ return [$tag => Registry::elementFactory()->make('INDI:NAME:' . $tag)->label()];
+ })
+ ->sort(I18N::comparator());
+
+ $all_plac_facts = Collection::make(self::ALL_PLAC_FACTS)
+ ->mapWithKeys(static function (string $tag): array {
+ return [$tag => Registry::elementFactory()->make('INDI:FACT:PLAC:' . $tag)->label()];
+ })
+ ->sort(I18N::comparator());
+
+ $all_repo_facts = Collection::make(self::ALL_REPO_FACTS)
+ ->mapWithKeys(static function (string $tag): array {
+ return [$tag => Registry::elementFactory()->make('SOUR:' . $tag)->label()];
+ })
+ ->sort(I18N::comparator());
+
+ $all_sour_facts = Collection::make(self::ALL_SOUR_FACTS)
+ ->mapWithKeys(static function (string $tag): array {
+ return [$tag => Registry::elementFactory()->make('SOUR:' . $tag)->label()];
+ })
+ ->sort(I18N::comparator());
$all_surname_traditions = SurnameTradition::allDescriptions();
diff --git a/app/Http/RequestHandlers/TreePrivacyPage.php b/app/Http/RequestHandlers/TreePrivacyPage.php
index e55b735744..5790fe1aa8 100644
--- a/app/Http/RequestHandlers/TreePrivacyPage.php
+++ b/app/Http/RequestHandlers/TreePrivacyPage.php
@@ -124,7 +124,7 @@ class TreePrivacyPage implements RequestHandlerInterface
return $row;
})
->sort(static function (stdClass $x, stdClass $y): int {
- return I18N::strcasecmp($x->tag_label, $y->tag_label);
+ return I18N::comparator()($x->tag_label, $y->tag_label);
})
->all();
}
@@ -170,7 +170,7 @@ class TreePrivacyPage implements RequestHandlerInterface
}
}
- uasort($all_tags, '\Fisharebest\Webtrees\I18N::strcasecmp');
+ uasort($all_tags, I18N::comparator());
return array_merge(
['' => I18N::translate('All facts and events')],
diff --git a/app/I18N.php b/app/I18N.php
index 8514a9b3f7..669ca333ae 100644
--- a/app/I18N.php
+++ b/app/I18N.php
@@ -19,6 +19,7 @@ declare(strict_types=1);
namespace Fisharebest\Webtrees;
+use Closure;
use Collator;
use Exception;
use Fisharebest\Localization\Locale;
@@ -541,22 +542,25 @@ class I18N
}
/**
- * Perform a case-insensitive comparison of two strings.
+ * A closure which will compare strings using local collation rules.
*
- * @param string $string1
- * @param string $string2
- *
- * @return int
+ * @return Closure
*/
- public static function strcasecmp(string $string1, string $string2): int
+ public static function comparator(): Closure
{
if (self::$collator instanceof Collator) {
- return self::$collator->compare($string1, $string2);
+ return static function (string $x, string $y): int {
+ return (int) self::$collator->compare($x, $y);
+ };
}
- return strcmp(self::strtolower($string1), self::strtolower($string2));
+ return static function (string $x, string $y): int {
+ return strcmp(self::strtolower($x), self::strtolower($y));
+ };
}
+
+
/**
* Convert a string to lower case.
*
diff --git a/app/Module/ChartsBlockModule.php b/app/Module/ChartsBlockModule.php
index e9ba06c74f..aaaf2ba5bf 100644
--- a/app/Module/ChartsBlockModule.php
+++ b/app/Module/ChartsBlockModule.php
@@ -270,7 +270,7 @@ class ChartsBlockModule extends AbstractModule implements ModuleBlockInterface
'hourglass' => I18N::translate('Hourglass chart'),
'treenav' => I18N::translate('Interactive tree'),
];
- uasort($charts, 'Fisharebest\Webtrees\I18N::strcasecmp');
+ uasort($charts, I18N::comparator());
$individual = Registry::individualFactory()->make($xref, $tree);
diff --git a/app/Module/ColorsTheme.php b/app/Module/ColorsTheme.php
index 22f40bc689..fe158e45e0 100644
--- a/app/Module/ColorsTheme.php
+++ b/app/Module/ColorsTheme.php
@@ -183,7 +183,7 @@ class ColorsTheme extends CloudsTheme
'tealtop' => I18N::translate('Teal Top'),
];
- uasort($palettes, '\Fisharebest\Webtrees\I18N::strcasecmp');
+ uasort($palettes, I18N::comparator());
return $palettes;
}
diff --git a/app/Module/FamilyTreeStatisticsModule.php b/app/Module/FamilyTreeStatisticsModule.php
index c03482a51d..ea6d913dff 100644
--- a/app/Module/FamilyTreeStatisticsModule.php
+++ b/app/Module/FamilyTreeStatisticsModule.php
@@ -124,7 +124,7 @@ class FamilyTreeStatisticsModule extends AbstractModule implements ModuleBlockIn
$all_surnames[$top_surname] = $variants;
}
- uksort($all_surnames, [I18N::class, 'strcasecmp']);
+ uksort($all_surnames, I18N::comparator());
//find a module providing individual lists
$module = app(ModuleService::class)->findByComponent(ModuleListInterface::class, $tree, Auth::user())->first(static function (ModuleInterface $module) {
diff --git a/app/Module/ModuleThemeTrait.php b/app/Module/ModuleThemeTrait.php
index 4023625f03..6753633d69 100644
--- a/app/Module/ModuleThemeTrait.php
+++ b/app/Module/ModuleThemeTrait.php
@@ -152,7 +152,7 @@ trait ModuleThemeTrait
}
usort($menus, static function (Menu $x, Menu $y): int {
- return I18N::strcasecmp($x->getLabel(), $y->getLabel());
+ return I18N::comparator()($x->getLabel(), $y->getLabel());
});
return $menus;
diff --git a/app/Module/TopSurnamesModule.php b/app/Module/TopSurnamesModule.php
index 6d79b4fabb..5ecb1b1e3f 100644
--- a/app/Module/TopSurnamesModule.php
+++ b/app/Module/TopSurnamesModule.php
@@ -133,7 +133,7 @@ class TopSurnamesModule extends AbstractModule implements ModuleBlockInterface
switch ($infoStyle) {
case 'tagcloud':
- uksort($all_surnames, [I18N::class, 'strcasecmp']);
+ uksort($all_surnames, I18N::comparator());
$content = FunctionsPrintLists::surnameTagCloud($all_surnames, $module, true, $tree);
break;
case 'list':
diff --git a/app/Services/ModuleService.php b/app/Services/ModuleService.php
index 7f780e7ef3..11f4fbdef6 100644
--- a/app/Services/ModuleService.php
+++ b/app/Services/ModuleService.php
@@ -515,20 +515,20 @@ class ModuleService
switch ($interface) {
case ModuleFooterInterface::class:
- return $modules->sort($this->footerSorter());
+ return $modules->sort($this->footerComparator());
case ModuleMenuInterface::class:
- return $modules->sort($this->menuSorter());
+ return $modules->sort($this->menuComparator());
case ModuleSidebarInterface::class:
- return $modules->sort($this->sidebarSorter());
+ return $modules->sort($this->sidebarComparator());
case ModuleTabInterface::class:
- return $modules->sort($this->tabSorter());
+ return $modules->sort($this->tabComparator());
default:
if ($sort) {
- return $modules->sort($this->moduleSorter());
+ return $modules->sort($this->moduleComparator());
}
return $modules;
@@ -725,7 +725,7 @@ class ModuleService
*
* @return Closure
*/
- private function footerSorter(): Closure
+ private function footerComparator(): Closure
{
return static function (ModuleFooterInterface $x, ModuleFooterInterface $y): int {
return $x->getFooterOrder() <=> $y->getFooterOrder();
@@ -737,7 +737,7 @@ class ModuleService
*
* @return Closure
*/
- private function menuSorter(): Closure
+ private function menuComparator(): Closure
{
return static function (ModuleMenuInterface $x, ModuleMenuInterface $y): int {
return $x->getMenuOrder() <=> $y->getMenuOrder();
@@ -749,7 +749,7 @@ class ModuleService
*
* @return Closure
*/
- private function sidebarSorter(): Closure
+ private function sidebarComparator(): Closure
{
return static function (ModuleSidebarInterface $x, ModuleSidebarInterface $y): int {
return $x->getSidebarOrder() <=> $y->getSidebarOrder();
@@ -761,7 +761,7 @@ class ModuleService
*
* @return Closure
*/
- private function tabSorter(): Closure
+ private function tabComparator(): Closure
{
return static function (ModuleTabInterface $x, ModuleTabInterface $y): int {
return $x->getTabOrder() <=> $y->getTabOrder();
@@ -776,13 +776,13 @@ class ModuleService
*
* @return Closure
*/
- private function moduleSorter(): Closure
+ private function moduleComparator(): Closure
{
return static function (ModuleInterface $x, ModuleInterface $y): int {
$title1 = $x instanceof ModuleLanguageInterface ? $x->locale()->endonymSortable() : $x->title();
$title2 = $y instanceof ModuleLanguageInterface ? $y->locale()->endonymSortable() : $y->title();
- return I18N::strcasecmp($title1, $title2);
+ return I18N::comparator()($title1, $title2);
};
}
diff --git a/app/Statistics/Repository/IndividualRepository.php b/app/Statistics/Repository/IndividualRepository.php
index b6ba89c233..92b0313c64 100644
--- a/app/Statistics/Repository/IndividualRepository.php
+++ b/app/Statistics/Repository/IndividualRepository.php
@@ -558,7 +558,7 @@ class IndividualRepository implements IndividualRepositoryInterface
switch ($sorting) {
default:
case 'alpha':
- uksort($surnames, [I18N::class, 'strcasecmp']);
+ uksort($surnames, I18N::comparator());
break;
case 'count':
break;
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 12e0949f4b..2457fd2f27 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -215,11 +215,6 @@ parameters:
path: app/GedcomRecord.php
-
- message: "#^Parameter \\#1 \\$num of function dechex expects int, float\\|int given\\.$#"
- count: 1
- path: app/GedcomTag.php
-
- -
message: "#^Strict comparison using \\=\\=\\= between '\\-dev' and '' will always evaluate to false\\.$#"
count: 1
path: app/Helpers/functions.php
@@ -560,7 +555,7 @@ parameters:
path: app/I18N.php
-
- message: "#^Method Fisharebest\\\\Webtrees\\\\I18N\\:\\:strcasecmp\\(\\) should return int but returns int\\|false\\.$#"
+ message: "#^Cannot call method compare\\(\\) on Collator\\|null\\.$#"
count: 1
path: app/I18N.php
diff --git a/tests/app/I18NTest.php b/tests/app/I18NTest.php
index b4ab2fb1f2..cc949fc037 100644
--- a/tests/app/I18NTest.php
+++ b/tests/app/I18NTest.php
@@ -47,18 +47,20 @@ class I18NTest extends TestCase
}
/**
- * @covers \Fisharebest\Webtrees\I18N::strcasecmp()
+ * @covers \Fisharebest\Webtrees\I18N::comparator()
*
* @return void
*/
- public function testStrcasecmp(): void
+ public function testComparator(): void
{
- self::assertSame(I18N::strcasecmp('', ''), 0);
- self::assertSame(I18N::strcasecmp('Abc', 'abc'), 0);
- self::assertTrue(I18N::strcasecmp('Abc', 'bcd') < 0);
- self::assertTrue(I18N::strcasecmp('bcd', 'ABC') > 0);
- self::assertTrue(I18N::strcasecmp('Abc', 'abcd') < 0);
- self::assertTrue(I18N::strcasecmp('Abcd', 'abc') > 0);
+ $comparator = I18N::comparator();
+
+ self::assertSame($comparator('', ''), 0);
+ self::assertSame($comparator('Abc', 'abc'), 0);
+ self::assertTrue($comparator('Abc', 'bcd') < 0);
+ self::assertTrue($comparator('bcd', 'ABC') > 0);
+ self::assertTrue($comparator('Abc', 'abcd') < 0);
+ self::assertTrue($comparator('Abcd', 'abc') > 0);
}
/**