drupal/core/scripts/migrate-dump-d6.sh

204 lines
6.6 KiB
Bash
Executable File

#!/usr/bin/env php
<?php
/**
* This script is designed for assisting core developers working on Migrate to
* regenerate the Migrate dump files. Technically this script can be used to
* dump any database into a PHP representation however that is not its primary
* use case.
*
* Dump files only need to be updated when you're adding or updating tests which
* need new Drupal 6 data.
*
* - Clone the repository from: https://www.drupal.org/sandbox/benjy/2405029
* - Create a database called d6_migrate and import core/migrate_drupal/src/Tests/d6/d6.gz
* - In drupal_6_migrate/sites/default, copy default.settings.php to settings.php and add an entry for the d6_migrate database, eg: $db_url = 'mysqli://username:password@localhost/d6_migrate';
* - Add an entry into your Drupal 8 settings file, eg: $databases['d6_migrate']['default'] = array ( // Credentials );
* - Use the Drupal 6 site to make data changes as needed (User ID 1 credentials are admin/admin).
* - Run ./core/scripts/migrate-dump-d6.sh to re-export the tables.
*/
use Doctrine\Common\Inflector\Inflector;
use Drupal\Core\Database\Database;
use Drupal\Component\Utility\Variable;
use Drupal\Core\DrupalKernel;
use Drupal\Core\Site\Settings;
use Symfony\Component\HttpFoundation\Request;
if (PHP_SAPI !== 'cli') {
return;
}
$autoloader = require __DIR__ . '/../../autoload.php';
require_once __DIR__ . '/../includes/bootstrap.inc';
$request = Request::createFromGlobals();
Settings::initialize(dirname(dirname(__DIR__)), DrupalKernel::findSitePath($request), $autoloader);
$output_folder = DRUPAL_ROOT . '/core/modules/migrate_drupal/src/Tests/Table/d6';
$class_template = '<?php
/**
* @file
* Contains \Drupal\migrate_drupal\Tests\Dump\{{CLASS_NAME}}.
*
* THIS IS A GENERATED FILE. DO NOT EDIT.
*
* @see cores/scripts/dump-database-d6.sh
* @see https://www.drupal.org/sandbox/benjy/2405029
*/
namespace Drupal\migrate_drupal\Tests\Table\d6;
use Drupal\migrate_drupal\Tests\Dump\DrupalDumpBase;
/**
* Generated file to represent the {{TABLE}} table.
*/
class {{CLASS_NAME}} extends DrupalDumpBase {
public function load() {
$this->createTable("{{TABLE}}", {{TABLE_DEFINITION}});
$this->database->insert("{{TABLE}}")->fields({{PHP_FIELDS}})
{{PHP_VALUES}}->execute();
}
}
';
// Generate a list of tables using the 'migrate' db connection.
$connection = Database::getConnection('default', 'd6_migrate');
$tables = $connection->query('SHOW TABLES')->fetchCol();
foreach ($tables as $table) {
if (substr($table, 0, 5) === 'cache' || $table === 'watchdog' || $table === 'menu_router' || $table === 'sessions') {
continue;
}
// Generate the class name.
$class = Inflector::classify($table);
// Order by primary keys
$order = '';
$query = "SELECT `COLUMN_NAME` FROM `information_schema`.`COLUMNS`
WHERE (`TABLE_SCHEMA` = 'd6_migrate') AND (`TABLE_NAME` = '{$table}') AND (`COLUMN_KEY` = 'PRI')
ORDER BY COLUMN_NAME";
$results = $connection->query($query);
while(($row = $results->fetchAssoc()) !== FALSE) {
$order .= '{' . $row['COLUMN_NAME'] . '}, ';
}
if (!(empty($order))) {
$order = rtrim ($order, ", ");
$order = ' ORDER BY ' . $order;
}
// Generate the field values.
$query = $connection->query(_db_get_query($table) . $order);
$values = '';
while(($row = $query->fetchAssoc()) !== FALSE) {
$values .= '->values(' . Variable::export($row, ' ') . ')';
}
// Generate the field names.
$query = $connection->query("SHOW COLUMNS FROM {$table}");
$definition = [];
while(($row = $query->fetchAssoc()) !== FALSE) {
$field_name = $row['Field'];
// Parse out the field type and meta information.
preg_match('@([a-z]+)(?:\((\d+)(?:,(\d+))?\))?\s*(unsigned)?@', $row['Type'], $matches);
$field_type = _db_field_type_map($matches[1]);
// If it's auto-increment then make it a serial instead.
if ($row['Extra'] === 'auto_increment') {
$field_type = 'serial';
}
// Add primary key entries as needed.
if ($row['Key'] === 'PRI') {
$definition['primary key'][] = $field_name;
}
// All fields have a type and not null.
$definition['fields'][$field_name] = [
'type' => $field_type,
'not null' => $row['Null'] === 'NO',
];
// If this is a numeric field, the meta will be precision and scale.
if (isset($matches[2]) && $field_type === 'numeric') {
$definition['fields'][$field_name]['precision'] = $matches[2];
$definition['fields'][$field_name]['scale'] = $matches[3];
}
elseif ($field_type === 'time' || $field_type === 'datetime') {
// We use varchar to replace the D6 datetime and time fields.
$definition['fields'][$field_name]['type'] = 'varchar';
$definition['fields'][$field_name]['length'] = '100';
}
else {
// Try use the provided length, if it doesn't exist default to 100. It's
// not great but good enough for our dumps at this point.
$definition['fields'][$field_name]['length'] = isset($matches[2]) ? $matches[2] : 100;
}
if (isset($row['Default'])) {
$definition['fields'][$field_name]['default'] = $row['Default'];
}
if (isset($matches[4])) {
$definition['fields'][$field_name]['unsigned'] = TRUE;
}
}
$fields = Variable::export(array_keys($definition['fields']), ' ');
$definition = Variable::export($definition, ' ');
// Do our substitutions.
$php = str_replace('{{TABLE}}', $table, $class_template);
$php = str_replace('{{CLASS_NAME}}', $class, $php);
$php = str_replace('{{PHP_VALUES}}', $values, $php);
$php = str_replace('{{PHP_FIELDS}}', $fields, $php);
$php = str_replace('{{TABLE_DEFINITION}}', $definition, $php);
// Save the file.
$php = implode("\n", array_map('rtrim', explode("\n", $php)));
file_put_contents("$output_folder/$class.php", $php);
}
function _db_field_type_map($sql_type) {
$map = array(
'longtext' => 'text',
'tinytext' => 'text',
'mediumtext' => 'text',
'tinyint' => 'int',
'smallint' => 'int',
'mediumint' => 'int',
'bigint' => 'int',
'int' => 'int',
'double' => 'numeric',
'float' => 'numeric',
'decimal' => 'numeric',
'longblob' => 'blob',
);
return isset($map[$sql_type]) ? $map[$sql_type] : $sql_type;
}
function _db_get_query($table) {
$queries = array(
'users' => 'SELECT * FROM {users} WHERE uid NOT IN (0,1)',
);
return isset($queries[$table]) ? $queries[$table] : 'SELECT * FROM {' . $table .'}';
}
$options = $connection->getConnectionOptions();
$user = $options['username'];
$pass = $options['password'];
$db = $options['database'];
@system("mysqldump -u$user -p$pass $db | gzip -c > core/modules/migrate_drupal/src/Tests/d6.gz");