protected function compileCommands()
{
$drop = array();
$create = array();
$return = array();
$sql_current = $this->getFromDb();
$sql_target = $this->getFromDca();
$sql_legacy = $this->getFromFile();
// Manually merge the legacy definitions (see #4766)
if (!empty($sql_legacy)) {
foreach ($sql_legacy as $table => $categories) {
foreach ($categories as $category => $fields) {
if (is_array($fields)) {
foreach ($fields as $name => $sql) {
$sql_target[$table][$category][$name] = $sql;
}
} else {
$sql_target[$table][$category] = $fields;
}
}
}
}
// Create tables
foreach (array_diff(array_keys($sql_target), array_keys($sql_current)) as $table) {
$return['CREATE'][] = "CREATE TABLE `" . $table . "` (\n " . implode(",\n ", $sql_target[$table]['TABLE_FIELDS']) . (!empty($sql_target[$table]['TABLE_CREATE_DEFINITIONS']) ? ',' . "\n " . implode(",\n ", $sql_target[$table]['TABLE_CREATE_DEFINITIONS']) : '') . "\n)" . $sql_target[$table]['TABLE_OPTIONS'] . ';';
$create[] = $table;
}
// Add or change fields
foreach ($sql_target as $k => $v) {
if (in_array($k, $create)) {
continue;
}
// Fields
if (is_array($v['TABLE_FIELDS'])) {
foreach ($v['TABLE_FIELDS'] as $kk => $vv) {
if (!isset($sql_current[$k]['TABLE_FIELDS'][$kk])) {
$return['ALTER_ADD'][] = 'ALTER TABLE `' . $k . '` ADD ' . $vv . ';';
} elseif ($sql_current[$k]['TABLE_FIELDS'][$kk] != $vv && $sql_current[$k]['TABLE_FIELDS'][$kk] != str_replace(' COLLATE ' . \Config::get('dbCollation'), '', $vv)) {
$return['ALTER_CHANGE'][] = 'ALTER TABLE `' . $k . '` CHANGE `' . $kk . '` ' . $vv . ';';
}
}
}
// Create definitions
if (is_array($v['TABLE_CREATE_DEFINITIONS'])) {
foreach ($v['TABLE_CREATE_DEFINITIONS'] as $kk => $vv) {
if (!isset($sql_current[$k]['TABLE_CREATE_DEFINITIONS'][$kk])) {
$return['ALTER_ADD'][] = 'ALTER TABLE `' . $k . '` ADD ' . $vv . ';';
} elseif ($sql_current[$k]['TABLE_CREATE_DEFINITIONS'][$kk] != str_replace('FULLTEXT ', '', $vv)) {
$return['ALTER_CHANGE'][] = 'ALTER TABLE `' . $k . '` DROP INDEX `' . $kk . '`, ADD ' . $vv . ';';
}
}
}
// Move auto_increment fields to the end of the array
if (is_array($return['ALTER_ADD'])) {
foreach (preg_grep('/auto_increment/i', $return['ALTER_ADD']) as $kk => $vv) {
unset($return['ALTER_ADD'][$kk]);
$return['ALTER_ADD'][$kk] = $vv;
}
}
if (is_array($return['ALTER_CHANGE'])) {
foreach (preg_grep('/auto_increment/i', $return['ALTER_CHANGE']) as $kk => $vv) {
unset($return['ALTER_CHANGE'][$kk]);
$return['ALTER_CHANGE'][$kk] = $vv;
}
}
}
// Drop tables
foreach (array_diff(array_keys($sql_current), array_keys($sql_target)) as $table) {
$return['DROP'][] = 'DROP TABLE `' . $table . '`;';
$drop[] = $table;
}
// Drop fields
foreach ($sql_current as $k => $v) {
if (!in_array($k, $drop)) {
// Create definitions
if (is_array($v['TABLE_CREATE_DEFINITIONS'])) {
foreach ($v['TABLE_CREATE_DEFINITIONS'] as $kk => $vv) {
if (!isset($sql_target[$k]['TABLE_CREATE_DEFINITIONS'][$kk])) {
$return['ALTER_DROP'][] = 'ALTER TABLE `' . $k . '` DROP INDEX `' . $kk . '`;';
}
}
}
// Fields
if (is_array($v['TABLE_FIELDS'])) {
foreach ($v['TABLE_FIELDS'] as $kk => $vv) {
if (!isset($sql_target[$k]['TABLE_FIELDS'][$kk])) {
$return['ALTER_DROP'][] = 'ALTER TABLE `' . $k . '` DROP `' . $kk . '`;';
}
}
}
}
}
// HOOK: allow third-party developers to modify the array (see #3281)
if (isset($GLOBALS['TL_HOOKS']['sqlCompileCommands']) && is_array($GLOBALS['TL_HOOKS']['sqlCompileCommands'])) {
foreach ($GLOBALS['TL_HOOKS']['sqlCompileCommands'] as $callback) {
$this->import($callback[0]);
$return = $this->{$callback[0]}->{$callback[1]}($return);
}
}
return $return;
}