Skip to content

Commit

Permalink
First stab for migrating 3.1 => 4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
alexweissman committed Nov 26, 2017
1 parent 2166f44 commit 0adb7bf
Show file tree
Hide file tree
Showing 2 changed files with 299 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.komodoproject
298 changes: 298 additions & 0 deletions src/Bakery/Upgrade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
<?php

namespace UserFrosting\Sprinkle\Upgrade\Bakery;

use Carbon\Carbon;
use Illuminate\Database\Capsule\Manager as DB;
use Illuminate\Support\Str;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use UserFrosting\Sprinkle\Account\Database\Models\Permission;
use UserFrosting\Sprinkle\Account\Database\Models\Role;
use UserFrosting\System\Bakery\BaseCommand;
use UserFrosting\System\Bakery\DatabaseTest;

class Upgrade extends BaseCommand
{
use DatabaseTest;

/**
* @var @Illuminate\Database\Schema
*/
protected $schema;

protected $sourceTables = [
'authorize_group',
'authorize_user',
'configuration',
'group',
'group_user',
'user',
'user_event',
'user_rememberme'
];

protected $defaultRoles;

protected $defaultPermissions;

protected $legacyPrefix = '';

protected function configure()
{
// the name of the command (the part after "php bakery")
$this->setName("upgrade");

// the short description shown while running "php bakery list"
$this->setDescription("Upgrade a UF 3.1 database to UF 4.1.");
}

protected function execute(InputInterface $input, OutputInterface $output)
{
// Set up DB connection
$this->testDB();

// Get schema required to run the table blueprints
$this->schema = DB::schema();

$this->io->writeln("<info>This command will attempt to install UserFrosting 4.1 on top of an existing UF 3.1 database, and migrate your users, groups, and events. Once this is complete, you should begin migrating the code from your UF 3.1 application to a new UF4 Sprinkle.</info>");

$command = $this->getApplication()->find('setup');
$command->run($input, $output);

$command = $this->getApplication()->find('debug');
$command->run($input, $output);

// Database has connected successfully, so we'll begin the migration process

// First, get the prefix for the 3.1 tables and confirm the tables that will be migrated.
$hasPrefix = $this->io->confirm('Do your UserFrosting 3.1 tables have a prefix?', true);

if ($hasPrefix) {
$this->legacyPrefix = $this->io->ask('What is the table prefix?', 'uf_');
}

$renamedSourceTables = $this->mapOldTableNames($this->sourceTables);
$notFoundTables = [];

$this->io->note('The following tables in your database will be renamed before being migrated to UF4');
foreach ($renamedSourceTables as $oldName => $newName) {
if ($this->schema->hasTable($oldName)) {
$this->io->text($oldName . ' => ' . $newName);
} else {
$notFoundTables[] = $oldName;
}
}

if (!empty($notFoundTables)) {
$this->io->caution('The following expected tables could not be found:');
$this->io->text($notFoundTables);
}

if (!$this->io->confirm('Continue?', true)) {
exit(0);
}
// Rename the 3.1 tables
foreach ($renamedSourceTables as $oldName => $newName) {
$this->schema->rename($oldName, $newName);
}

// Install the UF4 tables
$command = $this->getApplication()->find('migrate');
$command->run($input, $output);

// Get the default roles, and their permissions
$this->defaultPermissions = Permission::get();
$this->defaultRoles = Role::with('permissions')->get();

// Migrate data from 3.1 -> 4.1
// Groups become both Roles and Groups in UF4
$this->migrateGroups($renamedSourceTables[$this->legacyPrefix . 'group']);
$this->migrateRoles($renamedSourceTables[$this->legacyPrefix . 'group']);
$this->migratePermissions($renamedSourceTables[$this->legacyPrefix . 'authorize_group']);

$this->migrateUsers($renamedSourceTables[$this->legacyPrefix . 'user']);
$this->migrateUserRoles($renamedSourceTables[$this->legacyPrefix . 'group_user']);
$this->migrateActivities($renamedSourceTables[$this->legacyPrefix . 'user_event']);

// Re-add the default roles and permissions
$newPermissionsDictionary = [];
foreach ($this->defaultPermissions as $permission) {
$newId = DB::connection()->table('permissions')->insertGetId([
'slug' => $permission->slug,
'name' => $permission->name,
'conditions' => $permission->conditions,
'description' => $permission->description,
'created_at' => $permission->created_at,
'updated_at' => $permission->updated_at
]);

$newPermissionsDictionary[$permission->id] = $newId;
}

$newPermissionMappings = [];
foreach ($this->defaultRoles as $role) {
$newRoleId = DB::connection()->table('roles')->insertGetId([
'slug' => $role->slug,
'name' => $role->name,
'description' => $role->description,
'created_at' => $role->created_at,
'updated_at' => $role->updated_at
]);

foreach ($role->permissions as $permission) {
$newPermissionId = $newPermissionsDictionary[$permission->id];
$newPermissionMappings[] = [
'permission_id' => $newPermissionId,
'role_id' => $newRoleId,
'created_at' => $permission->pivot->created_at,
'updated_at' => $permission->pivot->updated_at
];
}
}

DB::connection()->table('permission_roles')->insert($newPermissionMappings);
}

protected function migrateGroups($tableName)
{
// Clear out the default UF4 groups
DB::connection()->table('groups')->truncate();

$legacyRows = DB::connection()->table($tableName)->get();

foreach ($legacyRows as $legacyRow) {
DB::connection()->table('groups')->insert([
'id' => $legacyRow->id,
'slug' => Str::slug($legacyRow->name),
'name' => $legacyRow->name,
'description' => '',
'icon' => $legacyRow->icon,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
}
}

protected function migrateRoles($tableName)
{
// Clear out the default UF4 roles
DB::connection()->table('roles')->truncate();

$legacyRows = DB::connection()->table($tableName)->get();

foreach ($legacyRows as $legacyRow) {
DB::connection()->table('roles')->insert([
'id' => $legacyRow->id,
'slug' => Str::slug($legacyRow->name),
'name' => $legacyRow->name,
'description' => '',
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
}
}

protected function migratePermissions($tableName)
{
// Clear out the default UF4 permissions
DB::connection()->table('permissions')->truncate();
DB::connection()->table('permission_roles')->truncate();

$legacyRows = DB::connection()->table($tableName)->where('id', '>', 10)->get();

foreach ($legacyRows as $legacyRow) {
DB::connection()->table('permissions')->insert([
'id' => $legacyRow->id,
'slug' => $legacyRow->hook,
'name' => $legacyRow->hook,
'conditions' => $legacyRow->conditions,
'description' => '',
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);

DB::connection()->table('permission_roles')->insert([
'permission_id' => $legacyRow->id,
'role_id' => $legacyRow->group_id,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now()
]);
}
}

protected function migrateUsers($tableName)
{
$legacyRows = DB::connection()->table($tableName)->get();

foreach ($legacyRows as $legacyRow) {
list($firstName, $lastName) = explode(' ', $legacyRow->display_name);

DB::connection()->table('users')->insert([
'id' => $legacyRow->id,
'user_name' => $legacyRow->user_name,
'email' => $legacyRow->email,
'first_name' => $firstName ? $firstName : '',
'last_name' => $lastName ? $lastName : '',
'locale' => $legacyRow->locale,
'theme' => null,
'group_id' => $legacyRow->primary_group_id,
'flag_verified' => $legacyRow->flag_verified,
'flag_enabled' => $legacyRow->flag_enabled,
'last_activity_id' => null,
'password' => $legacyRow->password,
'deleted_at' => null,
'created_at' => $legacyRow->created_at,
'updated_at' => $legacyRow->updated_at
]);
}

// TODO: set theme, last_activity_id for each user
}

protected function migrateUserRoles($tableName)
{
// Clear out the default UF4 mappings
DB::connection()->table('role_users')->truncate();

$legacyRows = DB::connection()->table($tableName)->get();

foreach ($legacyRows as $legacyRow) {
DB::connection()->table('role_users')->insert([
'user_id' => $legacyRow->user_id,
'role_id' => $legacyRow->group_id
]);
}
}

protected function migrateActivities($tableName)
{
$legacyRows = DB::connection()->table($tableName)->get();

foreach ($legacyRows as $legacyRow) {
DB::connection()->table('activities')->insert([
'ip_address' => null,
'user_id' => $legacyRow->user_id,
'type' => $legacyRow->event_type,
'occurred_at' => $legacyRow->occurred_at,
'description' => $legacyRow->description
]);
}
}

protected function mapOldTableNames($sourceTables)
{
$randomPrefix = str_random(10);

$renamedSourceTables = [];
foreach ($sourceTables as $baseName) {
$oldName = $this->legacyPrefix . $baseName;
$newName = $randomPrefix . '_' . $oldName;
$renamedSourceTables[$oldName] = $newName;
}

return $renamedSourceTables;
}
}

0 comments on commit 0adb7bf

Please sign in to comment.