<?php
namespace App\Repository\Auth;
use App\Data\SearchItem;
use App\Entity\Activities\Likes;
use App\Entity\Auth\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\Exception\ORMException;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use function get_class;
/**
* @extends ServiceEntityRepository<User>
*
* @method User|null find($id, $lockMode = null, $lockVersion = null)
* @method User|null findOneBy(array $criteria, array $orderBy = null)
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
{
/**
* @var PaginatorInterface
*/
private PaginatorInterface $paginator;
public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
{
parent::__construct($registry, User::class);
$this->paginator = $paginator;
}
/**
* @param User $entity
* @param bool $flush
* @throws OptimisticLockException
* @throws ORMException|\Doctrine\ORM\ORMException
*/
public function add(User $entity, bool $flush = false): void
{
$this->getEntityManager()->persist($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
/**
* @param User $entity
* @param bool $flush
* @throws OptimisticLockException
* @throws ORMException|\Doctrine\ORM\ORMException
*/
public function remove(User $entity, bool $flush = false): void
{
$this->getEntityManager()->remove($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
/**
* Used to upgrade (rehash) the user's password automatically over time.
* @param PasswordAuthenticatedUserInterface $user
* @param string $newHashedPassword
* @throws OptimisticLockException
* @throws ORMException|\Doctrine\ORM\ORMException
*/
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
}
$user->setPassword($newHashedPassword);
$this->add($user, true);
}
/**
* @param SearchItem $search
* @param Request $request
* @param bool $paginate
* @return array
*/
public function findSearch(SearchItem $search, Request $request, $paginate = true): array
{
$query = $this->getSearchQuery($search)->getQuery();
$page = $request->query->getInt('page', 1);
if ($request->get('ajax')) {
$limit = 6;
} else {
$limit = $paginate ? (6 * $page) : count($query->getResult());
}
$users = $this->paginator->paginate($query, $page, $limit);
return [$users, $page, count($users)];
}
/**
* @param SearchItem $search
* @return QueryBuilder
*/
private function getSearchQuery(SearchItem $search): QueryBuilder
{
$query = $this->createQueryBuilder('u');
if (!empty($search->q)) {
$query = $query
->andWhere('u.town LIKE :q OR u.firstname LIKE :q OR u.lastname LIKE :q OR u.zipCode LIKE :q OR u.address LIKE :q')
->setParameter('q', "%{$search->q}%");
}
if ($search->holiday) {
$query = $query->andWhere('u.emergencyKeeping = true');
}
if ($search->verified) {
$query = $query->andWhere('u.isConfirmed = true');
}
if ($search->nightKeeping) {
$query = $query->andWhere('u.nightKeeping = true');
}
if (!empty($search->status)) {
$query = $query
->andWhere('u.status != :status');
if ($search->status === 'home_care') {// La nounou se déplace
$query->setParameter('status', "Je me déplace uniquement");
}
if ($search->status === 'away_care') { // La nounou va chez le parent
$query->setParameter('status', "Je reçois uniquement");
}
}
return $query
->andWhere('u.isAdmin = false')
->andWhere('u.isParent = false')
->andWhere('u.isProfileCompleted = true')
->andWhere('u.isVerified = true')
->andWhere('u.bannedAt IS NULL')
->andWhere('u.deleteAt IS NULL')
->andWhere('u.confirmationToken IS NULL')
->orderBy('u.createdAt', 'DESC');
}
/**
* Récupère le prix minimum et maximum correspondant à une recherche
* @param SearchItem $search
* @return array|integer[]
*/
public function findMinMax(SearchItem $search): array
{
$results = $this->getSearchQuery($search)
->select('MIN(u.hourRate) as min', 'MAX(u.hourRate) as max')
->getQuery()
->getScalarResult();
return [(float)$results[0]['min'], (float)$results[0]['max']];
}
/**
* @param User|UserInterface $user
* @return User[]
*/
public function getFavorites(User $user)
{
return $this->createQueryBuilder('u')
->innerJoin(Likes::class, 'l', 'WITH', 'l.liked = u.id')
->innerJoin(User::class, 'liker', 'WITH', 'liker.id = l.liker')
->andWhere('l.isActive = true')
->andWhere('l.liker = :user')
->setParameter('user', $user)
->getQuery()->getResult();
}
/**
* @param string $emailOrUsername
* @return User|null
* @throws NonUniqueResultException
*/
public function findByEmailOrUsername(string $emailOrUsername)
{
return $this->createQueryBuilder('u')
->where('u.email = :emailOrUsername')
->orWhere('u.matricule = :emailOrUsername')
->setParameter('emailOrUsername', $emailOrUsername)
->getQuery()
->getOneOrNullResult();
}
}