Files
codecanyon-rest-api-for-per…/api/migration_runner.php
Oussama Douhou 23cc6629f1 license
2025-10-29 19:20:51 +01:00

307 lines
9.5 KiB
PHP

<?php
/**
* Advanced Database Migration Runner for API Module
* Supports both upgrades and rollbacks
*/
// Define necessary constants
define('BASEPATH', true);
define('APPPATH', '../application/');
define('ENVIRONMENT', 'production');
class APIMigrationRunner
{
private $CI;
private $module_name = 'api';
private $migration_path = 'migrations/';
public function __construct()
{
// Load Perfex CRM framework
require_once '../../index.php';
$this->CI =& get_instance();
}
public function run($target_version = null, $rollback = false)
{
$this->print_header();
// Validate environment
if (!$this->validate_environment()) {
return false;
}
// Get current version
$current_version = $this->get_current_version();
echo "📊 Current migration version: $current_version\n\n";
// Get available migrations
$migrations = $this->get_available_migrations();
if ($rollback) {
return $this->run_rollback($current_version, $target_version, $migrations);
} else {
return $this->run_upgrade($current_version, $target_version, $migrations);
}
}
private function validate_environment()
{
// Check if API module is active
if (!$this->CI->app_modules->is_active($this->module_name)) {
echo "❌ ERROR: API module is not active. Please activate it first.\n";
echo " Go to Admin → Setup → Modules and activate the API module.\n\n";
return false;
}
echo "✅ API module is active\n";
// Check database connection
if (!isset($this->CI->db) || !$this->CI->db->conn_id) {
echo "❌ ERROR: Database connection failed\n";
return false;
}
echo "✅ Database connection established\n";
return true;
}
private function get_current_version()
{
$migration_table = db_prefix() . 'migrations';
if ($this->CI->db->table_exists('migrations')) {
$result = $this->CI->db->select('version')
->from('migrations')
->where('module', $this->module_name)
->get();
if ($result->num_rows() > 0) {
return $result->row()->version;
}
}
return 0;
}
private function get_available_migrations()
{
$migrations = [];
// Scan migration files
$files = glob($this->migration_path . '*_version_*.php');
foreach ($files as $file) {
if (preg_match('/(\d+)_version_(\d+)\.php$/', basename($file), $matches)) {
$version = (int) $matches[1];
$migrations[$version] = [
'file' => $file,
'class' => 'Migration_Version_' . $matches[1]
];
}
}
ksort($migrations);
return $migrations;
}
private function run_upgrade($current_version, $target_version, $migrations)
{
// Determine which migrations to run
$migrations_to_run = [];
foreach ($migrations as $version => $migration) {
if ($version > $current_version && ($target_version === null || $version <= $target_version)) {
$migrations_to_run[$version] = $migration;
}
}
if (empty($migrations_to_run)) {
echo "✅ All migrations are up to date!\n\n";
return true;
}
echo "📋 Migrations to run:\n";
foreach ($migrations_to_run as $version => $migration) {
echo " - Version $version: {$migration['class']}\n";
}
echo "\n";
// Confirm execution
if (!$this->confirm_execution()) {
return false;
}
// Execute migrations
return $this->execute_migrations($migrations_to_run, 'up');
}
private function run_rollback($current_version, $target_version, $migrations)
{
// Determine rollback target
$target = $target_version ?? 0;
if ($target >= $current_version) {
echo "❌ ERROR: Target version ($target) must be less than current version ($current_version)\n";
return false;
}
// Find migrations to rollback
$migrations_to_rollback = [];
foreach (array_reverse($migrations, true) as $version => $migration) {
if ($version > $target && $version <= $current_version) {
$migrations_to_rollback[$version] = $migration;
}
}
if (empty($migrations_to_rollback)) {
echo "✅ No migrations to rollback!\n\n";
return true;
}
echo "📋 Migrations to rollback:\n";
foreach ($migrations_to_rollback as $version => $migration) {
echo " - Version $version: {$migration['class']}\n";
}
echo "\n";
// Confirm execution
if (!$this->confirm_execution('rollback')) {
return false;
}
// Execute rollbacks
return $this->execute_migrations($migrations_to_rollback, 'down');
}
private function confirm_execution($action = 'upgrade')
{
if (php_sapi_name() === 'cli') {
echo "Do you want to $action these migrations? (y/N): ";
$handle = fopen("php://stdin", "r");
$response = trim(fgets($handle));
fclose($handle);
if (strtolower($response) !== 'y' && strtolower($response) !== 'yes') {
echo "Migration $action cancelled.\n";
return false;
}
}
return true;
}
private function execute_migrations($migrations, $method)
{
$success_count = 0;
$error_count = 0;
foreach ($migrations as $version => $migration) {
echo "🔄 Running migration {$migration['class']}::$method()...\n";
try {
// Load migration file
if (!file_exists($migration['file'])) {
throw new Exception("Migration file not found: {$migration['file']}");
}
require_once $migration['file'];
// Instantiate migration class
if (!class_exists($migration['class'])) {
throw new Exception("Migration class not found: {$migration['class']}");
}
$migration_instance = new $migration['class']();
// Run the method
if (!method_exists($migration_instance, $method)) {
throw new Exception("Method $method() not found in migration class");
}
$migration_instance->$method();
echo " ✅ Migration completed successfully\n";
// Update migration version in database
if ($method === 'up') {
$this->CI->db->replace('migrations', [
'module' => $this->module_name,
'version' => $version
]);
} elseif ($method === 'down') {
// For rollback, set to previous version
$prev_version = $this->get_previous_version($version, $migrations);
if ($prev_version === null) {
$this->CI->db->delete('migrations', ['module' => $this->module_name]);
} else {
$this->CI->db->replace('migrations', [
'module' => $this->module_name,
'version' => $prev_version
]);
}
}
$success_count++;
} catch (Exception $e) {
echo " ❌ Migration failed: " . $e->getMessage() . "\n";
$error_count++;
}
echo "\n";
}
// Summary
$action_name = ($method === 'up') ? 'upgrade' : 'rollback';
echo "📊 Migration Summary ($action_name):\n";
echo " ✅ Successful: $success_count\n";
echo " ❌ Failed: $error_count\n\n";
if ($error_count > 0) {
echo "⚠️ Some migrations failed. Please check the errors above.\n";
return false;
} else {
echo "🎉 All migrations completed successfully!\n";
echo " API module database is now " . ($method === 'up' ? 'up to date' : 'rolled back') . ".\n";
return true;
}
}
private function get_previous_version($current_version, $migrations)
{
$versions = array_keys($migrations);
sort($versions);
$index = array_search($current_version, $versions);
if ($index === false || $index === 0) {
return null;
}
return $versions[$index - 1];
}
private function print_header()
{
echo "🚀 API Module Database Migration Runner\n";
echo "=======================================\n\n";
}
}
// CLI Interface
if (php_sapi_name() === 'cli') {
$options = getopt('t:r', ['target:', 'rollback']);
$target_version = isset($options['t']) ? (int)$options['t'] : (isset($options['target']) ? (int)$options['target'] : null);
$rollback = isset($options['r']) || isset($options['rollback']);
$runner = new APIMigrationRunner();
$success = $runner->run($target_version, $rollback);
exit($success ? 0 : 1);
} else {
// Web interface
echo "<pre>";
$runner = new APIMigrationRunner();
$runner->run();
echo "</pre>";
}
?>