<?php
declare(strict_types=1);
namespace Slivki\Repository\User;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\Query\Expr\Join;
use Slivki\Entity\Director;
use Slivki\Entity\MobileUserToken;
use Slivki\Entity\User;
use Slivki\Entity\User\Employee;
use Slivki\Exception\UserNotFoundException;
use function mb_strtolower;
final class UserRepository extends EntityRepository implements UserRepositoryInterface
{
public function __construct(EntityManagerInterface $entityManager)
{
parent::__construct($entityManager, new ClassMetadata(User::class));
}
public function save(User $user): void
{
$this->_em->persist($user);
$this->_em->flush($user);
}
public function getById(int $id): User
{
$qb = $this->createQueryBuilder('u');
$expr = $qb->expr();
$user = $qb
->andWhere($expr->eq('u.ID', ':id'))
->setParameter('id', $id)
->getQuery()
->getOneOrNullResult();
if (!$user instanceof User) {
throw UserNotFoundException::missingId($id);
}
return $user;
}
public function findByToken(string $token): ?User
{
$qb = $this->createQueryBuilder('user');
$expr = $qb->expr();
return $qb
->andWhere($expr->eq('user.token', ':token'))
->setParameter('token', $token)
->getQuery()
->getOneOrNullResult();
}
public function findByMobileToken(string $token): ?User
{
$qb = $this->createQueryBuilder('user');
$expr = $qb->expr();
return $qb
->innerJoin(
MobileUserToken::class,
'mobileUserToken',
Join::WITH,
$expr->eq('user', 'mobileUserToken.user'),
)
->andWhere($expr->eq('mobileUserToken.token', ':token'))
->setParameter('token', $token)
->getQuery()
->getOneOrNullResult();
}
/**
* @throws NonUniqueResultException
*/
public function findByPhoneNumber(string $phoneNumber): ?User
{
$qb = $this->createQueryBuilder('user');
$expr = $qb->expr();
return $qb
->innerJoin('user.phones', 'userPhone')
->andWhere($expr->eq('userPhone.confirmed', ':confirmed'))
->andWhere($expr->eq('userPhone.phoneNumber', ':phoneNumber'))
->setParameter('confirmed', true)
->setParameter('phoneNumber', $phoneNumber)
->getQuery()
->getOneOrNullResult();
}
public function getByEmail(string $email): User
{
$qb = $this->createQueryBuilder('u');
$expr = $qb->expr();
$user = $qb
->andWhere($expr->eq($expr->lower('u.email'), ':email'))
->setParameter('email', mb_strtolower($email))
->getQuery()
->getOneOrNullResult();
if (!$user instanceof User) {
throw UserNotFoundException::missingByEmail($email);
}
return $user;
}
public function findDirectorUserByEmployeeUserId(int $userId): ?User
{
$qb = $this->createQueryBuilder('user');
$expr = $qb->expr();
return $qb
->innerJoin(Director::class, 'director', Join::WITH, $expr->eq('director.email', 'user.email'))
->innerJoin(Employee::class, 'employee', Join::WITH, $expr->eq('employee.company', 'director'))
->andWhere($expr->eq('employee.user', ':userId'))
->setParameter('userId', $userId)
->getQuery()
->getOneOrNullResult();
}
}