diff --git a/database/migrations/2026_06_24_123911_backfill_existing_user_avatars.php b/database/migrations/2026_06_24_123911_backfill_existing_user_avatars.php index da81290..5be8b53 100644 --- a/database/migrations/2026_06_24_123911_backfill_existing_user_avatars.php +++ b/database/migrations/2026_06_24_123911_backfill_existing_user_avatars.php @@ -1,57 +1,25 @@ - */ - private const COLORS = [ - '#F97316', - '#22C55E', - '#06B6D4', - '#EC4899', - '#8B5CF6', - '#EAB308', - '#EF4444', - '#14B8A6', - ]; - /** * Run the migrations. */ public function up(): void { - DB::table('users') - ->select(['id', 'name']) + $avatars = app(UpdateUserAvatar::class); + + User::query() ->whereNull('avatar_path') ->orderBy('id') - ->chunkById(100, function (Collection $users): void { + ->chunkById(100, function (Collection $users) use ($avatars): void { foreach ($users as $user) { - $color = self::COLORS[random_int(0, count(self::COLORS) - 1)]; - $path = sprintf('avatars/generated/%d-%s.svg', $user->id, (string) Str::uuid()); - - $stored = Storage::disk('public')->put( - $path, - $this->svg($this->initials((string) $user->name), $color), - ); - - if (! $stored) { - throw new RuntimeException('Generated avatar could not be stored.'); - } - - DB::table('users') - ->where('id', $user->id) - ->update([ - 'avatar_path' => $path, - 'avatar_color' => $color, - 'avatar_is_generated' => true, - ]); + $avatars->generate($user); } }); } @@ -61,18 +29,19 @@ return new class extends Migration */ public function down(): void { - DB::table('users') - ->select(['avatar_path']) + $avatars = app(UpdateUserAvatar::class); + + User::query() ->where('avatar_is_generated', true) ->whereNotNull('avatar_path') ->orderBy('id') - ->chunkById(100, function (Collection $users): void { + ->chunkById(100, function (Collection $users) use ($avatars): void { foreach ($users as $user) { - Storage::disk('public')->delete($user->avatar_path); + $avatars->delete($user); } }); - DB::table('users') + User::query() ->where('avatar_is_generated', true) ->update([ 'avatar_path' => null, @@ -80,30 +49,4 @@ return new class extends Migration 'avatar_is_generated' => false, ]); } - - private function initials(string $name): string - { - $parts = preg_split('/\s+/u', trim($name)) ?: []; - - if ($parts === []) { - return '?'; - } - - $first = mb_substr($parts[0], 0, 1); - $last = count($parts) > 1 ? mb_substr($parts[count($parts) - 1], 0, 1) : ''; - - return mb_strtoupper($first.$last); - } - - private function svg(string $initials, string $color): string - { - $escapedInitials = htmlspecialchars($initials, ENT_QUOTES | ENT_XML1, 'UTF-8'); - - return << - - {$escapedInitials} - -SVG; - } };