DataInconsistency
1 month ago
License
2 months ago
Notices
3 months ago
pQuery
3 months ago
APIPermissionHelper.php
1 year ago
CdnAssetUrl.php
3 years ago
ConflictResolver.php
1 month ago
Cookies.php
2 months ago
DBCollationChecker.php
3 months ago
DOM.php
2 years ago
DateConverter.php
3 years ago
FreeDomains.php
3 years ago
Headers.php
1 year ago
Helpers.php
1 month ago
Installation.php
1 year ago
LegacyDatabase.php
1 year ago
Request.php
3 months ago
SecondLevelDomainNames.php
3 years ago
Security.php
3 months ago
ThirdPartyOutput.php
1 month ago
Url.php
3 months ago
index.php
3 years ago
DBCollationChecker.php
49 lines
| 1 | <?php declare(strict_types = 1); |
| 2 | |
| 3 | namespace MailPoet\Util; |
| 4 | |
| 5 | if (!defined('ABSPATH')) exit; |
| 6 | |
| 7 | |
| 8 | use MailPoetVendor\Doctrine\ORM\EntityManager; |
| 9 | |
| 10 | class DBCollationChecker { |
| 11 | |
| 12 | /** @var EntityManager */ |
| 13 | private $entityManager; |
| 14 | |
| 15 | public function __construct( |
| 16 | EntityManager $entityManager |
| 17 | ) { |
| 18 | $this->entityManager = $entityManager; |
| 19 | } |
| 20 | |
| 21 | /** |
| 22 | * If two columns have incompatible collations returns MySQL's COLLATE command to be used with the target table column. |
| 23 | * e.g. WHERE source_table.column = target_table.column COLLATE xyz |
| 24 | * |
| 25 | * In MySQL, if you have the same charset and collation in joined tables' columns it's perfect; |
| 26 | * if you have different charsets, utf8 and utf8mb4, it works too; but if you have the same charset |
| 27 | * with different collations, e.g. utf8mb4_unicode_ci and utf8mb4_unicode_520_ci, it will fail |
| 28 | * with an 'Illegal mix of collations' error. |
| 29 | */ |
| 30 | public function getCollateIfNeeded(string $sourceTable, string $sourceColumn, string $targetTable, string $targetColumn): string { |
| 31 | $connection = $this->entityManager->getConnection(); |
| 32 | $sourceColumnData = $connection->executeQuery("SHOW FULL COLUMNS FROM $sourceTable WHERE Field = '$sourceColumn';")->fetchAllAssociative(); |
| 33 | $sourceCollationRaw = $sourceColumnData[0]['Collation'] ?? ''; |
| 34 | $sourceCollation = is_string($sourceCollationRaw) ? $sourceCollationRaw : ''; |
| 35 | $targetColumnData = $connection->executeQuery("SHOW FULL COLUMNS FROM $targetTable WHERE Field = '$targetColumn';")->fetchAllAssociative(); |
| 36 | $targetCollationRaw = $targetColumnData[0]['Collation'] ?? ''; |
| 37 | $targetCollation = is_string($targetCollationRaw) ? $targetCollationRaw : ''; |
| 38 | if ($sourceCollation === $targetCollation) { |
| 39 | return ''; |
| 40 | } |
| 41 | list($sourceCharset) = explode('_', $sourceCollation); |
| 42 | list($targetCharset) = explode('_', $targetCollation); |
| 43 | if ($sourceCharset === $targetCharset) { |
| 44 | return "COLLATE $sourceCollation"; |
| 45 | } |
| 46 | return ''; |
| 47 | } |
| 48 | } |
| 49 |