Adds user avatar management
parent
84664f8b5f
commit
fd949f6f4f
|
@ -85,6 +85,78 @@ class User {
|
|||
|
||||
}
|
||||
|
||||
// remove an avatar
|
||||
public function removeAvatar($user_id, $old_avatar = '') {
|
||||
try {
|
||||
// remove from database
|
||||
$sql = 'UPDATE users_meta SET
|
||||
avatar = NULL
|
||||
WHERE user_id = :user_id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':user_id' => $user_id,
|
||||
]);
|
||||
|
||||
// delete the old avatar file
|
||||
if ($old_avatar && file_exists($old_avatar)) {
|
||||
unlink($old_avatar);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// change an avatar
|
||||
public function changeAvatar($user_id, $avatar_file, $avatars_path) {
|
||||
try {
|
||||
// check if the file was uploaded
|
||||
if (isset($avatar_file) && $avatar_file['error'] === UPLOAD_ERR_OK) {
|
||||
$fileTmpPath = $avatar_file['tmp_name'];
|
||||
$fileName = $avatar_file['name'];
|
||||
$fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
||||
|
||||
// validate file extension
|
||||
if (in_array($fileExtension, ['jpg', 'png', 'jpeg'])) {
|
||||
$newFileName = md5(time() . $fileName) . '.' . $fileExtension;
|
||||
$dest_path = $avatars_path . $newFileName;
|
||||
|
||||
// move the file to avatars folder
|
||||
if (move_uploaded_file($fileTmpPath, $dest_path)) {
|
||||
try {
|
||||
// update user's avatar path in DB
|
||||
$sql = 'UPDATE users_meta SET
|
||||
avatar = :avatar
|
||||
WHERE user_id = :user_id';
|
||||
$query = $this->db->prepare($sql);
|
||||
$query->execute([
|
||||
':avatar' => $newFileName,
|
||||
':user_id' => $user_id
|
||||
]);
|
||||
// all went OK
|
||||
$_SESSION['notice'] = 'Avatar updated successfully!';
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] = 'Error moving the uploaded file.';
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] = 'Invalid avatar file type.';
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] = 'Error uploading the avatar file.';
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -5,16 +5,41 @@ require '../app/classes/user.php';
|
|||
|
||||
$userObject = new User($dbWeb);
|
||||
|
||||
$userDetails = $userObject->getUserDetails($user);
|
||||
|
||||
// if a form is submitted, it's from the edit page
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
|
||||
$user_id = $userObject->getUserId($user)[0]['id'];
|
||||
|
||||
$item = $_REQUEST['item'] ?? '';
|
||||
|
||||
// avatar editing
|
||||
if ($item === 'avatar') {
|
||||
switch ($action) {
|
||||
case 'remove':
|
||||
$result = $userObject->removeAvatar($user_id, $config['avatars_path'].$userDetails[0]['avatar']);
|
||||
if ($result === true) {
|
||||
$_SESSION['notice'] = "Avatar for user \"{$user}\" is removed.";
|
||||
} else {
|
||||
$_SESSION['error'] = "Removing the avatar failed. Error: $result";
|
||||
}
|
||||
break;
|
||||
case 'edit':
|
||||
$result = $userObject->changeAvatar($user_id, $_FILES['avatar_file'], $config['avatars_path']);
|
||||
break;
|
||||
default:
|
||||
$_SESSION['error'] = "Unspecified avatar editing action.";
|
||||
}
|
||||
|
||||
header("Location: $app_root?page=profile");
|
||||
exit();
|
||||
}
|
||||
|
||||
// update the profile
|
||||
$updatedUser = [
|
||||
'name' => $_POST['name'] ?? '',
|
||||
'email' => $_POST['email'] ?? '',
|
||||
// 'avatar' => ,
|
||||
'bio' => $_POST['bio'] ?? '',
|
||||
];
|
||||
$result = $userObject->editUser($user_id, $updatedUser);
|
||||
|
@ -29,8 +54,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
|||
|
||||
// no form submitted, show the templates
|
||||
} else {
|
||||
$userDetails = $userObject->getUserDetails($user);
|
||||
$avatar = !empty($userDetails['avatar']) ? 'uploads/avatars/'.$userDetails['avatar'] : $config['default_avatar'];
|
||||
$avatar = !empty($userDetails[0]['avatar']) ? $config['avatars_path'] . $userDetails[0]['avatar'] : $config['default_avatar'];
|
||||
|
||||
switch ($action) {
|
||||
|
||||
|
|
|
@ -5,19 +5,29 @@
|
|||
<p class="h4 card-header">Profile of <?= $userDetails[0]['username'] ?></p>
|
||||
<div class="card-body">
|
||||
|
||||
<form method="POST" action="<?= $app_root ?>?page=profile">
|
||||
|
||||
<div class="row">
|
||||
<p class="border rounded bg-light mb-4"><small>edit the profile fields</small></p>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="border" style="width:200px; height: 200px;">
|
||||
<img src="<?= $app_root . htmlspecialchars($avatar) ?>" width="200" height="200" alt="avatar" />
|
||||
<div class="col-md-4 avatar-container">
|
||||
<div>
|
||||
<img class="avatar-img" src="<?= $app_root . htmlspecialchars($avatar) ?>" alt="avatar" />
|
||||
|
||||
<form method="POST" action="<?= $app_root ?>?page=profile&action=edit&item=avatar" enctype="multipart/form-data">
|
||||
<label for="avatar-upload" class="avatar-btn btn btn-primary"><small>select avatar</small></label>
|
||||
<input type="file" id="avatar-upload" name="avatar_file" accept="image/*" style="display:none;">
|
||||
<input type="submit" class="avatar-btn btn btn-success" value="upload new avatar">
|
||||
</form>
|
||||
|
||||
<form method="POST" action="<?= $app_root ?>?page=profile&action=remove&item=avatar">
|
||||
<input type="submit" id="avatar-remove" class="avatar-btn btn btn-danger" value="remove avatar" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
|
||||
<form method="POST" action="<?= $app_root ?>?page=profile">
|
||||
|
||||
<!--div class="row mb-3">
|
||||
<div class="col-md-4 text-end">
|
||||
<label for="username" class="form-label"><small>username:</small></label>
|
||||
|
@ -76,3 +86,13 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- /user profile -->
|
||||
|
||||
<script>
|
||||
document.getElementById('avatar-upload').addEventListener('change', function(event) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
document.querySelector('.avatar-img').src = reader.result;
|
||||
};
|
||||
reader.readAsDataURL(event.target.files[0]);
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="border" style="width:200px; height: 200px;">
|
||||
<img src="<?= $app_root . htmlspecialchars($avatar) ?>" width="200" height="200" alt="avatar" />
|
||||
<div class="col-md-4 avatar-container">
|
||||
<div>
|
||||
<img class="avatar-img" src="<?= $app_root . htmlspecialchars($avatar) ?>" alt="avatar" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -171,3 +171,18 @@
|
|||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* avatar */
|
||||
.avatar-container {
|
||||
text-align: center;
|
||||
}
|
||||
.avatar-img {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover; /* Ensures proper cropping of image */
|
||||
border: 3px solid #ccc;
|
||||
}
|
||||
.avatar-btn {
|
||||
margin-top: 10px;
|
||||
}
|
Loading…
Reference in New Issue