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,32 +5,56 @@ require '../app/classes/user.php';
|
||||||
|
|
||||||
$userObject = new User($dbWeb);
|
$userObject = new User($dbWeb);
|
||||||
|
|
||||||
|
$userDetails = $userObject->getUserDetails($user);
|
||||||
|
|
||||||
// if a form is submitted, it's from the edit page
|
// if a form is submitted, it's from the edit page
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
|
|
||||||
$user_id = $userObject->getUserId($user)[0]['id'];
|
$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
|
// update the profile
|
||||||
$updatedUser = [
|
$updatedUser = [
|
||||||
'name' => $_POST['name'] ?? '',
|
'name' => $_POST['name'] ?? '',
|
||||||
'email' => $_POST['email'] ?? '',
|
'email' => $_POST['email'] ?? '',
|
||||||
// 'avatar' => ,
|
|
||||||
'bio' => $_POST['bio'] ?? '',
|
'bio' => $_POST['bio'] ?? '',
|
||||||
];
|
];
|
||||||
$result = $userObject->editUser($user_id, $updatedUser);
|
$result = $userObject->editUser($user_id, $updatedUser);
|
||||||
if ($result === true) {
|
if ($result === true) {
|
||||||
$_SESSION['notice'] = "User details for \"{$updatedUser['name']}\" are edited.";
|
$_SESSION['notice'] = "User details for \"{$updatedUser['name']}\" are edited.";
|
||||||
} else {
|
} else {
|
||||||
$_SESSION['error'] = "Editing the user details failed. Error: $result";
|
$_SESSION['error'] = "Editing the user details failed. Error: $result";
|
||||||
}
|
}
|
||||||
|
|
||||||
header("Location: $app_root?page=profile");
|
header("Location: $app_root?page=profile");
|
||||||
exit();
|
exit();
|
||||||
|
|
||||||
// no form submitted, show the templates
|
// no form submitted, show the templates
|
||||||
} else {
|
} else {
|
||||||
$userDetails = $userObject->getUserDetails($user);
|
$avatar = !empty($userDetails[0]['avatar']) ? $config['avatars_path'] . $userDetails[0]['avatar'] : $config['default_avatar'];
|
||||||
$avatar = !empty($userDetails['avatar']) ? 'uploads/avatars/'.$userDetails['avatar'] : $config['default_avatar'];
|
|
||||||
|
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
|
|
||||||
|
|
|
@ -5,18 +5,28 @@
|
||||||
<p class="h4 card-header">Profile of <?= $userDetails[0]['username'] ?></p>
|
<p class="h4 card-header">Profile of <?= $userDetails[0]['username'] ?></p>
|
||||||
<div class="card-body">
|
<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="row">
|
<div class="col-md-4 avatar-container">
|
||||||
<p class="border rounded bg-light mb-4"><small>edit the profile fields</small></p>
|
<div>
|
||||||
|
<img class="avatar-img" src="<?= $app_root . htmlspecialchars($avatar) ?>" alt="avatar" />
|
||||||
|
|
||||||
<div class="col-md-4">
|
<form method="POST" action="<?= $app_root ?>?page=profile&action=edit&item=avatar" enctype="multipart/form-data">
|
||||||
<div class="border" style="width:200px; height: 200px;">
|
<label for="avatar-upload" class="avatar-btn btn btn-primary"><small>select avatar</small></label>
|
||||||
<img src="<?= $app_root . htmlspecialchars($avatar) ?>" width="200" height="200" alt="avatar" />
|
<input type="file" id="avatar-upload" name="avatar_file" accept="image/*" style="display:none;">
|
||||||
</div>
|
<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>
|
||||||
|
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
|
|
||||||
|
<form method="POST" action="<?= $app_root ?>?page=profile">
|
||||||
|
|
||||||
<!--div class="row mb-3">
|
<!--div class="row mb-3">
|
||||||
<div class="col-md-4 text-end">
|
<div class="col-md-4 text-end">
|
||||||
|
@ -76,3 +86,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- /user profile -->
|
<!-- /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="row">
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4 avatar-container">
|
||||||
<div class="border" style="width:200px; height: 200px;">
|
<div>
|
||||||
<img src="<?= $app_root . htmlspecialchars($avatar) ?>" width="200" height="200" alt="avatar" />
|
<img class="avatar-img" src="<?= $app_root . htmlspecialchars($avatar) ?>" alt="avatar" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -171,3 +171,18 @@
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: 14px;
|
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