Archived
1
0

Automatically crop uploaded profile pictures (fix #10) and migrate profile editing page to Bootstrap 4 (fix #8). General improvements to the process of profile editing

This commit is contained in:
KingOfDog 2018-10-23 22:22:22 +02:00
parent 2b5632fe95
commit 0ea56d1292
5 changed files with 1805 additions and 1757 deletions

View File

@ -14,7 +14,7 @@ class File extends MY_Controller
if ($title == null) {
redirect(base_url());
} else {
$file = $this->db->query('SELECT name, type, path FROM files WHERE name = ?', [urldecode($title)])->result_array();
$file = $this->db->query('SELECT name, type, path, isUserData FROM files WHERE name = ?', [urldecode($title)])->result_array();
if (!empty($file)) {
$file = $file[0];
@ -25,7 +25,7 @@ class File extends MY_Controller
header("Content-Disposition: attachment; filename=" . $file['name'] . '.' . explode('/', $file['type'])[1]);
}
$imagePath = 'files/' . (isset($_GET['w']) || isset($_GET['h']) ? 'thumbs/' : '') . $file['name'] . (isset($_GET['w']) ? '_w' . $_GET['w'] : '') . (isset($_GET['h']) ? '_h' . $_GET['h'] : '') . '.' . explode('.', $file['path'])[1];
$imagePath = 'files/' . ($file['isUserData'] ? 'userContent/' : '') . (isset($_GET['w']) || isset($_GET['h']) ? 'thumbs/' : '') . $file['name'] . (isset($_GET['w']) ? '_w' . $_GET['w'] : '') . (isset($_GET['h']) ? '_h' . $_GET['h'] : '') . '.' . explode('.', $file['path'])[1];
if (!file_exists($imagePath)) {
$config['image_library'] = 'gd2';

View File

@ -1,10 +1,10 @@
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
defined('BASEPATH') OR exit('No direct script access allowed');
use Coduo\PHPHumanizer\DateTimeHumanizer;
use Coduo\PHPHumanizer\DateTimeHumanizer;
class User extends MY_Controller
{
class User extends MY_Controller
{
public function __construct()
{
@ -221,7 +221,8 @@
if (strlen($content) >= 10000) {
?>
<div class="alert alert-warning" role="alert">
<b>Veröffentlichung des Posts fehlgeschlagen!</b> Dein Post ist leider zu lang. Er darf maximal 10.000 Zeichen umfassen.
<b>Veröffentlichung des Posts fehlgeschlagen!</b> Dein Post ist leider zu lang. Er darf maximal 10.000
Zeichen umfassen.
</div>
<?php
exit;
@ -231,7 +232,8 @@
if ($replyTo !== "-1" && !$this->PostsModel->isUUIDValid($replyTo)) {
?>
<div class="alert alert-warning" role="alert">
<b>Veröffentlichung des Posts fehlgeschlagen!</b> Der Post, an den du deine Antwort richten willst, existiert nicht (mehr).<br>
<b>Veröffentlichung des Posts fehlgeschlagen!</b> Der Post, an den du deine Antwort richten willst,
existiert nicht (mehr).<br>
Solltest du dies für einen Fehler halten, versuche es später erneut oder kontaktiere uns.
</div>
<?php
@ -261,7 +263,8 @@
<div class="alert alert-success" role="alert">
<b>Dein Post wurde erfolgreich veröffentlicht!</b> Möchtest du nun deine Posts ansehen? <br>
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal">Nein</button>
<a href='<?= base_url('user/' . $_SESSION['user']['username'] . '/posts') ?>' class='btn btn-sm btn-primary'>Ja</a>
<a href='<?= base_url('user/' . $_SESSION['user']['username'] . '/posts') ?>'
class='btn btn-sm btn-primary'>Ja</a>
</div>
<?php
}
@ -342,7 +345,7 @@
public function switchFollowing()
{
header('Content-Type: application/json');
if(!isset($_SESSION['currentProfilePage'])) {
if (!isset($_SESSION['currentProfilePage'])) {
$response = ['type' => 'error', 'code' => -1];
echo json_encode($response);
exit;
@ -446,16 +449,14 @@
}
// Avatar
if (isset($_FILES['avatar'])) {
$image = $this->FileModel->uploadImage('avatar', 4096, $_FILES['avatar']['name'], 200);
$image = $this->FileModel->uploadCroppedImage('avatar', 4096, $_FILES['avatar']['name'], 500, 500);
if ($image != null)
$newData['profile_picture'] = $image;
unset($_FILES['avatar']);
}
// Header
if (isset($_FILES['header'])) {
// var_dump($_FILES['header']);
$image = $this->FileModel->uploadImage('header', 4096, $_FILES['header']['name'], 1920);
// var_dump($image);
if ($image != null)
$newData['header_image'] = $image;
unset($_FILES['header']);
@ -543,10 +544,16 @@
}
if (!empty($newData)) {
// Add entry to history
unset($user_data['rankName']);
unset($_SESSION['user']);
$this->UserModel->insertIntoHistory($user_data);
// Update profile
$this->UserModel->updateProfile($newData, $user_data['ID']);
// redirect(base_url(uri_string()));
$this->db->cache_delete('user', $user_data['username']);
$this->LoginModel->reloadLoginSession($user_data);
redirect(base_url(uri_string()));
}
$user_stats = $this->UserModel->getUserStats($user_data['ID']);
@ -613,4 +620,4 @@
$this->load->view('network/posts/user_post_content', ['message' => $message, 'post' => $post, 'replies' => $replies]);
}
}
}

View File

@ -11,9 +11,13 @@ class FileModel extends CI_Model
parent::__construct();
}
public function uploadFile($original_name, $tmpname, $size, $type)
private function getPath($fileName, $userContent) {
return 'files/' . ($userContent ? 'userContent/' : '') . $fileName;
}
public function uploadFile($original_name, $tmpname, $size, $type, $userContent = true)
{
$target_dir = "files" . DIRECTORY_SEPARATOR;
$target_dir = "files" . DIRECTORY_SEPARATOR . ($userContent ? 'userContent' . DIRECTORY_SEPARATOR : '');
$filetype = pathinfo(basename($original_name), PATHINFO_EXTENSION);
$target_file = $target_dir . $this->generateName() . '.' . $filetype;
$name = explode('.' . $filetype, explode(DIRECTORY_SEPARATOR, $target_file)[1])[0];
@ -22,13 +26,13 @@ class FileModel extends CI_Model
die('File couldn\'t be uploaded!');
}
$this->db->query('INSERT INTO files (name, original_name, type, size, path) VALUES (?, ?, ?, ?, ?)', [$name, $original_name, $type, $size, $target_file]);
$this->db->query('INSERT INTO files (name, original_name, type, size, path, isUserData) VALUES (?, ?, ?, ?, ?, ?)', [$name, $original_name, $type, $size, $target_file, $userContent]);
return "/file/open/" . $name;
return "/f/" . $name;
}
public function uploadImage($name, $max_size, $originalname, $max_width) {
$config['upload_path'] = './files/';
public function uploadImage($name, $max_size, $originalname, $max_width, $userContent = true) {
$config['upload_path'] = '.' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . ($userContent ? 'userContent' . DIRECTORY_SEPARATOR : '');
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = $max_size;
$config['file_name'] = $this->generateName() . "." . pathinfo(basename($originalname), PATHINFO_EXTENSION);
@ -50,13 +54,65 @@ class FileModel extends CI_Model
$this->image_lib->resize();
$this->db->query('INSERT INTO files (name, original_name, type, size, path) VALUES (?, ?, ?, ?, ?)', [$data['raw_name'], $originalname, $data['file_type'], $data['file_size'] * 1024, 'files/' . $data['file_name']]);
$this->db->query('INSERT INTO files (name, original_name, type, size, path, isUserData) VALUES (?, ?, ?, ?, ?, ?)', [$data['raw_name'], $originalname, $data['file_type'], $data['file_size'] * 1024, $this->getPath($data['file_name'], $userContent), $userContent]);
return '/f/' . $data['raw_name'];
}
}
public function uploadFileByContent($content, $original_name, $fullType, $fileSize) {
$target_dir = "files" . DIRECTORY_SEPARATOR;
public function uploadCroppedImage($name, $max_size, $originalname, $width, $height, $userContent = true) {
$config['upload_path'] = '.' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . ($userContent ? 'userContent' . DIRECTORY_SEPARATOR : '');
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = $max_size;
$config['file_name'] = $this->generateName() . "." . pathinfo(basename($originalname), PATHINFO_EXTENSION);
$this->load->library('upload', $config);
if ( ! $this->upload->do_upload($name)) {
return null;
} else {
$data = $this->upload->data();
// Resize
$config['image_library'] = 'gd2';
$config['source_image'] = $data['full_path'];
$config['maintain_ratio'] = TRUE;
$size = getimagesize($data['full_path']);
if($size[0] > $size[1]) {
$config['height'] = $height;
} else {
$config['width'] = $width;
}
$this->load->library('image_lib');
$this->image_lib->initialize($config);
$this->image_lib->resize();
$config['source_image'] = $config['upload_path'] . $config['file_name'];
$config['maintain_ratio'] = FALSE;
$config['height'] = $height;
$config['width'] = $width;
$size = getimagesize($config['source_image']);
if($size[0] > $size[1]) {
$config['x_axis'] = ($size[0] - $width) / 2;
} else {
$config['y_axis'] = ($size[1] - $height) / 2;
}
$this->image_lib->clear();
$this->image_lib->initialize($config);
$this->image_lib->crop();
$this->db->query('INSERT INTO files (name, original_name, type, size, path, isUserData) VALUES (?, ?, ?, ?, ?, ?)', [$data['raw_name'], $originalname, $data['file_type'], $data['file_size'] * 1024, $this->getPath($data['file_name'], $userContent), $userContent]);
return '/f/' . $data['raw_name'];
}
}
public function uploadFileByContent($content, $original_name, $fullType, $fileSize, $userContent = true) {
$target_dir = "files" . DIRECTORY_SEPARATOR . ($userContent ? 'userContent' . DIRECTORY_SEPARATOR : '');
$filetype = pathinfo(basename($original_name), PATHINFO_EXTENSION);
$target_file = $target_dir . $this->generateName() . '.' . $filetype;
$name = explode('.' . $filetype, explode(DIRECTORY_SEPARATOR, $target_file)[1])[0];
@ -65,7 +121,7 @@ class FileModel extends CI_Model
fwrite($fp, $content);
fclose($fp);
$this->db->query('INSERT INTO files (name, original_name, type, size, path) VALUES (?, ?, ?, ?, ?)', [$name, $original_name, $fullType, $fileSize, $target_file]);
$this->db->query('INSERT INTO files (name, original_name, type, size, path, isUserData) VALUES (?, ?, ?, ?, ?, ?)', [$name, $original_name, $fullType, $fileSize, $target_file, $userContent]);
return '/f/' . $name;
}

View File

@ -69,6 +69,20 @@ class LoginModel extends CI_Model
}
}
public function reloadLoginSession($logindata) {
$_SESSION['user']['displayname'] = $logindata['displayname'];
$_SESSION['user']['username'] = $logindata['username'];
$_SESSION['user']['rank'] = $logindata['rank'];
$_SESSION['user']['ID'] = $logindata['ID'];
$_SESSION['user']['ads'] = $logindata['showAds'];
$profilePic = $logindata['profile_picture'];
if (empty($profilePic)) {
$_SESSION['user']['profilePic'] = '/assets/images/steam.jpg';
} else {
$_SESSION['user']['profilePic'] = $profilePic;
}
}
public function getUserHash($username, $password, $email, $id)
{
$hash = hash('sha256', $id . '//' . $username . '//' . substr($password, 0, 5) . '//' . substr($email, 0, 5));

View File

@ -10,32 +10,33 @@ $this->load->view('network/user/profile_page_header');
<?= $message ?>
<h1>Profil bearbeiten</h1>
<div class="row">
<div class="col-xs-3 vertical-tab-menu">
<div class="list-group">
<a href="#" class="list-group-item active text-center" id="general">
<div class="col-3">
<div class="nav nav-pills flex-column" role="tablist" aria-orientation="vertical">
<a href="#general" class="nav-link active text-center" role="tab" data-toggle="pill" id="general-pill" aria-controls="general" aria-selected="true">
<i class="fa fa-tasks"></i>
<br>
Allgemein
</a>
<a href="#" class="list-group-item text-center" id="email">
<a href="#email" class="nav-link text-center" role="tab" data-toggle="pill" id="email-pill" aria-controls="email" aria-selected="false">
<i class="fa fa-envelope"></i>
<br>
E-Mail
</a>
<a href="#" class="list-group-item text-center" id="password">
<a href="#password" class="nav-link text-center" role="tab" data-toggle="pill" id="password-pill" aria-controls="password" aria-selected="false">
<i class="fa fa-lock"></i>
<br>
Passwort & Sicherheit
</a>
<a href="#" class="list-group-item text-center" id="premium">
<a href="#premium" class="nav-link text-center" role="tab" data-toggle="pill" id="premium-pill" aria-controls="premium" aria-selected="false">
<i class="fa fa-star"></i>
<br>
Premium
</a>
</div>
</div>
<div class="col-xs-9 vertical-tabs">
<div class="vertical-tab-content active" id="general">
<div class="col-9">
<div class="tab-content" id="tabContent">
<div class="tab-pane fade show active" id="general" role="tabpanel" aria-labelledby="general-pill">
<form method="post" enctype="multipart/form-data">
<!-- Username -->
<div class="form-group">
@ -69,7 +70,7 @@ $this->load->view('network/user/profile_page_header');
<div class="form-group">
<label for="birthdate">Geburtsdatum</label>
<div class="row">
<div class="col-xs-6">
<div class="col-6">
<select name="birthdate-month" id="birthdate-month" class="form-control"
data-default="<?= isset($data['birthdate']) ? explode('.', $data['birthdate'])[1] : '' ?>">
<option value="">-- Monat --</option>
@ -87,7 +88,7 @@ $this->load->view('network/user/profile_page_header');
<option value="12">Dezember</option>
</select>
</div>
<div class="col-xs-6">
<div class="col-6">
<select name="birthdate-day" id="birthdate-day" class="form-control"
data-default="<?= isset($data['birthdate']) ? explode('.', $data['birthdate'])[0] : '' ?>">
<option value="">-- Tag --</option>
@ -95,7 +96,7 @@ $this->load->view('network/user/profile_page_header');
</div>
</div>
<div class="row">
<div class="col-xs-6 col-xs-offset-3">
<div class="col-6 col-offset-3">
<select name="birthdate-year" id="birthdate-year" class="form-control">
<option value="">-- Jahr --</option>
</select>
@ -1092,7 +1093,7 @@ $this->load->view('network/user/profile_page_header');
<div class="form-group">
<label for="avatar">Avatar</label>
<?php if (isset($data['profile_picture']) || $data['profile_picture'] != ""): ?>
<img class="img-fluid thumbnail picture-preview"
<img class="img-fluid img-thumbnail picture-preview d-block"
src="<?= $data['profile_picture'] ?>">
<?php endif; ?>
<input type="file" name="avatar">
@ -1101,7 +1102,7 @@ $this->load->view('network/user/profile_page_header');
<div class="form-group">
<label for="header">Header</label>
<?php if (isset($data['header_image']) || $data['header_image'] != ""): ?>
<img class="img-fluid thumbnail picture-preview"
<img class="img-fluid img-thumbnail picture-preview d-block"
src="<?= $data['header_image'] ?>">
<?php endif; ?>
<input type="file" name="header">
@ -1113,7 +1114,7 @@ $this->load->view('network/user/profile_page_header');
<input type="submit" class="btn btn-primary" value="Speichern">
</form>
</div>
<div class="vertical-tab-content" id="email">
<div class="tab-pane fade" id="email" role="tabpanel" aria-labelledby="email-pill">
<form method="post">
<div class="form-group">
<label for="email">E-Mail-Adresse</label>
@ -1138,7 +1139,7 @@ $this->load->view('network/user/profile_page_header');
<input type="submit" class="btn btn-primary" value="Speichern">
</form>
</div>
<div class="vertical-tab-content" id="password">
<div class="tab-pane fade" id="password" role="tabpanel" aria-labelledby="password-pill">
<form method="post">
<div class="form-group">
<label for="passwordOld">Altes Passwort</label>
@ -1155,7 +1156,7 @@ $this->load->view('network/user/profile_page_header');
<input type="submit" class="btn btn-primary" value="Speichern">
</form>
</div>
<div class="vertical-tab-content" id="premium">
<div class="tab-pane fade" id="premium" role="tabpanel" aria-labelledby="premium-pill">
<form method="post">
<?php if (isset($_SESSION['user']['rank']) && $_SESSION['user']['rank'] >= 2): ?>
<div class="form-group">
@ -1173,7 +1174,8 @@ $this->load->view('network/user/profile_page_header');
Services und gleichzeitig erhälst du die Möglichkeit, den Dienst ohne Werbung zu
erleben.</p>
<p>Plus-Nutzer oder Team-Mitglied kannst du nur auf persönliche Einladung eines
hochrangigen Team-Mitgliedes werden. Der Plus-Rang wird beispielsweise an YouTuber,
hochrangigen Team-Mitgliedes werden. Der Plus-Rang wird beispielsweise an
YouTuber,
bekannte Persönlichkeiten, sehr aktive Nutzer, sehr großzügige Spender, aktive
Abonnenten des Kanals <a href="https://youtube.com/KingOfDog" target="_blank">KingOfDog</a>
oder Freunde und Bekannte vergeben.</p>
@ -1186,51 +1188,15 @@ $this->load->view('network/user/profile_page_header');
</div>
</div>
</div>
</div>
</section>
<style>
#profile-content-container {
min-height: 375px;
.nav-pills .nav-link {
position: relative;
transition: color .2s, background-color .2s;
}
.vertical-tab-menu {
padding-right: 0;
padding-left: 0;
padding-bottom: 0;
}
.vertical-tab-menu .list-group {
margin-bottom: 0;
}
.vertical-tab-menu .list-group > a {
margin-bottom: 0;
border: 0;
}
.vertical-tab-menu .list-group > a .fa {
color: #2272FF;
}
.vertical-tab-menu .list-group > a:first-child {
border-top-right-radius: 0;
-moz-border-top-right-radius: 0;
}
.vertical-tab-menu .list-group > a:last-child {
border-bottom-right-radius: 0;
-moz-border-bottom-right-radius: 0;
}
.vertical-tab-menu .list-group > a.active {
background-color: #2272FF;
color: #ffffff;
}
.vertical-tab-menu .list-group > a.active .fa {
color: #ffffff;
}
.vertical-tab-menu .list-group > a.active:after {
.nav-pills .nav-link:after {
content: '';
position: absolute;
left: 100%;
@ -1239,21 +1205,26 @@ $this->load->view('network/user/profile_page_header');
border-left: 0;
border-bottom: 13px solid transparent;
border-top: 13px solid transparent;
border-left: 10px solid #2272FF;
border-left: 10px solid transparent;
transition: border-left-color .2s;
}
.vertical-tabs {
margin-left: -15px;
.nav-pills .nav-link:not(.active):hover,
.nav-pills .nav-link:not(.active):focus {
color: #2272ff !important;
}
.vertical-tab-content {
background-color: #ffffff;
padding: 10px 25px;
min-height: 285px;
.nav-pills .nav-link.active {
color: #fff !important;
background-color: #2272ff;
}
.vertical-tabs .vertical-tab-content:not(.active) {
display: none;
.nav-pills .nav-link.active:after {
border-left-color: #2272ff;
}
#profile-content-container {
min-height: 375px;
}
.picture-preview {