Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/Http/Controllers/Settings/ProfileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public function update(ProfileUpdateRequest $request): RedirectResponse

$request->user()->save();

if ($request->hasFile('photo')) {
$request->user()->updateProfilePhoto($request->validated('photo'));
}

return to_route('profile.edit');
}

Expand All @@ -53,6 +57,8 @@ public function destroy(Request $request): RedirectResponse

Auth::logout();

$user->deleteProfilePhoto();

$user->delete();

$request->session()->invalidate();
Expand Down
23 changes: 23 additions & 0 deletions app/Http/Controllers/Settings/ProfilePhotoController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\Http\Controllers\Settings;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class ProfilePhotoController extends Controller
{
/**
* Delete the current user's profile photo.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Request $request): RedirectResponse
{
$request->user()->deleteProfilePhoto();

return to_route('profile.edit');
}
}
2 changes: 2 additions & 0 deletions app/Http/Requests/Settings/ProfileUpdateRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public function rules(): array
'max:255',
Rule::unique(User::class)->ignore($this->user()->id),
],

'photo' => ['nullable', 'image', 'mimes:jpg,jpeg,png', 'max:2048'],
];
}
}
12 changes: 11 additions & 1 deletion app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use App\Traits\HasProfilePhoto;

class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
use HasFactory, Notifiable, HasProfilePhoto;

/**
* The attributes that are mass assignable.
Expand All @@ -33,6 +34,15 @@ class User extends Authenticatable
'remember_token',
];

/**
* The accessors to append to the model's array form.
*
* @var array<int, string>
*/
protected $appends = [
'avatar',
];

/**
* Get the attributes that should be cast.
*
Expand Down
79 changes: 79 additions & 0 deletions app/Traits/HasProfilePhoto.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

trait HasProfilePhoto
{
/**
* Update the user's profile photo.
*
* @param \Illuminate\Http\UploadedFile $photo
* @param string $storagePath
* @return void
*/
public function updateProfilePhoto(UploadedFile $photo, $storagePath = 'profile-photos'): void
{
tap($this->profile_photo_path, function ($previous) use ($photo, $storagePath) {
$this->forceFill([
'profile_photo_path' => $photo->storePublicly(
$storagePath, ['disk' => $this->profilePhotoDisk()]
),
])->save();

if ($previous) {
Storage::disk($this->profilePhotoDisk())->delete($previous);
}
});
}

/**
* Delete the user's profile photo.
*
* @return void
*/
public function deleteProfilePhoto(): void
{
if (is_null($this->profile_photo_path)) {
return;
}

Storage::disk($this->profilePhotoDisk())->delete($this->profile_photo_path);

$this->forceFill([
'profile_photo_path' => null,
])->save();
}

/**
* Get the URL to the user's profile photo.
*
* @return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function avatar(): Attribute
{
return Attribute::make(
get: function ($value) {
return $this->profile_photo_path
? Storage::disk($this->profilePhotoDisk())->url($this->profile_photo_path)
: null;
},
set: function ($value) {
return ['profile_photo_path' => $value];
}
);
}

/**
* Get the disk that profile photos should be stored on.
*
* @return string
*/
protected function profilePhotoDisk(): string
{
return 'public';
}
}
1 change: 1 addition & 0 deletions database/factories/UserFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function definition(): array
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
'profile_photo_path' => null,
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public function up(): void
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->string('profile_photo_path', 2048)->nullable();
$table->timestamps();
});

Expand Down
Loading