diff --git a/app/Commands/MergeAccountsCommand.php b/app/Commands/MergeAccountsCommand.php new file mode 100644 index 00000000..c41eb087 --- /dev/null +++ b/app/Commands/MergeAccountsCommand.php @@ -0,0 +1,120 @@ +. + */ + +namespace Poniverse\Ponyfm\Commands; + +use Carbon\Carbon; +use DB; +use Poniverse\Ponyfm\Models\Album; +use Poniverse\Ponyfm\Models\Comment; +use Poniverse\Ponyfm\Models\Favourite; +use Poniverse\Ponyfm\Models\Follower; +use Poniverse\Ponyfm\Models\Image; +use Poniverse\Ponyfm\Models\PinnedPlaylist; +use Poniverse\Ponyfm\Models\Playlist; +use Poniverse\Ponyfm\Models\ResourceLogItem; +use Poniverse\Ponyfm\Models\ResourceUser; +use Poniverse\Ponyfm\Models\Track; +use Poniverse\Ponyfm\Models\User; + +class MergeAccountsCommand extends CommandBase +{ + private $sourceAccount; + private $destinationAccount; + + function __construct(User $sourceAccount, User $destinationAccount) + { + $this->sourceAccount = $sourceAccount; + $this->destinationAccount = $destinationAccount; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + DB::transaction(function() { + $accountIds = [$this->sourceAccount->id]; + + foreach (Album::whereIn('user_id', $accountIds)->get() as $album) { + $album->user_id = $this->destinationAccount->id; + $album->save(); + } + + foreach (Comment::whereIn('user_id', $accountIds)->get() as $comment) { + $comment->user_id = $this->destinationAccount->id; + $comment->save(); + } + + foreach (Favourite::whereIn('user_id', $accountIds)->get() as $favourite) { + $favourite->user_id = $this->destinationAccount->id; + $favourite->save(); + } + + foreach (Follower::whereIn('artist_id', $accountIds)->get() as $follow) { + $follow->artist_id = $this->destinationAccount->id; + $follow->save(); + } + + foreach (Image::whereIn('uploaded_by', $accountIds)->get() as $image) { + $image->uploaded_by = $this->destinationAccount->id; + $image->save(); + } + + foreach (Image::whereIn('uploaded_by', $accountIds)->get() as $image) { + $image->uploaded_by = $this->destinationAccount->id; + $image->save(); + } + + DB::table('oauth2_tokens')->whereIn('user_id', $accountIds)->update(['user_id' => $this->destinationAccount->id]); + + foreach (PinnedPlaylist::whereIn('user_id', $accountIds)->get() as $playlist) { + $playlist->user_id = $this->destinationAccount->id; + $playlist->save(); + } + + foreach (Playlist::whereIn('user_id', $accountIds)->get() as $playlist) { + $playlist->user_id = $this->destinationAccount->id; + $playlist->save(); + } + + foreach (ResourceLogItem::whereIn('user_id', $accountIds)->get() as $item) { + $item->user_id = $this->destinationAccount->id; + $item->save(); + } + + foreach (ResourceUser::whereIn('user_id', $accountIds)->get() as $item) { + $item->user_id = $this->destinationAccount->id; + $item->save(); + } + + foreach (Track::whereIn('user_id', $accountIds)->get() as $track) { + $track->user_id = $this->destinationAccount->id; + $track->save(); + } + + $this->sourceAccount->disabled_at = Carbon::now(); + $this->sourceAccount->save(); + }); + + return CommandResponse::succeed(); + } +} diff --git a/app/Console/Commands/MergeAccounts.php b/app/Console/Commands/MergeAccounts.php new file mode 100644 index 00000000..1e3a12c6 --- /dev/null +++ b/app/Console/Commands/MergeAccounts.php @@ -0,0 +1,86 @@ +. + */ + +namespace Poniverse\Ponyfm\Console\Commands; + +use Carbon\Carbon; +use DB; +use Illuminate\Console\Command; +use Illuminate\Support\Collection; +use Poniverse\Ponyfm\Commands\MergeAccountsCommand; +use Poniverse\Ponyfm\Models\Album; +use Poniverse\Ponyfm\Models\Comment; +use Poniverse\Ponyfm\Models\Favourite; +use Poniverse\Ponyfm\Models\Follower; +use Poniverse\Ponyfm\Models\Image; +use Poniverse\Ponyfm\Models\PinnedPlaylist; +use Poniverse\Ponyfm\Models\Playlist; +use Poniverse\Ponyfm\Models\ResourceLogItem; +use Poniverse\Ponyfm\Models\ResourceUser; +use Poniverse\Ponyfm\Models\Track; +use Poniverse\Ponyfm\Models\User; + +class MergeAccounts extends Command +{ + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'accounts:merge + {sourceAccountId : ID of the source account (the one being disabled and having content transferred out of it)} + {destinationAccountId : ID of the destination account (the one gaining content)}'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Merges two accounts'; + + /** + * Create a new command instance. + * + * @return void + */ + public function __construct() + { + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + $sourceAccountId = $this->argument('sourceAccountId'); + $destinationAccountId = $this->argument('destinationAccountId'); + + $sourceAccount = User::find($sourceAccountId); + $destinationAccount = User::find($destinationAccountId); + + $this->info("Merging {$sourceAccount->display_name} ({$sourceAccountId}) into {$destinationAccount->display_name} ({$destinationAccountId})..."); + + $command = new MergeAccountsCommand($sourceAccount, $destinationAccount); + $command->execute(); + } +} diff --git a/app/Console/Commands/MergeDuplicateAccounts.php b/app/Console/Commands/MergeDuplicateAccounts.php deleted file mode 100644 index 0a400a55..00000000 --- a/app/Console/Commands/MergeDuplicateAccounts.php +++ /dev/null @@ -1,163 +0,0 @@ -. - */ - -namespace Poniverse\Ponyfm\Console\Commands; - -use Carbon\Carbon; -use DB; -use Illuminate\Console\Command; -use Illuminate\Support\Collection; -use Poniverse\Ponyfm\Models\Album; -use Poniverse\Ponyfm\Models\Comment; -use Poniverse\Ponyfm\Models\Favourite; -use Poniverse\Ponyfm\Models\Follower; -use Poniverse\Ponyfm\Models\Image; -use Poniverse\Ponyfm\Models\PinnedPlaylist; -use Poniverse\Ponyfm\Models\Playlist; -use Poniverse\Ponyfm\Models\ResourceLogItem; -use Poniverse\Ponyfm\Models\ResourceUser; -use Poniverse\Ponyfm\Models\Track; -use Poniverse\Ponyfm\Models\User; - -class MergeDuplicateAccounts extends Command -{ - /** - * The name and signature of the console command. - * - * @var string - */ - protected $signature = 'auth:merge-duplicates'; - - /** - * The console command description. - * - * @var string - */ - protected $description = 'Merges duplicate accounts'; - - /** - * Create a new command instance. - * - * @return void - */ - public function __construct() - { - parent::__construct(); - } - - /** - * Execute the console command. - * - * @return mixed - */ - public function handle() - { - // Get list of affected users - $usernames = DB::table('users') - ->select(['username', DB::raw('COUNT(*) as count')]) - ->whereNull('disabled_at') - ->whereNotNull('username') - ->groupBy(DB::raw('LOWER(username)')) - ->having('count', '>=', 2) - ->lists('username'); - - foreach($usernames as $username) { - // Find the relevant accounts - // ========================== - - /** @var Collection $accounts */ - $accounts = User::where('username', $username)->orderBy('created_at', 'ASC')->get(); - $firstAccount = $accounts[0]; - $accounts->forget(0); - $accountIds = $accounts->pluck('id'); - - - // Reassign content - // ================ - // This is done with the less-efficient-than-raw-SQL Eloquent - // methods to generate appropriate revision logs. - - $this->info('Merging duplicates for: '.$firstAccount->username); - DB::transaction(function() use ($accounts, $accountIds, $firstAccount) { - foreach (Album::whereIn('user_id', $accountIds)->get() as $album) { - $album->user_id = $firstAccount->id; - $album->save(); - } - - foreach (Comment::whereIn('user_id', $accountIds)->get() as $comment) { - $comment->user_id = $firstAccount->id; - $comment->save(); - } - - foreach (Favourite::whereIn('user_id', $accountIds)->get() as $favourite) { - $favourite->user_id = $firstAccount->id; - $favourite->save(); - } - - foreach (Follower::whereIn('artist_id', $accountIds)->get() as $follow) { - $follow->artist_id = $firstAccount->id; - $follow->save(); - } - - foreach (Image::whereIn('uploaded_by', $accountIds)->get() as $image) { - $image->uploaded_by = $firstAccount->id; - $image->save(); - } - - foreach (Image::whereIn('uploaded_by', $accountIds)->get() as $image) { - $image->uploaded_by = $firstAccount->id; - $image->save(); - } - - DB::table('oauth2_tokens')->whereIn('user_id', $accountIds)->update(['user_id' => $firstAccount->id]); - - foreach (PinnedPlaylist::whereIn('user_id', $accountIds)->get() as $playlist) { - $playlist->user_id = $firstAccount->id; - $playlist->save(); - } - - foreach (Playlist::whereIn('user_id', $accountIds)->get() as $playlist) { - $playlist->user_id = $firstAccount->id; - $playlist->save(); - } - - foreach (ResourceLogItem::whereIn('user_id', $accountIds)->get() as $item) { - $item->user_id = $firstAccount->id; - $item->save(); - } - - foreach (ResourceUser::whereIn('user_id', $accountIds)->get() as $item) { - $item->user_id = $firstAccount->id; - $item->save(); - } - - foreach (Track::whereIn('user_id', $accountIds)->get() as $track) { - $track->user_id = $firstAccount->id; - $track->save(); - } - - foreach($accounts as $account) { - $account->disabled_at = Carbon::now(); - $account->save(); - } - }); - } - } -} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 93446c6d..988d835e 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -43,7 +43,7 @@ class Kernel extends ConsoleKernel \Poniverse\Ponyfm\Console\Commands\RebuildTrack::class, \Poniverse\Ponyfm\Console\Commands\RebuildFilesizes::class, \Poniverse\Ponyfm\Console\Commands\RebuildSearchIndex::class, - \Poniverse\Ponyfm\Console\Commands\MergeDuplicateAccounts::class, + \Poniverse\Ponyfm\Console\Commands\MergeAccounts::class, ]; /**