103 lines
3 KiB
PHP
103 lines
3 KiB
PHP
<?php declare(strict_types = 1);
|
|
|
|
namespace MailPoet\Migrator;
|
|
|
|
if (!defined('ABSPATH')) exit;
|
|
|
|
|
|
use MailPoet\Config\Env;
|
|
use MailPoet\DI\ContainerWrapper;
|
|
use MailPoetVendor\Doctrine\DBAL\Connection;
|
|
use MailPoetVendor\Doctrine\DBAL\Exception;
|
|
use MailPoetVendor\Doctrine\ORM\EntityManager;
|
|
|
|
abstract class DbMigration {
|
|
/** @var Connection */
|
|
protected $connection;
|
|
|
|
/** @var EntityManager */
|
|
private $entityManager;
|
|
|
|
public function __construct(
|
|
ContainerWrapper $container
|
|
) {
|
|
$this->connection = $container->get(Connection::class);
|
|
$this->entityManager = $container->get(EntityManager::class);
|
|
}
|
|
|
|
abstract public function run(): void;
|
|
|
|
/**
|
|
* @param class-string<object> $entityClass
|
|
*/
|
|
protected function getTableName(string $entityClass): string {
|
|
return $this->entityManager->getClassMetadata($entityClass)->getTableName();
|
|
}
|
|
|
|
protected function createTable(string $tableName, array $attributes): void {
|
|
$prefix = Env::$dbPrefix;
|
|
$charsetCollate = Env::$dbCharsetCollate;
|
|
$sql = implode(",\n", $attributes);
|
|
$this->connection->executeStatement("
|
|
CREATE TABLE IF NOT EXISTS {$prefix}{$tableName} (
|
|
$sql
|
|
) {$charsetCollate};
|
|
");
|
|
}
|
|
|
|
protected function columnExists(string $tableName, string $columnName): bool {
|
|
global $wpdb;
|
|
$suppressErrors = $wpdb->suppress_errors();
|
|
try {
|
|
$this->connection->executeStatement("SELECT $columnName FROM $tableName LIMIT 0");
|
|
return true;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
} finally {
|
|
$wpdb->suppress_errors($suppressErrors);
|
|
}
|
|
}
|
|
|
|
protected function tableExists(string $tableName): bool {
|
|
global $wpdb;
|
|
$suppressErrors = $wpdb->suppress_errors();
|
|
try {
|
|
$this->connection->executeStatement("SELECT 1 FROM $tableName LIMIT 0");
|
|
return true;
|
|
} catch (Exception $e) {
|
|
return false;
|
|
} finally {
|
|
$wpdb->suppress_errors($suppressErrors);
|
|
}
|
|
}
|
|
|
|
protected function indexExists(string $tableName, string $indexName): bool {
|
|
global $wpdb;
|
|
$suppressErrors = $wpdb->suppress_errors();
|
|
try {
|
|
$this->connection->executeStatement("ALTER TABLE $tableName ADD INDEX $indexName (__non__existent__column__name__)");
|
|
} catch (Exception $e) {
|
|
// Index creating index failed on not existing column we use a fallback. This can happen on MySQL 5.7 and lower and on some MariaDB versions.
|
|
if ($e->getCode() === 1072) {
|
|
$database = $wpdb->dbname;
|
|
$result = $wpdb->get_var($wpdb->prepare(
|
|
"SELECT count(*)
|
|
FROM information_schema.statistics
|
|
WHERE table_schema = COALESCE(DATABASE(), %s)
|
|
AND table_name = %s
|
|
AND index_name = %s",
|
|
$database,
|
|
$tableName,
|
|
$indexName
|
|
));
|
|
|
|
return $result > 0;
|
|
}
|
|
// Index exists when the error message contains its name. Otherwise, it's the non-existent column error.
|
|
return strpos($e->getMessage(), $indexName) !== false;
|
|
} finally {
|
|
$wpdb->suppress_errors($suppressErrors);
|
|
}
|
|
return false;
|
|
}
|
|
}
|