ShahiAssist

Migration and Upgrades

Managing data migration and version upgrades is critical for maintaining system stability and user experience. This guide covers comprehensive strategies for migrating ShahiAssist data and handling upgrades.

Version Upgrade Strategy

Semantic Versioning

ShahiAssist follows semantic versioning (MAJOR.MINOR.PATCH):

    1. MAJOR: Breaking changes requiring migration
    2. MINOR: New features, backward compatible
    3. PATCH: Bug fixes, backward compatible
    4. Upgrade Path Planning

      `php
      class ShahiAssistUpgradeManager {
      private $current_version;
      private $target_version;

      public function __construct() {
      $this->currentversion = getoption(‘shahiassistversion’, ‘1.0.0’);
      }

      public function upgradeto($targetversion) {
      $this->targetversion = $targetversion;

      // Get upgrade path
      $upgradesteps = $this->getupgradepath($this->currentversion, $target_version);

      // Execute upgrades in order
      foreach ($upgrade_steps as $step) {
      $this->executeupgradestep($step);
      }

      // Update version
      updateoption(‘shahiassistversion’, $targetversion);
      }

      private function getupgradepath($from, $to) {
      // Define upgrade steps between versions
      $upgrade_paths = [
      ‘1.0.0’ => [‘1.1.0’, ‘1.2.0’, ‘2.0.0’],
      ‘1.1.0’ => [‘1.2.0’, ‘2.0.0’],
      ‘1.2.0’ => [‘2.0.0’],
      ‘2.0.0’ => [‘2.1.0’, ‘3.0.0’],
      ];

      $path = [];
      $current = $from;

      while (version_compare($current, $to, ‘<')) { if (!isset($upgrade_paths[$current])) { break; } $nextversions = $upgradepaths[$current];
      $next = null;

      foreach ($next_versions as $version) {
      if (version_compare($version, $to, ‘<=')) { $next = $version; break; } } if (!$next) { break; } $path[] = $next; $current = $next; } return $path; } private function executeupgradestep($version) {
      $method = ‘upgradeto‘ . strreplace(‘.’, ‘‘, $version);

      if (method_exists($this, $method)) {
      $this->$method();
      }
      }
      }
      `

      Database Migrations

      Migration Framework

      `php
      abstract class ShahiAssist_Migration {
      protected $db_version = ‘1.0’;

      abstract public function up();
      abstract public function down();

      public function get_version() {
      return $this->db_version;
      }
      }

      class CreateTicketsTableMigration extends ShahiAssistMigration {
      protected $db_version = ‘1.1’;

      public function up() {
      global $wpdb;

      $tablename = $wpdb->prefix . ‘shahiassist_tickets’;

      $sql = “CREATE TABLE $table_name (
      id int(11) NOT NULL AUTO_INCREMENT,
      title varchar(255) NOT NULL,
      description text,
      status varchar(50) DEFAULT ‘open’,
      priority varchar(20) DEFAULT ‘medium’,
      createdat datetime DEFAULT CURRENTTIMESTAMP,
      updatedat datetime DEFAULT CURRENTTIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (id),
      INDEX idx_status (status),
      INDEX idx_priority (priority)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4unicodeci;”;

      require_once(ABSPATH . ‘wp-admin/includes/upgrade.php’);
      dbDelta($sql);
      }

      public function down() {
      global $wpdb;
      $tablename = $wpdb->prefix . ‘shahiassist_tickets’;
      $wpdb->query(“DROP TABLE IF EXISTS $table_name”);
      }
      }
      `

      Migration Runner

      `php
      class ShahiAssistMigrationRunner {
      private $migrations_path;
      private $completed_migrations = [];

      public function __construct() {
      $this->migrationspath = plugindir_path(FILE) . ‘migrations/’;
      $this->completedmigrations = getoption(‘shahiassistcompleted_migrations’, []);
      }

      public function run_migrations() {
      $migrationfiles = glob($this->migrationspath . ‘*.php’);

      foreach ($migration_files as $file) {
      $migration_class = basename($file, ‘.php’);

      if (inarray($migrationclass, $this->completed_migrations)) {
      continue;
      }

      require_once $file;
      $migration = new $migration_class();

      try {
      $migration->up();
      $this->completedmigrations[] = $migrationclass;
      updateoption(‘shahiassistcompletedmigrations’, $this->completed_migrations);

      errorlog(“Migration completed: $migrationclass”);
      } catch (Exception $e) {
      errorlog(“Migration failed: $migrationclass – ” . $e->getMessage());
      // Rollback if needed
      $migration->down();
      break;
      }
      }
      }

      public function rollbackmigration($migrationclass) {
      if (!inarray($migrationclass, $this->completed_migrations)) {
      return false;
      }

      $file = $this->migrationspath . $migrationclass . ‘.php’;
      if (!file_exists($file)) {
      return false;
      }

      require_once $file;
      $migration = new $migration_class();
      $migration->down();

      $key = arraysearch($migrationclass, $this->completed_migrations);
      unset($this->completed_migrations[$key]);
      updateoption(‘shahiassistcompletedmigrations’, $this->completed_migrations);

      return true;
      }
      }
      `

      Data Migration Scripts

      Post Type Migration

      `php
      // Migrate from custom table to WordPress posts
      function migrateticketsto_posts() {
      global $wpdb;

      $oldtable = $wpdb->prefix . ‘shahiassist_tickets’;
      $tickets = $wpdb->getresults(“SELECT * FROM $oldtable”);

      foreach ($tickets as $ticket) {
      $post_data = [
      ‘post_title’ => $ticket->title,
      ‘post_content’ => $ticket->description,
      ‘post_type’ => ‘ticket’,
      ‘post_status’ => ‘publish’,
      ‘postdate’ => $ticket->createdat,
      ‘postmodified’ => $ticket->updatedat,
      ];

      $postid = wpinsertpost($postdata);

      if ($post_id) {
      // Migrate meta data
      updatepostmeta($postid, ‘ticket_status’, $ticket->status);
      updatepostmeta($postid, ‘ticket_priority’, $ticket->priority);
      updatepostmeta($postid, ‘migrated_from’, $ticket->id);
      }
      }

      // Mark migration as complete
      updateoption(‘shahiassistticketmigration_complete’, true);
      }
      `

      Settings Migration

      `php
      // Migrate old settings structure to new
      function migratesettingsstructure() {
      $oldsettings = getoption(‘shahiassistold_settings’, []);
      $new_settings = [];

      // Transform old settings to new structure
      if (isset($oldsettings[’emailnotifications’])) {
      $new_settings[‘notifications’] = [
      ’email’ => $oldsettings[’emailnotifications’],
      ‘enabled’ => true,
      ];
      }

      if (isset($oldsettings[‘ticketcategories’])) {
      $newsettings[‘categories’] = arraymap(function($cat) {
      return [
      ‘name’ => $cat[‘name’],
      ‘slug’ => sanitize_title($cat[‘name’]),
      ‘description’ => $cat[‘description’] ?? ”,
      ];
      }, $oldsettings[‘ticketcategories’]);
      }

      updateoption(‘shahiassistsettings’, $newsettings);
      deleteoption(‘shahiassistoldsettings’);
      }
      `

      User Data Migration

      `php
      // Migrate user roles and capabilities
      function migrateuserroles() {
      $users = getusers([‘rolenotin’ => [‘administrator’]]);

      foreach ($users as $user) {
      $oldrole = getusermeta($user->ID, ‘shahiassistoldrole’, true);

      if ($oldrole === ‘supportagent’) {
      $user->addrole(‘shahiagent’);
      } elseif ($old_role === ‘customer’) {
      $user->add_role(‘customer’);
      }

      // Migrate user preferences
      $oldprefs = getusermeta($user->ID, ‘shahiassist_preferences’, true);
      if ($old_prefs) {
      updateusermeta($user->ID, ‘shahiassistnewpreferences’, $oldprefs);
      deleteusermeta($user->ID, ‘shahiassistpreferences’);
      }
      }
      }
      `

      Breaking Changes Handling

      API Changes

      `php
      // Handle deprecated API endpoints
      addaction(‘restapi_init’, function() {
      // Register new endpoint
      registerrestroute(‘shahi-assist/v2’, ‘/tickets’, [
      ‘methods’ => ‘GET’,
      ‘callback’ => ‘getticketsv2′,
      ‘permissioncallback’ => ‘checkapi_permissions’,
      ]);

      // Handle deprecated v1 endpoint with warning
      registerrestroute(‘shahi-assist/v1’, ‘/tickets’, [
      ‘methods’ => ‘GET’,
      ‘callback’ => function() {
      // Log deprecation warning
      error_log(‘Deprecated API endpoint used: /shahi-assist/v1/tickets’);

      // Forward to new endpoint
      return getticketsv2();
      },
      ‘permissioncallback’ => ‘checkapi_permissions’,
      ]);
      });
      `

      Hook Changes

      `php
      // Maintain backward compatibility for hooks
      addaction(‘shahiassistticketcreated’, function($ticket_id) {
      // New hook implementation
      doaction(‘shahiassistnewticketcreated’, $ticketid);

      // Trigger deprecated hook for backward compatibility
      doaction(‘shahiassistoldticketcreated’, $ticketid);
      }, 10, 1);

      // Deprecation notice for old hooks
      addaction(‘deprecatedhookused’, function($hookname, $replacement, $version) {
      if (strpos($hookname, ‘shahiassistold‘) === 0) {
      errorlog(“Deprecated hook ‘$hookname’ used. Use ‘$replacement’ instead. Deprecated since version $version.”);
      }
      });
      `

      Rollback Strategies

      Safe Rollback

      `php
      class ShahiAssistRollbackManager {
      private $backup_tables = [];

      public function create_backup() {
      global $wpdb;

      $tablestobackup = [
      $wpdb->posts,
      $wpdb->postmeta,
      $wpdb->prefix . ‘shahiassistcustom_table’
      ];

      foreach ($tablestobackup as $table) {
      $backuptable = $table . ‘backup‘ . date(‘YmdHis’);

      $wpdb->query(“CREATE TABLE $backup_table AS SELECT * FROM $table”);

      $this->backuptables[$table] = $backuptable;
      }

      updateoption(‘shahiassistbackuptables’, $this->backup_tables);
      }

      public function rollback() {
      global $wpdb;

      $backuptables = getoption(‘shahiassistbackup_tables’, []);

      foreach ($backup_tables as $original => $backup) {
      // Drop original table
      $wpdb->query(“DROP TABLE IF EXISTS $original”);

      // Restore from backup
      $wpdb->query(“CREATE TABLE $original AS SELECT * FROM $backup”);
      }

      // Clean up backup tables
      foreach ($backup_tables as $backup) {
      $wpdb->query(“DROP TABLE IF EXISTS $backup”);
      }

      deleteoption(‘shahiassistbackuptables’);
      }
      }
      `

      Partial Rollback

      `php
      // Rollback specific changes
      function rollbackspecificchanges($version) {
      switch ($version) {
      case ‘2.1.0’:
      // Revert database schema changes
      global $wpdb;
      $wpdb->query(“ALTER TABLE {$wpdb->prefix}shahiassisttickets DROP COLUMN new_column”);
      break;

      case ‘2.0.0’:
      // Revert post type changes
      unregisterposttype(‘newposttype’);
      break;

      case ‘1.5.0’:
      // Revert option changes
      deleteoption(‘shahiassistnewoption’);
      break;
      }
      }
      `

      Testing Migrations

      Migration Testing Framework

      `php
      class ShahiAssistMigrationTest {
      public function testmigration($migrationclass) {
      // Create test database
      $this->createtestdatabase();

      // Run migration
      $migration = new $migration_class();
      $migration->up();

      // Verify migration results
      $this->verifymigrationresults($migration_class);

      // Test rollback
      $migration->down();
      $this->verifyrollbackresults($migration_class);

      // Clean up
      $this->cleanuptestdatabase();
      }

      private function createtestdatabase() {
      // Create isolated test environment
      // Use WordPress testing framework or custom setup
      }

      private function verifymigrationresults($migration_class) {
      // Check if tables exist, data is migrated correctly, etc.
      global $wpdb;

      switch ($migration_class) {
      case ‘CreateTicketsTable_Migration’:
      $tableexists = $wpdb->getvar(“SHOW TABLES LIKE ‘{$wpdb->prefix}shahiassisttickets'”);
      assert($table_exists, ‘Tickets table should exist after migration’);
      break;
      }
      }
      }
      `

      Upgrade UI and User Communication

      Admin Upgrade Interface

      `php
      // Add upgrade notice in admin
      addaction(‘adminnotices’, function() {
      $currentversion = getoption(‘shahiassistversion’);
      $latest_version = ‘2.1.0’; // From update API

      if (versioncompare($currentversion, $latest_version, ‘<')) { ?>

      ShahiAssist Update Available
      A new version () is available.

      Upgrade completed successfully!

      ‘;
      }

      // Display upgrade form
      ?>

      `

      User Communication

      `php
      // Notify users about changes
      function notifyusersof_changes($version) {
      $users = getusers([‘rolein’ => [‘administrator’, ‘shahiagent’]]);

      $changelog = getchangelogfor_version($version);

      foreach ($users as $user) {
      wp_mail(
      $user->user_email,
      “ShahiAssist Updated to $version”,
      “ShahiAssist has been updated to version $version.\n\n” .
      “Key changes:\n$changelog\n\n” .
      “Please review the documentation for any required actions.”
      );
      }
      }

      function getchangelogfor_version($version) {
      $changelogs = [
      ‘2.0.0’ => “- New ticket system architecture\n- Improved performance\n- Breaking changes in API endpoints”,
      ‘2.1.0’ => “- Added new features\n- Bug fixes\n- Performance improvements”,
      ];

      return $changelogs[$version] ?? ‘Various improvements and bug fixes’;
      }
      `

      Resources

    5. WordPress Database Migrations
    6. Semantic Versioning
    7. Database Change Management
    8. WordPress Upgrade API

Share this article

Was this article helpful?

Help us improve our documentation

Still need help?

Our support team is ready to assist you with personalized guidance for your workspace.

Submit a support ticket