3 * MySQL charset metadata and manipulations
6 declare(strict_types
=1);
10 use PhpMyAdmin\Charsets\Charset
;
11 use PhpMyAdmin\Charsets\Collation
;
12 use const SORT_STRING
;
13 use function array_keys
;
16 use function is_string
;
20 * Class used to manage MySQL charsets
29 public static $mysqlCharsetMap = [
36 'iso-8859-1' => 'latin1',
37 'iso-8859-2' => 'latin2',
38 'iso-8859-7' => 'greek',
39 'iso-8859-8' => 'hebrew',
40 'iso-8859-8-i' => 'hebrew',
41 'iso-8859-9' => 'latin5',
42 'iso-8859-13' => 'latin7',
43 'iso-8859-15' => 'latin1',
45 'shift_jis' => 'sjis',
46 'tis-620' => 'tis620',
48 'windows-1250' => 'cp1250',
49 'windows-1251' => 'cp1251',
50 'windows-1252' => 'latin1',
51 'windows-1256' => 'cp1256',
52 'windows-1257' => 'cp1257',
56 * The charset for the server
60 private static $serverCharset = null;
62 /** @var array<string, Charset> */
63 private static $charsets = [];
65 /** @var array<string, array<string, Collation>> */
66 private static $collations = [];
69 * Loads charset data from the server
71 * @param DatabaseInterface $dbi DatabaseInterface instance
72 * @param bool $disableIs Disable use of INFORMATION_SCHEMA
74 private static function loadCharsets(DatabaseInterface
$dbi, bool $disableIs): void
76 /* Data already loaded */
77 if (count(self
::$charsets) > 0) {
82 $sql = 'SHOW CHARACTER SET';
84 $sql = 'SELECT `CHARACTER_SET_NAME` AS `Charset`,'
85 . ' `DEFAULT_COLLATE_NAME` AS `Default collation`,'
86 . ' `DESCRIPTION` AS `Description`,'
87 . ' `MAXLEN` AS `Maxlen`'
88 . ' FROM `information_schema`.`CHARACTER_SETS`';
90 $res = $dbi->query($sql);
93 while ($row = $dbi->fetchAssoc($res)) {
94 self
::$charsets[$row['Charset']] = Charset
::fromServer($row);
96 $dbi->freeResult($res);
98 ksort(self
::$charsets, SORT_STRING
);
102 * Loads collation data from the server
104 * @param DatabaseInterface $dbi DatabaseInterface instance
105 * @param bool $disableIs Disable use of INFORMATION_SCHEMA
107 private static function loadCollations(DatabaseInterface
$dbi, bool $disableIs): void
109 /* Data already loaded */
110 if (count(self
::$collations) > 0) {
115 $sql = 'SHOW COLLATION';
117 $sql = 'SELECT `COLLATION_NAME` AS `Collation`,'
118 . ' `CHARACTER_SET_NAME` AS `Charset`,'
120 . ' `IS_DEFAULT` AS `Default`,'
121 . ' `IS_COMPILED` AS `Compiled`,'
122 . ' `SORTLEN` AS `Sortlen`'
123 . ' FROM `information_schema`.`COLLATIONS`';
125 $res = $dbi->query($sql);
127 self
::$collations = [];
128 while ($row = $dbi->fetchAssoc($res)) {
129 self
::$collations[$row['Charset']][$row['Collation']] = Collation
::fromServer($row);
131 $dbi->freeResult($res);
133 foreach (array_keys(self
::$collations) as $charset) {
134 ksort(self
::$collations[$charset], SORT_STRING
);
139 * Get current server charset
141 * @param DatabaseInterface $dbi DatabaseInterface instance
142 * @param bool $disableIs Disable use of INFORMATION_SCHEMA
144 public static function getServerCharset(DatabaseInterface
$dbi, bool $disableIs): Charset
146 if (self
::$serverCharset !== null) {
147 return self
::$serverCharset;
149 self
::loadCharsets($dbi, $disableIs);
150 $serverCharset = $dbi->getVariable('character_set_server');
151 if (! is_string($serverCharset)) {// MySQL 5.7.8 fallback, issue #15614
152 $serverCharset = $dbi->fetchValue('SELECT @@character_set_server;');
154 self
::$serverCharset = self
::$charsets[$serverCharset];
156 return self
::$serverCharset;
160 * Get all server charsets
162 * @param DatabaseInterface $dbi DatabaseInterface instance
163 * @param bool $disableIs Disable use of INFORMATION_SCHEMA
167 public static function getCharsets(DatabaseInterface
$dbi, bool $disableIs): array
169 self
::loadCharsets($dbi, $disableIs);
171 return self
::$charsets;
175 * Get all server collations
177 * @param DatabaseInterface $dbi DatabaseInterface instance
178 * @param bool $disableIs Disable use of INFORMATION_SCHEMA
182 public static function getCollations(DatabaseInterface
$dbi, bool $disableIs): array
184 self
::loadCollations($dbi, $disableIs);
186 return self
::$collations;
190 * @param DatabaseInterface $dbi DatabaseInterface instance
191 * @param bool $disableIs Disable use of INFORMATION_SCHEMA
192 * @param string|null $name Collation name
194 public static function findCollationByName(DatabaseInterface
$dbi, bool $disableIs, ?
string $name): ?Collation
196 $pieces = explode('_', (string) $name);
197 if ($pieces === false ||
! isset($pieces[0])) {
200 $charset = $pieces[0];
201 $collations = self
::getCollations($dbi, $disableIs);
203 return $collations[$charset][$name] ??
null;