ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
scan_shipped_case_duplicates.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
36$ilias_root = dirname(__DIR__, 5);
37
38// lower case and, where iconv can, without accents - roughly how utf8mb3_general_ci compares
39$fold = static function (string $text): string {
40 $lower = mb_strtolower($text);
41 $ascii = function_exists('iconv') ? @iconv('UTF-8', 'ASCII//TRANSLIT', $lower) : false;
42
43 return is_string($ascii) && $ascii !== '' ? strtolower($ascii) : $lower;
44};
45
46// folded module#:#identifier => spelling => file => line; only spellings within the same file collide
48$files = glob($ilias_root . '/lang/ilias_*.lang') ?: [];
50foreach ($files as $file) {
51 $started = false;
52 foreach (file($file, FILE_IGNORE_NEW_LINES) ?: [] as $number => $line) {
53 if (!$started) {
54 $started = trim($line) === '<!-- language file start -->';
55 continue;
56 }
57 $parts = explode('#:#', trim($line));
58 if (count($parts) < 3) {
59 continue;
60 }
61 $folded = $fold($parts[0]) . '#:#' . $fold($parts[1]);
62 $occurrences[$folded][$parts[1]][basename($file)] ??= $number + 1;
63 }
64}
66foreach ($occurrences as $folded => $spellings) {
67 $files_per_spelling = array_map('array_keys', $spellings);
68 $colliding_files = count($spellings) > 1 ? array_values(array_intersect(...array_values($files_per_spelling))) : [];
69 if ($colliding_files !== []) {
70 $duplicates[$folded] = [$spellings, $colliding_files];
71 }
72}
73ksort($duplicates);
74
75$callers_of = static function (string $identifier) use ($ilias_root): array {
76 $callers = [];
77 foreach (["txt('" . $identifier . "'", 'txt("' . $identifier . '"'] as $pattern) {
78 $output = [];
79 exec(sprintf(
80 'git -C %s grep -n -F %s -- %s 2>/dev/null',
81 escapeshellarg($ilias_root),
82 escapeshellarg($pattern),
83 escapeshellarg('components')
84 ), $output);
85 foreach ($output as $hit) {
86 $callers[] = implode(':', array_slice(explode(':', $hit), 0, 2));
87 }
88 }
89
90 return array_values(array_unique($callers));
91};
92
93echo sprintf("%d Identifier mit Varianten, die sich in derselben Sprachdatei nur in Groß-/Kleinschreibung unterscheiden\n\n", count($duplicates));
94echo "| Modul | Varianten | Betroffene Dateien | Fundstellen (Datei:Zeile) | Aufrufer (`txt('…')`) |\n|---|---|---|---|---|\n";
95foreach ($duplicates as $folded => [$spellings, $colliding_files]) {
96 $module = explode('#:#', $folded)[0];
97 $variants = [];
98 $places = [];
99 $callers = [];
100 $example = $colliding_files[0];
101 foreach ($spellings as $spelling => $lines) {
102 $variants[] = '`' . $spelling . '`';
103 $places[] = '`' . $spelling . '`: lang/' . $example . ':' . $lines[$example];
104 $found = $callers_of((string) $spelling);
105 $callers[] = '`' . $spelling . '`: ' . ($found === [] ? 'keine' : implode(', ', array_slice($found, 0, 5)) . (count($found) > 5 ? sprintf(' … (+%d)', count($found) - 5) : ''));
106 }
107 $affected = count($colliding_files) >= 25
108 ? 'fast alle (' . count($colliding_files) . ')'
109 : implode(', ', array_map(static fn(string $f): string => substr($f, 6, -5), $colliding_files));
110 echo sprintf("| `%s` | %s | %s | %s | %s |\n", $module, implode(', ', $variants), $affected, implode('<br>', $places), implode('<br>', $callers));
111}
if(!isset($arguments[0])) if(count( $arguments) > 3) if(! $remove_from_lang &&isset($arguments[2]) &&!is_dir($arguments[2])) $module
foreach($files as $file) $duplicates
$ilias_root
Lists every identifier of the shipped lang/ilias_*.lang files that occurs in one module in spellings ...
$text
Definition: xapiexit.php:21