Spaces:
No application file
No application file
namespace Mautic\CoreBundle\Doctrine; | |
use Doctrine\DBAL\Schema\Schema; | |
use Doctrine\Migrations\AbstractMigration; | |
use Doctrine\Migrations\Exception\AbortMigration; | |
use Symfony\Component\DependencyInjection\ContainerAwareInterface; | |
use Symfony\Component\DependencyInjection\ContainerInterface; | |
abstract class AbstractMauticMigration extends AbstractMigration implements ContainerAwareInterface | |
{ | |
/** | |
* @var ContainerInterface | |
*/ | |
protected $container; | |
/** | |
* Supported platforms. | |
* | |
* @var array | |
*/ | |
protected $supported = ['mysql']; | |
/** | |
* Database prefix. | |
* | |
* @var string | |
*/ | |
protected $prefix; | |
/** | |
* Database platform. | |
* | |
* @var string | |
*/ | |
protected $platform; | |
/** | |
* @throws \Doctrine\DBAL\Exception | |
* @throws AbortMigration | |
*/ | |
public function up(Schema $schema): void | |
{ | |
$platform = DatabasePlatform::getDatabasePlatform($this->connection->getDatabasePlatform()); | |
// Abort the migration if the platform is unsupported | |
$this->abortIf(!in_array($platform, $this->supported), 'The database platform is unsupported for migrations'); | |
$function = $this->platform.'Up'; | |
if (method_exists($this, $function)) { | |
$this->$function($schema); | |
} | |
} | |
/** | |
* @throws AbortMigration | |
*/ | |
public function down(Schema $schema): void | |
{ | |
// Not supported | |
} | |
/** | |
* @throws \Doctrine\DBAL\Exception | |
*/ | |
public function setContainer(ContainerInterface $container = null): void | |
{ | |
$this->container = $container; | |
$this->prefix = $container->getParameter('mautic.db_table_prefix'); | |
$this->platform = DatabasePlatform::getDatabasePlatform($this->connection->getDatabasePlatform()); | |
} | |
/** | |
* Finds/creates the local name for constraints and indexes. | |
* | |
* @return string | |
*/ | |
protected function findPropertyName($table, $type, $suffix) | |
{ | |
static $schemaManager; | |
static $tables = []; | |
if (empty($schemaManager)) { | |
$schemaManager = $this->connection->createSchemaManager(); | |
} | |
// Prepend prefix | |
$table = $this->prefix.$table; | |
if (!array_key_exists($table, $tables)) { | |
$tables[$table] = []; | |
} | |
$type = strtolower($type); | |
$suffix = strtolower(substr($suffix, -4)); | |
switch ($type) { | |
case 'fk': | |
if (!array_key_exists('fk', $tables[$table])) { | |
$keys = $schemaManager->listTableForeignKeys($table); | |
/** @var \Doctrine\DBAL\Schema\ForeignKeyConstraint $k */ | |
foreach ($keys as $k) { | |
$name = strtolower($k->getName()); | |
$key = substr($name, -4); | |
$tables[$table]['fk'][$key] = $name; | |
} | |
} | |
$localName = $tables[$table]['fk'][$suffix]; | |
break; | |
case 'idx': | |
case 'uniq': | |
if (!array_key_exists('idx', $tables[$table])) { | |
$tables[$table]['idx'] = [ | |
'idx' => [], | |
'uniq' => [], | |
]; | |
$indexes = $schemaManager->listTableIndexes($table); | |
/** @var \Doctrine\DBAL\Schema\Index $i */ | |
foreach ($indexes as $i) { | |
$name = strtolower($i->getName()); | |
$isIdx = stripos($name, 'idx'); | |
$isUniq = stripos($name, 'uniq'); | |
if (false !== $isIdx || false !== $isUniq) { | |
$key = substr($name, -4); | |
$keyType = (false !== $isIdx) ? 'idx' : 'uniq'; | |
$tables[$table]['idx'][$keyType][$key] = $name; | |
} | |
} | |
} | |
$localName = $tables[$table]['idx'][$type][$suffix]; | |
break; | |
} | |
return strtoupper($localName); | |
} | |
/** | |
* Generate the name for the property. | |
* | |
* @return string | |
*/ | |
protected function generatePropertyName($table, $type, array $columnNames) | |
{ | |
$columnNames = array_merge([$this->prefix.$table], $columnNames); | |
$hash = implode( | |
'', | |
array_map( | |
fn ($column): string => dechex(crc32($column)), | |
$columnNames | |
) | |
); | |
return substr(strtoupper($type.'_'.$hash), 0, 63); | |
} | |
/** | |
* Generate index and foreign constraint. | |
* | |
* @return array [idx, fk] | |
*/ | |
protected function generateKeys($table, array $columnNames) | |
{ | |
return [ | |
$this->generatePropertyName($table, 'idx', $columnNames), | |
$this->generatePropertyName($table, 'fk', $columnNames), | |
]; | |
} | |
/** | |
* Use this when you're doing a migration that | |
* purposely does not have any SQL statements, | |
* such as when moving data using the query builder. | |
*/ | |
protected function suppressNoSQLStatementError() | |
{ | |
$this->addSql('SELECT "This migration did not generate select statements." AS purpose'); | |
} | |
} | |