'big5', 'cp-866' => 'cp866', 'euc-jp' => 'ujis', 'euc-kr' => 'euckr', 'gb2312' => 'gb2312', 'gbk' => 'gbk', 'iso-8859-1' => 'latin1', 'iso-8859-2' => 'latin2', 'iso-8859-7' => 'greek', 'iso-8859-8' => 'hebrew', 'iso-8859-8-i' => 'hebrew', 'iso-8859-9' => 'latin5', 'iso-8859-13' => 'latin7', 'iso-8859-15' => 'latin1', 'koi8-r' => 'koi8r', 'shift_jis' => 'sjis', 'tis-620' => 'tis620', 'utf-8' => 'utf8', 'windows-1250' => 'cp1250', 'windows-1251' => 'cp1251', 'windows-1252' => 'latin1', 'windows-1256' => 'cp1256', 'windows-1257' => 'cp1257', ); private static $_charsets = array(); /** * The charset for the server * * @var string */ private static $_charset_server; private static $_charsets_descriptions = array(); private static $_collations = array(); private static $_default_collations = array(); /** * Loads charset data from the MySQL server. * * @param DatabaseInterface $dbi DatabaseInterface instance * @param boolean $disableIs Disable use of INFORMATION_SCHEMA * * @return void */ private static function loadCharsets(DatabaseInterface $dbi, $disableIs) { /* Data already loaded */ if (count(self::$_charsets) > 0) { return; } if ($disableIs) { $sql = 'SHOW CHARACTER SET'; } else { $sql = 'SELECT `CHARACTER_SET_NAME` AS `Charset`,' . ' `DESCRIPTION` AS `Description`' . ' FROM `information_schema`.`CHARACTER_SETS`'; } $res = $dbi->query($sql); self::$_charsets = array(); while ($row = $dbi->fetchAssoc($res)) { $name = $row['Charset']; self::$_charsets[] = $name; self::$_charsets_descriptions[$name] = $row['Description']; } $dbi->freeResult($res); sort(self::$_charsets, SORT_STRING); } /** * Loads collation data from the MySQL server. * * @param DatabaseInterface $dbi DatabaseInterface instance * @param boolean $disableIs Disable use of INFORMATION_SCHEMA * * @return void */ private static function loadCollations(DatabaseInterface $dbi, $disableIs) { /* Data already loaded */ if (count(self::$_collations) > 0) { return; } if ($disableIs) { $sql = 'SHOW COLLATION'; } else { $sql = 'SELECT `CHARACTER_SET_NAME` AS `Charset`,' . ' `COLLATION_NAME` AS `Collation`, `IS_DEFAULT` AS `Default`' . ' FROM `information_schema`.`COLLATIONS`'; } $res = $dbi->query($sql); while ($row = $dbi->fetchAssoc($res)) { $char_set_name = $row['Charset']; $name = $row['Collation']; self::$_collations[$char_set_name][] = $name; if ($row['Default'] == 'Yes' || $row['Default'] == '1') { self::$_default_collations[$char_set_name] = $name; } } $dbi->freeResult($res); foreach (self::$_collations as $key => $value) { sort(self::$_collations[$key], SORT_STRING); } } /** * Get current MySQL server charset. * * @param DatabaseInterface $dbi DatabaseInterface instance * * @return string */ public static function getServerCharset(DatabaseInterface $dbi) { if (self::$_charset_server) { return self::$_charset_server; } else { $charsetServer = $dbi->getVariable('character_set_server'); if (! is_string($charsetServer)) {// MySQL 5.7.8 fallback, issue #15614 $charsetServer = $dbi->fetchValue("SELECT @@character_set_server;"); } self::$_charset_server = $charsetServer; return self::$_charset_server; } } /** * Get MySQL charsets * * @param DatabaseInterface $dbi DatabaseInterface instance * @param boolean $disableIs Disable use of INFORMATION_SCHEMA * * @return array */ public static function getMySQLCharsets(DatabaseInterface $dbi, $disableIs) { self::loadCharsets($dbi, $disableIs); return self::$_charsets; } /** * Get MySQL charsets descriptions * * @param DatabaseInterface $dbi DatabaseInterface instance * @param boolean $disableIs Disable use of INFORMATION_SCHEMA * * @return array */ public static function getMySQLCharsetsDescriptions(DatabaseInterface $dbi, $disableIs) { self::loadCharsets($dbi, $disableIs); return self::$_charsets_descriptions; } /** * Get MySQL collations * * @param DatabaseInterface $dbi DatabaseInterface instance * @param boolean $disableIs Disable use of INFORMATION_SCHEMA * * @return array */ public static function getMySQLCollations(DatabaseInterface $dbi, $disableIs) { self::loadCollations($dbi, $disableIs); return self::$_collations; } /** * Get MySQL default collations * * @param DatabaseInterface $dbi DatabaseInterface instance * @param boolean $disableIs Disable use of INFORMATION_SCHEMA * * @return array */ public static function getMySQLCollationsDefault(DatabaseInterface $dbi, $disableIs) { self::loadCollations($dbi, $disableIs); return self::$_default_collations; } /** * Generate charset dropdown box * * @param DatabaseInterface $dbi DatabaseInterface instance * @param boolean $disableIs Disable use of INFORMATION_SCHEMA * @param string $name Element name * @param string $id Element id * @param null|string $default Default value * @param bool $label Label * @param bool $submitOnChange Submit on change * * @return string */ public static function getCharsetDropdownBox( DatabaseInterface $dbi, $disableIs, $name = null, $id = null, $default = null, $label = true, $submitOnChange = false ) { self::loadCharsets($dbi, $disableIs); if (empty($name)) { $name = 'character_set'; } $return_str = '' . "\n"; return $return_str; } /** * Generate collation dropdown box * * @param DatabaseInterface $dbi DatabaseInterface instance * @param boolean $disableIs Disable use of INFORMATION_SCHEMA * @param string $name Element name * @param string $id Element id * @param null|string $default Default value * @param bool $label Label * @param bool $submitOnChange Submit on change * * @return string */ public static function getCollationDropdownBox( DatabaseInterface $dbi, $disableIs, $name = null, $id = null, $default = null, $label = true, $submitOnChange = false ) { self::loadCharsets($dbi, $disableIs); self::loadCollations($dbi, $disableIs); if (empty($name)) { $name = 'collation'; } $return_str = '' . "\n"; return $return_str; } /** * Returns description for given collation * * @param string $collation MySQL collation string * * @return string collation description */ public static function getCollationDescr($collation) { $parts = explode('_', $collation); $name = __('Unknown'); $variant = null; $suffixes = array(); $unicode = false; $unknown = false; $level = 0; foreach ($parts as $part) { if ($level == 0) { /* Next will be language */ $level = 1; /* First should be charset */ switch ($part) { case 'binary': $name = _pgettext('Collation', 'Binary'); break; // Unicode charsets case 'utf8mb4': $variant = 'UCA 4.0.0'; // Fall through to other unicode case 'ucs2': case 'utf8': case 'utf16': case 'utf16le': case 'utf16be': case 'utf32': $name = _pgettext('Collation', 'Unicode'); $unicode = true; break; // West European charsets case 'ascii': case 'cp850': case 'dec8': case 'hp8': case 'latin1': case 'macroman': $name = _pgettext('Collation', 'West European'); break; // Central European charsets case 'cp1250': case 'cp852': case 'latin2': case 'macce': $name = _pgettext('Collation', 'Central European'); break; // Russian charsets case 'cp866': case 'koi8r': $name = _pgettext('Collation', 'Russian'); break; // Chinese charsets case 'gb2312': case 'gbk': $name = _pgettext('Collation', 'Simplified Chinese'); break; case 'big5': $name = _pgettext('Collation', 'Traditional Chinese'); break; case 'gb18030': $name = _pgettext('Collation', 'Chinese'); $unicode = true; break; // Japanese charsets case 'sjis': case 'ujis': case 'cp932': case 'eucjpms': $name = _pgettext('Collation', 'Japanese'); break; // Baltic charsets case 'cp1257': case 'latin7': $name = _pgettext('Collation', 'Baltic'); break; // Other case 'armscii8': case 'armscii': $name = _pgettext('Collation', 'Armenian'); break; case 'cp1251': $name = _pgettext('Collation', 'Cyrillic'); break; case 'cp1256': $name = _pgettext('Collation', 'Arabic'); break; case 'euckr': $name = _pgettext('Collation', 'Korean'); break; case 'hebrew': $name = _pgettext('Collation', 'Hebrew'); break; case 'geostd8': $name = _pgettext('Collation', 'Georgian'); break; case 'greek': $name = _pgettext('Collation', 'Greek'); break; case 'keybcs2': $name = _pgettext('Collation', 'Czech-Slovak'); break; case 'koi8u': $name = _pgettext('Collation', 'Ukrainian'); break; case 'latin5': $name = _pgettext('Collation', 'Turkish'); break; case 'swe7': $name = _pgettext('Collation', 'Swedish'); break; case 'tis620': $name = _pgettext('Collation', 'Thai'); break; default: $name = _pgettext('Collation', 'Unknown'); $unknown = true; break; } continue; } if ($level == 1) { /* Next will be variant unless changed later */ $level = 4; /* Locale name or code */ $found = true; switch ($part) { case 'general': break; case 'bulgarian': case 'bg': $name = _pgettext('Collation', 'Bulgarian'); break; case 'chinese': case 'cn': case 'zh': if ($unicode) { $name = _pgettext('Collation', 'Chinese'); } break; case 'croatian': case 'hr': $name = _pgettext('Collation', 'Croatian'); break; case 'czech': case 'cs': $name = _pgettext('Collation', 'Czech'); break; case 'danish': case 'da': $name = _pgettext('Collation', 'Danish'); break; case 'english': case 'en': $name = _pgettext('Collation', 'English'); break; case 'esperanto': case 'eo': $name = _pgettext('Collation', 'Esperanto'); break; case 'estonian': case 'et': $name = _pgettext('Collation', 'Estonian'); break; case 'german1': $name = _pgettext('Collation', 'German (dictionary order)'); break; case 'german2': $name = _pgettext('Collation', 'German (phone book order)'); break; case 'german': case 'de': /* Name is set later */ $level = 2; break; case 'hungarian': case 'hu': $name = _pgettext('Collation', 'Hungarian'); break; case 'icelandic': case 'is': $name = _pgettext('Collation', 'Icelandic'); break; case 'japanese': case 'ja': $name = _pgettext('Collation', 'Japanese'); break; case 'la': $name = _pgettext('Collation', 'Classical Latin'); break; case 'latvian': case 'lv': $name = _pgettext('Collation', 'Latvian'); break; case 'lithuanian': case 'lt': $name = _pgettext('Collation', 'Lithuanian'); break; case 'korean': case 'ko': $name = _pgettext('Collation', 'Korean'); break; case 'myanmar': case 'my': $name = _pgettext('Collation', 'Burmese'); break; case 'persian': $name = _pgettext('Collation', 'Persian'); break; case 'polish': case 'pl': $name = _pgettext('Collation', 'Polish'); break; case 'roman': $name = _pgettext('Collation', 'West European'); break; case 'romanian': case 'ro': $name = _pgettext('Collation', 'Romanian'); break; case 'ru': $name = _pgettext('Collation', 'Russian'); break; case 'si': case 'sinhala': $name = _pgettext('Collation', 'Sinhalese'); break; case 'slovak': case 'sk': $name = _pgettext('Collation', 'Slovak'); break; case 'slovenian': case 'sl': $name = _pgettext('Collation', 'Slovenian'); break; case 'spanish': $name = _pgettext('Collation', 'Spanish (modern)'); break; case 'es': /* Name is set later */ $level = 3; break; case 'spanish2': $name = _pgettext('Collation', 'Spanish (traditional)'); break; case 'swedish': case 'sv': $name = _pgettext('Collation', 'Swedish'); break; case 'thai': case 'th': $name = _pgettext('Collation', 'Thai'); break; case 'turkish': case 'tr': $name = _pgettext('Collation', 'Turkish'); break; case 'ukrainian': case 'uk': $name = _pgettext('Collation', 'Ukrainian'); break; case 'vietnamese': case 'vi': $name = _pgettext('Collation', 'Vietnamese'); break; case 'unicode': if ($unknown) { $name = _pgettext('Collation', 'Unicode'); } break; default: $found = false; } if ($found) { continue; } // Not parsed token, fall to next level } if ($level == 2) { /* Next will be variant */ $level = 4; /* Germal variant */ if ($part == 'pb') { $name = _pgettext('Collation', 'German (phone book order)'); continue; } $name = _pgettext('Collation', 'German (dictionary order)'); // Not parsed token, fall to next level } if ($level == 3) { /* Next will be variant */ $level = 4; /* Spanish variant */ if ($part == 'trad') { $name = _pgettext('Collation', 'Spanish (traditional)'); continue; } $name = _pgettext('Collation', 'Spanish (modern)'); // Not parsed token, fall to next level } if ($level == 4) { /* Next will be suffix */ $level = 5; /* Variant */ $found = true; switch ($part) { case '0900': $variant = 'UCA 9.0.0'; break; case '520': $variant = 'UCA 5.2.0'; break; case 'mysql561': $variant = 'MySQL 5.6.1'; break; case 'mysql500': $variant = 'MySQL 5.0.0'; break; default: $found = false; } if ($found) { continue; } // Not parsed token, fall to next level } if ($level == 5) { /* Suffixes */ switch ($part) { case 'ci': $suffixes[] = _pgettext('Collation variant', 'case-insensitive'); break; case 'cs': $suffixes[] = _pgettext('Collation variant', 'case-sensitive'); break; case 'ai': $suffixes[] = _pgettext('Collation variant', 'accent-insensitive'); break; case 'as': $suffixes[] = _pgettext('Collation variant', 'accent-sensitive'); break; case 'ks': $suffixes[] = _pgettext('Collation variant', 'kana-sensitive'); break; case 'w2': case 'l2': $suffixes[] = _pgettext('Collation variant', 'multi-level'); break; case 'bin': $suffixes[] = _pgettext('Collation variant', 'binary'); break; case 'nopad': $suffixes[] = _pgettext('Collation variant', 'no-pad'); break; } } } $result = $name; if (! is_null($variant)) { $result .= ' (' . $variant . ')'; } if (count($suffixes) > 0) { $result .= ', ' . implode(', ', $suffixes); } return $result; } }