diff --git a/src/application/controller/api/user/profile.php b/src/application/controller/api/user/profile.php index ead5216..8dff279 100644 --- a/src/application/controller/api/user/profile.php +++ b/src/application/controller/api/user/profile.php @@ -52,7 +52,6 @@ if (isset($_SESSION['userName'])) { $profile = [ 'userName' => $userName, - 'seq' => $profileInfo['seq'], 'fullName' => $profileInfo['fullName'], 'location' => $profileInfo['location'], 'url' => $profileInfo['url'], diff --git a/src/application/controller/settings/profile.php b/src/application/controller/settings/profile.php index e938c90..24cc35f 100644 --- a/src/application/controller/settings/profile.php +++ b/src/application/controller/settings/profile.php @@ -22,13 +22,13 @@ $metaScripts = [ ]; // Init variables -$seq = false; $fullName = false; $location = false; $url = false; $bitMessage = false; $tox = false; $bio = false; +$avatar = false; $errorFullName = false; $errorLocation = false; @@ -41,7 +41,6 @@ $errorBio = false; if (isset($_POST) && !empty($_POST)) { // Prepare request - $seq = isset($_POST['seq']) ? $_POST['seq'] : 0; $fullName = isset($_POST['fullName']) ? $_POST['fullName'] : ''; $location = isset($_POST['location']) ? $_POST['location'] : ''; $url = isset($_POST['url']) ? $_POST['url'] : ''; @@ -49,35 +48,76 @@ if (isset($_POST) && !empty($_POST)) { $tox = isset($_POST['tox']) ? $_POST['tox'] : ''; $bio = isset($_POST['bio']) ? $_POST['bio'] : ''; - // Increase revision number - $seq++; - // Get current block number $blockId = $_modelBlock->getThisBlock(); - // Save revision to DHT - $userProfileVersions = $_twister->putDHT( $_SESSION['userName'], - 'profile', - 's', - [ - 'fullname' => $fullName, - 'location' => $location, - 'url' => $url, - 'bitmessage' => $bitMessage, - 'tox' => $tox, - 'bio' => $bio, - ], - $_SESSION['userName'], - $seq); - - // Save revision to DB + // Avatar provided + if (isset($_FILES['avatar']['tmp_name']) && getimagesize($_FILES['avatar']['tmp_name'])) { + + // Prepare image + $image = new Imagick(); + + $image->readImage($_FILES['avatar']['tmp_name']); + $image->resizeImage(64, 64, 1, false); + $image->setImageFormat('jpeg'); + $image->setCompressionQuality(100); + + // Encode base 64 + $avatar = 'data:image/jpeg;base64,' . base64_encode($image->getImageBlob()); + + // Get avatar revision + $avatarSeq = $_modelAvatar->getMaxSeq($_SESSION['userId']) + 1; + + // Save avatar revision to DHT + $_twister->putDHT($_SESSION['userName'], + 'avatar', + 's', + $avatar, + $_SESSION['userName'], + $avatarSeq); + + // Save avatar revision to DB + if (!$_modelAvatar->versionExists($_SESSION['userId'], + $blockId, + $avatarSeq)) { + + $_modelAvatar->add( $_SESSION['userId'], + $blockId, + $avatarSeq, + time(), + $avatar); + } + + // Update avatar cache + $_memcache->set('api.user.avatar.' . $_SESSION['userName'], $avatar, MEMCACHE_COMPRESS, MEMCACHE_DHT_AVATAR_TIMEOUT); + } + + // Get profile revision + $profileSeq = $_modelProfile->getMaxSeq($_SESSION['userId']) + 1; + + // Save profile revision to DHT + $_twister->putDHT($_SESSION['userName'], + 'profile', + 's', + [ + 'fullname' => $fullName, + 'location' => $location, + 'url' => $url, + 'bitmessage' => $bitMessage, + 'tox' => $tox, + 'bio' => $bio, + ], + $_SESSION['userName'], + $profileSeq); + + // Save profile revision to DB if (!$_modelProfile->versionExists($_SESSION['userId'], $blockId, - $seq)) { + $profileSeq)) { $_modelProfile->add($_SESSION['userId'], $blockId, - $seq, + $profileSeq, time(), $fullName, $bio, @@ -87,10 +127,10 @@ if (isset($_POST) && !empty($_POST)) { $tox); } + // Update profile cache $_memcache->replace('api.user.profile.' . $_SESSION['userName'], [ 'userName' => $_SESSION['userName'], - 'seq' => $seq, 'fullName' => $fullName, 'location' => $location, 'url' => $url, @@ -103,10 +143,56 @@ if (isset($_POST) && !empty($_POST)) { } +// Get avatar details +if ($userAvatar = $_memcache->get('api.user.avatar.' . $_SESSION['userName'])) { + + $avatar = $userAvatar; + +} else if ($avatarVersions = $_twister->getDHT($_SESSION['userName'], 'avatar', 's')) { + + // Add DHT version if not exists + foreach ($avatarVersions as $avatarVersion) { + + if (!$_modelAvatar->versionExists($_SESSION['userId'], + $avatarVersion['p']['height'], + $avatarVersion['p']['seq'])) { + + $_modelAvatar->add( $_SESSION['userId'], + $avatarVersion['p']['height'], + $avatarVersion['p']['seq'], + $avatarVersion['p']['time'], + $avatarVersion['p']['v']); + } + } + + // Get latest version available + if ($avatarInfo = $_modelAvatar->get($_SESSION['userId'])) { + + $avatar = $avatarInfo['data']; + + $_memcache->set('api.user.avatar.' . $_SESSION['userName'], $avatarInfo['data'], MEMCACHE_COMPRESS, MEMCACHE_DHT_AVATAR_TIMEOUT); + } + +// Generate identity icon +} else { + + $fileName = md5($_SESSION['userName']); + $filePath = PROJECT_DIR . '/cache/image/' . $fileName . '.jpeg'; + + if (!file_exists($filePath)) { + + $icon = new Icon(); + $image = $icon->generateImageResource($fileName, 42, 42, false); + + file_put_contents($filePath, $image); + } + + $avatar = sprintf('data:image/jpeg;base64,%s', base64_encode(file_get_contents($filePath))); +} + // Get profile details if ($profile = $_memcache->get('api.user.profile.' . $_SESSION['userName'])) { - $seq = $profile['seq']; $fullName = $profile['fullName']; $location = $profile['location']; $url = $profile['url']; @@ -116,30 +202,26 @@ if ($profile = $_memcache->get('api.user.profile.' . $_SESSION['userName'])) { } else if ($userProfileVersions = $_twister->getDHT($_SESSION['userName'], 'profile', 's')) { - // Check user exists - if ($userId = $_modelUser->getUserId($_SESSION['userName'])) { - - // Add DHT version if not exists - foreach ($userProfileVersions as $userProfileVersion) { + // Add DHT version if not exists + foreach ($userProfileVersions as $userProfileVersion) { - if (!$_modelProfile->versionExists($userId, - $userProfileVersion['p']['height'], - $userProfileVersion['p']['seq'])) { + if (!$_modelProfile->versionExists($_SESSION['userId'], + $userProfileVersion['p']['height'], + $userProfileVersion['p']['seq'])) { - $profile = $userProfileVersion['p']['v']; + $profile = $userProfileVersion['p']['v']; - $_modelProfile->add($userId, - $userProfileVersion['p']['height'], - $userProfileVersion['p']['seq'], - $userProfileVersion['p']['time'], - - isset($profile['fullname']) ? $profile['fullname'] : '', - isset($profile['bio']) ? $profile['bio'] : '', - isset($profile['location']) ? $profile['location'] : '', - isset($profile['url']) ? $profile['url'] : '', - isset($profile['bitmessage']) ? $profile['bitmessage'] : '', - isset($profile['tox']) ? $profile['tox'] : ''); - } + $_modelProfile->add($_SESSION['userId'], + $userProfileVersion['p']['height'], + $userProfileVersion['p']['seq'], + $userProfileVersion['p']['time'], + + isset($profile['fullname']) ? $profile['fullname'] : '', + isset($profile['bio']) ? $profile['bio'] : '', + isset($profile['location']) ? $profile['location'] : '', + isset($profile['url']) ? $profile['url'] : '', + isset($profile['bitmessage']) ? $profile['bitmessage'] : '', + isset($profile['tox']) ? $profile['tox'] : ''); } } @@ -148,7 +230,6 @@ if ($profile = $_memcache->get('api.user.profile.' . $_SESSION['userName'])) { $profile = [ 'userName' => $_SESSION['userName'], - 'seq' => $profileInfo['seq'], 'fullName' => $profileInfo['fullName'], 'location' => $profileInfo['location'], 'url' => $profileInfo['url'], @@ -157,7 +238,6 @@ if ($profile = $_memcache->get('api.user.profile.' . $_SESSION['userName'])) { 'bio' => $profileInfo['bio'], ]; - $seq = $profile['seq']; $fullName = $profile['fullName']; $location = $profile['location']; $url = $profile['url']; diff --git a/src/application/model/avatar.php b/src/application/model/avatar.php index 95e886c..84f83eb 100644 --- a/src/application/model/avatar.php +++ b/src/application/model/avatar.php @@ -23,6 +23,23 @@ class ModelAvatar extends Model { } } + public function getMaxSeq(int $userId) { + + try { + + $query = $this->_db->prepare("SELECT MAX(`seq`) AS `revision` FROM `avatar` WHERE `userId` = ?"); + + $query->execute([$userId]); + + return (int) $query->fetch()['revision']; + + } catch (PDOException $e) { + + trigger_error($e->getMessage()); + return false; + } + } + public function versionExists(int $userId, int $blockId, int $seq) { try { diff --git a/src/application/model/profile.php b/src/application/model/profile.php index e8101c3..8cc4a21 100644 --- a/src/application/model/profile.php +++ b/src/application/model/profile.php @@ -23,6 +23,23 @@ class ModelProfile extends Model { } } + public function getMaxSeq(int $userId) { + + try { + + $query = $this->_db->prepare("SELECT MAX(`seq`) + 1 AS `revision` FROM `profile` WHERE `userId` = ?"); + + $query->execute([$userId]); + + return (int) $query->fetch()['revision']; + + } catch (PDOException $e) { + + trigger_error($e->getMessage()); + return false; + } + } + public function versionExists(int $userId, int $blockId, int $seq) { try { diff --git a/src/application/view/settings/profile.phtml b/src/application/view/settings/profile.phtml index 27c467c..596b9fd 100644 --- a/src/application/view/settings/profile.phtml +++ b/src/application/view/settings/profile.phtml @@ -7,8 +7,11 @@

-
- + +
+ + +
diff --git a/src/public/css/template/default/settings/profile.css b/src/public/css/template/default/settings/profile.css index b96c3a0..ca4100f 100644 --- a/src/public/css/template/default/settings/profile.css +++ b/src/public/css/template/default/settings/profile.css @@ -1,3 +1,17 @@ +.settingsProfile .avatar { + margin-bottom: 32px; + padding-bottom: 16px; + border-bottom: 1px #4d5666 solid;; +} + +.settingsProfile .avatar img { + border-radius: 50%; + border: 2px #fff solid; + vertical-align: middle; + margin-right: 16px; + width: 42px; +} + .settingsProfile form { background: rgba(39, 46, 57, 0.28); padding: 16px; @@ -18,7 +32,11 @@ color: #fff } -.settingsProfile form input:focus { +.settingsProfile form input[type="file"] { + width: 302px +} + +.settingsProfile form input[type="text"]:focus { background: rgb(238, 238, 238); color: #1c1d1e }