Removed the existing, broken follow system.
This commit is contained in:
parent
813d3421bb
commit
50dee8eeb4
17 changed files with 64 additions and 663 deletions
|
@ -15,7 +15,6 @@ var Misuzu = function() {
|
|||
Misuzu.CSRF.init();
|
||||
Misuzu.Urls.loadFromDocument();
|
||||
Misuzu.User.refreshLocalUser();
|
||||
Misuzu.UserRelations.init();
|
||||
Misuzu.FormUtils.initDataRequestMethod();
|
||||
Misuzu.initQuickSubmit();
|
||||
Misuzu.Comments.init();
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
Misuzu.UserRelations = {};
|
||||
Misuzu.UserRelations.Type = DefineEnum({ none: 0, follow: 1, });
|
||||
Misuzu.UserRelations.init = function() {
|
||||
var buttons = document.getElementsByClassName('js-user-relation-action');
|
||||
|
||||
for(var i = 0; i < buttons.length; ++i) {
|
||||
switch(buttons[i].tagName.toLowerCase()) {
|
||||
case 'a':
|
||||
buttons[i].removeAttribute('href');
|
||||
buttons[i].removeAttribute('target');
|
||||
buttons[i].removeAttribute('rel');
|
||||
break;
|
||||
}
|
||||
|
||||
buttons[i].addEventListener('click', Misuzu.UserRelations.setRelationHandler);
|
||||
}
|
||||
};
|
||||
Misuzu.UserRelations.setRelation = function(user, type, onSuccess, onFailure) {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.addEventListener('readystatechange', function() {
|
||||
if(xhr.readyState !== 4)
|
||||
return;
|
||||
|
||||
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
|
||||
|
||||
var json = JSON.parse(xhr.responseText),
|
||||
message = json.error || json.message;
|
||||
|
||||
if(message && onFailure)
|
||||
onFailure(message);
|
||||
else if(!message && onSuccess)
|
||||
onSuccess(json);
|
||||
});
|
||||
xhr.open('GET', Misuzu.Urls.format('user-relation-create', [Misuzu.Urls.v('user', user), Misuzu.Urls.v('type', type)]));
|
||||
xhr.setRequestHeader('X-Misuzu-XHR', 'user_relation');
|
||||
xhr.setRequestHeader('X-Misuzu-CSRF', Misuzu.CSRF.getToken());
|
||||
xhr.send();
|
||||
};
|
||||
Misuzu.UserRelations.ICO_ADD = 'fas fa-user-plus';
|
||||
Misuzu.UserRelations.ICO_REM = 'fas fa-user-minus';
|
||||
Misuzu.UserRelations.ICO_BUS = 'fas fa-spinner fa-pulse';
|
||||
Misuzu.UserRelations.BTN_BUS = 'input__button--busy';
|
||||
Misuzu.UserRelations.setRelationHandler = function(ev) {
|
||||
var target = this,
|
||||
userId = parseInt(target.dataset.relationUser),
|
||||
relationType = parseInt(target.dataset.relationType),
|
||||
isButton = target.classList.contains('input__button'),
|
||||
icon = target.querySelector('[class^="fa"]');
|
||||
|
||||
if(isButton) {
|
||||
if(target.classList.contains(Misuzu.UserRelations.BTN_BUS))
|
||||
return;
|
||||
target.classList.add(Misuzu.UserRelations.BTN_BUS);
|
||||
}
|
||||
|
||||
if(icon)
|
||||
icon.className = Misuzu.UserRelations.ICO_BUS;
|
||||
|
||||
Misuzu.UserRelations.setRelation(
|
||||
userId,
|
||||
relationType,
|
||||
function(info) {
|
||||
target.classList.remove(Misuzu.UserRelations.BTN_BUS);
|
||||
|
||||
switch(info.relation_type) {
|
||||
case Misuzu.UserRelations.Type.none:
|
||||
if(isButton) {
|
||||
if(target.classList.contains('input__button--destroy'))
|
||||
target.classList.remove('input__button--destroy');
|
||||
|
||||
target.textContent = 'Follow';
|
||||
}
|
||||
|
||||
if(icon) {
|
||||
icon.className = Misuzu.UserRelations.ICO_ADD;
|
||||
target.title = 'Follow';
|
||||
}
|
||||
|
||||
target.dataset.relationType = Misuzu.UserRelations.Type.follow.toString();
|
||||
break;
|
||||
|
||||
case Misuzu.UserRelations.Type.follow:
|
||||
if(isButton) {
|
||||
if(!target.classList.contains('input__button--destroy'))
|
||||
target.classList.add('input__button--destroy');
|
||||
|
||||
target.textContent = 'Unfollow';
|
||||
}
|
||||
|
||||
if(icon) {
|
||||
icon.className = Misuzu.UserRelations.ICO_REM;
|
||||
target.title = 'Unfollow';
|
||||
}
|
||||
|
||||
target.dataset.relationType = Misuzu.UserRelations.Type.none.toString();
|
||||
break;
|
||||
}
|
||||
},
|
||||
function(msg) {
|
||||
target.classList.remove(Misuzu.UserRelations.BTN_BUS);
|
||||
Misuzu.showMessageBox(msg);
|
||||
}
|
||||
);
|
||||
};
|
33
database/2021_08_28_220000_nuke_relations_table.php
Normal file
33
database/2021_08_28_220000_nuke_relations_table.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
namespace Misuzu\DatabaseMigrations\NukeRelationsTable;
|
||||
|
||||
use PDO;
|
||||
|
||||
function migrate_up(PDO $conn): void {
|
||||
$conn->exec("DROP TABLE `msz_user_relations`");
|
||||
}
|
||||
|
||||
function migrate_down(PDO $conn): void {
|
||||
$conn->exec("
|
||||
CREATE TABLE `msz_user_relations` (
|
||||
`user_id` INT(10) UNSIGNED NOT NULL,
|
||||
`subject_id` INT(10) UNSIGNED NOT NULL,
|
||||
`relation_type` TINYINT(3) UNSIGNED NOT NULL,
|
||||
`relation_created` TIMESTAMP NOT NULL DEFAULT current_timestamp(),
|
||||
UNIQUE INDEX `user_relations_unique` (`user_id`, `subject_id`) USING BTREE,
|
||||
INDEX `user_relations_subject_id_foreign` (`subject_id`) USING BTREE,
|
||||
INDEX `user_relations_type_index` (`relation_type`) USING BTREE,
|
||||
INDEX `user_relations_created_index` (`relation_created`) USING BTREE,
|
||||
CONSTRAINT `user_relations_subject_id_foreign`
|
||||
FOREIGN KEY (`subject_id`)
|
||||
REFERENCES `msz_users` (`user_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT `user_relations_user_id_foreign`
|
||||
FOREIGN KEY (`user_id`)
|
||||
REFERENCES `msz_users` (`user_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
) COLLATE='utf8mb4_bin' ENGINE=InnoDB;
|
||||
");
|
||||
}
|
|
@ -160,10 +160,6 @@ $statistics = DB::query('
|
|||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_users_password_resets`
|
||||
) AS `stat_user_password_resets`,
|
||||
(
|
||||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_user_relations`
|
||||
) AS `stat_user_relations`,
|
||||
(
|
||||
SELECT COUNT(`warning_id`)
|
||||
FROM `msz_user_warnings`
|
||||
|
|
|
@ -53,16 +53,6 @@ $orderFields = [
|
|||
'default-dir' => 'desc',
|
||||
'title' => 'Forum Posts',
|
||||
],
|
||||
'following' => [
|
||||
'column' => '`user_count_following`',
|
||||
'default-dir' => 'desc',
|
||||
'title' => 'Following',
|
||||
],
|
||||
'followers' => [
|
||||
'column' => '`user_count_followers`',
|
||||
'default-dir' => 'desc',
|
||||
'title' => 'Followers',
|
||||
],
|
||||
];
|
||||
|
||||
if(empty($orderBy)) {
|
||||
|
@ -111,31 +101,7 @@ $getUsers = DB::prepare(sprintf(
|
|||
FROM `msz_forum_posts`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `post_deleted` IS NULL
|
||||
) AS `user_count_posts`,
|
||||
(
|
||||
SELECT COUNT(`subject_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `relation_type` = %4$d
|
||||
) AS `user_count_following`,
|
||||
(
|
||||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `subject_id` = u.`user_id`
|
||||
AND `relation_type` = %4$d
|
||||
) AS `user_count_followers`,
|
||||
(
|
||||
SELECT `relation_type` = %4$d
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = `current_user_id`
|
||||
AND `subject_id` = u.`user_id`
|
||||
) AS `user_is_following`,
|
||||
(
|
||||
SELECT `relation_type` = %4$d
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `subject_id` = `current_user_id`
|
||||
) AS `user_is_follower`
|
||||
) AS `user_count_posts`
|
||||
FROM `msz_users` AS u
|
||||
LEFT JOIN `msz_roles` AS r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
|
@ -144,12 +110,11 @@ $getUsers = DB::prepare(sprintf(
|
|||
WHERE ur.`role_id` = :role_id
|
||||
%1$s
|
||||
ORDER BY %2$s %3$s
|
||||
LIMIT %5$d, %6$d
|
||||
LIMIT %4$d, %5$d
|
||||
',
|
||||
$canManageUsers ? '' : 'AND u.`user_deleted` IS NULL',
|
||||
$orderFields[$orderBy]['column'],
|
||||
$orderDir,
|
||||
\Misuzu\Users\UserRelation::TYPE_FOLLOW,
|
||||
$pagination->getOffset(),
|
||||
$pagination->getRange()
|
||||
));
|
||||
|
|
|
@ -262,7 +262,7 @@ if($isEditing) {
|
|||
}
|
||||
}
|
||||
|
||||
$profileStats = DB::prepare(sprintf('
|
||||
$profileStats = DB::prepare('
|
||||
SELECT (
|
||||
SELECT COUNT(`topic_id`)
|
||||
FROM `msz_forum_topics`
|
||||
|
@ -285,64 +285,16 @@ $profileStats = DB::prepare(sprintf('
|
|||
FROM `msz_comments_posts`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `comment_deleted` IS NULL
|
||||
) AS `comments_count`,
|
||||
(
|
||||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `subject_id` = u.`user_id`
|
||||
AND `relation_type` = %1$d
|
||||
) AS `followers_count`,
|
||||
(
|
||||
SELECT COUNT(`subject_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `relation_type` = %1$d
|
||||
) AS `following_count`
|
||||
) AS `comments_count`
|
||||
FROM `msz_users` AS u
|
||||
WHERE `user_id` = :user_id
|
||||
', \Misuzu\Users\UserRelation::TYPE_FOLLOW))->bind('user_id', $profileUser->getId())->fetch();
|
||||
')->bind('user_id', $profileUser->getId())->fetch();
|
||||
|
||||
switch($profileMode) {
|
||||
default:
|
||||
echo render_error(404);
|
||||
return;
|
||||
|
||||
case 'following':
|
||||
$template = 'profile.relations';
|
||||
$pagination = new Pagination($profileUser->getFollowingCount(), 15);
|
||||
|
||||
if(!$pagination->hasValidOffset()) {
|
||||
echo render_error(404);
|
||||
return;
|
||||
}
|
||||
|
||||
Template::set([
|
||||
'title' => $profileUser->getUsername() . ' / following',
|
||||
'canonical_url' => url('user-profile-following', ['user' => $profileUser->getId()]),
|
||||
'profile_users' => $profileUser->getFollowing($pagination),
|
||||
'profile_relation_pagination' => $pagination,
|
||||
'relation_prop' => 'subject',
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'followers':
|
||||
$template = 'profile.relations';
|
||||
$pagination = new Pagination($profileUser->getFollowersCount(), 15);
|
||||
|
||||
if(!$pagination->hasValidOffset()) {
|
||||
echo render_error(404);
|
||||
return;
|
||||
}
|
||||
|
||||
Template::set([
|
||||
'title' => $profileUser->getUsername() . ' / followers',
|
||||
'canonical_url' => url('user-profile-followers', ['user' => $profileUser->getId()]),
|
||||
'profile_users' => $profileUser->getFollowers($pagination),
|
||||
'profile_relation_pagination' => $pagination,
|
||||
'relation_prop' => 'user',
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'forum-topics':
|
||||
$template = 'profile.topics';
|
||||
$topicsCount = forum_topic_count_user($profileUser->getId(), $currentUserId);
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
namespace Misuzu;
|
||||
|
||||
use Misuzu\Config;
|
||||
use Misuzu\Users\User;
|
||||
use Misuzu\Users\UserNotFoundException;
|
||||
use Misuzu\Users\UserRelation;
|
||||
|
||||
require_once '../misuzu.php';
|
||||
|
||||
// basing whether or not this is an xhr request on whether a referrer header is present
|
||||
// this page is never directy accessed, under normal circumstances
|
||||
$redirect = !empty($_SERVER['HTTP_REFERER']) && empty($_SERVER['HTTP_X_MISUZU_XHR']) ? $_SERVER['HTTP_REFERER'] : '';
|
||||
$isXHR = !$redirect;
|
||||
|
||||
if($isXHR) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
} elseif(!is_local_url($redirect)) {
|
||||
echo render_info('Possible request forgery detected.', 403);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CSRF::validateRequest()) {
|
||||
echo render_info_or_json($isXHR, "Couldn't verify this request, please refresh the page and try again.", 403);
|
||||
return;
|
||||
}
|
||||
|
||||
header(CSRF::header());
|
||||
|
||||
$currentUser = User::getCurrent();
|
||||
|
||||
if($currentUser === null) {
|
||||
echo render_info_or_json($isXHR, 'You must be logged in to manage relations.', 401);
|
||||
return;
|
||||
}
|
||||
|
||||
if($currentUser->isBanned()) {
|
||||
echo render_info_or_json($isXHR, 'You have been banned, check your profile for more information.', 403);
|
||||
return;
|
||||
}
|
||||
|
||||
$subjectId = !empty($_GET['u']) && is_string($_GET['u']) ? (int)$_GET['u'] : 0;
|
||||
$relationType = isset($_GET['m']) && is_string($_GET['m']) ? (int)$_GET['m'] : -1;
|
||||
|
||||
if($relationType < 0) {
|
||||
echo render_info_or_json($isXHR, 'Invalid relation type.', 400);
|
||||
return;
|
||||
}
|
||||
|
||||
$relationType = $relationType > 0 ? UserRelation::TYPE_FOLLOW : UserRelation::TYPE_NONE;
|
||||
|
||||
try {
|
||||
$subjectInfo = User::byId($subjectId);
|
||||
} catch(UserNotFoundException $ex) {
|
||||
echo render_info_or_json($isXHR, "That user doesn't exist.", 400);
|
||||
return;
|
||||
}
|
||||
|
||||
if($relationType > 0)
|
||||
$subjectInfo->addFollower($currentUser);
|
||||
else
|
||||
$subjectInfo->removeRelation($currentUser);
|
||||
|
||||
if(in_array($subjectInfo->getId(), Config::get('relations.replicate', Config::TYPE_ARR))) {
|
||||
if($relationType > 0)
|
||||
$currentUser->addFollower($subjectInfo);
|
||||
else
|
||||
$currentUser->removeRelation($subjectInfo);
|
||||
}
|
||||
|
||||
if(!$isXHR) {
|
||||
redirect($redirect);
|
||||
return;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'user_id' => $currentUser->getId(),
|
||||
'subject_id' => $subjectInfo->getId(),
|
||||
'relation_type' => $relationType,
|
||||
]);
|
|
@ -13,62 +13,32 @@ if(!empty($searchQuery)) {
|
|||
$forumPosts = forum_post_search($searchQuery);
|
||||
$newsPosts = NewsPost::bySearchQuery($searchQuery);
|
||||
|
||||
$findUsers = DB::prepare(sprintf(
|
||||
'
|
||||
SELECT
|
||||
:current_user_id AS `current_user_id`,
|
||||
u.`user_id`, u.`username`, u.`user_country`,
|
||||
u.`user_created`, u.`user_active`, r.`role_id`,
|
||||
COALESCE(u.`user_title`, r.`role_title`) AS `user_title`,
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`,
|
||||
(
|
||||
SELECT COUNT(`topic_id`)
|
||||
FROM `msz_forum_topics`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `topic_deleted` IS NULL
|
||||
) AS `user_count_topics`,
|
||||
(
|
||||
SELECT COUNT(`post_Id`)
|
||||
FROM `msz_forum_posts`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `post_deleted` IS NULL
|
||||
) AS `user_count_posts`,
|
||||
(
|
||||
SELECT COUNT(`subject_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `relation_type` = %1$d
|
||||
) AS `user_count_following`,
|
||||
(
|
||||
SELECT COUNT(`user_id`)
|
||||
FROM `msz_user_relations`
|
||||
WHERE `subject_id` = u.`user_id`
|
||||
AND `relation_type` = %1$d
|
||||
) AS `user_count_followers`,
|
||||
(
|
||||
SELECT `relation_type` = %1$d
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = `current_user_id`
|
||||
AND `subject_id` = u.`user_id`
|
||||
) AS `user_is_following`,
|
||||
(
|
||||
SELECT `relation_type` = %1$d
|
||||
FROM `msz_user_relations`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `subject_id` = `current_user_id`
|
||||
) AS `user_is_follower`
|
||||
FROM `msz_users` AS u
|
||||
LEFT JOIN `msz_roles` AS r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
LEFT JOIN `msz_user_roles` AS ur
|
||||
ON ur.`user_id` = u.`user_id`
|
||||
WHERE LOWER(u.`username`) LIKE CONCAT("%%", LOWER(:query), "%%")
|
||||
GROUP BY u.`user_id`
|
||||
',
|
||||
\Misuzu\Users\UserRelation::TYPE_FOLLOW
|
||||
));
|
||||
$findUsers = DB::prepare('
|
||||
SELECT u.`user_id`, u.`username`, u.`user_country`,
|
||||
u.`user_created`, u.`user_active`, r.`role_id`,
|
||||
COALESCE(u.`user_title`, r.`role_title`) AS `user_title`,
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`,
|
||||
(
|
||||
SELECT COUNT(`topic_id`)
|
||||
FROM `msz_forum_topics`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `topic_deleted` IS NULL
|
||||
) AS `user_count_topics`,
|
||||
(
|
||||
SELECT COUNT(`post_Id`)
|
||||
FROM `msz_forum_posts`
|
||||
WHERE `user_id` = u.`user_id`
|
||||
AND `post_deleted` IS NULL
|
||||
) AS `user_count_posts`
|
||||
FROM `msz_users` AS u
|
||||
LEFT JOIN `msz_roles` AS r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
LEFT JOIN `msz_user_roles` AS ur
|
||||
ON ur.`user_id` = u.`user_id`
|
||||
WHERE LOWER(u.`username`) LIKE CONCAT("%%", LOWER(:query), "%%")
|
||||
GROUP BY u.`user_id`
|
||||
');
|
||||
$findUsers->bind('query', $searchQuery);
|
||||
$findUsers->bind('current_user_id', User::hasCurrent() ? User::getCurrent()->getId() : 0);
|
||||
$users = $findUsers->fetchAll();
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,6 @@ if(isset($_POST['action']) && is_string($_POST['action'])) {
|
|||
db_to_zip($archive, $currentUserId, 'users.json', 'SELECT *, NULL AS `password`, NULL AS `user_totp_key`, INET6_NTOA(`register_ip`) AS `register_ip`, INET6_NTOA(`last_ip`) AS `last_ip` FROM `msz_users` WHERE `user_id` = :user_id');
|
||||
db_to_zip($archive, $currentUserId, 'users_password_resets.json', 'SELECT *, INET6_NTOA(`reset_ip`) AS `reset_ip` FROM `msz_users_password_resets` WHERE `user_id` = :user_id');
|
||||
db_to_zip($archive, $currentUserId, 'user_chat_tokens.json', 'SELECT * FROM `msz_user_chat_tokens` WHERE `user_id` = :user_id');
|
||||
db_to_zip($archive, $currentUserId, 'user_relations.json', 'SELECT * FROM `msz_user_relations` WHERE `user_id` = :user_id_1 OR `subject_id` = :user_id_2', 2);
|
||||
db_to_zip($archive, $currentUserId, 'user_roles.json', 'SELECT * FROM `msz_user_roles` WHERE `user_id` = :user_id');
|
||||
db_to_zip($archive, $currentUserId, 'user_warnings.json', 'SELECT *, INET6_NTOA(`user_ip`) AS `user_ip`, NULL AS `issuer_id`, NULL AS `issuer_ip`, NULL AS `warning_note_private` FROM `msz_user_warnings` WHERE `user_id` = :user_id');
|
||||
|
||||
|
|
|
@ -54,8 +54,6 @@ class User implements HasRankInterface, JsonSerializable {
|
|||
public const ORDER_ACTIVE = 'last-online';
|
||||
public const ORDER_FORUM_TOPICS = 'forum-topics';
|
||||
public const ORDER_FORUM_POSTS = 'forum-posts';
|
||||
public const ORDER_FOLLOWING = 'following';
|
||||
public const ORDER_FOLLOWERS = 'followers';
|
||||
|
||||
// Database fields
|
||||
private $user_id = -1;
|
||||
|
@ -537,68 +535,6 @@ class User implements HasRankInterface, JsonSerializable {
|
|||
return array_key_exists($role->getId(), $this->getRoleRelations());
|
||||
}
|
||||
|
||||
/*************
|
||||
* RELATIONS *
|
||||
*************/
|
||||
|
||||
private $relationCache = [];
|
||||
private $relationFollowingCount = -1;
|
||||
private $relationFollowersCount = -1;
|
||||
|
||||
public function getRelation(self $other): UserRelation {
|
||||
if(isset($this->relationCache[$other->getId()]))
|
||||
return $this->relationCache[$other->getId()];
|
||||
return $this->relationCache[$other->getId()] = UserRelation::byUserAndSubject($this, $other);
|
||||
}
|
||||
public function getRelationString(self $other): string {
|
||||
if($other->getId() === $this->getId())
|
||||
return 'self';
|
||||
|
||||
$from = $this->getRelation($other);
|
||||
$to = $other->getRelation($this);
|
||||
|
||||
if($from->isFollow() && $to->isFollow())
|
||||
return 'mutual';
|
||||
if($from->isFollow())
|
||||
return 'following';
|
||||
if($to->isFollow())
|
||||
return 'followed';
|
||||
return 'none';
|
||||
}
|
||||
public function getRelationTime(self $other): int {
|
||||
if($other->getId() === $this->getId())
|
||||
return -1;
|
||||
|
||||
$from = $this->getRelation($other);
|
||||
$to = $other->getRelation($this);
|
||||
|
||||
return max($from->getCreationTime(), $to->getCreationTime());
|
||||
}
|
||||
public function addFollower(self $other): void {
|
||||
UserRelation::create($other, $this, UserRelation::TYPE_FOLLOW);
|
||||
unset($this->relationCache[$other->getId()]);
|
||||
}
|
||||
public function removeRelation(self $other): void {
|
||||
UserRelation::destroy($other, $this);
|
||||
unset($this->relationCache[$other->getId()]);
|
||||
}
|
||||
public function getFollowers(?Pagination $pagination = null): array {
|
||||
return UserRelation::bySubject($this, UserRelation::TYPE_FOLLOW, $pagination);
|
||||
}
|
||||
public function getFollowersCount(): int {
|
||||
if($this->relationFollowersCount < 0)
|
||||
$this->relationFollowersCount = UserRelation::countBySubject($this, UserRelation::TYPE_FOLLOW);
|
||||
return $this->relationFollowersCount;
|
||||
}
|
||||
public function getFollowing(?Pagination $pagination = null): array {
|
||||
return UserRelation::byUser($this, UserRelation::TYPE_FOLLOW, $pagination);
|
||||
}
|
||||
public function getFollowingCount(): int {
|
||||
if($this->relationFollowingCount < 0)
|
||||
$this->relationFollowingCount = UserRelation::countByUser($this, UserRelation::TYPE_FOLLOW);
|
||||
return $this->relationFollowingCount;
|
||||
}
|
||||
|
||||
/***************
|
||||
* FORUM STATS *
|
||||
***************/
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
<?php
|
||||
namespace Misuzu\Users;
|
||||
|
||||
use Misuzu\DB;
|
||||
use Misuzu\Pagination;
|
||||
|
||||
class UserRelation {
|
||||
public const TYPE_NONE = 0;
|
||||
public const TYPE_FOLLOW = 1;
|
||||
|
||||
// Database fields
|
||||
private $user_id = -1;
|
||||
private $subject_id = -1;
|
||||
private $relation_type = 0;
|
||||
private $relation_created = null;
|
||||
|
||||
private $user = null;
|
||||
private $subject = null;
|
||||
|
||||
public const TABLE = 'user_relations';
|
||||
private const QUERY_SELECT = 'SELECT %1$s FROM `' . DB::PREFIX . self::TABLE . '` AS '. self::TABLE;
|
||||
private const SELECT = '%1$s.`user_id`, %1$s.`subject_id`, %1$s.`relation_type`'
|
||||
. ', UNIX_TIMESTAMP(%1$s.`relation_created`) AS `relation_created`';
|
||||
|
||||
public function getUserId(): int {
|
||||
return $this->user_id < 1 ? -1 : $this->user_id;
|
||||
}
|
||||
public function getUser(): User {
|
||||
if($this->user === null)
|
||||
$this->user = User::byId($this->getUserId());
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function getSubjectId(): int {
|
||||
return $this->subject_id < 1 ? -1 : $this->subject_id;
|
||||
}
|
||||
public function getSubject(): User {
|
||||
if($this->subject === null)
|
||||
$this->subject = User::byId($this->getSubjectId());
|
||||
return $this->subject;
|
||||
}
|
||||
|
||||
public function getType(): int {
|
||||
return $this->relation_type;
|
||||
}
|
||||
public function isNone(): bool {
|
||||
return $this->getType() === self::TYPE_NONE;
|
||||
}
|
||||
public function isFollow(): bool {
|
||||
return $this->getType() === self::TYPE_FOLLOW;
|
||||
}
|
||||
|
||||
public function getCreationTime(): int {
|
||||
return $this->relation_created === null ? -1 : $this->relation_created;
|
||||
}
|
||||
|
||||
public static function destroy(User $user, User $subject): void {
|
||||
DB::prepare('DELETE FROM `' . DB::PREFIX . self::TABLE . '` WHERE `user_id` = :user AND `subject_id` = :subject')
|
||||
->bind('user', $user->getId())
|
||||
->bind('subject', $subject->getId())
|
||||
->execute();
|
||||
}
|
||||
|
||||
public static function create(User $user, User $subject, int $type): void {
|
||||
if($type === self::TYPE_NONE) {
|
||||
self::destroy($user, $subject);
|
||||
return;
|
||||
}
|
||||
|
||||
DB::prepare(
|
||||
'REPLACE INTO `' . DB::PREFIX . self::TABLE . '` (`user_id`, `subject_id`, `relation_type`)'
|
||||
. ' VALUES (:user, :subject, :type)'
|
||||
) ->bind('user', $user->getId())
|
||||
->bind('subject', $subject->getId())
|
||||
->bind('type', $type)
|
||||
->execute();
|
||||
}
|
||||
|
||||
private static function countQueryBase(): string {
|
||||
return sprintf(self::QUERY_SELECT, sprintf('COUNT(*)', self::TABLE));
|
||||
}
|
||||
public static function countByUser(User $user, ?int $type = null): int {
|
||||
$count = DB::prepare(
|
||||
self::countQueryBase()
|
||||
. ' WHERE `user_id` = :user'
|
||||
. ($type === null ? '' : ' AND `relation_type` = :type')
|
||||
) ->bind('user', $user->getId());
|
||||
if($type !== null)
|
||||
$count->bind('type', $type);
|
||||
return (int)$count->fetchColumn();
|
||||
}
|
||||
public static function countBySubject(User $subject, ?int $type = null): int {
|
||||
$count = DB::prepare(
|
||||
self::countQueryBase()
|
||||
. ' WHERE `subject_id` = :subject'
|
||||
. ($type === null ? '' : ' AND `relation_type` = :type')
|
||||
) ->bind('subject', $subject->getId());
|
||||
if($type !== null)
|
||||
$count->bind('type', $type);
|
||||
return (int)$count->fetchColumn();
|
||||
}
|
||||
|
||||
private static function byQueryBase(): string {
|
||||
return sprintf(self::QUERY_SELECT, sprintf(self::SELECT, self::TABLE));
|
||||
}
|
||||
public static function byUserAndSubject(User $user, User $subject): self {
|
||||
$object = DB::prepare(self::byQueryBase() . ' WHERE `user_id` = :user AND `subject_id` = :subject')
|
||||
->bind('user', $user->getId())
|
||||
->bind('subject', $subject->getId())
|
||||
->fetchObject(self::class);
|
||||
|
||||
if(!$object) {
|
||||
$fake = new static;
|
||||
$fake->user_id = $user->getId();
|
||||
$fake->user = $user;
|
||||
$fake->subject_id = $subject->getId();
|
||||
$fake->subject = $subject;
|
||||
return $fake;
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
public static function byUser(User $user, ?int $type = null, ?Pagination $pagination = null): array {
|
||||
$query = self::byQueryBase()
|
||||
. ' WHERE `user_id` = :user'
|
||||
. ($type === null ? '' : ' AND `relation_type` = :type')
|
||||
. ' ORDER BY `relation_created` DESC';
|
||||
|
||||
if($pagination !== null)
|
||||
$query .= ' LIMIT :range OFFSET :offset';
|
||||
|
||||
$get = DB::prepare($query)
|
||||
->bind('user', $user->getId());
|
||||
|
||||
if($type !== null)
|
||||
$get->bind('type', $type);
|
||||
|
||||
if($pagination !== null)
|
||||
$get->bind('range', $pagination->getRange())
|
||||
->bind('offset', $pagination->getOffset());
|
||||
|
||||
return $get->fetchObjects(self::class);
|
||||
}
|
||||
public static function bySubject(User $subject, ?int $type = null, ?Pagination $pagination = null): array {
|
||||
$query = self::byQueryBase()
|
||||
. ' WHERE `subject_id` = :subject'
|
||||
. ($type === null ? '' : ' AND `relation_type` = :type')
|
||||
. ' ORDER BY `relation_created` DESC';
|
||||
|
||||
if($pagination !== null)
|
||||
$query .= ' LIMIT :range OFFSET :offset';
|
||||
|
||||
$get = DB::prepare($query)
|
||||
->bind('subject', $subject->getId());
|
||||
|
||||
if($type !== null)
|
||||
$get->bind('type', $type);
|
||||
|
||||
if($pagination !== null)
|
||||
$get->bind('range', $pagination->getRange())
|
||||
->bind('offset', $pagination->getOffset());
|
||||
|
||||
return $get->fetchObjects(self::class);
|
||||
}
|
||||
}
|
|
@ -67,8 +67,6 @@ define('MSZ_URLS', [
|
|||
'user-list' => ['/members.php', ['r' => '<role>', 'ss' => '<sort>', 'sd' => '<direction>', 'p' => '<page>']],
|
||||
|
||||
'user-profile' => ['/profile.php', ['u' => '<user>']],
|
||||
'user-profile-following' => ['/profile.php', ['u' => '<user>', 'm' => 'following']],
|
||||
'user-profile-followers' => ['/profile.php', ['u' => '<user>', 'm' => 'followers']],
|
||||
'user-profile-forum-topics' => ['/profile.php', ['u' => '<user>', 'm' => 'forum-topics']],
|
||||
'user-profile-forum-posts' => ['/profile.php', ['u' => '<user>', 'm' => 'forum-posts']],
|
||||
'user-profile-edit' => ['/profile.php', ['u' => '<user>', 'edit' => '1']],
|
||||
|
@ -77,10 +75,6 @@ define('MSZ_URLS', [
|
|||
'user-avatar' => ['/assets/avatar/<user>', ['res' => '<res>']],
|
||||
'user-background' => ['/assets/profile-background/<user>'],
|
||||
|
||||
'user-relation-create' => ['/relations.php', ['u' => '<user>', 'm' => '<type>', 'csrf' => '{csrf}']],
|
||||
'user-relation-none' => ['/relations.php', ['u' => '<user>', 'm' => '[\Misuzu\Users\UserRelation::TYPE_NONE]', 'csrf' => '{csrf}']],
|
||||
'user-relation-follow' => ['/relations.php', ['u' => '<user>', 'm' => '[\Misuzu\Users\UserRelation::TYPE_FOLLOW]', 'csrf' => '{csrf}']],
|
||||
|
||||
'settings-index' => ['/settings'],
|
||||
'settings-account' => ['/settings/account.php'],
|
||||
'settings-sessions' => ['/settings/sessions.php'],
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<p class="auth__register__paragraph">By creating an account you agree to the <a href="{{ url('info', {'title': 'rules'}) }}" class="auth__register__link">rules</a>.</p>
|
||||
<p class="auth__register__paragraph">Engaging in borderline illegal activity on platforms provided by Flashii will result in a permanent ban, as described by Global Rule 5.</p>
|
||||
<p class="auth__register__paragraph">You are not allowed to have more than one account unless given explicit permission, as described by Global Rule 6.</p>
|
||||
<p class="auth__register__paragraph">You must be at least 13 years of age to use this website, as described by Global Rule 8.</p>
|
||||
<p class="auth__register__paragraph">You must be at least 18 years of age to use this website, as described by Global Rule 8.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
'stat_login_attempts_failed': 'Failed Login Attempts',
|
||||
'stat_user_sessions': 'Active User Sessions',
|
||||
'stat_user_password_resets': 'Pending Password Resets',
|
||||
'stat_user_relations': 'User Relations',
|
||||
'stat_user_warnings': 'User Warnings',
|
||||
} %}
|
||||
|
||||
|
|
|
@ -56,18 +56,6 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if profile_viewer is not null and profile_user.id != profile_viewer.id and profile_user.relationString(profile_viewer) != 'none' %}
|
||||
<div class="profile__header__details__relation" title="Since {{ profile_user.relationTime(profile_viewer)|date('r') }}">
|
||||
{% if profile_user.relationString(profile_viewer) == 'mutual' %}
|
||||
Mutual Friends
|
||||
{% elseif profile_user.relationString(profile_viewer) == 'followed' %}
|
||||
You Follow
|
||||
{% elseif profile_user.relationString(profile_viewer) == 'following' %}
|
||||
Follows You
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="profile__header__options">
|
||||
|
@ -81,14 +69,6 @@
|
|||
{% elseif profile_can_edit %}
|
||||
<a href="{{ url('user-profile-edit', {'user': profile_user.id}) }}" class="input__button profile__header__action">Edit Profile</a>
|
||||
{% endif %}
|
||||
|
||||
{% if current_user is defined and current_user.id|default(0) != profile_user.id and not profile_is_editing %}
|
||||
{% if profile_user.relationString(profile_viewer) != 'following' %}
|
||||
<a href="{{ url('user-relation-none', {'user': profile_user.id}) }}" class="input__button input__button--destroy profile__header__action js-user-relation-action" data-relation-user="{{ profile_user.id }}" data-relation-type="0">Unfollow</a>
|
||||
{% else %}
|
||||
<a href="{{ url('user-relation-follow', {'user': profile_user.id}) }}" class="input__button profile__header__action js-user-relation-action" data-relation-user="{{ profile_user.id }}" data-relation-type="1">Follow</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{{ url('user-profile', {'user': profile_user.id}) }}" class="input__button profile__header__action">Return</a>
|
||||
{% endif %}
|
||||
|
|
|
@ -17,18 +17,6 @@
|
|||
'is_date': true,
|
||||
'value': profile_user.activeTime,
|
||||
},
|
||||
{
|
||||
'title': 'Following',
|
||||
'value': profile_stats.following_count,
|
||||
'url': url('user-profile-following', {'user': profile_user.id}),
|
||||
'active': profile_mode == 'following',
|
||||
},
|
||||
{
|
||||
'title': 'Followers',
|
||||
'value': profile_stats.followers_count,
|
||||
'url': url('user-profile-followers', {'user': profile_user.id}),
|
||||
'active': profile_mode == 'followers',
|
||||
},
|
||||
{
|
||||
'title': 'Topics',
|
||||
'value': profile_stats.forum_topic_count,
|
||||
|
|
|
@ -47,28 +47,6 @@
|
|||
|
||||
<div class="usercard__container">
|
||||
<div class="usercard__stats">
|
||||
{% if user.followingCount > 0 %}
|
||||
<a class="usercard__stat" href="{{ url('user-profile-following', {'user': user.id}) }}">
|
||||
<div class="usercard__stat__name">
|
||||
Following
|
||||
</div>
|
||||
<div class="usercard__stat__value">
|
||||
{{ user.followingCount|number_format }}
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if user.followersCount > 0 %}
|
||||
<a class="usercard__stat" href="{{ url('user-profile-followers', {'user': user.id}) }}">
|
||||
<div class="usercard__stat__name">
|
||||
Followers
|
||||
</div>
|
||||
<div class="usercard__stat__value">
|
||||
{{ user.followersCount|number_format }}
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if user.forumTopicCount > 0 %}
|
||||
<a class="usercard__stat" href="{{ url('user-profile-forum-topics', {'user': user.id}) }}">
|
||||
<div class="usercard__stat__name">
|
||||
|
@ -112,14 +90,6 @@
|
|||
<a class="usercard__action" href="{{ url('user-profile', {'user': user.id}) }}" title="View Profile">
|
||||
<i class="fas fa-user"></i>
|
||||
</a>
|
||||
|
||||
{% if current_user is not null %}
|
||||
{% set is_following = current_user.relationString(user) in ['mutual', 'following'] %}
|
||||
<a class="usercard__action js-user-relation-action" href="{{ url('user-relation-follow', {'user': user.id}) }}" title="{{ is_following ? 'Unfollow' : 'Follow' }}"
|
||||
data-relation-user="{{ user.id }}" data-relation-type="{{ is_following ? 0 : 1 }}">
|
||||
<i class="fas fa-user-{{ is_following ? 'minus' : 'plus' }}"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -164,28 +134,6 @@
|
|||
|
||||
<div class="usercard__container">
|
||||
<div class="usercard__stats">
|
||||
{% if user.user_count_following|default(0) > 0 %}
|
||||
<a class="usercard__stat" href="{{ url('user-profile-following', {'user': user.user_id}) }}">
|
||||
<div class="usercard__stat__name">
|
||||
Following
|
||||
</div>
|
||||
<div class="usercard__stat__value">
|
||||
{{ user.user_count_following|number_format }}
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if user.user_count_followers|default(0) > 0 %}
|
||||
<a class="usercard__stat" href="{{ url('user-profile-followers', {'user': user.user_id}) }}">
|
||||
<div class="usercard__stat__name">
|
||||
Followers
|
||||
</div>
|
||||
<div class="usercard__stat__value">
|
||||
{{ user.user_count_followers|number_format }}
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if user.user_count_topics|default(0) > 0 %}
|
||||
<a class="usercard__stat" href="{{ url('user-profile-forum-topics', {'user': user.user_id}) }}">
|
||||
<div class="usercard__stat__name">
|
||||
|
@ -233,15 +181,6 @@
|
|||
<a class="usercard__action" href="{{ url('user-profile', {'user': user.user_id}) }}" title="View Profile">
|
||||
<i class="fas fa-user"></i>
|
||||
</a>
|
||||
|
||||
{% if user.current_user_id|default(0) != 0 and user.current_user_id != user.user_id %}
|
||||
{% set is_following = user.user_is_following|default(false) %}
|
||||
|
||||
<a class="usercard__action js-user-relation-action" href="{{ url('user-relation-follow', {'user': user.user_id}) }}" title="{{ is_following ? 'Unfollow' : 'Follow' }}"
|
||||
data-relation-user="{{ user.user_id }}" data-relation-type="{{ is_following ? 0 : 1 }}">
|
||||
<i class="fas fa-user-{{ is_following ? 'minus' : 'plus' }}"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue