mirror of
https://github.com/YGGverse/YGGtracker.git
synced 2025-02-08 13:04:25 +00:00
implement user stars feature
This commit is contained in:
parent
d97a678952
commit
0a218cfd3a
@ -3,6 +3,8 @@
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -56,7 +58,7 @@ class UserController extends AbstractController
|
||||
continue;
|
||||
}
|
||||
|
||||
$activityUser = $userService->get(
|
||||
$activityUser = $userService->getUser(
|
||||
$activity->getUserId()
|
||||
);
|
||||
|
||||
@ -168,7 +170,7 @@ class UserController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route(
|
||||
'/{_locale}/user/{id}',
|
||||
'/{_locale}/user/{userId}',
|
||||
name: 'user_info',
|
||||
defaults: [
|
||||
'_locale' => '%app.locale%'
|
||||
@ -178,12 +180,25 @@ class UserController extends AbstractController
|
||||
],
|
||||
)]
|
||||
public function info(
|
||||
int $id,
|
||||
Request $request,
|
||||
TranslatorInterface $translator,
|
||||
UserService $userService): Response
|
||||
{
|
||||
// Init user
|
||||
if (!$user = $userService->get($id))
|
||||
$user = $userService->init(
|
||||
$request->getClientIp()
|
||||
);
|
||||
|
||||
if (!$user->isStatus())
|
||||
{
|
||||
// @TODO
|
||||
throw new \Exception(
|
||||
$translator->trans('Access denied')
|
||||
);
|
||||
}
|
||||
|
||||
// Init target user
|
||||
if (!$userTarget = $userService->getUser($request->get('userId')))
|
||||
{
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
@ -193,23 +208,87 @@ class UserController extends AbstractController
|
||||
'default/user/info.html.twig',
|
||||
[
|
||||
'user' => [
|
||||
'id' => $user->getId(),
|
||||
'address' => $request->getClientIp() == $user->getAddress() ? $user->getAddress() : false,
|
||||
'moderator' => $user->isModerator(),
|
||||
'approved' => $user->isApproved(),
|
||||
'status' => $user->isStatus(),
|
||||
'locale' => $user->getLocale(),
|
||||
'locales' => $user->getLocales(),
|
||||
'added' => $user->getAdded(),
|
||||
'id' => $userTarget->getId(),
|
||||
'address' => $request->getClientIp() == $userTarget->getAddress() ? $userTarget->getAddress() : false,
|
||||
'moderator' => $userTarget->isModerator(),
|
||||
'approved' => $userTarget->isApproved(),
|
||||
'status' => $userTarget->isStatus(),
|
||||
'locale' => $userTarget->getLocale(),
|
||||
'locales' => $userTarget->getLocales(),
|
||||
'added' => $userTarget->getAdded(),
|
||||
'identicon' => $userService->identicon(
|
||||
$user->getAddress(),
|
||||
$userTarget->getAddress(),
|
||||
48
|
||||
),
|
||||
'star' =>
|
||||
[
|
||||
'exist' => (bool) $userService->findUserStar(
|
||||
$user->getId(),
|
||||
$userTarget->getId()
|
||||
),
|
||||
'total' => $userService->findUserStarsTotalByUserIdTarget(
|
||||
$userTarget->getId()
|
||||
)
|
||||
],
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[Route(
|
||||
'/{_locale}/user/star/toggle/{userId}',
|
||||
name: 'user_star_toggle',
|
||||
requirements:
|
||||
[
|
||||
'userId' => '\d+',
|
||||
],
|
||||
methods:
|
||||
[
|
||||
'GET'
|
||||
]
|
||||
)]
|
||||
public function toggleStar(
|
||||
Request $request,
|
||||
TranslatorInterface $translator,
|
||||
UserService $userService
|
||||
): Response
|
||||
{
|
||||
// Init user
|
||||
$user = $userService->init(
|
||||
$request->getClientIp()
|
||||
);
|
||||
|
||||
if (!$user->isStatus())
|
||||
{
|
||||
// @TODO
|
||||
throw new \Exception(
|
||||
$translator->trans('Access denied')
|
||||
);
|
||||
}
|
||||
|
||||
// Init target user
|
||||
if (!$userTarget = $userService->getUser($request->get('userId')))
|
||||
{
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
// Update
|
||||
$userService->toggleUserStar(
|
||||
$user->getId(),
|
||||
$userTarget->getId(),
|
||||
time()
|
||||
);
|
||||
|
||||
// Redirect to info page created
|
||||
return $this->redirectToRoute(
|
||||
'user_info',
|
||||
[
|
||||
'_locale' => $request->get('_locale'),
|
||||
'userId' => $userTarget->getId()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function module(string $route = ''): Response
|
||||
{
|
||||
return $this->render(
|
||||
|
65
src/Entity/UserStar.php
Normal file
65
src/Entity/UserStar.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\UserStarRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: UserStarRepository::class)]
|
||||
class UserStar
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?int $userId = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?int $userIdTarget = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?int $added = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getUserId(): ?int
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function setUserId(int $userId): static
|
||||
{
|
||||
$this->userId = $userId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserIdTarget(): ?int
|
||||
{
|
||||
return $this->userIdTarget;
|
||||
}
|
||||
|
||||
public function setUserIdTarget(int $userIdTarget): static
|
||||
{
|
||||
$this->userIdTarget = $userIdTarget;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAdded(): ?int
|
||||
{
|
||||
return $this->added;
|
||||
}
|
||||
|
||||
public function setAdded(int $added): static
|
||||
{
|
||||
$this->added = $added;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
52
src/Repository/UserStarRepository.php
Normal file
52
src/Repository/UserStarRepository.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\UserStar;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<UserStar>
|
||||
*
|
||||
* @method UserStar|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method UserStar|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method UserStar[] findAll()
|
||||
* @method UserStar[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class UserStarRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, UserStar::class);
|
||||
}
|
||||
|
||||
public function findUserStar(
|
||||
int $userId,
|
||||
int $userIdTarget
|
||||
): ?UserStar
|
||||
{
|
||||
return $this->createQueryBuilder('us')
|
||||
->where('us.userId = :userId')
|
||||
->andWhere('us.userIdTarget = :userIdTarget')
|
||||
->setParameter('userId', $userId)
|
||||
->setParameter('userIdTarget', $userIdTarget)
|
||||
->setMaxResults(1)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
|
||||
public function findUserStarsTotalByUserIdTarget(
|
||||
int $userIdTarget
|
||||
): int
|
||||
{
|
||||
return $this->createQueryBuilder('us')
|
||||
->select('count(us.userId)')
|
||||
->where('us.userIdTarget = :userIdTarget')
|
||||
->setParameter('userIdTarget', $userIdTarget)
|
||||
->getQuery()
|
||||
->getSingleScalarResult()
|
||||
;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Entity\UserStar;
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
@ -10,24 +11,24 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
|
||||
class UserService
|
||||
{
|
||||
private EntityManagerInterface $entityManager;
|
||||
private UserRepository $userRepository;
|
||||
private EntityManagerInterface $entityManagerInterface;
|
||||
private ParameterBagInterface $parameterBagInterface;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $entityManager,
|
||||
EntityManagerInterface $entityManagerInterface,
|
||||
ParameterBagInterface $parameterBagInterface
|
||||
)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->userRepository = $entityManager->getRepository(User::class);
|
||||
$this->entityManagerInterface = $entityManagerInterface;
|
||||
$this->parameterBagInterface = $parameterBagInterface;
|
||||
}
|
||||
|
||||
public function init(string $address): User
|
||||
{
|
||||
// Return existing user
|
||||
if ($result = $this->userRepository->findOneByAddressField($address))
|
||||
if ($result = $this->entityManagerInterface
|
||||
->getRepository(User::class)
|
||||
->findOneByAddressField($address))
|
||||
{
|
||||
return $result;
|
||||
}
|
||||
@ -61,9 +62,11 @@ class UserService
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function get(int $id): ?User
|
||||
public function getUser(int $userId): ?User
|
||||
{
|
||||
return $this->userRepository->getUser($id);
|
||||
return $this->entityManagerInterface
|
||||
->getRepository(User::class)
|
||||
->getUser($userId);
|
||||
}
|
||||
|
||||
public function identicon(
|
||||
@ -86,9 +89,52 @@ class UserService
|
||||
return $identicon->getImageDataUri($format);
|
||||
}
|
||||
|
||||
public function save(User $user) : void
|
||||
public function save(User $user) : void // @TODO delete
|
||||
{
|
||||
$this->entityManager->persist($user);
|
||||
$this->entityManager->flush();
|
||||
$this->entityManagerInterface->persist($user);
|
||||
$this->entityManagerInterface->flush();
|
||||
}
|
||||
|
||||
// User star
|
||||
public function findUserStar(
|
||||
int $userId,
|
||||
int $userIdTarget
|
||||
): ?UserStar
|
||||
{
|
||||
return $this->entityManagerInterface
|
||||
->getRepository(UserStar::class)
|
||||
->findUserStar($userId, $userIdTarget);
|
||||
}
|
||||
|
||||
public function findUserStarsTotalByUserIdTarget(int $torrentId): int
|
||||
{
|
||||
return $this->entityManagerInterface
|
||||
->getRepository(UserStar::class)
|
||||
->findUserStarsTotalByUserIdTarget($torrentId);
|
||||
}
|
||||
|
||||
public function toggleUserStar(
|
||||
int $userId,
|
||||
int $userIdTarget,
|
||||
int $added
|
||||
): void
|
||||
{
|
||||
if ($userStar = $this->findUserStar($userId, $userIdTarget))
|
||||
{
|
||||
$this->entityManagerInterface->remove($userStar);
|
||||
$this->entityManagerInterface->flush();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
$userStar = new UserStar();
|
||||
|
||||
$userStar->setUserId($userId);
|
||||
$userStar->setUserIdTarget($userIdTarget);
|
||||
$userStar->setAdded($added);
|
||||
|
||||
$this->entityManagerInterface->persist($userStar);
|
||||
$this->entityManagerInterface->flush();
|
||||
}
|
||||
}
|
||||
}
|
@ -2,10 +2,30 @@
|
||||
{% block title %}{{ 'User'|trans }} #{{ user.id }} - {{ name }}{% endblock %}
|
||||
{% block main_content %}
|
||||
<div class="padding-24-px margin-y-8-px border-radius-3-px background-color-night">
|
||||
<div class="text-center">
|
||||
<div class="margin-b-16-px text-center">
|
||||
<img class="border-radius-50 border-color-default border-width-2-px" src="{{ user.identicon }}" alt="{{ 'identicon'|trans }}" />
|
||||
</div>
|
||||
<h2>{{ 'Profile'|trans }}</h2>
|
||||
<div class="margin-b-16-px">
|
||||
<h1 class="display-block text-center margin-b-16-px">
|
||||
{{ 'User'|trans }} #{{ user.id }}
|
||||
</h1>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<a class="margin-l-8-px margin-r-4-px" href="{{ path('user_star_toggle', {userId : user.id}) }}" title="{{ 'Bookmark' | trans }}">
|
||||
{% if user.star.exist %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
|
||||
</svg>
|
||||
{% else %}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M2.866 14.85c-.078.444.36.791.746.593l4.39-2.256 4.389 2.256c.386.198.824-.149.746-.592l-.83-4.73 3.522-3.356c.33-.314.16-.888-.282-.95l-4.898-.696L8.465.792a.513.513 0 0 0-.927 0L5.354 5.12l-4.898.696c-.441.062-.612.636-.283.95l3.523 3.356-.83 4.73zm4.905-2.767-3.686 1.894.694-3.957a.565.565 0 0 0-.163-.505L1.71 6.745l4.052-.576a.525.525 0 0 0 .393-.288L8 2.223l1.847 3.658a.525.525 0 0 0 .393.288l4.052.575-2.906 2.77a.565.565 0 0 0-.163.506l.694 3.957-3.686-1.894a.503.503 0 0 0-.461 0z"/>
|
||||
</svg>
|
||||
{% endif %}
|
||||
</a>
|
||||
<sup class="cursor-default" title="{{ 'Total' | trans }}">
|
||||
{{ user.star.total }}
|
||||
</sup>
|
||||
</div>
|
||||
<table class="width-100">
|
||||
<tbody>
|
||||
<tr>
|
||||
|
Loading…
x
Reference in New Issue
Block a user