chg: dev: increase the minimum PHP version to the latest major - and massive refactor on back-end, like Controllers and Repositories #4
This commit is contained in:
@@ -11,9 +11,14 @@
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\PlayedGame;
|
||||
use App\Entity\User;
|
||||
use DateTime;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\NonUniqueResultException;
|
||||
use Doctrine\ORM\NoResultException;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class PlayedGameRepository
|
||||
@@ -29,37 +34,267 @@ use Doctrine\Persistence\ManagerRegistry;
|
||||
* @method PlayedGame|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method PlayedGame[] findAll()
|
||||
* @method PlayedGame[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
* @method PlayedGame|null findOneByGameAssoc($gameAssoc)
|
||||
*/
|
||||
class PlayedGameRepository extends ServiceEntityRepository
|
||||
{
|
||||
/**
|
||||
* PlayedGameRepository constructor.
|
||||
*
|
||||
* @param ManagerRegistry $registry
|
||||
*/
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
public function __construct(ManagerRegistry $registry, private readonly LoggerInterface $logger)
|
||||
{
|
||||
parent::__construct($registry, PlayedGame::class);
|
||||
}
|
||||
|
||||
public function findOneByGameAssoc(string $gameAssoc): ?PlayedGame
|
||||
{
|
||||
$qb = $this->createQueryBuilder('p');
|
||||
|
||||
try {
|
||||
return $qb
|
||||
->where($qb->expr()->eq('p.gameAssoc', ':gameAssoc'))
|
||||
->setParameter('gameAssoc', $gameAssoc)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
} catch (NonUniqueResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly multiple results found when looking up gameAssoc: $gameAssoc",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function countFinishedForUser(User $user): int
|
||||
{
|
||||
$qb = $this->createQueryBuilder('g');
|
||||
|
||||
try {
|
||||
return (int) $qb
|
||||
->select('COUNT(g.id)')
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->eq('g.red', ':u'),
|
||||
$qb->expr()->eq('g.blue', ':u'),
|
||||
),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNotNull('g.redPoints'),
|
||||
$qb->expr()->isNotNull('g.resign'),
|
||||
),
|
||||
))
|
||||
->setParameter('u', $user)
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
} catch (NoResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly no result found when counting finished games for user: {$user->getUsername()}",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
} catch (NonUniqueResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly multiple results found when counting finished games for user: {$user->getUsername()}",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function countWinsForUser(User $user): int
|
||||
{
|
||||
$qb = $this->createQueryBuilder('g');
|
||||
|
||||
try {
|
||||
return (int) $qb
|
||||
->select('COUNT(g.id)')
|
||||
->where($qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.red', ':u'),
|
||||
$qb->expr()->gt('g.redPoints', 'g.bluePoints'),
|
||||
$qb->expr()->isNull('g.resign'),
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.blue', ':u'),
|
||||
$qb->expr()->gt('g.bluePoints', 'g.redPoints'),
|
||||
$qb->expr()->isNull('g.resign'),
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.red', ':u'),
|
||||
$qb->expr()->eq('g.resign', ':blue'),
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.blue', ':u'),
|
||||
$qb->expr()->eq('g.resign', ':red'),
|
||||
),
|
||||
))
|
||||
->setParameter('u', $user)
|
||||
->setParameter('blue', 'blue')
|
||||
->setParameter('red', 'red')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
} catch (NoResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly no result found when counting wins for user: {$user->getUsername()}",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
} catch (NonUniqueResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly multiple results found when counting wins for user: {$user->getUsername()}",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function countLossesForUser(User $user): int
|
||||
{
|
||||
$qb = $this->createQueryBuilder('g');
|
||||
|
||||
try {
|
||||
return (int) $qb
|
||||
->select('COUNT(g.id)')
|
||||
->where($qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.red', ':u'),
|
||||
$qb->expr()->gt('g.bluePoints', 'g.redPoints'),
|
||||
$qb->expr()->isNull('g.resign'),
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.blue', ':u'),
|
||||
$qb->expr()->gt('g.redPoints', 'g.bluePoints'),
|
||||
$qb->expr()->isNull('g.resign'),
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.red', ':u'),
|
||||
$qb->expr()->eq('g.resign', ':red'),
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.blue', ':u'),
|
||||
$qb->expr()->eq('g.resign', ':blue'),
|
||||
),
|
||||
))
|
||||
->setParameter('u', $user)
|
||||
->setParameter('red', 'red')
|
||||
->setParameter('blue', 'blue')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
} catch (NoResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly no result found when counting losses for user: {$user->getUsername()}",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
} catch (NonUniqueResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly multiple results found when counting losses for user: {$user->getUsername()}",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function countBombsForUser(User $user): int
|
||||
{
|
||||
$qb = $this->createQueryBuilder('g');
|
||||
|
||||
try {
|
||||
return (int) $qb
|
||||
->select('COUNT(g.id)')
|
||||
->where($qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.red', ':u'),
|
||||
$qb->expr()->eq('g.redExplodedBomb', 'true'),
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('g.blue', ':u'),
|
||||
$qb->expr()->eq('g.blueExplodedBomb', 'true'),
|
||||
),
|
||||
))
|
||||
->setParameter('u', $user)
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
} catch (NoResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly no result found when counting bombs for user: {$user->getUsername()}",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
} catch (NonUniqueResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException(
|
||||
"Unexpectedly multiple results found when counting bombs for user: {$user->getUsername()}",
|
||||
0,
|
||||
$e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PlayedGame[]
|
||||
*/
|
||||
public function findRecentFinishedForUser(User $user, int $limit = 10): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('g');
|
||||
|
||||
return $qb
|
||||
->addSelect('rr', 'bb', 'ra', 'ba')
|
||||
->leftJoin('g.red', 'rr')
|
||||
->leftJoin('g.blue', 'bb')
|
||||
->leftJoin('g.redAnon', 'ra')
|
||||
->leftJoin('g.blueAnon', 'ba')
|
||||
->where($qb->expr()->andX(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->eq('g.red', ':u'),
|
||||
$qb->expr()->eq('g.blue', ':u'),
|
||||
),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNotNull('g.redPoints'),
|
||||
$qb->expr()->isNotNull('g.resign'),
|
||||
),
|
||||
))
|
||||
->setParameter('u', $user)
|
||||
->orderBy('g.updated', 'DESC')
|
||||
->setMaxResults($limit)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
public function findWaitingGames(int $limit = 20): array
|
||||
{
|
||||
// Any legitimately waiting game was updated within the last 10 minutes.
|
||||
// Abandoned games are stamped with updated = 2000-01-01, so they fail this filter.
|
||||
$cutoff = new DateTime('-10 minutes');
|
||||
$qb = $this->createQueryBuilder('p');
|
||||
|
||||
return $this->createQueryBuilder('p')
|
||||
->where('p.resign IS NULL')
|
||||
->andWhere('p.updated > :cutoff')
|
||||
->andWhere(
|
||||
'(p.red IS NOT NULL OR p.redAnon IS NOT NULL) AND (p.blue IS NULL AND p.blueAnon IS NULL)
|
||||
OR (p.blue IS NOT NULL OR p.blueAnon IS NOT NULL) AND (p.red IS NULL AND p.redAnon IS NULL)'
|
||||
)
|
||||
return $qb
|
||||
->where($qb->expr()->isNull('p.resign'))
|
||||
->andWhere($qb->expr()->gt('p.updated', ':cutoff'))
|
||||
->andWhere($qb->expr()->orX(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNotNull('p.red'),
|
||||
$qb->expr()->isNotNull('p.redAnon'),
|
||||
),
|
||||
$qb->expr()->isNull('p.blue'),
|
||||
$qb->expr()->isNull('p.blueAnon'),
|
||||
),
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNotNull('p.blue'),
|
||||
$qb->expr()->isNotNull('p.blueAnon'),
|
||||
),
|
||||
$qb->expr()->isNull('p.red'),
|
||||
$qb->expr()->isNull('p.redAnon'),
|
||||
),
|
||||
))
|
||||
->orderBy('p.updated', 'DESC')
|
||||
->setParameter('cutoff', $cutoff)
|
||||
->setParameter('cutoff', new DateTime('-10 minutes'))
|
||||
->setMaxResults($limit)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,10 @@ namespace App\Repository;
|
||||
|
||||
use App\Entity\User;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\NonUniqueResultException;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
@@ -31,14 +34,25 @@ use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
|
||||
*/
|
||||
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
public function __construct(ManagerRegistry $registry, private readonly LoggerInterface $logger)
|
||||
{
|
||||
parent::__construct($registry, User::class);
|
||||
}
|
||||
|
||||
public function findOneByUsername(string $username): ?User
|
||||
{
|
||||
return $this->findOneBy(['username' => $username]);
|
||||
$qb = $this->createQueryBuilder('u');
|
||||
|
||||
try {
|
||||
return $qb
|
||||
->where($qb->expr()->eq('u.username', ':username'))
|
||||
->setParameter('username', $username)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
} catch (NonUniqueResultException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
throw new RuntimeException("Multiple users found with the same username: $username", 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
|
||||
|
||||
Reference in New Issue
Block a user