Create a migration system to migrate database.

+ Use this system to migrate from 0.8 to 0.9 (WIP)
This commit is contained in:
Olivier PEREZ 2014-12-31 01:33:56 +01:00
parent ca00c4953c
commit 88cae82e71
7 changed files with 239 additions and 139 deletions

View File

@ -30,11 +30,23 @@ class FramaDB {
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
} }
function areTablesCreated() { /**
* @return \PDO Connection to database
*/
function getPDO() {
return $this->pdo;
}
/**
* Find all tables in database.
*
* @return array The array of table names
*/
function allTables() {
$result = $this->pdo->query('SHOW TABLES'); $result = $this->pdo->query('SHOW TABLES');
$schemas = $result->fetchAll(\PDO::FETCH_COLUMN); $schemas = $result->fetchAll(\PDO::FETCH_COLUMN);
return 0 != count(array_diff($schemas, ['comment', 'poll', 'slot', 'vote'])); return $schemas;
} }
function prepare($sql) { function prepare($sql) {

View File

@ -0,0 +1,144 @@
<?php
namespace Framadate\Migration;
/**
* This class executes the aciton in database to migrate data from version 0.8 to 0.9.
*
* @package Framadate\Migration
*/
class From_0_8_to_0_9_Migration implements Migration {
function __construct() {
}
function execute(\PDO $pdo) {
$this->createPollTable($pdo);
$this->migrateFromSondageToPoll($pdo);
$this->createSlotTable($pdo);
$this->migrateFromSujetStudsToSlot($pdo);
$this->createCommentTable($pdo);
$this->migrateFromCommentsToComment($pdo);
$this->createVoteTable($pdo);
$this->migrateFromUserStudsToVote($pdo);
return true;
}
private function createPollTable(\PDO $pdo) {
$pdo->exec('
CREATE TABLE IF NOT EXISTS `poll` (
`id` CHAR(16) NOT NULL,
`admin_id` CHAR(24) NOT NULL,
`title` TEXT NOT NULL,
`description` TEXT,
`admin_name` VARCHAR(64) DEFAULT NULL,
`admin_mail` VARCHAR(128) DEFAULT NULL,
`creation_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`end_date` TIMESTAMP NOT NULL DEFAULT \'0000-00-00 00:00:00\',
`format` VARCHAR(1) DEFAULT NULL,
`editable` TINYINT(1) DEFAULT \'0\',
`receiveNewVotes` TINYINT(1) DEFAULT \'0\',
`active` TINYINT(1) DEFAULT \'1\',
PRIMARY KEY (`id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8');
}
private function migrateFromSondageToPoll(\PDO $pdo) {
$pdo->exec('
INSERT INTO `poll`
(`id`, `admin_id`, `title`, `description`, `admin_name`, `admin_mail`, `creation_date`, `end_date`, `format`, `editable`, `receiveNewVotes`, `active`)
SELECT
`id_sondage`,
`id_sondage_admin`,
`titre`,
`commentaires`,
`nom_admin`,
`mail_admin`,
`date_creation`,
`date_fin`,
SUBSTR(`format`, 1, 1) AS `format`,
CASE SUBSTR(`format`, 2, 1)
WHEN \'+\' THEN 1
ELSE 0 END AS `editable`,
`mailsonde`,
CASE SUBSTR(`format`, 2, 1)
WHEN \'-\' THEN 0
ELSE 1 END AS `active`
FROM sondage');
}
private function createSlotTable(\PDO $pdo) {
$pdo->exec('
CREATE TABLE IF NOT EXISTS `slot` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`poll_id` CHAR(16) NOT NULL,
`title` TEXT,
`moments` TEXT,
PRIMARY KEY (`id`),
KEY `poll_id` (`poll_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8');
}
private function migrateFromSujetStudsToSlot(\PDO $pdo) {
// TODO Implements
}
private function createCommentTable(\PDO $pdo) {
$pdo->exec('
CREATE TABLE IF NOT EXISTS `comment` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`poll_id` CHAR(16) NOT NULL,
`name` TEXT,
`comment` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `poll_id` (`poll_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8');
}
private function migrateFromCommentsToComment(\PDO $pdo) {
$pdo->exec('
INSERT INTO `comment`
(`poll_id`, `name`, `comment`)
SELECT
`id_sondage`,
`usercomment`,
`comment`
FROM `comments`');
}
private function createVoteTable(\PDO $pdo) {
$pdo->exec('
CREATE TABLE IF NOT EXISTS `vote` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`poll_id` CHAR(16) NOT NULL,
`name` VARCHAR(64) NOT NULL,
`choices` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `poll_id` (`poll_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8');
}
private function migrateFromUserStudsToVote(\PDO $pdo) {
$pdo->exec('
INSERT INTO `vote`
(`poll_id`, `name`, `choices`)
SELECT
`id_sondage`,
`nom`,
REPLACE(REPLACE(REPLACE(`reponses`, 1, \'X\'), 2, 1), \'X\', 2)
FROM `user_studs`');
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace Framadate\Migration;
interface Migration {
/**
* This methode is called only one time in the migration page.
*
* @param \PDO $pdo The connection to database
* @return bool true is the execution succeeded
*/
function execute(\PDO $pdo);
}

View File

@ -41,6 +41,9 @@ const DB_PASSWORD = '<database password>';
// Database server name, leave empty to use a socket // Database server name, leave empty to use a socket
const DB_CONNECTION_STRING = 'mysql:host=<database host>;dbname=<database name>;port=<database port>'; const DB_CONNECTION_STRING = 'mysql:host=<database host>;dbname=<database name>;port=<database port>';
// Name of the table that store migration script already executed
const MIGRATION_TABLE = 'framadate_migration';
// Default Language using POSIX variant of BC P47 standard (choose in $ALLOWED_LANGUAGES) // Default Language using POSIX variant of BC P47 standard (choose in $ALLOWED_LANGUAGES)
const LANGUE = 'fr_FR'; const LANGUE = 'fr_FR';

View File

@ -45,7 +45,9 @@ function bandeau_titre($titre)
<main role="main">'; <main role="main">';
global $connect; global $connect;
if ($connect->areTablesCreated()) { $tables = $connect->allTables();
$diff = array_diff($tables, ['comment', 'poll', 'slot', 'vote']);
if (0 != count($diff)) {
echo '<div class="alert alert-danger">'. _('Framadate is not properly installed, please check the "INSTALL" to setup the database before continuing.') .'</div>'; echo '<div class="alert alert-danger">'. _('Framadate is not properly installed, please check the "INSTALL" to setup the database before continuing.') .'</div>';
bandeau_pied(); bandeau_pied();
die(); die();

View File

@ -1,136 +0,0 @@
-- --------------------------------------------------------
--
-- Table structure `poll`
--
CREATE TABLE IF NOT EXISTS `poll` (
`id` CHAR(16) NOT NULL,
`admin_id` CHAR(24) NOT NULL,
`title` TEXT NOT NULL,
`description` TEXT,
`admin_name` VARCHAR(64) DEFAULT NULL,
`admin_mail` VARCHAR(128) DEFAULT NULL,
`creation_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`end_date` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
`format` VARCHAR(1) DEFAULT NULL,
`editable` TINYINT(1) DEFAULT '0',
`receiveNewVotes` TINYINT(1) DEFAULT '0',
`active` TINYINT(1) DEFAULT '1',
PRIMARY KEY (`id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- --------------------------------------------------------
--
-- Table structure `slot`
--
CREATE TABLE IF NOT EXISTS `slot` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`poll_id` CHAR(16) NOT NULL,
`title` TEXT,
`moments` TEXT,
PRIMARY KEY (`id`),
KEY `poll_id` (`poll_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- --------------------------------------------------------
--
-- Table structure `comment`
--
CREATE TABLE IF NOT EXISTS `comment` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`poll_id` CHAR(16) NOT NULL,
`name` TEXT,
`comment` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `poll_id` (`poll_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- --------------------------------------------------------
--
-- Table structure `vote`
--
CREATE TABLE IF NOT EXISTS `vote` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`poll_id` CHAR(16) NOT NULL,
`name` VARCHAR(64) NOT NULL,
`choices` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `poll_id` (`poll_id`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- --------------------------------------------------------
--
-- Migrate data from `sondage` to `poll`
--
INSERT INTO `poll`
(`id`, `admin_id`, `title`, `description`, `admin_name`, `admin_mail`, `creation_date`, `end_date`, `format`, `editable`, `receiveNewVotes`, `active`)
SELECT
`id_sondage`,
`id_sondage_admin`,
`titre`,
`commentaires`,
`nom_admin`,
`mail_admin`,
`titre`,
`date_creation`,
`date_fin`,
SUBSTR(`format`, 1, 1) AS `format`,
CASE SUBSTR(`format`, 2, 1)
WHEN '+' THEN 1
ELSE 0 END AS `editable`,
`mailsonde`,
CASE SUBSTR(`format`, 2, 1)
WHEN '-' THEN 0
ELSE 1 END AS `active`
FROM sondage;
-- --------------------------------------------------------
--
-- Migrate data from `sujet_studs` to `slot`
--
-- TODO Migrate this, is not so simple
/*INSERT INTO `slot`
(`poll_id`, `title`, `moments`)
SELECT `id_sondage`,
FROM `user_studs`;*/
-- --------------------------------------------------------
--
-- Migrate data from `comments` to `comment`
--
INSERT INTO `comment`
(`poll_id`, `name`, `comment`)
SELECT `id_sondage`, `usercomment`, `comment`
FROM `comments`;
-- --------------------------------------------------------
--
-- Migrate data from `user_studs` to `vote`
--
INSERT INTO `vote`
(`poll_id`, `name`, `choices`)
SELECT `id_sondage`, `nom`, REPLACE(REPLACE(REPLACE(`reponses`, '1', 'X'), '2', '1'), 'X', 2)
FROM `user_studs`;

60
migration.php Normal file
View File

@ -0,0 +1,60 @@
<?php
use Framadate\Migration\From_0_8_to_0_9_Migration;
use Framadate\Migration\Migration;
use Framadate\Utils;
include_once __DIR__ . '/app/inc/init.php';
function output($msg) {
echo $msg . '<br/>';
}
// List a Migration sub classes to execute
$migrations = [
new From_0_8_to_0_9_Migration(),
new From_0_8_to_0_9_Migration()
];
// Check if MIGRATION_TABLE already exists
$tables = $connect->allTables();
$pdo = $connect->getPDO();
if (!in_array(MIGRATION_TABLE, $tables)) {
$pdo->exec('
CREATE TABLE IF NOT EXISTS `' . MIGRATION_TABLE . '` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` TEXT NOT NULL,
`execute_date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
)
ENGINE = MyISAM
DEFAULT CHARSET = utf8;');
output('Table ' . MIGRATION_TABLE . ' created.');
}
$selectStmt = $pdo->prepare('SELECT id FROM ' . MIGRATION_TABLE . ' WHERE name=?');
$insertStmt = $pdo->prepare('INSERT INTO ' . MIGRATION_TABLE . ' (name) VALUES (?)');
// Loop on every Migration sub classes
foreach ($migrations as $migration) {
$className = get_class($migration);
// Check if $className is a Migration sub class
if (!$migration instanceof Migration) {
output('The class '. $className . ' is not a sub class of Framadate\\Migration\\Migration.');
exit;
}
// Check if the Migration is already executed
$selectStmt->execute([$className]);
$executed = $selectStmt->rowCount();
$selectStmt->closeCursor();
if (!$executed) {
$migration->execute($pdo);
$insertStmt->execute([$className]);
output('Migration done: ' . $className);
}
}