Files
myep/src/Repository/UserRepository.php
T

126 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\Groups\AccommodationBooking;
use App\Entity\User;
use App\Form\Model\Filter\UserFilterDto;
use App\Repository\Filter\AppliesListFiltersTrait;
use App\Security\Role;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<User>
*/
class UserRepository extends ServiceEntityRepository
{
use AppliesListFiltersTrait;
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
public function createFilteredQueryBuilder(UserFilterDto $filter): QueryBuilder
{
$qb = $this->createQueryBuilder('user');
$this->applySearchTerm($qb, $filter->searchTerm(), [
'user.email',
'user.firstName',
'user.lastName',
'user.addressId',
'user.personId',
]);
$this->applyDateWithin($qb, 'user.lastLoginAt', $filter->dateFrom, $filter->dateTo);
if (null !== $filter->role && '' !== $filter->role) {
// Same reasoning as findGroupsStaff(): the roles are a JSON array column and no
// JSON_CONTAINS is registered, so the needle carries its quotes to stay anchored
// to a whole array entry.
$qb
->andWhere('user.roles LIKE :role')
->setParameter('role', '%"'.$filter->role.'"%')
;
}
return $qb;
}
/**
* Users who can look after a group booking. The roles are a JSON array column and no
* JSON_CONTAINS is registered, so the needles carry their quotes to stay anchored to
* whole array entries. Only the literal roles count — a plain ROLE_ADMIN is not offered.
*
* @return User[]
*/
public function findGroupsStaff(): array
{
return $this->createQueryBuilder('u')
->andWhere('u.roles LIKE :groupsAdmin OR u.roles LIKE :groupsManager')
->setParameter('groupsAdmin', '%"ROLE_GROUPS_ADMIN"%')
->setParameter('groupsManager', '%"ROLE_GROUPS_MANAGER"%')
->orderBy('u.email', 'ASC')
->getQuery()
->getResult();
}
/**
* Everyone worth filtering an accommodation booking by: current groups staff, plus whoever
* a booking is still assigned to even after losing the role — otherwise a booking assigned
* last season would become unfindable the moment its manager is deroled.
*/
public function createAccommodationBookingManagersQueryBuilder(): QueryBuilder
{
return $this->createQueryBuilder('u')
->leftJoin(AccommodationBooking::class, 'booking', Join::ON, 'booking.managedBy = u')
->andWhere('u.roles LIKE :groupsAdmin OR u.roles LIKE :groupsManager OR booking.id IS NOT NULL')
->setParameter('groupsAdmin', '%"ROLE_GROUPS_ADMIN"%')
->setParameter('groupsManager', '%"ROLE_GROUPS_MANAGER"%')
->distinct()
->orderBy('u.firstName')
->addOrderBy('u.lastName')
->addOrderBy('u.email')
;
}
/**
* The accounts carrying a nomination nobody has approved yet.
*
* Same reasoning as findGroupsStaff(): the roles are a JSON array column and no
* JSON_CONTAINS is registered, so each needle carries its quotes to stay anchored to a whole
* array entry. The markers are spelled out one by one rather than matched as '%_PENDING"%'
* because "_" is a single-character wildcard in LIKE, which would match more than markers.
*
* @return User[]
*/
public function findWithPendingRoles(int $limit): array
{
$qb = $this->createQueryBuilder('u');
$orX = $qb->expr()->orX();
foreach (Role::ADMINISTRATIVE as $index => $role) {
$parameter = 'pending'.$index;
$orX->add('u.roles LIKE :'.$parameter);
$qb->setParameter($parameter, '%"'.Role::pending($role).'"%');
}
/** @var User[] $users */
$users = $qb
->andWhere($orX)
->orderBy('u.lastLoginAt', 'DESC')
->setMaxResults($limit)
->getQuery()
->getResult()
;
return $users;
}
}