Collation.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. <?php
  2. /**
  3. * Value object class for a collation
  4. * @package PhpMyAdmin\Charsets
  5. */
  6. declare(strict_types=1);
  7. namespace PhpMyAdmin\Charsets;
  8. use PhpMyAdmin\Charsets;
  9. /**
  10. * Value object class for a collation
  11. * @package PhpMyAdmin\Charsets
  12. */
  13. final class Collation
  14. {
  15. /**
  16. * The collation name
  17. * @var string
  18. */
  19. private $name;
  20. /**
  21. * A description of the collation
  22. * @var string
  23. */
  24. private $description;
  25. /**
  26. * The name of the character set with which the collation is associated
  27. * @var string
  28. */
  29. private $charset;
  30. /**
  31. * The collation ID
  32. * @var int
  33. */
  34. private $id;
  35. /**
  36. * Whether the collation is the default for its character set
  37. * @var bool
  38. */
  39. private $isDefault;
  40. /**
  41. * Whether the character set is compiled into the server
  42. * @var bool
  43. */
  44. private $isCompiled;
  45. /**
  46. * Used for determining the memory used to sort strings in this collation
  47. * @var int
  48. */
  49. private $sortLength;
  50. /**
  51. * The collation pad attribute
  52. * @var string
  53. */
  54. private $padAttribute;
  55. /**
  56. * @param string $name Collation name
  57. * @param string $charset Related charset
  58. * @param int $id Collation ID
  59. * @param bool $isDefault Whether is the default
  60. * @param bool $isCompiled Whether the charset is compiled
  61. * @param int $sortLength Sort length
  62. * @param string $padAttribute Pad attribute
  63. */
  64. private function __construct(
  65. string $name,
  66. string $charset,
  67. int $id,
  68. bool $isDefault,
  69. bool $isCompiled,
  70. int $sortLength,
  71. string $padAttribute
  72. ) {
  73. $this->name = $name;
  74. $this->charset = $charset;
  75. $this->id = $id;
  76. $this->isDefault = $isDefault;
  77. $this->isCompiled = $isCompiled;
  78. $this->sortLength = $sortLength;
  79. $this->padAttribute = $padAttribute;
  80. $this->description = $this->buildDescription();
  81. }
  82. /**
  83. * @param array $state State obtained from the database server
  84. * @return self
  85. */
  86. public static function fromServer(array $state): self
  87. {
  88. return new self(
  89. $state['Collation'] ?? '',
  90. $state['Charset'] ?? '',
  91. (int) ($state['Id'] ?? 0),
  92. isset($state['Default']) && ($state['Default'] === 'Yes' || $state['Default'] === '1'),
  93. isset($state['Compiled']) && ($state['Compiled'] === 'Yes' || $state['Compiled'] === '1'),
  94. (int) ($state['Sortlen'] ?? 0),
  95. $state['Pad_attribute'] ?? ''
  96. );
  97. }
  98. /**
  99. * @return string
  100. */
  101. public function getName(): string
  102. {
  103. return $this->name;
  104. }
  105. /**
  106. * @return string
  107. */
  108. public function getDescription(): string
  109. {
  110. return $this->description;
  111. }
  112. /**
  113. * @return string
  114. */
  115. public function getCharset(): string
  116. {
  117. return $this->charset;
  118. }
  119. /**
  120. * @return int
  121. */
  122. public function getId(): int
  123. {
  124. return $this->id;
  125. }
  126. /**
  127. * @return bool
  128. */
  129. public function isDefault(): bool
  130. {
  131. return $this->isDefault;
  132. }
  133. /**
  134. * @return bool
  135. */
  136. public function isCompiled(): bool
  137. {
  138. return $this->isCompiled;
  139. }
  140. /**
  141. * @return int
  142. */
  143. public function getSortLength(): int
  144. {
  145. return $this->sortLength;
  146. }
  147. /**
  148. * @return string
  149. */
  150. public function getPadAttribute(): string
  151. {
  152. return $this->padAttribute;
  153. }
  154. /**
  155. * Returns description for given collation
  156. *
  157. * @return string collation description
  158. */
  159. private function buildDescription(): string
  160. {
  161. $parts = explode('_', $this->getName());
  162. $name = __('Unknown');
  163. $variant = null;
  164. $suffixes = [];
  165. $unicode = false;
  166. $unknown = false;
  167. $level = 0;
  168. foreach ($parts as $part) {
  169. if ($level == 0) {
  170. /* Next will be language */
  171. $level = 1;
  172. /* First should be charset */
  173. switch ($part) {
  174. case 'binary':
  175. $name = _pgettext('Collation', 'Binary');
  176. break;
  177. // Unicode charsets
  178. case 'utf8mb4':
  179. $variant = 'UCA 4.0.0';
  180. // Fall through to other unicode
  181. case 'ucs2':
  182. case 'utf8':
  183. case 'utf16':
  184. case 'utf16le':
  185. case 'utf16be':
  186. case 'utf32':
  187. $name = _pgettext('Collation', 'Unicode');
  188. $unicode = true;
  189. break;
  190. // West European charsets
  191. case 'ascii':
  192. case 'cp850':
  193. case 'dec8':
  194. case 'hp8':
  195. case 'latin1':
  196. case 'macroman':
  197. $name = _pgettext('Collation', 'West European');
  198. break;
  199. // Central European charsets
  200. case 'cp1250':
  201. case 'cp852':
  202. case 'latin2':
  203. case 'macce':
  204. $name = _pgettext('Collation', 'Central European');
  205. break;
  206. // Russian charsets
  207. case 'cp866':
  208. case 'koi8r':
  209. $name = _pgettext('Collation', 'Russian');
  210. break;
  211. // Chinese charsets
  212. case 'gb2312':
  213. case 'gbk':
  214. $name = _pgettext('Collation', 'Simplified Chinese');
  215. break;
  216. case 'big5':
  217. $name = _pgettext('Collation', 'Traditional Chinese');
  218. break;
  219. case 'gb18030':
  220. $name = _pgettext('Collation', 'Chinese');
  221. $unicode = true;
  222. break;
  223. // Japanese charsets
  224. case 'sjis':
  225. case 'ujis':
  226. case 'cp932':
  227. case 'eucjpms':
  228. $name = _pgettext('Collation', 'Japanese');
  229. break;
  230. // Baltic charsets
  231. case 'cp1257':
  232. case 'latin7':
  233. $name = _pgettext('Collation', 'Baltic');
  234. break;
  235. // Other
  236. case 'armscii8':
  237. case 'armscii':
  238. $name = _pgettext('Collation', 'Armenian');
  239. break;
  240. case 'cp1251':
  241. $name = _pgettext('Collation', 'Cyrillic');
  242. break;
  243. case 'cp1256':
  244. $name = _pgettext('Collation', 'Arabic');
  245. break;
  246. case 'euckr':
  247. $name = _pgettext('Collation', 'Korean');
  248. break;
  249. case 'hebrew':
  250. $name = _pgettext('Collation', 'Hebrew');
  251. break;
  252. case 'geostd8':
  253. $name = _pgettext('Collation', 'Georgian');
  254. break;
  255. case 'greek':
  256. $name = _pgettext('Collation', 'Greek');
  257. break;
  258. case 'keybcs2':
  259. $name = _pgettext('Collation', 'Czech-Slovak');
  260. break;
  261. case 'koi8u':
  262. $name = _pgettext('Collation', 'Ukrainian');
  263. break;
  264. case 'latin5':
  265. $name = _pgettext('Collation', 'Turkish');
  266. break;
  267. case 'swe7':
  268. $name = _pgettext('Collation', 'Swedish');
  269. break;
  270. case 'tis620':
  271. $name = _pgettext('Collation', 'Thai');
  272. break;
  273. default:
  274. $name = _pgettext('Collation', 'Unknown');
  275. $unknown = true;
  276. break;
  277. }
  278. continue;
  279. }
  280. if ($level == 1) {
  281. /* Next will be variant unless changed later */
  282. $level = 4;
  283. /* Locale name or code */
  284. $found = true;
  285. switch ($part) {
  286. case 'general':
  287. break;
  288. case 'bulgarian':
  289. case 'bg':
  290. $name = _pgettext('Collation', 'Bulgarian');
  291. break;
  292. case 'chinese':
  293. case 'cn':
  294. case 'zh':
  295. if ($unicode) {
  296. $name = _pgettext('Collation', 'Chinese');
  297. }
  298. break;
  299. case 'croatian':
  300. case 'hr':
  301. $name = _pgettext('Collation', 'Croatian');
  302. break;
  303. case 'czech':
  304. case 'cs':
  305. $name = _pgettext('Collation', 'Czech');
  306. break;
  307. case 'danish':
  308. case 'da':
  309. $name = _pgettext('Collation', 'Danish');
  310. break;
  311. case 'english':
  312. case 'en':
  313. $name = _pgettext('Collation', 'English');
  314. break;
  315. case 'esperanto':
  316. case 'eo':
  317. $name = _pgettext('Collation', 'Esperanto');
  318. break;
  319. case 'estonian':
  320. case 'et':
  321. $name = _pgettext('Collation', 'Estonian');
  322. break;
  323. case 'german1':
  324. $name = _pgettext('Collation', 'German (dictionary order)');
  325. break;
  326. case 'german2':
  327. $name = _pgettext('Collation', 'German (phone book order)');
  328. break;
  329. case 'german':
  330. case 'de':
  331. /* Name is set later */
  332. $level = 2;
  333. break;
  334. case 'hungarian':
  335. case 'hu':
  336. $name = _pgettext('Collation', 'Hungarian');
  337. break;
  338. case 'icelandic':
  339. case 'is':
  340. $name = _pgettext('Collation', 'Icelandic');
  341. break;
  342. case 'japanese':
  343. case 'ja':
  344. $name = _pgettext('Collation', 'Japanese');
  345. break;
  346. case 'la':
  347. $name = _pgettext('Collation', 'Classical Latin');
  348. break;
  349. case 'latvian':
  350. case 'lv':
  351. $name = _pgettext('Collation', 'Latvian');
  352. break;
  353. case 'lithuanian':
  354. case 'lt':
  355. $name = _pgettext('Collation', 'Lithuanian');
  356. break;
  357. case 'korean':
  358. case 'ko':
  359. $name = _pgettext('Collation', 'Korean');
  360. break;
  361. case 'myanmar':
  362. case 'my':
  363. $name = _pgettext('Collation', 'Burmese');
  364. break;
  365. case 'persian':
  366. $name = _pgettext('Collation', 'Persian');
  367. break;
  368. case 'polish':
  369. case 'pl':
  370. $name = _pgettext('Collation', 'Polish');
  371. break;
  372. case 'roman':
  373. $name = _pgettext('Collation', 'West European');
  374. break;
  375. case 'romanian':
  376. case 'ro':
  377. $name = _pgettext('Collation', 'Romanian');
  378. break;
  379. case 'ru':
  380. $name = _pgettext('Collation', 'Russian');
  381. break;
  382. case 'si':
  383. case 'sinhala':
  384. $name = _pgettext('Collation', 'Sinhalese');
  385. break;
  386. case 'slovak':
  387. case 'sk':
  388. $name = _pgettext('Collation', 'Slovak');
  389. break;
  390. case 'slovenian':
  391. case 'sl':
  392. $name = _pgettext('Collation', 'Slovenian');
  393. break;
  394. case 'spanish':
  395. $name = _pgettext('Collation', 'Spanish (modern)');
  396. break;
  397. case 'es':
  398. /* Name is set later */
  399. $level = 3;
  400. break;
  401. case 'spanish2':
  402. $name = _pgettext('Collation', 'Spanish (traditional)');
  403. break;
  404. case 'swedish':
  405. case 'sv':
  406. $name = _pgettext('Collation', 'Swedish');
  407. break;
  408. case 'thai':
  409. case 'th':
  410. $name = _pgettext('Collation', 'Thai');
  411. break;
  412. case 'turkish':
  413. case 'tr':
  414. $name = _pgettext('Collation', 'Turkish');
  415. break;
  416. case 'ukrainian':
  417. case 'uk':
  418. $name = _pgettext('Collation', 'Ukrainian');
  419. break;
  420. case 'vietnamese':
  421. case 'vi':
  422. $name = _pgettext('Collation', 'Vietnamese');
  423. break;
  424. case 'unicode':
  425. if ($unknown) {
  426. $name = _pgettext('Collation', 'Unicode');
  427. }
  428. break;
  429. default:
  430. $found = false;
  431. }
  432. if ($found) {
  433. continue;
  434. }
  435. // Not parsed token, fall to next level
  436. }
  437. if ($level == 2) {
  438. /* Next will be variant */
  439. $level = 4;
  440. /* Germal variant */
  441. if ($part == 'pb') {
  442. $name = _pgettext('Collation', 'German (phone book order)');
  443. continue;
  444. }
  445. $name = _pgettext('Collation', 'German (dictionary order)');
  446. // Not parsed token, fall to next level
  447. }
  448. if ($level == 3) {
  449. /* Next will be variant */
  450. $level = 4;
  451. /* Spanish variant */
  452. if ($part == 'trad') {
  453. $name = _pgettext('Collation', 'Spanish (traditional)');
  454. continue;
  455. }
  456. $name = _pgettext('Collation', 'Spanish (modern)');
  457. // Not parsed token, fall to next level
  458. }
  459. if ($level == 4) {
  460. /* Next will be suffix */
  461. $level = 5;
  462. /* Variant */
  463. $found = true;
  464. switch ($part) {
  465. case '0900':
  466. $variant = 'UCA 9.0.0';
  467. break;
  468. case '520':
  469. $variant = 'UCA 5.2.0';
  470. break;
  471. case 'mysql561':
  472. $variant = 'MySQL 5.6.1';
  473. break;
  474. case 'mysql500':
  475. $variant = 'MySQL 5.0.0';
  476. break;
  477. default:
  478. $found = false;
  479. }
  480. if ($found) {
  481. continue;
  482. }
  483. // Not parsed token, fall to next level
  484. }
  485. if ($level == 5) {
  486. /* Suffixes */
  487. switch ($part) {
  488. case 'ci':
  489. $suffixes[] = _pgettext('Collation variant', 'case-insensitive');
  490. break;
  491. case 'cs':
  492. $suffixes[] = _pgettext('Collation variant', 'case-sensitive');
  493. break;
  494. case 'ai':
  495. $suffixes[] = _pgettext('Collation variant', 'accent-insensitive');
  496. break;
  497. case 'as':
  498. $suffixes[] = _pgettext('Collation variant', 'accent-sensitive');
  499. break;
  500. case 'ks':
  501. $suffixes[] = _pgettext('Collation variant', 'kana-sensitive');
  502. break;
  503. case 'w2':
  504. case 'l2':
  505. $suffixes[] = _pgettext('Collation variant', 'multi-level');
  506. break;
  507. case 'bin':
  508. $suffixes[] = _pgettext('Collation variant', 'binary');
  509. break;
  510. case 'nopad':
  511. $suffixes[] = _pgettext('Collation variant', 'no-pad');
  512. break;
  513. }
  514. }
  515. }
  516. $result = $name;
  517. if ($variant !== null) {
  518. $result .= ' (' . $variant . ')';
  519. }
  520. if (count($suffixes) > 0) {
  521. $result .= ', ' . implode(', ', $suffixes);
  522. }
  523. return $result;
  524. }
  525. }