Added basis of migration framework

skala
Yannick Warnier 13 years ago
parent 1c8ec45f00
commit e73b91558b
  1. 48
      tests/migrate/config.dist.php
  2. 49
      tests/migrate/db_matches.dist.php
  3. 32
      tests/migrate/migrate.php
  4. 96
      tests/migrate/migration.class.php
  5. 47
      tests/migrate/migration.custom.class.php
  6. 35
      tests/migrate/migration.mssql.class.php

@ -0,0 +1,48 @@
<?php
/**
* This is the configuration file allowing you to connect to the origin
* database. You should either fill this one in or generate your own
* copy as config.php
*/
/**
* Define all connection variables
*/
/*
* The database type allows you to define with database driver to use.
* Currently allowed values are: mssql. Defaults to: mssql
*/
$db_type = 'mssql';
/*
* The database host is the name of the server on which the origin
* database is located. This name should be routeable by PHP.
* Defaults to: localhost
*/
$db_host = 'localhost';
/*
* The database port is the port on which to connect on the origin
* database host. The default port for MS-SQL is 1433, which we
* use as a default port here. Defaults to: 1433
*/
$db_port = '1433';
/*
* The database user is the name under which to connect to the
* origin database server. Defaults to: lms
*/
$db_user = 'lms';
/*
* The database password is the password for the user on the origin
* database server. Defaults to: password
*/
$db_pass = 'password';
/*
* The database name on the database origin server.
* Defaults to: master
*/
$db_name = 'master';
/**
* Load the real configuration file (except if we're already in config.php)
*/
if ((basename(__FILE__) != 'config.php') && is_file('config.php')) {
include 'config.php';
}

@ -0,0 +1,49 @@
<?php
/**
* This script defines as closely as possible the matches between
* original tables and destination (chamilo) tables and fields.
*/
// This is an array that matches objects (for Chamilo)
$matches = array(
/* We need a numerical index for each table for easier reference later.
The same origin table can be defined several time if it has fields that
go into different destination tables */
0 => array (
/* Original table */
'orig_table' => 'Alumno',
/* Destination table. Leave empty if you just want to scan the
original table to build up migration data.
*/
'dest_table' => '',
/* Function to insert in dest table */
'dest_func' => 'MigrationCustom::store_user_data1',
/* List of fields */
'fields_match' => array(
/* Each field has a numerical ID for later processing */
0 => array(
/* Original field name */
'orig' => 'intIdAlumno',
/* If the SQL select has to alter the data before getting it in PHP,
define the method that will return the right SQL select part
*/
'sql_alter' => 'sql_alter_unhash_50',
/* Destination field name - leave empty
and manage in func for complex operations */
'dest' => 'user_id',
/* The special method that will be called from
migration.custom.class.php when dealing with this particular field.
Use 'none' if the field can be transferred "as is"
If the original ID will not be re-used as is but will be required
for the relationships with other tables, you should define a method
that will log the relationship in a specific array.
*/
'func' => 'none',
),
1 => array(
'orig' => 'chrUsuarioCreacion',
'dest' => 'creation_date',
'func' => 'none',
),
)
)
);

@ -0,0 +1,32 @@
<?php
/**
* Load required classes
*/
require_once '../../main/inc/global.inc.php';
require_once 'config.dist.php';
if (is_file(dirname(__FILE__).'/migration.custom.class.php')) {
require_once 'migration.custom.class.php';
} else {
die ("You need to define a custom migration class as migration.custom.class.php\n(copy it from migration.custom.class.dist.php, otherwise this migration process\n will not know what to do with the original database fields\n");
}
require_once 'migration.class.php';
if (empty($db_type)) {
die("This script requires a DB type to work. Please update orig_db_conn.inc.php\n");
}
$file = dirname(__FILE__).'/migration.'.$db_type.'.class.php';
if (!is_file($file)) {
die("Could not find db type file ".$file."\n");
}
require_once $file;
$class = 'Migration'.strtoupper($db_type);
$m = new $class($db_host,$db_port,$db_user,$db_pass,$db_name);
$m->connect();
/**
* Prepare the arrays of matches that will allow for the migration
*/
$migrate = array();
include 'db_matches.php';
$m->migrate($matches);
print_r($m->errors_stack);
echo "OK so far\n";

@ -0,0 +1,96 @@
<?php
/**
* Migration class (ease the migration work)
*/
class Migration {
public $odbtype = '';
public $odbhost = '';
public $odbport = '';
public $odbuser = '';
public $odbpass = '';
public $odbname = '';
public $errors_stack = array();
public $origin_tables = array();
public $destination_tables = array();
public $relationship_tables = array();
public $odbrows = null;
/**
*
*/
public function __construct($dbhost, $dbport, $dbuser, $dbpass, $dbname) {
if (empty($dbhost) || empty($dbport) || empty($dbuser) || empty ($dbpass) || empty($dbname)) {
$this->errors_stack[] = 'All origin database params must be given. Received '.print_r(func_get_args(),1);
return false;
}
$this->odbtype = $dbtype;
$this->odbhost = $dbhost;
$this->odbport = $dbport;
$this->odbuser = $dbuser;
$this->odbpass = $dbpass;
$this->odbname = $dbname;
}
/**
*
*/
public function connect() {
//extend in child class
}
/**
*
*/
public function migrate($matches) {
$found = false;
$table_idx = -1;
foreach ($matches as $id => $table) {
error_log('Found table '.$table['orig_table']);
$build_only = false;
if (empty($table['dest_table'])) {
error_log(' ...which is just for data building');
$build_only = true;
}
// Process the migration of fields from the given table
$sql_select_fields = array();
foreach ($table['fields_match'] as $id_field => $details) {
if (empty($details['orig'])) {
//Ignore if the field declared in $matches doesn't exist in
// the original database
continue;
}
$sql_select_fields[$details['orig']] = $details['orig'];
// If there is something to alter in the SQL query, rewrite the entry
if (!empty($details['sql_alter'])) {
$func_alter = $details['sql_alter'];
$sql_select_fields[$details['orig']] = MigrationCustom::$func_alter($details['orig']);
}
error_log(' Found field '.$details['orig'].' to be selected as '.$sql_select_fields[$details['orig']]);
}
$this->select_all($table['orig_table'], $sql_select_fields);
if (count($table['fields_match']) == 0) {
error_log('No fields found');
continue;
}
while ($row = $this->fetch_row()) {
$dest_row = array();
$first_field = '';
foreach ($table['fields_match'] as $id_field => $details) {
if ($id_field == 0) { $first_field = $details['dest']; }
// process the fields one by one
if ($details['func'] == 'none') {
$dest_data = $row[$details['orig']];
} else {
$dest_data = MigrationCustom::$details['func']($row[$details['orig']]);
}
$dest_row[$details['dest']] = $dest_data;
}
if (!empty($table['dest_func'])) {
error_log('Calling MigrationCustom::'.$table['dest_func'].' on data recovered: '.print_r($dest_row,1));
//$table['dest_func']($dest_row);
} else {
$this->errors_stack[] = "No destination data dest_func found. Abandoning data with first field $first_field = ".$dest_row[$first_field];
}
}
error_log('Finished processing table '.$table['orig_table']);
}
die();
}
}

@ -0,0 +1,47 @@
<?php
/**
* This file contains the MigrationCustom class, which defines methods to
* alter the data from the original database when importing it to the Chamilo
* database
*/
/**
* The custom migration class allows you to define rules to process data
* during the migration
*/
class MigrationCustom {
/**
* The only required method is the 'none' method, which will not trigger
* any process at all
* @param mixed Data
* @param mixed Unaltered data
*/
public function none($data) {
return $data;
}
/**
* Transform the uid identifiers from MSSQL to a string
* @param string Field name
* @return string SQL select string to include in the final select
*/
public function sql_alter_unhash_50($field) {
return 'cast('.$field.' as varchar(50))';
}
/**
* Log data from the original users table
*/
public function log_original_user_unique_id(&$omigrate, $data) {
$omigrate['users'][$data] = 0;
}
/**
* Log data from the original users table
*/
public function log_original_course_unique_id(&$omigrate, $data) {
$omigrate['courses'][$data] = 0;
}
/**
* Log data from the original users table
*/
public function log_original_session_unique_id(&$omigrate, $data) {
$omigrate['sessions'][$data] = 0;
}
}

@ -0,0 +1,35 @@
<?php
/**
*
*/
class MigrationMSSQL extends Migration {
public function __construct($dbhost, $dbport='1433', $dbuser, $dbpass, $dbname) {
parent::__construct($dbhost, $dbport, $dbuser, $dbpass, $dbname);
ini_set('display_errors',1);
ini_set('mssql.datetimeconvert',0);
$this->odbtype = 'mssql';
}
public function connect() {
$this->c = mssql_connect($this->odbhost,$this->odbuser,$this->odbpass,TRUE);
if ($this->c === false) {
$this->errors_stack[] = 'Could not connect. MSSQL error: '.mssql_get_last_message();
return false;
}
mssql_select_db($dbname,$this->c);
return true;
}
public function select_all($table, $fields) {
$fields_sql = '';
foreach ($fields as $field) {
$fields_sql .= $field.', ';
}
$fields_sql = substr($fields_sql,0,-2);
$sql = 'SELECT '.$fields_sql.' FROM '.$table;
//remove
error_log($sql);
$this->rows_iterator = mssql_query($sql,$this->c);
}
public function fetch_row() {
return mssql_fetch_row($this->rows_iterator);
}
}
Loading…
Cancel
Save