Added basic friends system.

This commit is contained in:
flash 2018-09-19 00:16:29 +02:00
parent 5556a9789a
commit 818ea9c4c9
8 changed files with 187 additions and 6 deletions

View file

@ -46,6 +46,7 @@
border-radius: 2px; border-radius: 2px;
line-height: 1.2em; line-height: 1.2em;
padding: 1px 5px 4px; padding: 1px 5px 4px;
cursor: default;
} }
} }
@ -98,6 +99,7 @@
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
padding: 10px; padding: 10px;
cursor: default;
&--date { &--date {
min-width: 130px; min-width: 130px;
@ -106,11 +108,13 @@
&__name { &__name {
font-size: .9em; font-size: .9em;
font-variant: small-caps; font-variant: small-caps;
cursor: inherit;
} }
&__value { &__value {
font-size: 1.3em; font-size: 1.3em;
text-align: right; text-align: right;
cursor: inherit;
} }
} }

View file

@ -0,0 +1,33 @@
<?php
namespace Misuzu\DatabaseMigrations\AddRelationsTable;
use PDO;
function migrate_up(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`),
INDEX `user_relations_subject_id_foreign` (`subject_id`),
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
)
');
}
function migrate_down(PDO $conn): void
{
$conn->exec('DROP TABLE `msz_user_relations`');
}

View file

@ -42,6 +42,7 @@ require_once __DIR__ . '/src/Forum/topic.php';
require_once __DIR__ . '/src/Forum/validate.php'; require_once __DIR__ . '/src/Forum/validate.php';
require_once __DIR__ . '/src/Users/login_attempt.php'; require_once __DIR__ . '/src/Users/login_attempt.php';
require_once __DIR__ . '/src/Users/profile.php'; require_once __DIR__ . '/src/Users/profile.php';
require_once __DIR__ . '/src/Users/relations.php';
require_once __DIR__ . '/src/Users/role.php'; require_once __DIR__ . '/src/Users/role.php';
require_once __DIR__ . '/src/Users/session.php'; require_once __DIR__ . '/src/Users/session.php';
require_once __DIR__ . '/src/Users/user.php'; require_once __DIR__ . '/src/Users/user.php';

View file

@ -94,6 +94,36 @@ switch ($mode) {
break; break;
} }
if ($app->hasActiveSession()) {
$getFriendInfo = Database::prepare('
SELECT
:visitor as `visitor`, :profile as `profile`,
(
SELECT `relation_type`
FROM `msz_user_relations`
WHERE `user_id` = `visitor`
AND `subject_id` = `profile`
) as `visitor_relation`,
(
SELECT `relation_type`
FROM `msz_user_relations`
WHERE `subject_id` = `visitor`
AND `user_id` = `profile`
) as `profile_relation`,
(
SELECT MAX(`relation_created`)
FROM `msz_user_relations`
WHERE (`user_id` = `visitor` AND `subject_id` = `profile`)
OR (`user_id` = `profile` AND `subject_id` = `visitor`)
) as `relation_created`
');
$getFriendInfo->bindValue('visitor', $app->getUserId());
$getFriendInfo->bindValue('profile', $profile['user_id']);
$friendInfo = $getFriendInfo->execute() ? $getFriendInfo->fetch(PDO::FETCH_ASSOC) : [];
tpl_var('friend_info', $friendInfo);
}
tpl_vars([ tpl_vars([
'profile' => $profile, 'profile' => $profile,
'profile_fields' => $app->hasActiveSession() ? user_profile_fields_display($profile) : [], 'profile_fields' => $app->hasActiveSession() ? user_profile_fields_display($profile) : [],

41
public/relations.php Normal file
View file

@ -0,0 +1,41 @@
<?php
use Misuzu\Database;
require_once __DIR__ . '/../misuzu.php';
if (empty($_SERVER['HTTP_REFERER']) || !is_local_url($_SERVER['HTTP_REFERER'])) {
header('Location: /');
return;
}
if (!$app->hasActiveSession()) {
echo render_error(403);
return;
}
$subjectId = (int)($_GET['u'] ?? 0);
switch ($_GET['m'] ?? null) {
case 'add':
switch ($_GET['t'] ?? null) {
case 'follow':
default:
$type = MSZ_USER_RELATION_FOLLOW;
break;
}
if (user_relation_add($app->getUserId(), $subjectId, $type) !== MSZ_USER_RELATION_E_OK) {
echo render_error(500);
return;
}
break;
case 'remove':
if (!user_relation_remove($app->getUserId(), $subjectId)) {
echo render_error(500);
return;
}
break;
}
header('Location: ' . $_SERVER['HTTP_REFERER']);

56
src/Users/relations.php Normal file
View file

@ -0,0 +1,56 @@
<?php
use Misuzu\Database;
define('MSZ_USER_RELATION_FOLLOW', 1);
define('MSZ_USER_RELATION_TYPES', [
MSZ_USER_RELATION_FOLLOW,
]);
define('MSZ_USER_RELATION_E_OK', 0);
define('MSZ_USER_RELATION_E_USER_ID', 1);
define('MSZ_USER_RELATION_E_DATABASE', 2);
define('MSZ_USER_RELATION_E_INVALID_TYPE', 2);
function user_relation_add(int $userId, int $subjectId, int $type = MSZ_USER_RELATION_FOLLOW): int
{
if ($userId < 1 || $subjectId < 1) {
return MSZ_USER_RELATION_E_USER_ID;
}
if (!in_array($type, MSZ_USER_RELATION_TYPES, true)) {
return MSZ_USER_RELATION_E_INVALID_TYPE;
}
$addRelation = Database::prepare('
REPLACE INTO `msz_user_relations`
(`user_id`, `subject_id`, `relation_type`)
VALUES
(:user_id, :subject_id, :type)
');
$addRelation->bindValue('user_id', $userId);
$addRelation->bindValue('subject_id', $subjectId);
$addRelation->bindValue('type', $type);
$addRelation->execute();
return $addRelation->execute()
? MSZ_USER_RELATION_E_OK
: MSZ_USER_RELATION_E_DATABASE;
}
function user_relation_remove(int $userId, int $subjectId): bool
{
if ($userId < 1 || $subjectId < 1) {
return false;
}
$removeRelation = Database::prepare('
DELETE FROM `msz_user_relations`
WHERE `user_id` = :user_id
AND `subject_id` = :subject_id
');
$removeRelation->bindValue('user_id', $userId);
$removeRelation->bindValue('subject_id', $subjectId);
return $removeRelation->execute();
}

View file

@ -38,18 +38,29 @@
</div> </div>
</div> </div>
<!--div class="profile__header__details__relation"> {% if friend_info is defined and (friend_info.profile_relation is not null or friend_info.visitor_relation is not null) %}
Follows you <div class="profile__header__details__relation" title="Since {{ friend_info.relation_created|date('r') }}">
</div--> {% if friend_info.profile_relation and friend_info.visitor_relation %}
Mutual Friends
{% elseif friend_info.visitor_relation %}
You Follow
{% elseif friend_info.profile_relation %}
Follows You
{% endif %}
</div>
{% endif %}
</div> </div>
<div class="profile__header__options"> <div class="profile__header__options">
<div class="profile__header__actions"> <div class="profile__header__actions">
{% if current_user.user_id|default(0) == profile.user_id %} {% if current_user.user_id|default(0) == profile.user_id %}
<a href="/settings.php" class="profile__header__action">Edit Profile</a> <a href="/settings.php" class="profile__header__action">Edit Profile</a>
{# else %} {% elseif current_user is defined %}
<a href="#" class="profile__header__action">Add Friend</a> {% if friend_info.visitor_relation %}
<a href="#" class="profile__header__action profile__header__action--destroy">Unfriend</a>#} <a href="/relations.php?u={{ profile.user_id }}&amp;m=remove" class="profile__header__action profile__header__action--destroy">Unfriend</a>
{% else %}
<a href="/relations.php?u={{ profile.user_id }}&amp;m=add&amp;t=follow" class="profile__header__action">Add Friend</a>
{% endif %}
{% endif %} {% endif %}
</div> </div>

View file

@ -423,3 +423,8 @@ function snake_to_camel(string $snake): string
{ {
return str_replace('_', '', ucwords($snake, '_')); return str_replace('_', '', ucwords($snake, '_'));
} }
function is_user_int($value): bool
{
return ctype_digit(strval($value));
}