/** * Determines what action should be performed and takes that action. * * @uses MpmLatestController::displayHelp() * @uses MpmDbHelper::test() * @uses MpmMigrationHelper::getMigrationCount() * @uses MpmCommandLineWriter::getInstance() * @uses MpmMigrationHelper::getLatestMigration() * @uses MpmUpController::doAction() * * @param bool $quiet supresses certain text when true * * @return void */ public function doAction($quiet = false) { // make sure we're init'd MpmDbHelper::test(); // are we forcing this? $forced = ''; if (isset($this->arguments[0]) && strcasecmp($this->arguments[0], '--force') == 0) { $forced = '--force'; } try { $total_migrations = MpmMigrationHelper::getMigrationCount(); if ($total_migrations == 0) { $clw = MpmCommandLineWriter::getInstance(); $clw->addText('No migrations exist.'); $clw->write(); } else { $to_id = MpmMigrationHelper::getLatestMigration(); $obj = new MpmUpController('up', array($to_id, $forced)); $obj->doAction($quiet); } } catch (Exception $e) { echo "\n\nERROR: " . $e->getMessage() . "\n\n"; exit; } }
/** * Object constructor. * * @uses MpmDbHelper::test() * @uses MpmListHelper::mergeFilesWithDb() * * @param array $arguments an array of command line arguments (minus the first two elements which should already be shifted off from the MpmControllerFactory) * * @return MpmController */ public function __construct($command = 'help', $arguments = array()) { $this->arguments = $arguments; $this->command = $command; if ($command != 'help' && $command != 'init') { MpmDbHelper::test(); MpmListHelper::mergeFilesWithDb(); } }
/** * Determines what action should be performed and takes that action. * * @uses MpmDbHelper::test() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::addText() * @uses MpmCommandLineWriter::write() * @uses MpmCommandLineWriter::writeHeader() * @uses MpmCommandLineWriter::writeFooter() * @uses MpmBuildController::build() * @uses MPM_DB_PATH * * @return void */ public function doAction() { // make sure system is init'ed MpmDbHelper::test(); $this->clw = MpmCommandLineWriter::getInstance(); $with_data = $forced = $dryrun = false; // are we adding a schema file? if (isset($this->arguments[0])) { if ($this->arguments[0] == 'add') { $this->add(); // stop here exit; } else { if ($this->arguments[0] == 'with_data') { $with_data = true; // remove the first 'with_data' array_shift($this->arguments); } } } // parse other optional arguments list($forced, $dryrun) = $this->parse_options($this->arguments); // make sure the schema file exists if (!file_exists(MPM_DB_PATH . 'schema.php')) { $this->clw->addText('The schema file does not exist. Run this command with the "add" argument to create one (only a stub).'); $this->clw->write(); exit; } // make sure the test data file exists if ($with_data == true && !file_exists(MPM_DB_PATH . 'test_data.php')) { $this->clw->addText('The test data file does not exist. Run this command with the "add" argument to create one (only a stub).'); $this->clw->write(); exit; } $this->clw->writeHeader(); if (!$forced && !$dryrun) { echo "\nWARNING: IF YOU CONTINUE, ALL TABLES IN YOUR DATABASE WILL BE ERASED!"; echo "\nDO YOU WANT TO CONTINUE? [y/N] "; $answer = fgets(STDIN); $answer = trim($answer); $answer = strtolower($answer); if (empty($answer) || substr($answer, 0, 1) == 'n') { echo "\nABORTED!\n\n"; $this->clw->writeFooter(); exit; } } echo "\n"; $this->build($with_data); $this->clw->writeFooter(); exit; }
/** * Determines what action should be performed and takes that action. * * @uses MpmRunController::displayHelp() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::addText() * @uses MpmCommandLineWriter::write() * @uses MpmCommandLineWriter::writeHeader() * @uses MpmCommandLineWriter::writeFooter() * @uses MpmMigrationHelper::doesMigrationExist() * @uses MpmMigrationHelper::getMigrationObject() * @uses MpmMigrationHelper::runMigration() * * @return void */ public function doAction() { // make sure system is init'ed MpmDbHelper::test(); if (count($this->arguments) != 2) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('ERROR: You must provide two arguments with this command.'); $obj->addText(' '); $this->displayHelp(); return; } // are we running the up or the down? $type = strtolower($this->arguments[0]); // what number do we want to run? $num = $this->arguments[1]; if (!is_numeric($num)) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('ERROR: Migration number must be numeric.'); $obj->addText(' '); $this->displayHelp(); return; } if ($type != 'up' && $type != 'down') { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('ERROR: Method must be either up or down.'); $obj->addText(' '); $this->displayHelp(); return; } // does this migration number exist? if (!MpmMigrationHelper::doesMigrationExist($num)) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('ERROR: Migration ' . $num . ' does not exist.'); $obj->write(); return; } $row = MpmMigrationHelper::getMigrationObject($num); $obj = MpmCommandLineWriter::getInstance(); $obj->writeHeader(); MpmMigrationHelper::runMigration($row, $type); echo "\n"; $obj->writeFooter(); }
/** * Returns the requested template file as a string * * @uses MPM_PATH * * @param string $file the filename of the template being requested * @param array $vars an array of key value pairs that correspond to variables that should be replaced in the template file * * @return string */ public static function getTemplate($file, $vars = array()) { // don't raise exception $db_config = MpmDbHelper::get_db_config(false); if (!$db_config) { $db_config = new stdClass(); $db_config->db_path = MPM_PATH . '/lib/templates/'; } // has the file been customized? if (file_exists($db_config->db_path . 'templates/' . $file)) { $contents = file_get_contents($db_config->db_path . 'templates/' . $file); } else { $contents = file_get_contents(MPM_PATH . '/lib/templates/' . $file); } foreach ($vars as $key => $val) { $contents = str_replace('@@' . $key . '@@', $val, $contents); } return $contents; }
/** * Determines what action should be performed and takes that action. * * @uses MPM_DB_PATH * @uses MpmDbHelper::test() * @uses MpmListHelper::getFiles() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::addText() * @uses MpmCommandLineWriter::write() * @uses MpmDbHelper::getMethod() * @uses MpmUpController::displayHelp() * * @return void */ public function doAction() { // make sure system is init'ed MpmDbHelper::test(); // get date stamp for use in generating filename $date_stamp = date('Y_m_d_H_i_s'); $filename = $date_stamp . '.php'; $vars = array('timestamp' => $date_stamp); //$classname = 'Migration_' . $date_stamp; // get list of files $files = MpmListHelper::getFiles(); // if filename is taken, throw error if (in_array($filename, $files)) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to obtain a unique filename for your migration. Please try again in a few seconds.'); $obj->write(); } // create file if (MpmDbHelper::getMethod() == MPM_METHOD_PDO) { $file = MpmTemplateHelper::getTemplate('pdo_migration.txt', $vars); } else { $file = MpmTemplateHelper::getTemplate('mysqli_migration.txt', $vars); } // write the file $fp = fopen(MPM_DB_PATH . $filename, "w"); if ($fp == false) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to write new migration file.'); $obj->write(); } $success = fwrite($fp, $file); if ($success == false) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to write new migration file.'); $obj->write(); } fclose($fp); // display success message $obj = MpmCommandLineWriter::getInstance(); $obj->addText('New migration created: file /db/' . $filename); $obj->write(); }
/** * Determines what action should be performed and takes that action. * * @uses MpmLatestController::displayHelp() * @uses MpmDbHelper::test() * @uses MpmMigrationHelper::getMigrationCount() * @uses MpmCommandLineWriter::getInstance() * @uses MpmMigrationHelper::getLatestMigration() * @uses MpmUpController::doAction() * * @param bool $quiet supresses certain text when true * * @return void */ public function doAction($quiet = false) { // make sure we're init'd MpmDbHelper::test(); try { $total_migrations = MpmMigrationHelper::getMigrationCount(); if ($total_migrations == 0) { $clw = MpmCommandLineWriter::getInstance(); $clw->addText('No migrations exist.'); $clw->write(); } else { $to_id = MpmMigrationHelper::getLatestMigration(); $obj = new MpmUpController('up', array_merge(array($to_id), $this->arguments)); $obj->doAction($quiet); } } catch (Exception $e) { echo "\n\nERROR: " . $e->getMessage() . "\n\n"; exit; } }
/** * Determines what action should be performed and takes that action. * * @uses MpmDbHelper::test() * @uses MpmMigrationHelper::getCurrentMigrationTimestamp() * @uses MpmMigrationHelper::getCurrentMigrationNumber() * @uses MpmListHelper::getFullList() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::writeHeader() * @uses MpmCommandLineWriter::writeFooter() * * @return void */ public function doAction() { // make sure we're init'd MpmDbHelper::test(); // get latest timestamp $latest = MpmMigrationHelper::getCurrentMigrationTimestamp(); // get latest number $num = MpmMigrationHelper::getCurrentMigrationNumber(); // get list of migrations $list = MpmListHelper::getFullList(); // get command line writer $clw = MpmCommandLineWriter::getInstance(); $clw->writeHeader(); if (empty($latest)) { echo "You have not performed any migrations yet."; } else { echo "You are currently on migration {$num} -- " . $latest . '.'; } echo "\n"; $clw->writeFooter(); }
/** * Determines what action should be performed and takes that action. * * @uses MpmDbHelper::test() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::addText() * @uses MpmCommandLineWriter::write() * @uses MpmCommandLineWriter::writeHeader() * @uses MpmCommandLineWriter::writeFooter() * @uses MpmBuildController::build() * @uses MPM_DB_PATH * * @return void */ public function doAction() { // make sure system is init'ed MpmDbHelper::test(); $clw = MpmCommandLineWriter::getInstance(); $forced = false; $with_data = false; // are we adding a schema file? if (isset($this->arguments[0]) && $this->arguments[0] == 'add') { // make sure the schema file doesn't exist if (file_exists(MPM_DB_PATH . 'schema.php') || file_exists(MPM_DB_PATH . 'test_data.php')) { $clw->addText('The schema and/or test data files already exist. Delete them first if you want to use this option.'); $clw->write(); exit; } $file = MpmTemplateHelper::getTemplate('schema.txt'); $test_data_file = MpmTemplateHelper::getTemplate('test_data.txt'); $fp = fopen(MPM_DB_PATH . 'schema.php', "w"); if ($fp == false) { echo "\nUnable to write to file. Initialization failed!\n\n"; exit; } $success = fwrite($fp, $file); if ($success == false) { echo "\nUnable to write to file. Initialization failed!\n\n"; exit; } fclose($fp); $fp = fopen(MPM_DB_PATH . 'test_data.php', "w"); if ($fp == false) { echo "\nUnable to write to file. Initialization failed!\n\n"; exit; } $success = fwrite($fp, $test_data_file); if ($success == false) { echo "\nUnable to write to file. Initialization failed!\n\n"; exit; } fclose($fp); $clw->addText('File ' . MPM_DB_PATH . 'schema.php has been created.'); $clw->addText('File ' . MPM_DB_PATH . 'test_data.php has been created.'); $clw->write(); exit; } else { if (isset($this->arguments[0]) && $this->arguments[0] == 'with_data') { $with_data = true; } else { if (isset($this->arguments[0]) && $this->arguments[0] == '--force') { $forced = true; } } } // make sure the schema file exists if (!file_exists(MPM_DB_PATH . 'schema.php')) { $clw->addText('The schema file does not exist. Run this command with the "add" argument to create one (only a stub).'); $clw->write(); exit; } // make sure the test data file exists if ($with_data == true && !file_exists(MPM_DB_PATH . 'test_data.php')) { $clw->addText('The test data file does not exist. Run this command with the "add" argument to create one (only a stub).'); $clw->write(); exit; } $clw->writeHeader(); if (!$forced) { echo "\nWARNING: IF YOU CONTINUE, ALL TABLES IN YOUR DATABASE WILL BE ERASED!"; echo "\nDO YOU WANT TO CONTINUE? [y/N] "; $answer = fgets(STDIN); $answer = trim($answer); $answer = strtolower($answer); if (empty($answer) || substr($answer, 0, 1) == 'n') { echo "\nABORTED!\n\n"; $clw->writeFooter(); exit; } } echo "\n"; $this->build($with_data); $clw->writeFooter(); exit; }
/** * Fetches a list of migrations which have already been run. * * @uses MpmDbHelper::doSingleRowSelect() * @uses MpmDbHelper::doMultiRowSelect() * * @param string $latestTimestamp the current timestamp of the migration run last * @param string $direction the way we are migrating; should either be up or down * * @return array */ public static function getListFromDb($latestTimestamp, $direction = 'up') { $db_config = $GLOBALS['db_config']; $migrations_table = $db_config->migrations_table; if ($direction == 'down') { $sql = "SELECT * FROM `{$migrations_table}` WHERE `timestamp` <= '{$latestTimestamp}' AND `active` = 1"; $countSql = "SELECT COUNT(*) as total FROM `{$migrations_table}` WHERE `timestamp` <= '{$latestTimestamp}' AND `active` = 1"; } else { $sql = "SELECT * FROM `{$migrations_table}` WHERE `timestamp` >= '{$latestTimestamp}' AND `active` = 1"; $countSql = "SELECT COUNT(*) as total FROM `{$migrations_table}` WHERE `timestamp` >= '{$latestTimestamp}' AND `active` = 1"; } $list = array(); $countObj = MpmDbHelper::doSingleRowSelect($countSql); if ($countObj->total > 0) { $results = MpmDbHelper::doMultiRowSelect($sql); foreach ($results as $obj) { $list[] = $obj->timestamp; } } return $list; }
/** * Returns a migration object; this object contains all data stored in the DB for the particular migration ID. * * @uses MpmDbHelper::getMethod() * @uses MpmDbHelper::getDbObj() * @uses MPM_METHOD_MYSQLI * @uses MPM_METHOD_PDO * * @param int $id the ID of the migration * * @return object */ public static function getMigrationObject($id) { $sql = "SELECT * FROM `mpm_migrations` WHERE `id` = '{$id}'"; $obj = null; try { switch (MpmDbHelper::getMethod()) { case MPM_METHOD_PDO: $pdo = MpmDbHelper::getDbObj(); $stmt = $pdo->query($sql); $obj = $stmt->fetch(PDO::FETCH_OBJ); break; case MPM_METHOD_MYSQLI: $mysqli = MpmDbHelper::getDbObj(); $stmt = $mysqli->query($sql); $obj = $stmt->fetch_object(); break; } } catch (Exception $e) { echo "\n\nERROR: " . $e->getMessage() . "\n\n"; exit; } return $obj; }
/** * Clears the migrations table and then rebuilds it. * * @uses MpmListHelper::mergeFilesWithDb() * @uses MpmDbHelper::doSingleRowSelect() * * @return void */ public function reloadMigrations() { $db_config = $GLOBALS['db_config']; $migrations_table = $db_config->migrations_table; echo 'Clearing out existing migration data... '; $this->dbObj->exec('TRUNCATE TABLE `' . $migrations_table . '`'); echo 'done.', "\n\n", 'Rebuilding migration data... '; MpmListHelper::mergeFilesWithDb(); echo 'done.', "\n"; if ($this->initialMigrationTimestamp != null) { echo "\n", 'Updating initial migration timestamp to ', $this->initialMigrationTimestamp, '... '; $result = MpmDbHelper::doSingleRowSelect('SELECT COUNT(*) AS total FROM `' . $migrations_table . '` WHERE `timestamp` = "' . $this->initialMigrationTimestamp . '"', $this->dbObj); if ($result->total == 1) { $this->dbObj->exec('UPDATE `' . $migrations_table . '` SET `is_current` = 0'); $this->dbObj->exec('UPDATE `' . $migrations_table . '` SET `is_current` = 1 WHERE `timestamp` = "' . $this->initialMigrationTimestamp . '"'); $this->dbObj->exec('UPDATE `' . $migrations_table . '` SET `active` = 1 WHERE `timestamp` <= "' . $this->initialMigrationTimestamp . '"'); } echo 'done.', "\n"; } }
/** * @param $migrations_table */ public function init_migration_db_table($migrations_table) { echo "\nlooking for existing migrations table... "; try { if (false === MpmDbHelper::checkForDbTable()) { echo "not found.\n"; echo "Creating migrations table... "; $sql1 = "CREATE TABLE IF NOT EXISTS `{$migrations_table}` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `timestamp` DATETIME NOT NULL, `active` TINYINT(1) NOT NULL DEFAULT 0, `is_current` TINYINT(1) NOT NULL DEFAULT 0, PRIMARY KEY ( `id` ) ) ENGINE=InnoDB"; $sql2 = "CREATE UNIQUE INDEX `TIMESTAMP_INDEX` ON `{$migrations_table}` ( `timestamp` )"; if (MpmDbHelper::getMethod() == MPM_METHOD_PDO) { $pdo = MpmDbHelper::getDbObj(); $pdo->beginTransaction(); try { $pdo->internal_exec($sql1); $pdo->internal_exec($sql2); } catch (Exception $e) { $pdo->rollback(); echo "failure!\n\n" . 'Unable to create required ' . $migrations_table . ' table:' . $e->getMessage(); echo "\n\n"; exit; } $pdo->commit(); } else { $mysqli = MpmDbHelper::getDbObj(); $mysqli->internal_exec($sql1); if ($mysqli->errno) { echo "failure!\n\n" . 'Unable to create required ' . $migrations_table . ' table:' . $mysqli->error; echo "\n\n"; exit; } $mysqli->internal_exec($sql2); if ($mysqli->errno) { echo "failure!\n\n" . 'Unable to create required ' . $migrations_table . ' table:' . $mysqli->error; echo "\n\n"; exit; } } echo "done.\n\n"; } else { echo "found.\n\n"; } } catch (Exception $e) { echo "failure!\n\nUnable to complete initialization: " . $e->getMessage() . "\n\n"; echo "Check your database settings and re-run init.\n\n"; exit; } }
/** * Determines what action should be performed and takes that action. * * @uses MPM_DB_PATH * @uses MpmDbHelper::test() * @uses MpmListHelper::getFiles() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::addText() * @uses MpmCommandLineWriter::write() * @uses MpmDbHelper::getMethod() * @uses MpmUpController::displayHelp() * * @return void */ public function doAction() { // make sure system is init'ed MpmDbHelper::test(); // get date stamp for use in generating filename $date_stamp = date('Y_m_d_H_i_s'); $filename = $date_stamp . '.php'; $classname = 'Migration_' . $date_stamp; // get list of files $files = MpmListHelper::getFiles(); // if filename is taken, throw error if (in_array($filename, $files)) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to obtain a unique filename for your migration. Please try again in a few seconds.'); $obj->write(); } // create file if (MpmDbHelper::getMethod() == MPM_METHOD_PDO) { $file = "<?php\n\n"; $file .= 'class ' . $classname . ' extends MpmMigration' . "\n"; $file .= "{\n\n"; $file .= "\t" . 'public function up(PDO &$pdo)' . "\n"; $file .= "\t{\n\t\t\n"; $file .= "\t}\n\n"; $file .= "\t" . 'public function down(PDO &$pdo)' . "\n"; $file .= "\t{\n\t\t\n"; $file .= "\t}\n\n"; $file .= "}\n\n"; $file .= "?>"; } else { $file = "<?php\n\n"; $file .= 'class ' . $classname . ' extends MpmMysqliMigration' . "\n"; $file .= "{\n\n"; $file .= "\t" . 'public function up(ExceptionalMysqli &$mysqli)' . "\n"; $file .= "\t{\n\t\t\n"; $file .= "\t}\n\n"; $file .= "\t" . 'public function down(ExceptionalMysqli &$mysqli)' . "\n"; $file .= "\t{\n\t\t\n"; $file .= "\t}\n\n"; $file .= "}\n\n"; $file .= "?>"; } // write the file $fp = fopen(MPM_DB_PATH . $filename, "w"); if ($fp == false) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to write new migration file.'); $obj->write(); } $success = fwrite($fp, $file); if ($success == false) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to write new migration file.'); $obj->write(); } fclose($fp); // display success message $obj = MpmCommandLineWriter::getInstance(); $obj->addText('New migration created: file /db/' . $filename); $obj->write(); }
/** * Determines what action should be performed and takes that action. * * @uses MPM_PATH * @uses MPM_METHOD_PDO * @uses MPM_METHOD_MYSQLI * @uses MpmDbHelper::checkForDbTable() * @uses MpmDbHelper::getDbObj() * @uses MpmDbHelper::getMethod() * @uses MpmInitController::displayHelp() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::writeHeader() * @uses MpmCommandLineWriter::writeFooter() * @uses MpmBuildController::build() * * @return void */ public function doAction() { $user = ''; $dbname = ''; $port = ''; $db_path = ''; $method = 0; $clw = MpmCommandLineWriter::getInstance(); $clw->writeHeader(); echo "Defaults are in brackets ([]). To accept the default, simply press ENTER.\n\n"; if (file_exists(MPM_PATH . '/config/db_config.php')) { echo "\nWARNING: IF YOU CONTINUE, YOUR EXISTING MIGRATION SETUP WILL BE ERASED!"; echo "\nThis will not affect your existing migrations or database, but \ncould cause your future migrations to fail."; echo "\nDO YOU WANT TO CONTINUE? [y/N] "; $answer = fgets(STDIN); $answer = trim($answer); $answer = strtolower($answer); if (empty($answer) || substr($answer, 0, 1) == 'n') { echo "\nABORTED!\n\n"; $clw->writeFooter(); exit; } else { require MPM_PATH . '/config/db_config.php'; } } do { echo "\nWhich method would you like to use to connect to\nthe database? " . MPM_METHOD_PDO . "=PDO or " . MPM_METHOD_MYSQLI . "=MySQLi"; if (isset($db_config)) { echo " [" . $db_config->method . "]"; } echo ": "; $method = fgets(STDIN); $method = trim($method); if (!is_numeric($method)) { $method = 0; } if (empty($method) && isset($db_config)) { $method = $db_config->method; } } while ($method < MPM_METHOD_PDO || $method > MPM_METHOD_MYSQLI || $method == 0); echo "\nEnter your MySQL database hostname or IP address ["; if (isset($db_config)) { echo $db_config->host; } else { echo 'localhost'; } echo ']: '; $host = fgets(STDIN); $host = trim($host); if (empty($host)) { if (isset($db_config)) { $host = $db_config->host; } else { $host = 'localhost'; } } while (empty($port)) { echo "\nEnter your MySQL database port ["; if (isset($db_config)) { echo $db_config->port; } else { echo '3306'; } echo ']: '; $port = fgets(STDIN); $port = trim($port); if (empty($port)) { $port = 3306; } if (!is_numeric($port)) { $port = ''; } } while (empty($user)) { echo "\nEnter your MySQL database username"; if (isset($db_config)) { echo ' [', $db_config->user, ']'; } echo ': '; $user = fgets(STDIN); $user = trim($user); if (empty($user) && isset($db_config)) { $user = $db_config->user; } } echo "\nEnter your MySQL database password (enter - for no password) ["; if (isset($db_config)) { echo $db_config->pass; } echo ']: '; $pass = fgets(STDIN); $pass = trim($pass); if (empty($pass) && isset($db_config)) { $pass = $db_config->pass; } else { if ($pass == '-') { $pass = ''; } } while (empty($dbname)) { echo "\nEnter your MySQL database name"; if (isset($db_config)) { echo ' [', $db_config->name, ']'; } echo ': '; $dbname = fgets(STDIN); $dbname = trim($dbname); if (empty($dbname) && isset($db_config)) { $dbname = $db_config->name; } } echo "\nEnter the directory where you'd like to store your\nmigration files ["; if (isset($db_config)) { echo $db_config->db_path; } else { echo MPM_PATH . '/db/'; } echo ']: '; $db_path = fgets(STDIN); $db_path = trim($db_path); if (empty($db_path) && isset($db_config)) { $db_path = $db_config->db_path; } else { if (empty($db_path) && !isset($db_config)) { $db_path = MPM_PATH . '/db/'; } } if (substr($db_path, strlen($db_path) - 1, 1) != '/') { $db_path .= '/'; } $method = (int) $method; if (file_exists($db_path . 'schema.php')) { echo "\nPerform build of database after initialization (builds schema\nand runs all existing migrations) [y/N]: "; $do_build = fgets(STDIN); $do_build = trim($do_build); $doBuild = false; if (strcasecmp(substr($do_build, 0, 1), 'y') == 0) { $doBuild = true; } } $file = '<?php' . "\n\n"; $file .= '$db_config = (object) array();' . "\n"; $file .= '$db_config->host = ' . "'" . $host . "';" . "\n"; $file .= '$db_config->port = ' . "'" . $port . "';" . "\n"; $file .= '$db_config->user = '******'" . $user . "';" . "\n"; $file .= '$db_config->pass = '******'" . $pass . "';" . "\n"; $file .= '$db_config->name = ' . "'" . $dbname . "';" . "\n"; $file .= '$db_config->db_path = ' . "'" . $db_path . "';" . "\n"; $file .= '$db_config->method = ' . $method . ";" . "\n"; $file .= "\n?>"; if (file_exists(MPM_PATH . '/config/db_config.php')) { unlink(MPM_PATH . '/config/db_config.php'); } $fp = fopen(MPM_PATH . '/config/db_config.php', "w"); if ($fp == false) { echo "\nUnable to write to file. Initialization failed!\n\n"; exit; } $success = fwrite($fp, $file); if ($success == false) { echo "\nUnable to write to file. Initialization failed!\n\n"; exit; } fclose($fp); require MPM_PATH . '/config/db_config.php'; $GLOBALS['db_config'] = $db_config; echo "\nConfiguration saved... looking for existing migrations table... "; try { if (false === MpmDbHelper::checkForDbTable()) { echo "not found.\n"; echo "Creating migrations table... "; $sql1 = "CREATE TABLE IF NOT EXISTS `mpm_migrations` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `timestamp` DATETIME NOT NULL, `active` TINYINT(1) NOT NULL DEFAULT 0, `is_current` TINYINT(1) NOT NULL DEFAULT 0, PRIMARY KEY ( `id` ) ) ENGINE=InnoDB"; $sql2 = "CREATE UNIQUE INDEX `TIMESTAMP_INDEX` ON `mpm_migrations` ( `timestamp` )"; if (MpmDbHelper::getMethod() == MPM_METHOD_PDO) { $pdo = MpmDbHelper::getDbObj(); $pdo->beginTransaction(); try { $pdo->exec($sql1); $pdo->exec($sql2); } catch (Exception $e) { $pdo->rollback(); echo "failure!\n\n" . 'Unable to create required mpm_migrations table:' . $e->getMessage(); echo "\n\n"; exit; } $pdo->commit(); } else { $mysqli = MpmDbHelper::getDbObj(); $mysqli->query($sql1); if ($mysqli->errno) { echo "failure!\n\n" . 'Unable to create required mpm_migrations table:' . $mysqli->error; echo "\n\n"; exit; } $mysqli->query($sql2); if ($mysqli->errno) { echo "failure!\n\n" . 'Unable to create required mpm_migrations table:' . $mysqli->error; echo "\n\n"; exit; } } echo "done.\n\n"; } else { echo "found.\n\n"; } } catch (Exception $e) { echo "failure!\n\nUnable to complete initialization: " . $e->getMessage() . "\n\n"; echo "Check your database settings and re-run init.\n\n"; exit; } if (isset($doBuild) && $doBuild === true) { $obj = new MpmBuildController(); $obj->build(); echo "\n\n"; } echo "Initalization complete! Type 'php migrate.php help' for a list of commands.\n\n"; $clw->writeFooter(); exit; }
/** * Returns an array of all the tables in the database. * * @uses MpmDbHelper::getDbObj() * @uses MpmDbHelper::getMethod() * * @return array */ public static function getTables(&$dbObj = null) { if ($dbObj == null) { $dbObj = MpmDbHelper::getDbObj(); } $sql = "SHOW TABLES"; $tables = array(); switch (MpmDbHelper::getMethod()) { case MPM_METHOD_PDO: try { foreach ($dbObj->query($sql) as $row) { $tables[] = $row[0]; } } catch (Exception $e) { } break; case MPM_METHOD_MYSQLI: try { $result = $dbObj->query($sql); while ($row = $result->fetch_array()) { $tables[] = $row[0]; } } catch (Exception $e) { } break; } return $tables; }
/** * Determines what action should be performed and takes that action. * * @uses MpmLatestController::displayHelp() * @uses MpmDbHelper::test() * @uses MpmMigrationHelper::getMigrationCount() * @uses MpmCommandLineWriter::getInstance() * @uses MpmMigrationHelper::getLatestMigration() * @uses MpmUpController::doAction() * * @param bool $quiet supresses certain text when true * * @return void */ public function doAction($quiet = false) { // make sure we're init'd MpmDbHelper::test(); //get completed migrations from database //get migrations from file $oldest_migration_id = MpmMigrationHelper::getOldestMigration(); $current_timestamp = MpmMigrationHelper::getCurrentMigrationTimestamp(); $current_num = MpmMigrationHelper::getCurrentMigrationNumber(); /*$latest_num = MpmMigrationHelper::getLatestMigration(); $latest_timestamp = MpmMigrationHelper::getTimestampFromId($latest_num);*/ $db_migrations = MpmListHelper::getListFromDb($current_timestamp, 'down'); $files = MpmListHelper::getListOfFiles(); $all_file_timestamps = MpmListHelper::getTimestampArray($files); $file_timestamps = array(); foreach ($all_file_timestamps as $timestamp) { if ($timestamp <= $current_timestamp) { $file_timestamps[] = $timestamp; } } end($all_file_timestamps); $latest_timestamp = current($all_file_timestamps); //compare timestamps that are in either array to timestamps that are in both arrays to find missing timestamps in either //$missing_merges = array_diff(array_unique( array_merge($file_timestamps,$db_migrations) ), array_intersect($file_timestamps,$db_migrations) ); $missing_database = array_diff($file_timestamps, $db_migrations); $missing_files = array_diff($db_migrations, $file_timestamps); $missing_merges = array_merge($missing_files, $missing_database); sort($missing_merges); reset($missing_merges); $oldest_missing = current($missing_merges); $clw = MpmCommandLineWriter::getInstance(); $clw->writeHeader(); if (!$current_num) { echo 'You have not run any migrations'; } else { echo "You are currently on migration {$current_num} -- " . $current_timestamp . '.'; } if (!empty($missing_files)) { echo "\n\nCompleted migrations that are no longer in migrations directory\n----------\n"; foreach ($missing_files as $file) { echo " {$file}\n"; } } if (!empty($missing_database)) { echo "\n\nOld migrations that have not been run\n----------"; foreach ($missing_database as $db) { echo "\n {$db}"; } } if ($current_timestamp < $latest_timestamp) { echo "\nLatest migration is: {$latest_timestamp}."; } if ($oldest_missing && $oldest_missing <= $current_timestamp || $current_timestamp < $latest_timestamp) { echo "\n\n--- Migration Path --------------------------\n"; $post_down_timestamp = $current_timestamp; if ($oldest_missing && $oldest_missing <= $current_timestamp) { //find target down timestamp $previous_migration = MpmMigrationHelper::getNextTimestamp($oldest_missing, 'down'); if ($previous_migration) { $post_down_timestamp = $previous_migration->timestamp; echo "\n Migrate down to: {$previous_migration->id} -- {$previous_migration->timestamp}"; } else { $post_down_timestamp = 0; echo "\n Remove all migrations"; } } if ($post_down_timestamp < $latest_timestamp) { echo "\n Migrate up to latest: {$latest_timestamp}"; } } else { echo "\n\n You are up to date"; } /*$total_migrations = MpmMigrationHelper::getMigrationCount(); if ($total_migrations == 0) { $clw = MpmCommandLineWriter::getInstance(); $clw->addText('No migrations exist.'); $clw->write(); exit; } $to_id = MpmMigrationHelper::getLatestMigration(); $obj = new MpmUpController('up', array ( $to_id, $forced )); $obj->doAction($quiet); */ $clw->writeFooter(); }
/** * Determines what action should be performed and takes that action. * * @uses MpmDbHelper::test() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::addText() * @uses MpmCommandLineWriter::write() * @uses MpmCommandLineWriter::writeHeader() * @uses MpmCommandLineWriter::writeFooter() * @uses MpmBuildController::build() * @uses MPM_DB_PATH * * @return void */ public function doAction() { // make sure system is init'ed MpmDbHelper::test(); $clw = MpmCommandLineWriter::getInstance(); $forced = false; // are we adding a schema file? if (isset($this->arguments[0]) && $this->arguments[0] == 'add') { // make sure the schema file doesn't exist if (file_exists(MPM_DB_PATH . 'schema.php')) { $clw->addText('The schema file already exists. Delete it first if you want to use this option.'); $clw->write(); exit; } $db = MpmDbHelper::getDbObj(); $result = $db->exec("show tables"); $schema_queries = array(); while ($row = $result->fetch_array(MYSQLI_NUM)) { if ($row[0] === 'mpm_migrations') { continue; } $tabres = $db->exec("show create table {$row[0]}"); $tabrow = $tabres->fetch_array(MYSQLI_NUM); $schema_queries[] = $tabrow[1]; } $file = "<?php\n"; $file .= "/**\n"; $file .= " * This file houses the MpmInitialSchema class.\n"; $file .= " *\n"; $file .= " * This file may be deleted if you do not wish to use the build command or build on init features.\n"; $file .= " *\n"; $file .= " * @package mysql_php_migrations\n"; $file .= " * @subpackage Classes\n"; $file .= " * @license http://www.opensource.org/licenses/bsd-license.php The New BSD License\n"; $file .= " * @link http://code.google.com/p/mysql-php-migrations/\n"; $file .= " */\n"; $file .= "\n"; $file .= "/**\n"; $file .= " * The MpmInitialSchema class is used to build an initial database structure.\n"; $file .= " *\n"; $file .= " * @package mysql_php_migrations\n"; $file .= " * @subpackage Classes\n"; $file .= " */\n"; $file .= "class MpmInitialSchema extends MpmSchema\n"; $file .= "{\n"; $file .= "\n"; $file .= "\t" . 'protected $tables = array(' . "\n"; $file .= "\t\"" . implode("\",\n\t\"", $schema_queries); $file .= "\"\n\t);\n\n"; $file .= "\tpublic function __construct()\n"; $file .= "\t{\n"; $file .= "\t\tparent::__construct();\n"; $file .= "\n"; $file .= "\t\t/* If you build your initial schema having already executed a number of migrations,\n"; $file .= "\t\t* you should set the initial migration timestamp.\n"; $file .= "\t\t*\n"; $file .= "\t\t* The initial migration timestamp will be set to active and this migration and all\n"; $file .= "\t\t* previous will be ignored when the build command is used.\n"; $file .= "\t\t*\n"; $file .= "\t\t* EX:\n"; $file .= "\t\t*\n"; $file .= "\t\t* " . '$' . "this->initialMigrationTimestamp = '2009-08-01 15:23:44';\n"; $file .= "\t\t*/\n"; $file .= "\t\t" . '$' . "this->initialMigrationTimestamp = date('Y-m-d H:i:s');\n"; $file .= "\t}\n"; $file .= "\n"; $file .= "\tpublic function build()\n"; $file .= " \t{\n"; $file .= "\t\t/* Add the queries needed to build the initial structure of your database.\n"; $file .= "\t\t*\n"; $file .= "\t\t* EX:\n"; $file .= "\t\t*\n"; $file .= "\t\t* " . '$' . "this->dbObj->exec('CREATE TABLE `testing` ( `id` INT(11) AUTO_INCREMENT NOT NULL, `vals` INT(11) NOT NULL, PRIMARY KEY ( `id` ))');\n"; $file .= "\t\t*/\n"; $file .= "\t\tforeach(\$this->tables as \$table)\n"; $file .= "\t\t{\n"; $file .= "\t\t\t\$this->dbObj->exec(\$table);\n"; $file .= "\t\t}\n"; $file .= "\t}\n"; $file .= "\n"; $file .= "}\n"; $file .= "\n"; $file .= "?>"; $fp = fopen(MPM_DB_PATH . 'schema.php', "w"); if ($fp == false) { echo "\nUnable to write to file. Initialization failed!\n\n"; exit; } $success = fwrite($fp, $file); if ($success == false) { echo "\nUnable to write to file. Initialization failed!\n\n"; exit; } fclose($fp); $clw->addText('File ' . MPM_DB_PATH . 'schema.php has been created.'); $clw->write(); exit; } else { if (isset($this->arguments[0]) && $this->arguments[0] == '--force') { $forced = true; } } // make sure the schema file exists if (!file_exists(MPM_DB_PATH . 'schema.php')) { $clw->addText('The schema file does not exist. Run this command with the "add" argument to create one (only a stub).'); $clw->write(); exit; } $clw->writeHeader(); if (!$forced) { echo "\nWARNING: IF YOU CONTINUE, ALL TABLES IN YOUR DATABASE WILL BE ERASED!"; echo "\nDO YOU WANT TO CONTINUE? [y/N] "; $answer = fgets(STDIN); $answer = trim($answer); $answer = strtolower($answer); if (empty($answer) || substr($answer, 0, 1) == 'n') { echo "\nABORTED!\n\n"; $clw->writeFooter(); exit; } } echo "\n"; $this->build(); $clw->writeFooter(); exit; }
/** * Determines what action should be performed and takes that action. * * @uses MpmLatestController::displayHelp() * @uses MpmDbHelper::test() * @uses MpmMigrationHelper::getMigrationCount() * @uses MpmCommandLineWriter::getInstance() * @uses MpmMigrationHelper::getLatestMigration() * @uses MpmUpController::doAction() * * @param bool $quiet supresses certain text when true * * @return void */ public function doAction($quiet = false) { // make sure we're init'd MpmDbHelper::test(); $clw = MpmCommandLineWriter::getInstance(); $clw->writeHeader(); // are we forcing this? $forced = ''; if (isset($this->arguments[0]) && strcasecmp($this->arguments[0], '--force') == 0) { $forced = '--force'; } //get completed migrations from database //get migrations from file $oldest_migration_id = MpmMigrationHelper::getOldestMigration(); $current_timestamp = MpmMigrationHelper::getCurrentMigrationTimestamp(); $current_num = MpmMigrationHelper::getCurrentMigrationNumber(); //$latest_num = MpmMigrationHelper::getLatestMigration(); //$latest_timestamp = MpmMigrationHelper::getTimestampFromId($latest_num); $db_migrations = MpmListHelper::getListFromDb($current_timestamp, 'down'); $files = MpmListHelper::getListOfFiles(); $all_file_timestamps = MpmListHelper::getTimestampArray($files); $file_timestamps = array(); foreach ($all_file_timestamps as $timestamp) { if ($timestamp <= $current_timestamp) { $file_timestamps[] = $timestamp; } } end($file_timestamps); $latest_timestamp = current($file_timestamps); //compare timestamps that are in either array to timestamps that are in both arrays to find missing timestamps in either //$missing_merges = array_diff(array_unique( array_merge($file_timestamps,$db_migrations) ), array_intersect($file_timestamps,$db_migrations) ); $missing_database = array_diff($file_timestamps, $db_migrations); $missing_files = array_diff($db_migrations, $file_timestamps); $missing_merges = array_merge($missing_files, $missing_database); sort($missing_merges); reset($missing_merges); $oldest_missing = current($missing_merges); try { if ($oldest_missing && $oldest_missing <= $current_timestamp) { $previous_migration = MpmMigrationHelper::getNextTimestamp($oldest_missing, 'down'); if ($previous_migration) { $target_down = $previous_migration->id; } else { $target_down = -1; } $down = new MpmDownController('down', array($target_down, $forced, true)); $down->doAction($quiet); } //merge files with database MpmListHelper::mergeFilesWithDb(); $newest_id = MpmMigrationHelper::getLatestMigration(); if ($newest_id) { $newest_timestamp = MpmMigrationHelper::getTimestampFromId($newest_id); $current_timestamp = MpmMigrationHelper::getCurrentMigrationTimestamp(); if ($newest_timestamp > $current_timestamp) { $obj = new MpmUpController('up', array($newest_id, $forced, true)); $obj->doAction($quiet); } else { echo "\nUp to Date"; } } else { echo "\nUp to Date"; } } catch (Exception $e) { echo "\n\nERROR: " . $e->getMessage() . "\n\n"; exit; } $clw->writeFooter(); }
/** * Determines what action should be performed and takes that action. * * @uses MPM_DB_PATH * @uses MpmDbHelper::test() * @uses MpmListHelper::getFiles() * @uses MpmCommandLineWriter::getInstance() * @uses MpmCommandLineWriter::addText() * @uses MpmCommandLineWriter::write() * @uses MpmDbHelper::getMethod() * @uses MpmUpController::displayHelp() * * @return void */ public function doAction() { // make sure system is init'ed MpmDbHelper::test(); $filename_note = ''; if (!empty($this->arguments)) { $argument = preg_replace('|[^a-zA-Z0-9_-]|', '', $this->arguments[0]); if (!empty($argument)) { $filename_note = '_' . $argument; } } // get date stamp for use in generating filename $date_stamp = date('Y_m_d_H_i_s'); $filename = $date_stamp . $filename_note . '.php'; $classname = 'Migration_' . $date_stamp; // get list of files $files = glob(MPM_DB_PATH . $date_stamp . '*.php'); // if filename is taken, throw error if (!empty($files)) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to obtain a unique filename for your migration. Please try again in a few seconds.'); $obj->write(); exit; } // create file if (MpmDbHelper::getMethod() == MPM_METHOD_PDO) { $file = "<?php\n\n"; $file .= 'class ' . $classname . ' extends MpmMigration' . "\n"; $file .= "{\n\n"; $file .= "\t" . 'public function up(PDO &$pdo)' . "\n"; $file .= "\t{\n"; $file .= "\t\t" . '$pdo->exec("DO 0");' . "\n"; $file .= "\t}\n\n"; $file .= "\t" . 'public function down(PDO &$pdo)' . "\n"; $file .= "\t{\n"; $file .= "\t\t" . '$pdo->exec("DO 0");' . "\n"; $file .= "\t}\n\n"; $file .= "}\n\n"; $file .= "?>"; } else { $file = "<?php\n\n"; $file .= 'class ' . $classname . ' extends MpmMysqliMigration' . "\n"; $file .= "{\n\n"; $file .= "\t" . 'public function up(ExceptionalMysqli &$mysqli)' . "\n"; $file .= "\t{\n"; $file .= "\t\t" . '$mysqli->exec("DO 0");' . "\n"; $file .= "\t}\n\n"; $file .= "\t" . 'public function down(ExceptionalMysqli &$mysqli)' . "\n"; $file .= "\t{\n"; $file .= "\t\t" . '$mysqli->exec("DO 0");' . "\n"; $file .= "\t}\n\n"; $file .= "}\n\n"; $file .= "?>"; } // write the file $fp = fopen(MPM_DB_PATH . $filename, "w"); if ($fp == false) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to write new migration file.'); $obj->write(); } $success = fwrite($fp, $file); if ($success == false) { $obj = MpmCommandLineWriter::getInstance(); $obj->addText('Unable to write new migration file.'); $obj->write(); } fclose($fp); // display success message $obj = MpmCommandLineWriter::getInstance(); $obj->addText('New migration created: file ' . MPM_DB_PATH . $filename); $obj->write(); }