chg: pkg: upgrade the doctrine related back-end pkgs to the latest available version #7
This commit is contained in:
@@ -174,7 +174,6 @@ const OnlinePlayersDialog = ({ open, onClose, currentGameAssoc, isEnvDev = false
|
|||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
onClose={0 < waitingCountdown ? undefined : onClose}
|
onClose={0 < waitingCountdown ? undefined : onClose}
|
||||||
disableEscapeKeyDown={0 < waitingCountdown}
|
|
||||||
sx={DIALOG_SX}
|
sx={DIALOG_SX}
|
||||||
>
|
>
|
||||||
<div className="opd">
|
<div className="opd">
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"doctrine/dbal": "^4.3",
|
"doctrine/dbal": "^4.3",
|
||||||
"doctrine/doctrine-bundle": "^2.14",
|
"doctrine/doctrine-bundle": "^3.2",
|
||||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
"doctrine/doctrine-migrations-bundle": "^4.0",
|
||||||
"doctrine/orm": "^3.5",
|
"doctrine/orm": "^3.5",
|
||||||
"endroid/qr-code": "^6.1",
|
"endroid/qr-code": "^6.1",
|
||||||
"firebase/php-jwt": "^7.0",
|
"firebase/php-jwt": "^7.0",
|
||||||
|
|||||||
123
composer.lock
generated
123
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "af396dcff9af321b624ed8fdbe437cea",
|
"content-hash": "6f52982c6e7461757ab66e20a764b9a8",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-crt-php",
|
"name": "aws/aws-crt-php",
|
||||||
@@ -563,63 +563,57 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/doctrine-bundle",
|
"name": "doctrine/doctrine-bundle",
|
||||||
"version": "2.18.2",
|
"version": "3.2.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/DoctrineBundle.git",
|
"url": "https://github.com/doctrine/DoctrineBundle.git",
|
||||||
"reference": "0ff098b29b8b3c68307c8987dcaed7fd829c6546"
|
"reference": "af84173db6978c3d2688ea3bcf3a91720b0704ce"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0ff098b29b8b3c68307c8987dcaed7fd829c6546",
|
"url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/af84173db6978c3d2688ea3bcf3a91720b0704ce",
|
||||||
"reference": "0ff098b29b8b3c68307c8987dcaed7fd829c6546",
|
"reference": "af84173db6978c3d2688ea3bcf3a91720b0704ce",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"doctrine/dbal": "^3.7.0 || ^4.0",
|
"doctrine/dbal": "^4.0",
|
||||||
"doctrine/deprecations": "^1.0",
|
"doctrine/deprecations": "^1.0",
|
||||||
"doctrine/persistence": "^3.1 || ^4",
|
"doctrine/persistence": "^4",
|
||||||
"doctrine/sql-formatter": "^1.0.1",
|
"doctrine/sql-formatter": "^1.0.1",
|
||||||
"php": "^8.1",
|
"php": "^8.4",
|
||||||
"symfony/cache": "^6.4 || ^7.0",
|
"symfony/cache": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/config": "^6.4 || ^7.0",
|
"symfony/config": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/console": "^6.4 || ^7.0",
|
"symfony/console": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/dependency-injection": "^6.4 || ^7.0",
|
"symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/doctrine-bridge": "^6.4.3 || ^7.0.3",
|
"symfony/doctrine-bridge": "^6.4.3 || ^7.0.3 || ^8.0",
|
||||||
"symfony/framework-bundle": "^6.4 || ^7.0",
|
"symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/service-contracts": "^2.5 || ^3"
|
"symfony/service-contracts": "^3"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"doctrine/annotations": ">=3.0",
|
"doctrine/orm": "<3.0 || >=4.0",
|
||||||
"doctrine/cache": "< 1.11",
|
"twig/twig": "<3.0.4"
|
||||||
"doctrine/orm": "<2.17 || >=4.0",
|
|
||||||
"symfony/var-exporter": "< 6.4.1 || 7.0.0",
|
|
||||||
"twig/twig": "<2.13 || >=3.0 <3.0.4"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/annotations": "^1 || ^2",
|
|
||||||
"doctrine/cache": "^1.11 || ^2.0",
|
|
||||||
"doctrine/coding-standard": "^14",
|
"doctrine/coding-standard": "^14",
|
||||||
"doctrine/orm": "^2.17 || ^3.1",
|
"doctrine/orm": "^3.4.4",
|
||||||
"friendsofphp/proxy-manager-lts": "^1.0",
|
|
||||||
"phpstan/phpstan": "2.1.1",
|
"phpstan/phpstan": "2.1.1",
|
||||||
"phpstan/phpstan-phpunit": "2.0.3",
|
"phpstan/phpstan-phpunit": "2.0.3",
|
||||||
"phpstan/phpstan-strict-rules": "^2",
|
"phpstan/phpstan-strict-rules": "^2",
|
||||||
"phpunit/phpunit": "^10.5.53 || ^12.3.10",
|
"phpstan/phpstan-symfony": "^2.0",
|
||||||
"psr/log": "^1.1.4 || ^2.0 || ^3.0",
|
"phpunit/phpunit": "^12.3.10",
|
||||||
"symfony/doctrine-messenger": "^6.4 || ^7.0",
|
"psr/log": "^3.0",
|
||||||
"symfony/expression-language": "^6.4 || ^7.0",
|
"symfony/doctrine-messenger": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/messenger": "^6.4 || ^7.0",
|
"symfony/expression-language": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/property-info": "^6.4 || ^7.0",
|
"symfony/messenger": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/security-bundle": "^6.4 || ^7.0",
|
"symfony/property-info": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/stopwatch": "^6.4 || ^7.0",
|
"symfony/security-bundle": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/string": "^6.4 || ^7.0",
|
"symfony/stopwatch": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/twig-bridge": "^6.4 || ^7.0",
|
"symfony/string": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/validator": "^6.4 || ^7.0",
|
"symfony/twig-bridge": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/var-exporter": "^6.4.1 || ^7.0.1",
|
"symfony/validator": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/web-profiler-bundle": "^6.4 || ^7.0",
|
"symfony/web-profiler-bundle": "^6.4 || ^7.0 || ^8.0",
|
||||||
"symfony/yaml": "^6.4 || ^7.0",
|
"symfony/yaml": "^6.4 || ^7.0 || ^8.0",
|
||||||
"twig/twig": "^2.14.7 || ^3.0.4"
|
"twig/twig": "^3.21.1"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"doctrine/orm": "The Doctrine ORM integration is optional in the bundle.",
|
"doctrine/orm": "The Doctrine ORM integration is optional in the bundle.",
|
||||||
@@ -664,7 +658,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/doctrine/DoctrineBundle/issues",
|
"issues": "https://github.com/doctrine/DoctrineBundle/issues",
|
||||||
"source": "https://github.com/doctrine/DoctrineBundle/tree/2.18.2"
|
"source": "https://github.com/doctrine/DoctrineBundle/tree/3.2.2"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -680,41 +674,48 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-12-20T21:35:32+00:00"
|
"time": "2025-12-24T12:24:29+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/doctrine-migrations-bundle",
|
"name": "doctrine/doctrine-migrations-bundle",
|
||||||
"version": "3.7.0",
|
"version": "4.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/DoctrineMigrationsBundle.git",
|
"url": "https://github.com/doctrine/DoctrineMigrationsBundle.git",
|
||||||
"reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b"
|
"reference": "20505da78735744fb4a42a3bb9a416b345ad6f7c"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1e380c6dd8ac8488217f39cff6b77e367f1a644b",
|
"url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/20505da78735744fb4a42a3bb9a416b345ad6f7c",
|
||||||
"reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b",
|
"reference": "20505da78735744fb4a42a3bb9a416b345ad6f7c",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"doctrine/doctrine-bundle": "^2.4 || ^3.0",
|
"doctrine/dbal": "^4",
|
||||||
|
"doctrine/doctrine-bundle": "^3",
|
||||||
"doctrine/migrations": "^3.2",
|
"doctrine/migrations": "^3.2",
|
||||||
"php": "^7.2 || ^8.0",
|
"php": "^8.4",
|
||||||
"symfony/deprecation-contracts": "^2.1 || ^3",
|
"psr/log": "^3",
|
||||||
"symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0"
|
"symfony/config": "^6.4 || ^7.0 || ^8.0",
|
||||||
|
"symfony/console": "^6.4 || ^7.0 || ^8.0",
|
||||||
|
"symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0",
|
||||||
|
"symfony/deprecation-contracts": "^3",
|
||||||
|
"symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0",
|
||||||
|
"symfony/http-foundation": "^6.4 || ^7.0 || ^8.0",
|
||||||
|
"symfony/http-kernel": "^6.4 || ^7.0 || ^8.0",
|
||||||
|
"symfony/service-contracts": "^3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"composer/semver": "^3.0",
|
"composer/semver": "^3.0",
|
||||||
"doctrine/coding-standard": "^12 || ^14",
|
"doctrine/coding-standard": "^14",
|
||||||
"doctrine/orm": "^2.6 || ^3",
|
"doctrine/orm": "^3",
|
||||||
"phpstan/phpstan": "^1.4 || ^2",
|
"phpstan/phpstan": "^2",
|
||||||
"phpstan/phpstan-deprecation-rules": "^1 || ^2",
|
"phpstan/phpstan-deprecation-rules": "^2",
|
||||||
"phpstan/phpstan-phpunit": "^1 || ^2",
|
"phpstan/phpstan-phpunit": "^2",
|
||||||
"phpstan/phpstan-strict-rules": "^1.1 || ^2",
|
"phpstan/phpstan-strict-rules": "^2",
|
||||||
"phpstan/phpstan-symfony": "^1.3 || ^2",
|
"phpstan/phpstan-symfony": "^2",
|
||||||
"phpunit/phpunit": "^8.5 || ^9.5",
|
"phpunit/phpunit": "^12.5",
|
||||||
"symfony/phpunit-bridge": "^6.3 || ^7 || ^8",
|
"symfony/var-exporter": "^6.4 || ^7 || ^8"
|
||||||
"symfony/var-exporter": "^5.4 || ^6 || ^7 || ^8"
|
|
||||||
},
|
},
|
||||||
"type": "symfony-bundle",
|
"type": "symfony-bundle",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -749,7 +750,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues",
|
"issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues",
|
||||||
"source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.7.0"
|
"source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/4.0.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -765,7 +766,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-11-15T19:02:59+00:00"
|
"time": "2025-12-05T08:14:38+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/event-manager",
|
"name": "doctrine/event-manager",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ doctrine:
|
|||||||
url: '%env(resolve:DATABASE_URL)%'
|
url: '%env(resolve:DATABASE_URL)%'
|
||||||
|
|
||||||
orm:
|
orm:
|
||||||
auto_generate_proxy_classes: '%kernel.debug%'
|
enable_native_lazy_objects: true
|
||||||
naming_strategy: doctrine.orm.naming_strategy.underscore
|
naming_strategy: doctrine.orm.naming_strategy.underscore
|
||||||
auto_mapping: true
|
auto_mapping: true
|
||||||
mappings:
|
mappings:
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class GameController extends AbstractController
|
|||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
$contactMessage->setIpAddress($request->getClientIp());
|
$contactMessage->ipAddress = $request->getClientIp();
|
||||||
|
|
||||||
$em->persist($contactMessage);
|
$em->persist($contactMessage);
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|||||||
@@ -137,16 +137,16 @@ class MercureController extends AbstractController
|
|||||||
|
|
||||||
$result = array_map(static function (PlayedGame $g): array {
|
$result = array_map(static function (PlayedGame $g): array {
|
||||||
$name = match (true) {
|
$name = match (true) {
|
||||||
null !== $g->getRed() => $g->getRed()->getUsername(),
|
null !== $g->red => $g->red->getUsername(),
|
||||||
null !== $g->getRedAnon() => $g->getRedAnon()->getUserName(),
|
null !== $g->redAnon => $g->redAnon->userName,
|
||||||
null !== $g->getBlue() => $g->getBlue()->getUsername(),
|
null !== $g->blue => $g->blue->getUsername(),
|
||||||
default => $g->getBlueAnon()?->getUserName() ?? 'Unknown',
|
default => $g->blueAnon?->userName ?? 'Unknown',
|
||||||
};
|
};
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'gameAssoc' => $g->getGameAssoc(),
|
'gameAssoc' => $g->gameAssoc,
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'since' => $g->getCreated()?->format(\DateTimeInterface::ATOM) ?? '',
|
'since' => $g->created?->format(\DateTimeInterface::ATOM) ?? '',
|
||||||
];
|
];
|
||||||
}, $games);
|
}, $games);
|
||||||
|
|
||||||
|
|||||||
@@ -78,22 +78,22 @@ class ProfileController extends AbstractController
|
|||||||
|
|
||||||
$since = new DateTime('first day of -5 months midnight');
|
$since = new DateTime('first day of -5 months midnight');
|
||||||
$recentGames = $this->repo->findFinishedForUserSince($user, $since);
|
$recentGames = $this->repo->findFinishedForUserSince($user, $since);
|
||||||
$userId = $user->getId();
|
$userId = $user->id;
|
||||||
|
|
||||||
foreach ($recentGames as $game) {
|
foreach ($recentGames as $game) {
|
||||||
if (!$game->getUpdated()) {
|
if (!$game->updated) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$month = $game->getUpdated()->format('Y-m');
|
$month = $game->updated->format('Y-m');
|
||||||
if (!isset($monthlyData[$month])) {
|
if (!isset($monthlyData[$month])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$isRed = $game->getRed()?->getId() === $userId;
|
$isRed = $game->red?->id === $userId;
|
||||||
$myPts = $isRed ? $game->getRedPoints() : $game->getBluePoints();
|
$myPts = $isRed ? $game->redPoints : $game->bluePoints;
|
||||||
$oppPts = $isRed ? $game->getBluePoints() : $game->getRedPoints();
|
$oppPts = $isRed ? $game->bluePoints : $game->redPoints;
|
||||||
$resign = $game->getResign();
|
$resign = $game->resign;
|
||||||
$myColor = $isRed ? 'red' : 'blue';
|
$myColor = $isRed ? 'red' : 'blue';
|
||||||
$oppColor = $isRed ? 'blue' : 'red';
|
$oppColor = $isRed ? 'blue' : 'red';
|
||||||
|
|
||||||
@@ -131,12 +131,12 @@ class ProfileController extends AbstractController
|
|||||||
],
|
],
|
||||||
'recent' => ($recent = $this->repo->findRecentFinishedForUser($user, 30)),
|
'recent' => ($recent = $this->repo->findRecentFinishedForUser($user, 30)),
|
||||||
'gamesData' => array_map(function (PlayedGame $game) use ($userId, $cacheManager): array {
|
'gamesData' => array_map(function (PlayedGame $game) use ($userId, $cacheManager): array {
|
||||||
$isRed = $game->getRed()?->getId() === $userId;
|
$isRed = $game->red?->id === $userId;
|
||||||
$resign = $game->getResign();
|
$resign = $game->resign;
|
||||||
$myColor = $isRed ? 'red' : 'blue';
|
$myColor = $isRed ? 'red' : 'blue';
|
||||||
$oppColor = $isRed ? 'blue' : 'red';
|
$oppColor = $isRed ? 'blue' : 'red';
|
||||||
$myPts = $isRed ? $game->getRedPoints() : $game->getBluePoints();
|
$myPts = $isRed ? $game->redPoints : $game->bluePoints;
|
||||||
$oppPts = $isRed ? $game->getBluePoints() : $game->getRedPoints();
|
$oppPts = $isRed ? $game->bluePoints : $game->redPoints;
|
||||||
$result = 'draw';
|
$result = 'draw';
|
||||||
|
|
||||||
if ($resign === $myColor) $result = 'loss';
|
if ($resign === $myColor) $result = 'loss';
|
||||||
@@ -146,33 +146,33 @@ class ProfileController extends AbstractController
|
|||||||
elseif ($myPts < $oppPts) $result = 'loss';
|
elseif ($myPts < $oppPts) $result = 'loss';
|
||||||
}
|
}
|
||||||
|
|
||||||
$redAvatarPath = $game->getRed()?->getAvatarPath();
|
$redAvatarPath = $game->red?->avatarPath;
|
||||||
$blueAvatarPath = $game->getBlue()?->getAvatarPath();
|
$blueAvatarPath = $game->blue?->avatarPath;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'id' => $game->getId(),
|
'id' => $game->id,
|
||||||
'uuid' => $game->getUuid()?->toRfc4122(),
|
'uuid' => $game->uuid?->toRfc4122(),
|
||||||
'redName' =>
|
'redName' =>
|
||||||
$game->getRed()?->getUsername() ?? $game->getRedAnon()?->getUserName() ?? 'Guest',
|
$game->red?->getUsername() ?? $game->redAnon?->userName ?? 'Guest',
|
||||||
'blueName' =>
|
'blueName' =>
|
||||||
$game->getBlue()?->getUsername() ?? $game->getBlueAnon()?->getUserName() ?? 'Guest',
|
$game->blue?->getUsername() ?? $game->blueAnon?->userName ?? 'Guest',
|
||||||
'redAvatar' => $redAvatarPath ? $cacheManager->generateUrl($redAvatarPath, 'avatar_thumb') : null,
|
'redAvatar' => $redAvatarPath ? $cacheManager->generateUrl($redAvatarPath, 'avatar_thumb') : null,
|
||||||
'blueAvatar' => $blueAvatarPath ? $cacheManager->generateUrl($blueAvatarPath, 'avatar_thumb') : null,
|
'blueAvatar' => $blueAvatarPath ? $cacheManager->generateUrl($blueAvatarPath, 'avatar_thumb') : null,
|
||||||
'redPoints' => $game->getRedPoints(),
|
'redPoints' => $game->redPoints,
|
||||||
'bluePoints' => $game->getBluePoints(),
|
'bluePoints' => $game->bluePoints,
|
||||||
'redExplodedBomb' => $game->getRedExplodedBomb(),
|
'redExplodedBomb' => $game->redExplodedBomb,
|
||||||
'blueExplodedBomb' => $game->getBlueExplodedBomb(),
|
'blueExplodedBomb' => $game->blueExplodedBomb,
|
||||||
'resign' => $resign,
|
'resign' => $resign,
|
||||||
'created' => $game->getCreated()?->format('Y-m-d H:i'),
|
'created' => $game->created?->format('Y-m-d H:i'),
|
||||||
'date' => $game->getUpdated()?->format('Y-m-d H:i'),
|
'date' => $game->updated?->format('Y-m-d H:i'),
|
||||||
'isRed' => $isRed,
|
'isRed' => $isRed,
|
||||||
'result' => $result,
|
'result' => $result,
|
||||||
'myPoints' => $myPts,
|
'myPoints' => $myPts,
|
||||||
'oppPoints' => $oppPts,
|
'oppPoints' => $oppPts,
|
||||||
'redBonusPoints' => $game->getRedBonusPoints() ?? 0,
|
'redBonusPoints' => $game->redBonusPoints ?? 0,
|
||||||
'blueBonusPoints' => $game->getBlueBonusPoints() ?? 0,
|
'blueBonusPoints' => $game->blueBonusPoints ?? 0,
|
||||||
'redBonusStats' => $game->getRedBonusStats() ?? [],
|
'redBonusStats' => $game->redBonusStats ?? [],
|
||||||
'blueBonusStats' => $game->getBlueBonusStats() ?? [],
|
'blueBonusStats' => $game->blueBonusStats ?? [],
|
||||||
];
|
];
|
||||||
}, $recent),
|
}, $recent),
|
||||||
'chartData' => [
|
'chartData' => [
|
||||||
@@ -202,10 +202,10 @@ class ProfileController extends AbstractController
|
|||||||
$mines = [];
|
$mines = [];
|
||||||
$bonus = [];
|
$bonus = [];
|
||||||
foreach ($recent as $i => $game) {
|
foreach ($recent as $i => $game) {
|
||||||
$isRed = $game->getRed()?->getId() === $userId;
|
$isRed = $game->red?->id === $userId;
|
||||||
$labels[] = '#' . ($i + 1);
|
$labels[] = '#' . ($i + 1);
|
||||||
$mines[] = (int)($isRed ? $game->getRedPoints() : $game->getBluePoints());
|
$mines[] = (int)($isRed ? $game->redPoints : $game->bluePoints);
|
||||||
$bonus[] = (float)($isRed ? $game->getRedBonusPoints() : $game->getBlueBonusPoints()) ?: 0;
|
$bonus[] = (float)($isRed ? $game->redBonusPoints : $game->blueBonusPoints) ?: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['labels' => $labels, 'mines' => $mines, 'bonus' => $bonus];
|
return ['labels' => $labels, 'mines' => $mines, 'bonus' => $bonus];
|
||||||
@@ -224,17 +224,17 @@ class ProfileController extends AbstractController
|
|||||||
throw $this->createNotFoundException('Battle not found.');
|
throw $this->createNotFoundException('Battle not found.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$redName = $game->getRed()?->getUsername() ?? ($game->getRedAnon() !== null ? 'Anonymous' : 'Guest');
|
$redName = $game->red?->getUsername() ?? ($game->redAnon !== null ? 'Anonymous' : 'Guest');
|
||||||
$blueName = $game->getBlue()?->getUsername() ?? ($game->getBlueAnon() !== null ? 'Anonymous' : 'Guest');
|
$blueName = $game->blue?->getUsername() ?? ($game->blueAnon !== null ? 'Anonymous' : 'Guest');
|
||||||
$redPts = $game->getRedPoints();
|
$redPts = $game->redPoints;
|
||||||
$bluePts = $game->getBluePoints();
|
$bluePts = $game->bluePoints;
|
||||||
$resign = $game->getResign();
|
$resign = $game->resign;
|
||||||
$redAvatar = $game->getRed()?->getAvatarPath();
|
$redAvatar = $game->red?->avatarPath;
|
||||||
$blueAvatar = $game->getBlue()?->getAvatarPath();
|
$blueAvatar = $game->blue?->avatarPath;
|
||||||
$redBonusPoints = $game->getRedBonusPoints() ?? 0;
|
$redBonusPoints = $game->redBonusPoints ?? 0;
|
||||||
$blueBonusPoints = $game->getBlueBonusPoints() ?? 0;
|
$blueBonusPoints = $game->blueBonusPoints ?? 0;
|
||||||
$redBonusStats = $game->getRedBonusStats() ?? [];
|
$redBonusStats = $game->redBonusStats ?? [];
|
||||||
$blueBonusStats = $game->getBlueBonusStats() ?? [];
|
$blueBonusStats = $game->blueBonusStats ?? [];
|
||||||
|
|
||||||
if ($resign === 'red') {
|
if ($resign === 'red') {
|
||||||
$summary = "$redName resigned — $blueName wins";
|
$summary = "$redName resigned — $blueName wins";
|
||||||
@@ -321,7 +321,7 @@ class ProfileController extends AbstractController
|
|||||||
|
|
||||||
$ext = $file->guessExtension() ?? 'jpg';
|
$ext = $file->guessExtension() ?? 'jpg';
|
||||||
$newPath = sprintf('avatar/%s.%s', Uuid::v4()->toRfc4122(), $ext);
|
$newPath = sprintf('avatar/%s.%s', Uuid::v4()->toRfc4122(), $ext);
|
||||||
$oldPath = $user->getAvatarPath();
|
$oldPath = $user->avatarPath;
|
||||||
|
|
||||||
/** Remove old file and any cached thumbnails */
|
/** Remove old file and any cached thumbnails */
|
||||||
if ($oldPath) {
|
if ($oldPath) {
|
||||||
@@ -343,7 +343,7 @@ class ProfileController extends AbstractController
|
|||||||
}
|
}
|
||||||
fclose($stream);
|
fclose($stream);
|
||||||
|
|
||||||
$user->setAvatarPath($newPath);
|
$user->avatarPath = $newPath;
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
return $this->json([
|
return $this->json([
|
||||||
@@ -360,18 +360,18 @@ class ProfileController extends AbstractController
|
|||||||
|
|
||||||
$credentials = $this->webAuthnService->getCredentialsForUser($user);
|
$credentials = $this->webAuthnService->getCredentialsForUser($user);
|
||||||
$credentialsData = array_map(fn($cred) => [
|
$credentialsData = array_map(fn($cred) => [
|
||||||
'id' => $cred->getId(),
|
'id' => $cred->id,
|
||||||
'credentialName' => $cred->getCredentialName(),
|
'credentialName' => $cred->credentialName,
|
||||||
'createdAt' => $cred->getCreatedAt()?->format('Y-m-d H:i:s'),
|
'createdAt' => $cred->createdAt?->format('Y-m-d H:i:s'),
|
||||||
'lastUsedAt' => $cred->getLastUsedAt()?->format('Y-m-d H:i:s'),
|
'lastUsedAt' => $cred->lastUsedAt?->format('Y-m-d H:i:s'),
|
||||||
'isBackupEligible' => $cred->isBackupEligible(),
|
'isBackupEligible' => $cred->isBackupEligible,
|
||||||
'isBackupAuthenticated' => $cred->isBackupAuthenticated(),
|
'isBackupAuthenticated' => $cred->isBackupAuthenticated,
|
||||||
], $credentials);
|
], $credentials);
|
||||||
|
|
||||||
return $this->render('Security/profile_security.html.twig', [
|
return $this->render('Security/profile_security.html.twig', [
|
||||||
'credentials' => $credentialsData,
|
'credentials' => $credentialsData,
|
||||||
'isTotpEnabled' => $user->isTotpAuthenticationEnabled(),
|
'isTotpEnabled' => $user->isTotpAuthenticationEnabled(),
|
||||||
'backupCodesCount' => count($user->getBackupCodes()),
|
'backupCodesCount' => count($user->backupCodes),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,10 +86,9 @@ class SecurityController extends AbstractController
|
|||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
$token = bin2hex(random_bytes(32));
|
$token = bin2hex(random_bytes(32));
|
||||||
|
|
||||||
$user
|
$user->isVerified = false;
|
||||||
->setIsVerified(false)
|
$user->verificationToken = $token;
|
||||||
->setVerificationToken($token)
|
$user->password = $hasher->hashPassword($user, $form->get('plainPassword')->getData());
|
||||||
->setPassword($hasher->hashPassword($user, $form->get('plainPassword')->getData()));
|
|
||||||
|
|
||||||
$em->persist($user);
|
$em->persist($user);
|
||||||
$em->flush();
|
$em->flush();
|
||||||
@@ -108,7 +107,7 @@ class SecurityController extends AbstractController
|
|||||||
$mailer->send(
|
$mailer->send(
|
||||||
new TemplatedEmail()
|
new TemplatedEmail()
|
||||||
->from('noreply@mineseeker.hu')
|
->from('noreply@mineseeker.hu')
|
||||||
->to($user->getEmail())
|
->to($user->email)
|
||||||
->subject('Activate your MineSeeker account')
|
->subject('Activate your MineSeeker account')
|
||||||
->htmlTemplate('emails/activation.html.twig')
|
->htmlTemplate('emails/activation.html.twig')
|
||||||
->context([
|
->context([
|
||||||
@@ -130,7 +129,7 @@ class SecurityController extends AbstractController
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->addFlash('verify_email', $user->getEmail());
|
$this->addFlash('verify_email', $user->email);
|
||||||
|
|
||||||
return $this->redirectToRoute('MineSeekerBundle_register');
|
return $this->redirectToRoute('MineSeekerBundle_register');
|
||||||
}
|
}
|
||||||
@@ -156,11 +155,10 @@ class SecurityController extends AbstractController
|
|||||||
$email = $form->get('email')->getData();
|
$email = $form->get('email')->getData();
|
||||||
$user = $userRepository->findOneByEmail($email);
|
$user = $userRepository->findOneByEmail($email);
|
||||||
|
|
||||||
if ($user && $user->isVerified()) {
|
if ($user && $user->isVerified) {
|
||||||
$token = bin2hex(random_bytes(32));
|
$token = bin2hex(random_bytes(32));
|
||||||
$user
|
$user->resetToken = $token;
|
||||||
->setResetToken($token)
|
$user->resetTokenExpiresAt = new DateTime('+1 hour');
|
||||||
->setResetTokenExpiresAt(new DateTime('+1 hour'));
|
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
$resetUrl = $this->generateUrl(
|
$resetUrl = $this->generateUrl(
|
||||||
@@ -206,7 +204,7 @@ class SecurityController extends AbstractController
|
|||||||
): Response {
|
): Response {
|
||||||
$user = $userRepository->findOneByResetToken($token);
|
$user = $userRepository->findOneByResetToken($token);
|
||||||
|
|
||||||
if (!$user || $user->getResetTokenExpiresAt() < new DateTime()) {
|
if (!$user || $user->resetTokenExpiresAt < new DateTime()) {
|
||||||
$this->addFlash('error', 'This password reset link is invalid or has expired.');
|
$this->addFlash('error', 'This password reset link is invalid or has expired.');
|
||||||
return $this->redirectToRoute('MineSeekerBundle_forgot_password');
|
return $this->redirectToRoute('MineSeekerBundle_forgot_password');
|
||||||
}
|
}
|
||||||
@@ -215,10 +213,9 @@ class SecurityController extends AbstractController
|
|||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
$user
|
$user->password = $hasher->hashPassword($user, $form->get('plainPassword')->getData());
|
||||||
->setPassword($hasher->hashPassword($user, $form->get('plainPassword')->getData()))
|
$user->resetToken = null;
|
||||||
->setResetToken(null)
|
$user->resetTokenExpiresAt = null;
|
||||||
->setResetTokenExpiresAt(null);
|
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
$this->addFlash('success', 'Your password has been reset. You can now sign in.');
|
$this->addFlash('success', 'Your password has been reset. You can now sign in.');
|
||||||
@@ -239,7 +236,8 @@ class SecurityController extends AbstractController
|
|||||||
return $this->redirectToRoute('MineSeekerBundle_login');
|
return $this->redirectToRoute('MineSeekerBundle_login');
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->setIsVerified(true)->setVerificationToken(null);
|
$user->isVerified = true;
|
||||||
|
$user->verificationToken = null;
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
/** Send admin notification about account activation */
|
/** Send admin notification about account activation */
|
||||||
|
|||||||
@@ -156,16 +156,16 @@ class TwoFactorController extends AbstractController
|
|||||||
$code = $request->request->getString('_auth_code');
|
$code = $request->request->getString('_auth_code');
|
||||||
|
|
||||||
// Temporarily set the pending secret to verify the code
|
// Temporarily set the pending secret to verify the code
|
||||||
$user->setTotpSecret($pendingSecret);
|
$user->totpSecret = $pendingSecret;
|
||||||
|
|
||||||
if (!$this->totpAuthenticator->checkCode($user, $code)) {
|
if (!$this->totpAuthenticator->checkCode($user, $code)) {
|
||||||
$user->setTotpSecret(null);
|
$user->totpSecret = null;
|
||||||
$this->addFlash('error', 'Invalid verification code. Please try again.');
|
$this->addFlash('error', 'Invalid verification code. Please try again.');
|
||||||
return $this->redirectToRoute('MineSeekerBundle_2fa_setup');
|
return $this->redirectToRoute('MineSeekerBundle_2fa_setup');
|
||||||
}
|
}
|
||||||
|
|
||||||
$backupCodes = $this->generateBackupCodes();
|
$backupCodes = $this->generateBackupCodes();
|
||||||
$user->setBackupCodes($backupCodes);
|
$user->backupCodes = $backupCodes;
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
|
|
||||||
$request->getSession()->remove('totp_pending_secret');
|
$request->getSession()->remove('totp_pending_secret');
|
||||||
@@ -187,8 +187,8 @@ class TwoFactorController extends AbstractController
|
|||||||
|
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
$user->setTotpSecret(null);
|
$user->totpSecret = null;
|
||||||
$user->setBackupCodes([]);
|
$user->backupCodes = [];
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
|
|
||||||
$this->addFlash('success', 'Two-factor authentication has been disabled.');
|
$this->addFlash('success', 'Two-factor authentication has been disabled.');
|
||||||
@@ -217,7 +217,7 @@ class TwoFactorController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$backupCodes = $this->generateBackupCodes();
|
$backupCodes = $this->generateBackupCodes();
|
||||||
$user->setBackupCodes($backupCodes);
|
$user->backupCodes = $backupCodes;
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
|
|
||||||
$this->addFlash('2fa_backup_codes', $backupCodes);
|
$this->addFlash('2fa_backup_codes', $backupCodes);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class WebAuthnController extends AbstractController
|
|||||||
|
|
||||||
$userEntity = new PublicKeyCredentialUserEntity(
|
$userEntity = new PublicKeyCredentialUserEntity(
|
||||||
$user->getUserIdentifier(),
|
$user->getUserIdentifier(),
|
||||||
(string)$user->getId(),
|
(string)$user->id,
|
||||||
$user->getUsername(),
|
$user->getUsername(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ class WebAuthnController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Store the credential with user ID for later retrieval during authentication */
|
/** Store the credential with user ID for later retrieval during authentication */
|
||||||
$credentialJson['userId'] = $user->getId();
|
$credentialJson['userId'] = $user->id;
|
||||||
$credentialJson['username'] = $user->getUsername();
|
$credentialJson['username'] = $user->getUsername();
|
||||||
|
|
||||||
/** Save the credential data directly */
|
/** Save the credential data directly */
|
||||||
@@ -173,12 +173,12 @@ class WebAuthnController extends AbstractController
|
|||||||
$credentials = $this->webAuthnService->getCredentialsForUser($user);
|
$credentials = $this->webAuthnService->getCredentialsForUser($user);
|
||||||
|
|
||||||
return new JsonResponse(array_map(fn($credential) => [
|
return new JsonResponse(array_map(fn($credential) => [
|
||||||
'id' => $credential->getId(),
|
'id' => $credential->id,
|
||||||
'name' => $credential->getCredentialName(),
|
'name' => $credential->credentialName,
|
||||||
'createdAt' => $credential->getCreatedAt()?->format('Y-m-d H:i:s'),
|
'createdAt' => $credential->createdAt?->format('Y-m-d H:i:s'),
|
||||||
'lastUsedAt' => $credential->getLastUsedAt()?->format('Y-m-d H:i:s'),
|
'lastUsedAt' => $credential->lastUsedAt?->format('Y-m-d H:i:s'),
|
||||||
'isBackupEligible' => $credential->isBackupEligible(),
|
'isBackupEligible' => $credential->isBackupEligible,
|
||||||
'isBackupAuthenticated' => $credential->isBackupAuthenticated(),
|
'isBackupAuthenticated' => $credential->isBackupAuthenticated,
|
||||||
], $credentials));
|
], $credentials));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,95 +34,29 @@ use Doctrine\ORM\Mapping\Table;
|
|||||||
class ContactMessage
|
class ContactMessage
|
||||||
{
|
{
|
||||||
#[Id, GeneratedValue, Column]
|
#[Id, GeneratedValue, Column]
|
||||||
private ?int $id = null;
|
public private(set) ?int $id = null;
|
||||||
|
|
||||||
#[Column]
|
#[Column]
|
||||||
private string $name;
|
public string $name;
|
||||||
|
|
||||||
#[Column]
|
#[Column]
|
||||||
private string $email;
|
public string $email;
|
||||||
|
|
||||||
#[Column(type: Types::TEXT)]
|
#[Column(type: Types::TEXT)]
|
||||||
private string $content;
|
public string $content;
|
||||||
|
|
||||||
#[Column]
|
#[Column]
|
||||||
private bool $consent = false;
|
public bool $consent = false;
|
||||||
|
|
||||||
#[Column]
|
#[Column]
|
||||||
private DateTimeImmutable $createdAt;
|
public private(set) DateTimeImmutable $createdAt;
|
||||||
|
|
||||||
#[Column(length: 45, nullable: true)]
|
#[Column(length: 45, nullable: true)]
|
||||||
private ?string $ipAddress = null;
|
public ?string $ipAddress = null;
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->createdAt = new DateTimeImmutable();
|
$this->createdAt = new DateTimeImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName(): string
|
|
||||||
{
|
|
||||||
return $this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setName(string $name): self
|
|
||||||
{
|
|
||||||
$this->name = $name;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEmail(): string
|
|
||||||
{
|
|
||||||
return $this->email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setEmail(string $email): self
|
|
||||||
{
|
|
||||||
$this->email = $email;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getContent(): string
|
|
||||||
{
|
|
||||||
return $this->content;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setContent(string $content): self
|
|
||||||
{
|
|
||||||
$this->content = $content;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isConsent(): bool
|
|
||||||
{
|
|
||||||
return $this->consent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setConsent(bool $consent): self
|
|
||||||
{
|
|
||||||
$this->consent = $consent;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedAt(): DateTimeImmutable
|
|
||||||
{
|
|
||||||
return $this->createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIpAddress(): ?string
|
|
||||||
{
|
|
||||||
return $this->ipAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setIpAddress(?string $ipAddress): self
|
|
||||||
{
|
|
||||||
$this->ipAddress = $ipAddress;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,76 +32,20 @@ use Doctrine\ORM\Mapping\Id;
|
|||||||
class Gamer
|
class Gamer
|
||||||
{
|
{
|
||||||
#[Id, GeneratedValue, Column]
|
#[Id, GeneratedValue, Column]
|
||||||
private ?int $id = null;
|
public private(set) ?int $id = null;
|
||||||
|
|
||||||
#[Column(length: 100)]
|
#[Column(length: 100)]
|
||||||
private ?string $userName = null;
|
public ?string $userName = null;
|
||||||
|
|
||||||
#[Column(length: 20, nullable: true)]
|
#[Column(length: 20, nullable: true)]
|
||||||
private ?string $ip = null;
|
public ?string $ip = null;
|
||||||
|
|
||||||
#[Column(length: 100, nullable: true)]
|
#[Column(length: 100, nullable: true)]
|
||||||
private ?string $country = null;
|
public ?string $country = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?string $userAgent = null;
|
public ?string $userAgent = null;
|
||||||
|
|
||||||
#[Column(type: Types::DATETIME_MUTABLE)]
|
#[Column(type: Types::DATETIME_MUTABLE)]
|
||||||
private ?DateTime $connTimestamp = null;
|
public ?DateTime $connTimestamp = null;
|
||||||
|
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUserName(): ?string
|
|
||||||
{
|
|
||||||
return $this->userName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUserName(?string $userName): void
|
|
||||||
{
|
|
||||||
$this->userName = $userName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIp(): ?string
|
|
||||||
{
|
|
||||||
return $this->ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setIp(?string $ip): void
|
|
||||||
{
|
|
||||||
$this->ip = $ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCountry(): ?string
|
|
||||||
{
|
|
||||||
return $this->country;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCountry(?string $country): void
|
|
||||||
{
|
|
||||||
$this->country = $country;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUserAgent(): ?string
|
|
||||||
{
|
|
||||||
return $this->userAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUserAgent(?string $userAgent): void
|
|
||||||
{
|
|
||||||
$this->userAgent = $userAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getConnTimestamp(): ?DateTime
|
|
||||||
{
|
|
||||||
return $this->connTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setConnTimestamp(?DateTime $connTimestamp): void
|
|
||||||
{
|
|
||||||
$this->connTimestamp = $connTimestamp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,14 +35,14 @@ use Doctrine\ORM\Mapping\OneToOne;
|
|||||||
class Grid
|
class Grid
|
||||||
{
|
{
|
||||||
#[Id, GeneratedValue, Column]
|
#[Id, GeneratedValue, Column]
|
||||||
private ?int $id = null;
|
public private(set) ?int $id = null;
|
||||||
|
|
||||||
#[OneToOne(inversedBy: 'grid', cascade: ['persist'])]
|
#[OneToOne(inversedBy: 'grid', cascade: ['persist'])]
|
||||||
private ?PlayedGame $playedGame = null;
|
public ?PlayedGame $playedGame = null;
|
||||||
|
|
||||||
#[OneToMany(mappedBy: 'grid', targetEntity: GridRow::class, cascade: ['persist'])]
|
#[OneToMany(targetEntity: GridRow::class, mappedBy: 'grid', cascade: ['persist'])]
|
||||||
#[JoinColumn(name: 'grid_row', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
#[JoinColumn(name: 'grid_row', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
||||||
private Collection $gridRow;
|
public private(set) Collection $gridRow;
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@@ -50,30 +50,10 @@ class Grid
|
|||||||
$this->gridRow = new ArrayCollection();
|
$this->gridRow = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPlayedGame(): ?PlayedGame
|
|
||||||
{
|
|
||||||
return $this->playedGame;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setPlayedGame(?PlayedGame $playedGame): void
|
|
||||||
{
|
|
||||||
$this->playedGame = $playedGame;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGridRow(): Collection
|
|
||||||
{
|
|
||||||
return $this->gridRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addGridRow(GridRow $gridRow): void
|
public function addGridRow(GridRow $gridRow): void
|
||||||
{
|
{
|
||||||
$this->gridRow->add($gridRow);
|
$this->gridRow->add($gridRow);
|
||||||
$gridRow->setGrid($this);
|
$gridRow->grid = $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeGridRow(GridRow $gridRow): void
|
public function removeGridRow(GridRow $gridRow): void
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
/*
|
/**
|
||||||
* This file is part of the SplendidBear Websites' projects.
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2026 @ www.splendidbear.org
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
@@ -33,38 +33,12 @@ use Doctrine\ORM\Mapping\ManyToOne;
|
|||||||
class GridRow
|
class GridRow
|
||||||
{
|
{
|
||||||
#[Id, GeneratedValue, Column]
|
#[Id, GeneratedValue, Column]
|
||||||
private ?int $id = null;
|
public private(set) ?int $id = null;
|
||||||
|
|
||||||
#[ManyToOne(cascade: ['persist'], inversedBy: 'gridRow')]
|
#[ManyToOne(cascade: ['persist'], inversedBy: 'gridRow')]
|
||||||
#[JoinColumn(name: 'grid', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
#[JoinColumn(name: 'grid', referencedColumnName: 'id', onDelete: 'CASCADE')]
|
||||||
private ?Grid $grid = null;
|
public ?Grid $grid = null;
|
||||||
|
|
||||||
#[Column(name: 'grid_col', type: Types::JSON, nullable: false)]
|
#[Column(name: 'grid_col', type: Types::JSON, nullable: false)]
|
||||||
private ?array $gridCol = null;
|
public ?array $gridCol = null;
|
||||||
|
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGrid(): ?Grid
|
|
||||||
{
|
|
||||||
return $this->grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setGrid(?Grid $grid): void
|
|
||||||
{
|
|
||||||
$this->grid = $grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGridCol(): ?array
|
|
||||||
{
|
|
||||||
return $this->gridCol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setGridCol(?array $gridCol): void
|
|
||||||
{
|
|
||||||
$this->gridCol = $gridCol;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,68 +39,68 @@ use Symfony\Component\Uid\Uuid;
|
|||||||
class PlayedGame
|
class PlayedGame
|
||||||
{
|
{
|
||||||
#[Id, GeneratedValue, Column]
|
#[Id, GeneratedValue, Column]
|
||||||
private ?int $id = null;
|
public private(set) ?int $id = null;
|
||||||
|
|
||||||
#[Column(type: 'uuid', unique: true)]
|
#[Column(type: 'uuid', unique: true)]
|
||||||
private ?Uuid $uuid = null;
|
public ?Uuid $uuid = null;
|
||||||
|
|
||||||
#[Column(length: 50)]
|
#[Column(length: 50)]
|
||||||
private ?string $gameAssoc = null;
|
public ?string $gameAssoc = null;
|
||||||
|
|
||||||
#[Column(length: 5, nullable: true)]
|
#[Column(length: 5, nullable: true)]
|
||||||
private ?int $redPoints = null;
|
public ?int $redPoints = null;
|
||||||
|
|
||||||
#[Column(length: 5, nullable: true)]
|
#[Column(length: 5, nullable: true)]
|
||||||
private ?int $bluePoints = null;
|
public ?int $bluePoints = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?bool $redExplodedBomb = null;
|
public ?bool $redExplodedBomb = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?bool $blueExplodedBomb = null;
|
public ?bool $blueExplodedBomb = null;
|
||||||
|
|
||||||
#[Column(length: 7, nullable: true)]
|
#[Column(length: 7, nullable: true)]
|
||||||
private ?string $resign = null;
|
public ?string $resign = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?float $redBonusPoints = null;
|
public ?float $redBonusPoints = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?float $blueBonusPoints = null;
|
public ?float $blueBonusPoints = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?array $redBonusStats = null;
|
public ?array $redBonusStats = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?array $blueBonusStats = null;
|
public ?array $blueBonusStats = null;
|
||||||
|
|
||||||
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
||||||
private ?DateTime $created = null;
|
public ?DateTime $created = null;
|
||||||
|
|
||||||
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
||||||
private ?DateTime $updated = null;
|
public ?DateTime $updated = null;
|
||||||
|
|
||||||
#[OneToOne(mappedBy: 'playedGame', cascade: ['persist'])]
|
#[OneToOne(mappedBy: 'playedGame', cascade: ['persist'])]
|
||||||
private ?Grid $grid = null;
|
public ?Grid $grid = null;
|
||||||
|
|
||||||
#[ManyToOne]
|
#[ManyToOne]
|
||||||
#[JoinColumn(name: 'red_id', referencedColumnName: 'id', nullable: true)]
|
#[JoinColumn(name: 'red_id', referencedColumnName: 'id', nullable: true)]
|
||||||
private ?User $red = null;
|
public ?User $red = null;
|
||||||
|
|
||||||
#[ManyToOne]
|
#[ManyToOne]
|
||||||
#[JoinColumn(name: 'red_anon', referencedColumnName: 'id', nullable: true)]
|
#[JoinColumn(name: 'red_anon', referencedColumnName: 'id', nullable: true)]
|
||||||
private ?Gamer $redAnon = null;
|
public ?Gamer $redAnon = null;
|
||||||
|
|
||||||
#[ManyToOne]
|
#[ManyToOne]
|
||||||
#[JoinColumn(name: 'blue_id', referencedColumnName: 'id', nullable: true)]
|
#[JoinColumn(name: 'blue_id', referencedColumnName: 'id', nullable: true)]
|
||||||
private ?User $blue = null;
|
public ?User $blue = null;
|
||||||
|
|
||||||
#[ManyToOne]
|
#[ManyToOne]
|
||||||
#[JoinColumn(name: 'blue_anon', referencedColumnName: 'id', nullable: true)]
|
#[JoinColumn(name: 'blue_anon', referencedColumnName: 'id', nullable: true)]
|
||||||
private ?Gamer $blueAnon = null;
|
public ?Gamer $blueAnon = null;
|
||||||
|
|
||||||
#[OneToMany(mappedBy: 'playedGame', targetEntity: Step::class)]
|
#[OneToMany(mappedBy: 'playedGame', targetEntity: Step::class)]
|
||||||
private Collection $steps;
|
public private(set) Collection $steps;
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@@ -108,196 +108,4 @@ class PlayedGame
|
|||||||
$this->steps = new ArrayCollection();
|
$this->steps = new ArrayCollection();
|
||||||
$this->uuid = Uuid::v4();
|
$this->uuid = Uuid::v4();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUuid(): ?Uuid
|
|
||||||
{
|
|
||||||
return $this->uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUuid(?Uuid $uuid): void
|
|
||||||
{
|
|
||||||
$this->uuid = $uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGameAssoc(): ?string
|
|
||||||
{
|
|
||||||
return $this->gameAssoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setGameAssoc(?string $gameAssoc): void
|
|
||||||
{
|
|
||||||
$this->gameAssoc = $gameAssoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGrid(): ?Grid
|
|
||||||
{
|
|
||||||
return $this->grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setGrid(?Grid $grid): void
|
|
||||||
{
|
|
||||||
$this->grid = $grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRed(): ?User
|
|
||||||
{
|
|
||||||
return $this->red;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRed(?User $red): void
|
|
||||||
{
|
|
||||||
$this->red = $red;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRedAnon(): ?Gamer
|
|
||||||
{
|
|
||||||
return $this->redAnon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRedAnon(?Gamer $redAnon): void
|
|
||||||
{
|
|
||||||
$this->redAnon = $redAnon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBlue(): ?User
|
|
||||||
{
|
|
||||||
return $this->blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBlue(?User $blue): void
|
|
||||||
{
|
|
||||||
$this->blue = $blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBlueAnon(): ?Gamer
|
|
||||||
{
|
|
||||||
return $this->blueAnon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBlueAnon(?Gamer $blueAnon): void
|
|
||||||
{
|
|
||||||
$this->blueAnon = $blueAnon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRedPoints(): ?int
|
|
||||||
{
|
|
||||||
return $this->redPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRedPoints(?int $redPoints): void
|
|
||||||
{
|
|
||||||
$this->redPoints = $redPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBluePoints(): ?int
|
|
||||||
{
|
|
||||||
return $this->bluePoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBluePoints(?int $bluePoints): void
|
|
||||||
{
|
|
||||||
$this->bluePoints = $bluePoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRedExplodedBomb(): ?bool
|
|
||||||
{
|
|
||||||
return $this->redExplodedBomb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRedExplodedBomb(?bool $redExplodedBomb): void
|
|
||||||
{
|
|
||||||
$this->redExplodedBomb = $redExplodedBomb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBlueExplodedBomb(): ?bool
|
|
||||||
{
|
|
||||||
return $this->blueExplodedBomb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBlueExplodedBomb(?bool $blueExplodedBomb): void
|
|
||||||
{
|
|
||||||
$this->blueExplodedBomb = $blueExplodedBomb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResign(): ?string
|
|
||||||
{
|
|
||||||
return $this->resign;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setResign(?string $resign): void
|
|
||||||
{
|
|
||||||
$this->resign = $resign;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRedBonusPoints(): ?float
|
|
||||||
{
|
|
||||||
return $this->redBonusPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRedBonusPoints(?float $redBonusPoints): void
|
|
||||||
{
|
|
||||||
$this->redBonusPoints = $redBonusPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBlueBonusPoints(): ?float
|
|
||||||
{
|
|
||||||
return $this->blueBonusPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBlueBonusPoints(?float $blueBonusPoints): void
|
|
||||||
{
|
|
||||||
$this->blueBonusPoints = $blueBonusPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRedBonusStats(): ?array
|
|
||||||
{
|
|
||||||
return $this->redBonusStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRedBonusStats(?array $redBonusStats): void
|
|
||||||
{
|
|
||||||
$this->redBonusStats = $redBonusStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBlueBonusStats(): ?array
|
|
||||||
{
|
|
||||||
return $this->blueBonusStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBlueBonusStats(?array $blueBonusStats): void
|
|
||||||
{
|
|
||||||
$this->blueBonusStats = $blueBonusStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreated(): ?DateTime
|
|
||||||
{
|
|
||||||
return $this->created;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCreated(?DateTime $created): void
|
|
||||||
{
|
|
||||||
$this->created = $created;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUpdated(): ?DateTime
|
|
||||||
{
|
|
||||||
return $this->updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUpdated(?DateTime $updated): void
|
|
||||||
{
|
|
||||||
$this->updated = $updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSteps(): Collection
|
|
||||||
{
|
|
||||||
return $this->steps;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
/*
|
/**
|
||||||
* This file is part of the SplendidBear Websites' projects.
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2026 @ www.splendidbear.org
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
@@ -33,102 +33,26 @@ use Doctrine\ORM\Mapping\ManyToOne;
|
|||||||
class Step
|
class Step
|
||||||
{
|
{
|
||||||
#[Id, GeneratedValue, Column]
|
#[Id, GeneratedValue, Column]
|
||||||
private ?int $id = null;
|
public private(set) ?int $id = null;
|
||||||
|
|
||||||
#[Column(length: 3)]
|
#[Column(length: 3)]
|
||||||
private ?int $row = null;
|
public ?int $row = null;
|
||||||
|
|
||||||
#[Column(length: 3)]
|
#[Column(length: 3)]
|
||||||
private ?int $col = null;
|
public ?int $col = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?bool $wBomb = null;
|
public ?bool $wBomb = null;
|
||||||
|
|
||||||
#[Column(length: 10, nullable: true)]
|
#[Column(length: 10, nullable: true)]
|
||||||
private ?string $player = null;
|
public ?string $player = null;
|
||||||
|
|
||||||
#[Column(type: Types::JSON, nullable: true)]
|
#[Column(type: Types::JSON, nullable: true)]
|
||||||
private ?array $revealedCells = null;
|
public ?array $revealedCells = null;
|
||||||
|
|
||||||
#[ManyToOne(inversedBy: 'steps')]
|
#[ManyToOne(inversedBy: 'steps')]
|
||||||
private ?PlayedGame $playedGame = null;
|
public ?PlayedGame $playedGame = null;
|
||||||
|
|
||||||
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
||||||
private ?DateTime $created = null;
|
public ?DateTime $created = null;
|
||||||
|
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRow(): ?int
|
|
||||||
{
|
|
||||||
return $this->row;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRow(?int $row): void
|
|
||||||
{
|
|
||||||
$this->row = $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCol(): ?int
|
|
||||||
{
|
|
||||||
return $this->col;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCol(?int $col): void
|
|
||||||
{
|
|
||||||
$this->col = $col;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getWBomb(): ?bool
|
|
||||||
{
|
|
||||||
return $this->wBomb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setWBomb(?bool $wBomb): void
|
|
||||||
{
|
|
||||||
$this->wBomb = $wBomb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPlayer(): ?string
|
|
||||||
{
|
|
||||||
return $this->player;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setPlayer(?string $player): void
|
|
||||||
{
|
|
||||||
$this->player = $player;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRevealedCells(): ?array
|
|
||||||
{
|
|
||||||
return $this->revealedCells;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRevealedCells(?array $revealedCells): void
|
|
||||||
{
|
|
||||||
$this->revealedCells = $revealedCells;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPlayedGame(): ?PlayedGame
|
|
||||||
{
|
|
||||||
return $this->playedGame;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setPlayedGame(?PlayedGame $playedGame): void
|
|
||||||
{
|
|
||||||
$this->playedGame = $playedGame;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreated(): ?DateTime
|
|
||||||
{
|
|
||||||
return $this->created;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCreated(?DateTime $created): void
|
|
||||||
{
|
|
||||||
$this->created = $created;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,61 +43,53 @@ use Symfony\Component\Security\Core\User\UserInterface;
|
|||||||
class User implements UserInterface, PasswordAuthenticatedUserInterface, TotpTwoFactorInterface, BackupCodeInterface
|
class User implements UserInterface, PasswordAuthenticatedUserInterface, TotpTwoFactorInterface, BackupCodeInterface
|
||||||
{
|
{
|
||||||
#[Id, GeneratedValue, Column]
|
#[Id, GeneratedValue, Column]
|
||||||
private ?int $id = null;
|
public private(set) ?int $id = null;
|
||||||
|
|
||||||
#[Column(length: 180, unique: true)]
|
#[Column(length: 180, unique: true)]
|
||||||
private ?string $username = null;
|
public ?string $username = null;
|
||||||
|
|
||||||
#[Column]
|
#[Column]
|
||||||
private array $roles = [];
|
public array $roles = [];
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?string $password = null;
|
public ?string $password = null;
|
||||||
|
|
||||||
#[Column(length: 254, unique: true, nullable: true)]
|
#[Column(length: 254, unique: true, nullable: true)]
|
||||||
private ?string $email = null;
|
public ?string $email = null;
|
||||||
|
|
||||||
#[Column]
|
#[Column]
|
||||||
private bool $isVerified = false;
|
public bool $isVerified = false;
|
||||||
|
|
||||||
#[Column(length: 64, nullable: true)]
|
#[Column(length: 64, nullable: true)]
|
||||||
private ?string $verificationToken = null;
|
public ?string $verificationToken = null;
|
||||||
|
|
||||||
#[Column(length: 64, nullable: true)]
|
#[Column(length: 64, nullable: true)]
|
||||||
private ?string $resetToken = null;
|
public ?string $resetToken = null;
|
||||||
|
|
||||||
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
||||||
private ?DateTime $resetTokenExpiresAt = null;
|
public ?DateTime $resetTokenExpiresAt = null;
|
||||||
|
|
||||||
#[Column(length: 255, nullable: true)]
|
#[Column(length: 255, nullable: true)]
|
||||||
private ?string $totpSecret = null;
|
public ?string $totpSecret = null;
|
||||||
|
|
||||||
|
/** Stored as nullable JSON; the get hook always exposes a non-null array. */
|
||||||
#[Column(type: Types::JSON, nullable: true)]
|
#[Column(type: Types::JSON, nullable: true)]
|
||||||
private ?array $backupCodes = [];
|
public ?array $backupCodes = [] {
|
||||||
|
get => $this->backupCodes ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
#[Column(length: 255, nullable: true)]
|
#[Column(length: 255, nullable: true)]
|
||||||
private ?string $avatarPath = null;
|
public ?string $avatarPath = null;
|
||||||
|
|
||||||
#[Column(nullable: true)]
|
#[Column(nullable: true)]
|
||||||
private ?bool $consentGiven = null;
|
public ?bool $consentGiven = null;
|
||||||
|
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUsername(): ?string
|
public function getUsername(): ?string
|
||||||
{
|
{
|
||||||
return $this->username;
|
return $this->username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUsername(string $username): self
|
|
||||||
{
|
|
||||||
$this->username = $username;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUserIdentifier(): string
|
public function getUserIdentifier(): string
|
||||||
{
|
{
|
||||||
return (string)$this->username;
|
return (string)$this->username;
|
||||||
@@ -105,15 +97,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, TotpTwo
|
|||||||
|
|
||||||
public function getRoles(): array
|
public function getRoles(): array
|
||||||
{
|
{
|
||||||
$roles = $this->roles;
|
return array_unique([...$this->roles, 'ROLE_USER']);
|
||||||
$roles[] = 'ROLE_USER';
|
|
||||||
return array_unique($roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setRoles(array $roles): self
|
|
||||||
{
|
|
||||||
$this->roles = $roles;
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPassword(): ?string
|
public function getPassword(): ?string
|
||||||
@@ -121,82 +105,10 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, TotpTwo
|
|||||||
return $this->password;
|
return $this->password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPassword(?string $password): self
|
|
||||||
{
|
|
||||||
$this->password = $password;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function eraseCredentials(): void
|
public function eraseCredentials(): void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEmail(): ?string
|
|
||||||
{
|
|
||||||
return $this->email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setEmail(?string $email): self
|
|
||||||
{
|
|
||||||
$this->email = $email;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isVerified(): bool
|
|
||||||
{
|
|
||||||
return $this->isVerified;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setIsVerified(bool $isVerified): self
|
|
||||||
{
|
|
||||||
$this->isVerified = $isVerified;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVerificationToken(): ?string
|
|
||||||
{
|
|
||||||
return $this->verificationToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setVerificationToken(?string $verificationToken): self
|
|
||||||
{
|
|
||||||
$this->verificationToken = $verificationToken;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResetToken(): ?string
|
|
||||||
{
|
|
||||||
return $this->resetToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setResetToken(?string $resetToken): self
|
|
||||||
{
|
|
||||||
$this->resetToken = $resetToken;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getResetTokenExpiresAt(): ?DateTime
|
|
||||||
{
|
|
||||||
return $this->resetTokenExpiresAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setResetTokenExpiresAt(?DateTime $resetTokenExpiresAt): self
|
|
||||||
{
|
|
||||||
$this->resetTokenExpiresAt = $resetTokenExpiresAt;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAvatarPath(): ?string
|
|
||||||
{
|
|
||||||
return $this->avatarPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setAvatarPath(?string $avatarPath): self
|
|
||||||
{
|
|
||||||
$this->avatarPath = $avatarPath;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isTotpAuthenticationEnabled(): bool
|
public function isTotpAuthenticationEnabled(): bool
|
||||||
{
|
{
|
||||||
return null !== $this->totpSecret;
|
return null !== $this->totpSecret;
|
||||||
@@ -215,46 +127,13 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, TotpTwo
|
|||||||
return new TotpConfiguration($this->totpSecret, TotpConfiguration::ALGORITHM_SHA1, 30, 6);
|
return new TotpConfiguration($this->totpSecret, TotpConfiguration::ALGORITHM_SHA1, 30, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTotpSecret(): ?string
|
|
||||||
{
|
|
||||||
return $this->totpSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTotpSecret(?string $totpSecret): self
|
|
||||||
{
|
|
||||||
$this->totpSecret = $totpSecret;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isBackupCode(string $code): bool
|
public function isBackupCode(string $code): bool
|
||||||
{
|
{
|
||||||
return \in_array($code, $this->backupCodes ?? [], true);
|
return \in_array($code, $this->backupCodes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function invalidateBackupCode(string $code): void
|
public function invalidateBackupCode(string $code): void
|
||||||
{
|
{
|
||||||
$this->backupCodes = array_values(array_filter($this->backupCodes ?? [], fn($c) => $c !== $code));
|
$this->backupCodes = array_values(array_filter($this->backupCodes, fn($c) => $c !== $code));
|
||||||
}
|
|
||||||
|
|
||||||
public function getBackupCodes(): array
|
|
||||||
{
|
|
||||||
return $this->backupCodes ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBackupCodes(array $backupCodes): self
|
|
||||||
{
|
|
||||||
$this->backupCodes = $backupCodes;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isConsentGiven(): ?bool
|
|
||||||
{
|
|
||||||
return $this->consentGiven;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setConsentGiven(?bool $consentGiven): self
|
|
||||||
{
|
|
||||||
$this->consentGiven = $consentGiven;
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ use Doctrine\ORM\Mapping\Id;
|
|||||||
use Doctrine\ORM\Mapping\JoinColumn;
|
use Doctrine\ORM\Mapping\JoinColumn;
|
||||||
use Doctrine\ORM\Mapping\ManyToOne;
|
use Doctrine\ORM\Mapping\ManyToOne;
|
||||||
use Doctrine\ORM\Mapping\Table;
|
use Doctrine\ORM\Mapping\Table;
|
||||||
|
use JsonException;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class WebAuthnCredential
|
* Class WebAuthnCredential
|
||||||
@@ -36,29 +38,29 @@ use Doctrine\ORM\Mapping\Table;
|
|||||||
class WebAuthnCredential
|
class WebAuthnCredential
|
||||||
{
|
{
|
||||||
#[Id, GeneratedValue, Column]
|
#[Id, GeneratedValue, Column]
|
||||||
private ?int $id = null;
|
public private(set) ?int $id = null;
|
||||||
|
|
||||||
#[ManyToOne(targetEntity: User::class)]
|
#[ManyToOne(targetEntity: User::class)]
|
||||||
#[JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
#[JoinColumn(nullable: false, onDelete: 'CASCADE')]
|
||||||
private ?User $user = null;
|
public ?User $user = null;
|
||||||
|
|
||||||
#[Column(type: Types::TEXT)]
|
#[Column(type: Types::TEXT)]
|
||||||
private ?string $credentialData = null;
|
public ?string $credentialData = null;
|
||||||
|
|
||||||
#[Column(length: 255)]
|
#[Column(length: 255)]
|
||||||
private ?string $credentialName = null;
|
public ?string $credentialName = null;
|
||||||
|
|
||||||
#[Column(type: Types::DATETIME_MUTABLE)]
|
#[Column(type: Types::DATETIME_MUTABLE)]
|
||||||
private ?DateTime $createdAt = null;
|
public ?DateTime $createdAt = null;
|
||||||
|
|
||||||
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
#[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
|
||||||
private ?DateTime $lastUsedAt = null;
|
public ?DateTime $lastUsedAt = null;
|
||||||
|
|
||||||
#[Column]
|
#[Column]
|
||||||
private bool $isBackupEligible = false;
|
public bool $isBackupEligible = false;
|
||||||
|
|
||||||
#[Column]
|
#[Column]
|
||||||
private bool $isBackupAuthenticated = false;
|
public bool $isBackupAuthenticated = false;
|
||||||
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
@@ -66,106 +68,27 @@ class WebAuthnCredential
|
|||||||
$this->createdAt = new DateTime();
|
$this->createdAt = new DateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUser(): ?User
|
|
||||||
{
|
|
||||||
return $this->user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUser(?User $user): self
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCredentialData(): ?string
|
|
||||||
{
|
|
||||||
return $this->credentialData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCredentialData(?string $credentialData): self
|
|
||||||
{
|
|
||||||
$this->credentialData = $credentialData;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCredentialName(): ?string
|
|
||||||
{
|
|
||||||
return $this->credentialName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCredentialName(?string $credentialName): self
|
|
||||||
{
|
|
||||||
$this->credentialName = $credentialName;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedAt(): ?DateTime
|
|
||||||
{
|
|
||||||
return $this->createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCreatedAt(?DateTime $createdAt): self
|
|
||||||
{
|
|
||||||
$this->createdAt = $createdAt;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLastUsedAt(): ?DateTime
|
|
||||||
{
|
|
||||||
return $this->lastUsedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setLastUsedAt(?DateTime $lastUsedAt): self
|
|
||||||
{
|
|
||||||
$this->lastUsedAt = $lastUsedAt;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isBackupEligible(): bool
|
|
||||||
{
|
|
||||||
return $this->isBackupEligible;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBackupEligible(bool $isBackupEligible): self
|
|
||||||
{
|
|
||||||
$this->isBackupEligible = $isBackupEligible;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isBackupAuthenticated(): bool
|
|
||||||
{
|
|
||||||
return $this->isBackupAuthenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBackupAuthenticated(bool $isBackupAuthenticated): self
|
|
||||||
{
|
|
||||||
$this->isBackupAuthenticated = $isBackupAuthenticated;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPublicKeyCredentialSource()
|
public function getPublicKeyCredentialSource()
|
||||||
{
|
{
|
||||||
// Return the raw credential data (JSON decoded)
|
|
||||||
if ($this->credentialData === null) {
|
if ($this->credentialData === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return json_decode($this->credentialData, true);
|
|
||||||
|
try {
|
||||||
|
return json_decode($this->credentialData, true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
} catch (JsonException $e) {
|
||||||
|
throw new RuntimeException("Unable to parse JSON: {$e->getMessage()}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPublicKeyCredentialSource($source): self
|
public function setPublicKeyCredentialSource($source): self
|
||||||
{
|
{
|
||||||
// Handle both array and object input
|
try {
|
||||||
if (is_array($source)) {
|
$this->credentialData = is_array($source) ? json_encode($source, JSON_THROW_ON_ERROR) : (string)$source;
|
||||||
$this->credentialData = json_encode($source);
|
} catch (JsonException $e) {
|
||||||
} else {
|
throw new RuntimeException("Unable to encode JSON: {$e->getMessage()}");
|
||||||
$this->credentialData = (string)$source;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
66
src/Migrations/2026/04/Version20260420064216.php
Normal file
66
src/Migrations/2026/04/Version20260420064216.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
/**
|
||||||
|
* This file is part of the SplendidBear Websites' projects.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2026 @ www.splendidbear.org
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Migrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Version20260420064216
|
||||||
|
*
|
||||||
|
* Realign each PostgreSQL IDENTITY counter to MAX(id)+1.
|
||||||
|
*
|
||||||
|
* Required because Version20260419195925 converted the ID columns from sequences to
|
||||||
|
* GENERATED BY DEFAULT AS IDENTITY (DBAL 4 / ORM 3 default), but PostgreSQL starts
|
||||||
|
* the new IDENTITY counter at 1 instead of inheriting the old sequence's last_value.
|
||||||
|
* The first INSERT on every table thus produced a duplicate-key collision.
|
||||||
|
*
|
||||||
|
* @package App\Migrations
|
||||||
|
* @author Lang <https://www.splendidbear.org>
|
||||||
|
* @category Class
|
||||||
|
* @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
|
||||||
|
* @link www.splendidbear.org
|
||||||
|
* @since 2026. 04. 20.
|
||||||
|
*/
|
||||||
|
final class Version20260420064216 extends AbstractMigration
|
||||||
|
{
|
||||||
|
private const TABLES = [
|
||||||
|
'played_game',
|
||||||
|
'grid',
|
||||||
|
'grid_row',
|
||||||
|
'step',
|
||||||
|
'app_user',
|
||||||
|
'app_webauthn_credential',
|
||||||
|
'gamer',
|
||||||
|
'contact_messages',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Realign IDENTITY counters to MAX(id)+1 after the sequence-to-identity conversion.';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
foreach (self::TABLES as $table) {
|
||||||
|
$this->addSql(sprintf(
|
||||||
|
"SELECT setval(pg_get_serial_sequence('%s', 'id'), COALESCE((SELECT MAX(id) FROM %s), 0) + 1, false)",
|
||||||
|
$table,
|
||||||
|
$table,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->throwIrreversibleMigrationException('Identity counter realignment cannot be reversed safely.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -269,7 +269,7 @@ class PlayedGameRepository extends ServiceEntityRepository
|
|||||||
COALESCE(SUM(CASE WHEN g.red_id = :uid THEN g.red_points ELSE g.blue_points END), 0) AS total_pts
|
COALESCE(SUM(CASE WHEN g.red_id = :uid THEN g.red_points ELSE g.blue_points END), 0) AS total_pts
|
||||||
FROM played_game g
|
FROM played_game g
|
||||||
WHERE (g.red_id = :uid OR g.blue_id = :uid)',
|
WHERE (g.red_id = :uid OR g.blue_id = :uid)',
|
||||||
['uid' => $user->getId()],
|
['uid' => $user->id],
|
||||||
)->fetchAssociative();
|
)->fetchAssociative();
|
||||||
|
|
||||||
return (int) ($result['total_pts'] ?? 0);
|
return (int) ($result['total_pts'] ?? 0);
|
||||||
@@ -289,7 +289,7 @@ class PlayedGameRepository extends ServiceEntityRepository
|
|||||||
(g.red_id = :uid AND g.red_points IS NOT NULL)
|
(g.red_id = :uid AND g.red_points IS NOT NULL)
|
||||||
OR (g.blue_id = :uid AND g.blue_points IS NOT NULL)
|
OR (g.blue_id = :uid AND g.blue_points IS NOT NULL)
|
||||||
)',
|
)',
|
||||||
['uid' => $user->getId()],
|
['uid' => $user->id],
|
||||||
)->fetchAssociative();
|
)->fetchAssociative();
|
||||||
|
|
||||||
if (!$result || (int) $result['total_games'] === 0) {
|
if (!$result || (int) $result['total_games'] === 0) {
|
||||||
@@ -306,7 +306,7 @@ class PlayedGameRepository extends ServiceEntityRepository
|
|||||||
*/
|
*/
|
||||||
public function findBonusStatsForUser(User $user): array
|
public function findBonusStatsForUser(User $user): array
|
||||||
{
|
{
|
||||||
$userId = $user->getId();
|
$userId = $user->id;
|
||||||
$qb = $this->createQueryBuilder('g');
|
$qb = $this->createQueryBuilder('g');
|
||||||
$qb->where($qb->expr()->orX(
|
$qb->where($qb->expr()->orX(
|
||||||
$qb->expr()->eq('g.red', ':u'),
|
$qb->expr()->eq('g.red', ':u'),
|
||||||
@@ -323,10 +323,10 @@ class PlayedGameRepository extends ServiceEntityRepository
|
|||||||
$gameCount = 0;
|
$gameCount = 0;
|
||||||
|
|
||||||
foreach ($games as $game) {
|
foreach ($games as $game) {
|
||||||
$isRed = $game->getRed()?->getId() === $userId;
|
$isRed = $game->red?->id === $userId;
|
||||||
$totalBonusPoints += (float) (($isRed ? $game->getRedBonusPoints() : $game->getBlueBonusPoints()) ?? 0.0);
|
$totalBonusPoints += (float) (($isRed ? $game->redBonusPoints : $game->blueBonusPoints) ?? 0.0);
|
||||||
|
|
||||||
$stats = ($isRed ? $game->getRedBonusStats() : $game->getBlueBonusStats()) ?? [];
|
$stats = ($isRed ? $game->redBonusStats : $game->blueBonusStats) ?? [];
|
||||||
$bestChain = max($bestChain, (int) ($stats['chainBest'] ?? 0));
|
$bestChain = max($bestChain, (int) ($stats['chainBest'] ?? 0));
|
||||||
$totalBlindHits += (int) ($stats['blindHits'] ?? 0);
|
$totalBlindHits += (int) ($stats['blindHits'] ?? 0);
|
||||||
$totalEdgeMines += (int) ($stats['edgeMines'] ?? 0);
|
$totalEdgeMines += (int) ($stats['edgeMines'] ?? 0);
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ class StepRepository extends ServiceEntityRepository
|
|||||||
public function findMostRecent(PlayedGame $playedGame): ?Step
|
public function findMostRecent(PlayedGame $playedGame): ?Step
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return $this->createQueryBuilder('s')
|
return $this
|
||||||
|
->createQueryBuilder('s')
|
||||||
->andWhere('s.playedGame = :game')
|
->andWhere('s.playedGame = :game')
|
||||||
->setParameter('game', $playedGame)
|
->setParameter('game', $playedGame)
|
||||||
->orderBy('s.created', 'DESC')
|
->orderBy('s.created', 'DESC')
|
||||||
@@ -53,7 +54,7 @@ class StepRepository extends ServiceEntityRepository
|
|||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Expected at most one result for the most recent step of game ID %d, but got multiple.',
|
'Expected at most one result for the most recent step of game ID %d, but got multiple.',
|
||||||
$playedGame->getId(),
|
$playedGame->id,
|
||||||
),
|
),
|
||||||
0,
|
0,
|
||||||
$e,
|
$e,
|
||||||
@@ -64,7 +65,8 @@ class StepRepository extends ServiceEntityRepository
|
|||||||
public function findMostRecentForPlayer(PlayedGame $playedGame, string $player): ?Step
|
public function findMostRecentForPlayer(PlayedGame $playedGame, string $player): ?Step
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return $this->createQueryBuilder('s')
|
return $this
|
||||||
|
->createQueryBuilder('s')
|
||||||
->andWhere('s.playedGame = :game')
|
->andWhere('s.playedGame = :game')
|
||||||
->andWhere('s.player = :player')
|
->andWhere('s.player = :player')
|
||||||
->setParameter('game', $playedGame)
|
->setParameter('game', $playedGame)
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class UserRepository extends ServiceEntityRepository implements PasswordUpgrader
|
|||||||
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
|
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
$user->setPassword($newHashedPassword);
|
$user->password = $newHashedPassword;
|
||||||
$this->getEntityManager()->persist($user);
|
$this->getEntityManager()->persist($user);
|
||||||
$this->getEntityManager()->flush();
|
$this->getEntityManager()->flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,15 @@ use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
|||||||
use Doctrine\Persistence\ManagerRegistry;
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Class WebAuthnCredentialRepository
|
||||||
|
*
|
||||||
|
* @package App\Repository
|
||||||
|
* @author Lang <https://www.splendidbear.org>
|
||||||
|
* @category Class
|
||||||
|
* @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
|
||||||
|
* @link www.splendidbear.org
|
||||||
|
* @since 2026. 04. 12.
|
||||||
|
*
|
||||||
* @extends ServiceEntityRepository<WebAuthnCredential>
|
* @extends ServiceEntityRepository<WebAuthnCredential>
|
||||||
*
|
*
|
||||||
* @method WebAuthnCredential|null find($id, $lockMode = null, $lockVersion = null)
|
* @method WebAuthnCredential|null find($id, $lockMode = null, $lockVersion = null)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ final class UserChecker implements UserCheckerInterface
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$user->isVerified()) {
|
if (!$user->isVerified) {
|
||||||
throw new CustomUserMessageAuthenticationException(
|
throw new CustomUserMessageAuthenticationException(
|
||||||
'Please verify your email address before signing in. Check your inbox for the activation link.'
|
'Please verify your email address before signing in. Check your inbox for the activation link.'
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class BattleCardGenerator
|
|||||||
|
|
||||||
public function generate(PlayedGame $game): string
|
public function generate(PlayedGame $game): string
|
||||||
{
|
{
|
||||||
$path = $this->cachePath((int)$game->getId());
|
$path = $this->cachePath((int)$game->id);
|
||||||
|
|
||||||
// Always regenerate to ensure bonus points are included
|
// Always regenerate to ensure bonus points are included
|
||||||
if (is_file($path)) {
|
if (is_file($path)) {
|
||||||
@@ -108,13 +108,13 @@ class BattleCardGenerator
|
|||||||
imageline($im, self::WIDTH / 2, 110, self::WIDTH / 2, self::HEIGHT - 80, $divider);
|
imageline($im, self::WIDTH / 2, 110, self::WIDTH / 2, self::HEIGHT - 80, $divider);
|
||||||
|
|
||||||
/** Resolve names*/
|
/** Resolve names*/
|
||||||
$redName = $game->getRed()?->getUsername()
|
$redName = $game->red?->getUsername()
|
||||||
?? ($game->getRedAnon() !== null ? 'Anonymous' : 'Guest');
|
?? ($game->redAnon !== null ? 'Anonymous' : 'Guest');
|
||||||
$blueName = $game->getBlue()?->getUsername()
|
$blueName = $game->blue?->getUsername()
|
||||||
?? ($game->getBlueAnon() !== null ? 'Anonymous' : 'Guest');
|
?? ($game->blueAnon !== null ? 'Anonymous' : 'Guest');
|
||||||
$redPts = $game->getRedPoints();
|
$redPts = $game->redPoints;
|
||||||
$bluePts = $game->getBluePoints();
|
$bluePts = $game->bluePoints;
|
||||||
$resign = $game->getResign();
|
$resign = $game->resign;
|
||||||
|
|
||||||
/** Winner*/
|
/** Winner*/
|
||||||
$winner = null;
|
$winner = null;
|
||||||
@@ -135,8 +135,8 @@ class BattleCardGenerator
|
|||||||
$this->centeredText($im, 'BLUE', 16, 980, 130, $blue);
|
$this->centeredText($im, 'BLUE', 16, 980, 130, $blue);
|
||||||
|
|
||||||
/** Draw avatars below the team labels (moved down by 60px total: 200 → 260)*/
|
/** Draw avatars below the team labels (moved down by 60px total: 200 → 260)*/
|
||||||
$redAvatar = $game->getRed()?->getAvatarPath();
|
$redAvatar = $game->red?->avatarPath;
|
||||||
$blueAvatar = $game->getBlue()?->getAvatarPath();
|
$blueAvatar = $game->blue?->avatarPath;
|
||||||
|
|
||||||
$this->drawAvatar($im, $redAvatar, 220, 260, $red, $redName);
|
$this->drawAvatar($im, $redAvatar, 220, 260, $red, $redName);
|
||||||
$this->drawAvatar($im, $blueAvatar, 980, 260, $blue, $blueName);
|
$this->drawAvatar($im, $blueAvatar, 980, 260, $blue, $blueName);
|
||||||
@@ -156,8 +156,8 @@ class BattleCardGenerator
|
|||||||
$this->centeredText($im, $scoreText, 72, self::WIDTH / 2, 390, $white);
|
$this->centeredText($im, $scoreText, 72, self::WIDTH / 2, 390, $white);
|
||||||
|
|
||||||
/** Bonus points below score*/
|
/** Bonus points below score*/
|
||||||
$redBonusPoints = $game->getRedBonusPoints() ?? 0;
|
$redBonusPoints = $game->redBonusPoints ?? 0;
|
||||||
$blueBonusPoints = $game->getBlueBonusPoints() ?? 0;
|
$blueBonusPoints = $game->blueBonusPoints ?? 0;
|
||||||
$bonusText = number_format((float)$redBonusPoints, 1, '.', '') . ' * : * ' . number_format((float)$blueBonusPoints, 1, '.', '');
|
$bonusText = number_format((float)$redBonusPoints, 1, '.', '') . ' * : * ' . number_format((float)$blueBonusPoints, 1, '.', '');
|
||||||
$this->centeredText($im, $bonusText, 24, self::WIDTH / 2, 425, $gold);
|
$this->centeredText($im, $bonusText, 24, self::WIDTH / 2, 425, $gold);
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ readonly final class SendContactMailService
|
|||||||
new TemplatedEmail()
|
new TemplatedEmail()
|
||||||
->from('noreply@mineseeker.hu')
|
->from('noreply@mineseeker.hu')
|
||||||
->to($this->appContactMailAddress)
|
->to($this->appContactMailAddress)
|
||||||
->replyTo($contactMessage->getEmail())
|
->replyTo($contactMessage->email)
|
||||||
->subject('New Contact Message from ' . $contactMessage->getName())
|
->subject('New Contact Message from ' . $contactMessage->name)
|
||||||
->htmlTemplate('emails/contact_notification.html.twig')
|
->htmlTemplate('emails/contact_notification.html.twig')
|
||||||
->context(['message' => $contactMessage])
|
->context(['message' => $contactMessage])
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -70,10 +70,10 @@ readonly final class ResolveUserNamesService
|
|||||||
|
|
||||||
private function resolveOpponentName(PlayedGame $game, string $myUserName): string
|
private function resolveOpponentName(PlayedGame $game, string $myUserName): string
|
||||||
{
|
{
|
||||||
$redName = $game->getRed()?->getUsername();
|
$redName = $game->red?->getUsername();
|
||||||
$blueName = $game->getBlue()?->getUsername();
|
$blueName = $game->blue?->getUsername();
|
||||||
$redAnonName = $game->getRedAnon()?->getUserName();
|
$redAnonName = $game->redAnon?->userName;
|
||||||
$blueAnonName = $game->getBlueAnon()?->getUserName();
|
$blueAnonName = $game->blueAnon?->userName;
|
||||||
|
|
||||||
$isRed = $myUserName === $redName || $myUserName === $redAnonName;
|
$isRed = $myUserName === $redName || $myUserName === $redAnonName;
|
||||||
$isBlue = $myUserName === $blueName || $myUserName === $blueAnonName;
|
$isBlue = $myUserName === $blueName || $myUserName === $blueAnonName;
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ readonly class WebAuthnService
|
|||||||
public function saveCredential(User $user, array $credentialData, string $name): WebAuthnCredential
|
public function saveCredential(User $user, array $credentialData, string $name): WebAuthnCredential
|
||||||
{
|
{
|
||||||
$credential = new WebAuthnCredential();
|
$credential = new WebAuthnCredential();
|
||||||
$credential->setUser($user);
|
$credential->user = $user;
|
||||||
$credential->setCredentialData(json_encode($credentialData));
|
$credential->credentialData = json_encode($credentialData);
|
||||||
$credential->setCredentialName($name);
|
$credential->credentialName = $name;
|
||||||
$credential->setBackupEligible($credentialData['isBackupEligible'] ?? false);
|
$credential->isBackupEligible = $credentialData['isBackupEligible'] ?? false;
|
||||||
$credential->setBackupAuthenticated($credentialData['isBackupAuthenticated'] ?? false);
|
$credential->isBackupAuthenticated = $credentialData['isBackupAuthenticated'] ?? false;
|
||||||
|
|
||||||
$this->entityManager->persist($credential);
|
$this->entityManager->persist($credential);
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
@@ -60,7 +60,7 @@ readonly class WebAuthnService
|
|||||||
{
|
{
|
||||||
$credential = $this->credentialRepository->find($id);
|
$credential = $this->credentialRepository->find($id);
|
||||||
|
|
||||||
if ($credential === null || $credential->getUser() !== $user) {
|
if ($credential === null || $credential->user !== $user) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,11 +74,11 @@ readonly class WebAuthnService
|
|||||||
{
|
{
|
||||||
$credential = $this->credentialRepository->find($id);
|
$credential = $this->credentialRepository->find($id);
|
||||||
|
|
||||||
if ($credential === null || $credential->getUser() !== $user) {
|
if ($credential === null || $credential->user !== $user) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credential->setCredentialName($name);
|
$credential->credentialName = $name;
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -99,7 +99,7 @@ readonly class WebAuthnService
|
|||||||
$sources = [];
|
$sources = [];
|
||||||
|
|
||||||
foreach ($credentials as $credential) {
|
foreach ($credentials as $credential) {
|
||||||
$data = $credential->getCredentialData();
|
$data = $credential->credentialData;
|
||||||
|
|
||||||
if ($data === null) {
|
if ($data === null) {
|
||||||
continue;
|
continue;
|
||||||
@@ -109,7 +109,7 @@ readonly class WebAuthnService
|
|||||||
$sources[] = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
|
$sources[] = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
|
||||||
} catch (JsonException $e) {
|
} catch (JsonException $e) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Failed to decode credential data for credential ID $credential->getId(): $e->getMessage()",
|
"Failed to decode credential data for credential ID {$credential->id}: {$e->getMessage()}",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,13 +122,13 @@ readonly class WebAuthnService
|
|||||||
$credentials = $this->credentialRepository->findByUser($user);
|
$credentials = $this->credentialRepository->findByUser($user);
|
||||||
|
|
||||||
foreach ($credentials as $credential) {
|
foreach ($credentials as $credential) {
|
||||||
$data = json_decode($credential->getCredentialData() ?? '{}', true);
|
$data = json_decode($credential->credentialData ?? '{}', true);
|
||||||
|
|
||||||
if (($data['id'] ?? null) !== $credentialId) {
|
if (($data['id'] ?? null) !== $credentialId) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$credential->setLastUsedAt(new DateTime());
|
$credential->lastUsedAt = new DateTime();
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -139,13 +139,13 @@ readonly class WebAuthnService
|
|||||||
$allCredentials = $this->credentialRepository->findAll();
|
$allCredentials = $this->credentialRepository->findAll();
|
||||||
|
|
||||||
foreach ($allCredentials as $credential) {
|
foreach ($allCredentials as $credential) {
|
||||||
$data = json_decode($credential->getCredentialData() ?? '{}', true);
|
$data = json_decode($credential->credentialData ?? '{}', true);
|
||||||
|
|
||||||
if (($data['id'] ?? null) !== $credentialId) {
|
if (($data['id'] ?? null) !== $credentialId) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $credential->getUser();
|
return $credential->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ class RpcManager implements RpcManagerInterface
|
|||||||
$revealedCells = $this->aggregateRevealedCells($playedGame);
|
$revealedCells = $this->aggregateRevealedCells($playedGame);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$redPoints = $playedGame->getRedPoints() ?? 0;
|
$redPoints = $playedGame->redPoints ?? 0;
|
||||||
$bluePoints = $playedGame->getBluePoints() ?? 0;
|
$bluePoints = $playedGame->bluePoints ?? 0;
|
||||||
$gameFinished = $redPoints > 25 || $bluePoints > 25;
|
$gameFinished = $redPoints > 25 || $bluePoints > 25;
|
||||||
|
|
||||||
return base64_encode(json_encode([
|
return base64_encode(json_encode([
|
||||||
@@ -91,10 +91,10 @@ class RpcManager implements RpcManagerInterface
|
|||||||
'mostRecentStep' => $this->getMostRecentStep($playedGame),
|
'mostRecentStep' => $this->getMostRecentStep($playedGame),
|
||||||
'redPoints' => $redPoints,
|
'redPoints' => $redPoints,
|
||||||
'bluePoints' => $bluePoints,
|
'bluePoints' => $bluePoints,
|
||||||
'redBonusPoints' => $playedGame->getRedBonusPoints() ?? 0,
|
'redBonusPoints' => $playedGame->redBonusPoints ?? 0,
|
||||||
'blueBonusPoints' => $playedGame->getBlueBonusPoints() ?? 0,
|
'blueBonusPoints' => $playedGame->blueBonusPoints ?? 0,
|
||||||
'redBonusStats' => $playedGame->getRedBonusStats() ?? [],
|
'redBonusStats' => $playedGame->redBonusStats ?? [],
|
||||||
'blueBonusStats' => $playedGame->getBlueBonusStats() ?? [],
|
'blueBonusStats' => $playedGame->blueBonusStats ?? [],
|
||||||
'gameFinished' => $gameFinished,
|
'gameFinished' => $gameFinished,
|
||||||
], JSON_THROW_ON_ERROR));
|
], JSON_THROW_ON_ERROR));
|
||||||
} catch (JsonException $e) {
|
} catch (JsonException $e) {
|
||||||
@@ -131,19 +131,19 @@ class RpcManager implements RpcManagerInterface
|
|||||||
try {
|
try {
|
||||||
foreach ($grid2d as $row) {
|
foreach ($grid2d as $row) {
|
||||||
$gridRow = new GridRow();
|
$gridRow = new GridRow();
|
||||||
$gridRow->setGridCol($row);
|
$gridRow->gridCol = $row;
|
||||||
$gridRow->setGrid($grid);
|
$gridRow->grid = $grid;
|
||||||
$this->em->persist($gridRow);
|
$this->em->persist($gridRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
$grid->setPlayedGame($playedGame);
|
$grid->playedGame = $playedGame;
|
||||||
$this->em->persist($grid);
|
$this->em->persist($grid);
|
||||||
|
|
||||||
$playedGame->setGameAssoc($gameAssoc);
|
$playedGame->gameAssoc = $gameAssoc;
|
||||||
$playedGame->setUuid(Uuid::fromString($gameAssoc));
|
$playedGame->uuid = Uuid::fromString($gameAssoc);
|
||||||
$playedGame->setGrid($grid);
|
$playedGame->grid = $grid;
|
||||||
$playedGame->setCreated(new DateTime());
|
$playedGame->created = new DateTime();
|
||||||
$playedGame->setUpdated(new DateTime());
|
$playedGame->updated = new DateTime();
|
||||||
$this->em->persist($playedGame);
|
$this->em->persist($playedGame);
|
||||||
|
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
@@ -212,12 +212,12 @@ class RpcManager implements RpcManagerInterface
|
|||||||
{
|
{
|
||||||
$all = [];
|
$all = [];
|
||||||
|
|
||||||
foreach ($playedGame->getSteps() as $step) {
|
foreach ($playedGame->steps as $step) {
|
||||||
if (null === $step->getRevealedCells()) {
|
if (null === $step->revealedCells) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$player = $step->getPlayer();
|
$player = $step->player;
|
||||||
foreach ($step->getRevealedCells() as $cell) {
|
foreach ($step->revealedCells as $cell) {
|
||||||
$all[] = array_merge($cell, ['player' => $player]);
|
$all[] = array_merge($cell, ['player' => $player]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,19 +250,19 @@ class RpcManager implements RpcManagerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'player' => $step->getPlayer(),
|
'player' => $step->player,
|
||||||
'row' => (int)$step->getRow(),
|
'row' => (int)$step->row,
|
||||||
'col' => (int)$step->getCol(),
|
'col' => (int)$step->col,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getUserCollection(PlayedGame $playedGame): array
|
private function getUserCollection(PlayedGame $playedGame): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'red' => null !== $playedGame->getRed() ? $playedGame->getRed()->getUsername() : '',
|
'red' => null !== $playedGame->red ? $playedGame->red->getUsername() : '',
|
||||||
'blue' => null !== $playedGame->getBlue() ? $playedGame->getBlue()->getUsername() : '',
|
'blue' => null !== $playedGame->blue ? $playedGame->blue->getUsername() : '',
|
||||||
'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '',
|
'redAnon' => null !== $playedGame->redAnon ? $playedGame->redAnon->userName : '',
|
||||||
'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : '',
|
'blueAnon' => null !== $playedGame->blueAnon ? $playedGame->blueAnon->userName : '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
// ── Lobby updates ──────────────────────────────────────────────────
|
// ── Lobby updates ──────────────────────────────────────────────────
|
||||||
if ($count === 1) {
|
if ($count === 1) {
|
||||||
// One player waiting — mark as active and announce to the lobby
|
// One player waiting — mark as active and announce to the lobby
|
||||||
$playedGame->setUpdated(new DateTime());
|
$playedGame->updated = new DateTime();
|
||||||
|
|
||||||
$this->em->persist($playedGame);
|
$this->em->persist($playedGame);
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
@@ -106,7 +106,7 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
'action' => 'join',
|
'action' => 'join',
|
||||||
'gameAssoc' => $gameAssoc,
|
'gameAssoc' => $gameAssoc,
|
||||||
'name' => $displayName,
|
'name' => $displayName,
|
||||||
'since' => $playedGame->getCreated()?->format(DateTimeInterface::ATOM) ?? '',
|
'since' => $playedGame->created?->format(DateTimeInterface::ATOM) ?? '',
|
||||||
]);
|
]);
|
||||||
} elseif ($count === 2) {
|
} elseif ($count === 2) {
|
||||||
// Both players joined — remove from lobby
|
// Both players joined — remove from lobby
|
||||||
@@ -122,7 +122,7 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
if (null !== $playedGame) {
|
if (null !== $playedGame) {
|
||||||
$users = $this->getUserCollection($playedGame);
|
$users = $this->getUserCollection($playedGame);
|
||||||
if ($this->getPlayerCount($users) === 1) {
|
if ($this->getPlayerCount($users) === 1) {
|
||||||
$playedGame->setUpdated(new DateTime('2000-01-01 00:00:00'));
|
$playedGame->updated = new DateTime('2000-01-01 00:00:00');
|
||||||
$this->em->persist($playedGame);
|
$this->em->persist($playedGame);
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
$this->publishToLobby(['action' => 'leave', 'gameAssoc' => $gameAssoc]);
|
$this->publishToLobby(['action' => 'leave', 'gameAssoc' => $gameAssoc]);
|
||||||
@@ -194,8 +194,8 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
$minesFound = count(array_filter($revealedCells, static fn($c) => 'm' === $c['value']));
|
$minesFound = count(array_filter($revealedCells, static fn($c) => 'm' === $c['value']));
|
||||||
$safeCellsFound = count(array_filter($revealedCells, static fn($c) => 'm' !== $c['value']));
|
$safeCellsFound = count(array_filter($revealedCells, static fn($c) => 'm' !== $c['value']));
|
||||||
|
|
||||||
$redPoints = ($playedGame->getRedPoints() ?? 0) + ('red' === $player ? $minesFound : 0);
|
$redPoints = ($playedGame->redPoints ?? 0) + ('red' === $player ? $minesFound : 0);
|
||||||
$bluePoints = ($playedGame->getBluePoints() ?? 0) + ('blue' === $player ? $minesFound : 0);
|
$bluePoints = ($playedGame->bluePoints ?? 0) + ('blue' === $player ? $minesFound : 0);
|
||||||
$gameOver = $redPoints > 25 || $bluePoints > 25;
|
$gameOver = $redPoints > 25 || $bluePoints > 25;
|
||||||
|
|
||||||
/** Calculate bonus points and stats */
|
/** Calculate bonus points and stats */
|
||||||
@@ -266,7 +266,7 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
private function loadGrid(string $gameAssoc): array
|
private function loadGrid(string $gameAssoc): array
|
||||||
{
|
{
|
||||||
$playedGame = $this->getPlayedGame($gameAssoc);
|
$playedGame = $this->getPlayedGame($gameAssoc);
|
||||||
$gridEntity = $playedGame?->getGrid();
|
$gridEntity = $playedGame?->grid;
|
||||||
|
|
||||||
if (null === $gridEntity) {
|
if (null === $gridEntity) {
|
||||||
return [];
|
return [];
|
||||||
@@ -274,8 +274,8 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
|
|
||||||
$grid = [];
|
$grid = [];
|
||||||
/** @var GridRow $row */
|
/** @var GridRow $row */
|
||||||
foreach ($gridEntity->getGridRow() as $row) {
|
foreach ($gridEntity->gridRow as $row) {
|
||||||
$grid[] = $row->getGridCol();
|
$grid[] = $row->gridCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $grid;
|
return $grid;
|
||||||
@@ -293,7 +293,7 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
int $bluePoints
|
int $bluePoints
|
||||||
): array {
|
): array {
|
||||||
/** Initialize or load existing bonus stats */
|
/** Initialize or load existing bonus stats */
|
||||||
$redBonusStats = $playedGame->getRedBonusStats() ?? [
|
$redBonusStats = $playedGame->redBonusStats ?? [
|
||||||
'blindHits' => 0,
|
'blindHits' => 0,
|
||||||
'chainBest' => 0,
|
'chainBest' => 0,
|
||||||
'chainCurrent' => 0,
|
'chainCurrent' => 0,
|
||||||
@@ -301,7 +301,7 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
'edgeMines' => 0,
|
'edgeMines' => 0,
|
||||||
'biggestReveal' => 0,
|
'biggestReveal' => 0,
|
||||||
];
|
];
|
||||||
$blueBonusStats = $playedGame->getBlueBonusStats() ?? [
|
$blueBonusStats = $playedGame->blueBonusStats ?? [
|
||||||
'blindHits' => 0,
|
'blindHits' => 0,
|
||||||
'chainBest' => 0,
|
'chainBest' => 0,
|
||||||
'chainCurrent' => 0,
|
'chainCurrent' => 0,
|
||||||
@@ -310,8 +310,8 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
'biggestReveal' => 0,
|
'biggestReveal' => 0,
|
||||||
];
|
];
|
||||||
|
|
||||||
$redBonusPoints = $playedGame->getRedBonusPoints() ?? 0;
|
$redBonusPoints = $playedGame->redBonusPoints ?? 0;
|
||||||
$blueBonusPoints = $playedGame->getBlueBonusPoints() ?? 0;
|
$blueBonusPoints = $playedGame->blueBonusPoints ?? 0;
|
||||||
|
|
||||||
$isRed = 'red' === $player;
|
$isRed = 'red' === $player;
|
||||||
$currentStats = $isRed ? $redBonusStats : $blueBonusStats;
|
$currentStats = $isRed ? $redBonusStats : $blueBonusStats;
|
||||||
@@ -376,10 +376,10 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Persist updated stats to the database */
|
/** Persist updated stats to the database */
|
||||||
$playedGame->setRedBonusStats($redBonusStats);
|
$playedGame->redBonusStats = $redBonusStats;
|
||||||
$playedGame->setBlueBonusStats($blueBonusStats);
|
$playedGame->blueBonusStats = $blueBonusStats;
|
||||||
$playedGame->setRedBonusPoints($redBonusPoints);
|
$playedGame->redBonusPoints = $redBonusPoints;
|
||||||
$playedGame->setBlueBonusPoints($blueBonusPoints);
|
$playedGame->blueBonusPoints = $blueBonusPoints;
|
||||||
$this->em->persist($playedGame);
|
$this->em->persist($playedGame);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -538,8 +538,8 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
private function buildRevealedMap(PlayedGame $playedGame): array
|
private function buildRevealedMap(PlayedGame $playedGame): array
|
||||||
{
|
{
|
||||||
$map = [];
|
$map = [];
|
||||||
foreach ($playedGame->getSteps() as $step) {
|
foreach ($playedGame->steps as $step) {
|
||||||
foreach ($step->getRevealedCells() ?? [] as $cell) {
|
foreach ($step->revealedCells ?? [] as $cell) {
|
||||||
$map[$cell['row'] . ',' . $cell['col']] = true;
|
$map[$cell['row'] . ',' . $cell['col']] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -583,7 +583,7 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
private function saveResignToDb(string $gameAssoc, string $color): void
|
private function saveResignToDb(string $gameAssoc, string $color): void
|
||||||
{
|
{
|
||||||
$playedGame = $this->getPlayedGame($gameAssoc);
|
$playedGame = $this->getPlayedGame($gameAssoc);
|
||||||
$playedGame->setResign($color);
|
$playedGame->resign = $color;
|
||||||
$this->em->persist($playedGame);
|
$this->em->persist($playedGame);
|
||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
}
|
}
|
||||||
@@ -601,32 +601,32 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
$playedGame = $this->getPlayedGame($gameAssoc);
|
$playedGame = $this->getPlayedGame($gameAssoc);
|
||||||
|
|
||||||
$step = new Step();
|
$step = new Step();
|
||||||
$step->setRow($event['coords'][0]);
|
$step->row = $event['coords'][0];
|
||||||
$step->setCol($event['coords'][1]);
|
$step->col = $event['coords'][1];
|
||||||
$step->setWBomb((bool)$event['bomb']);
|
$step->wBomb = (bool)$event['bomb'];
|
||||||
$step->setPlayer($player);
|
$step->player = $player;
|
||||||
$step->setRevealedCells($revealedCells);
|
$step->revealedCells = $revealedCells;
|
||||||
$step->setPlayedGame($playedGame);
|
$step->playedGame = $playedGame;
|
||||||
$step->setCreated(new DateTime());
|
$step->created = new DateTime();
|
||||||
$this->em->persist($step);
|
$this->em->persist($step);
|
||||||
|
|
||||||
$playedGame->setRedPoints($redPoints);
|
$playedGame->redPoints = $redPoints;
|
||||||
$playedGame->setBluePoints($bluePoints);
|
$playedGame->bluePoints = $bluePoints;
|
||||||
if ((bool)$event['bomb']) {
|
if ((bool)$event['bomb']) {
|
||||||
if ('red' === $player) {
|
if ('red' === $player) {
|
||||||
$playedGame->setRedExplodedBomb(true);
|
$playedGame->redExplodedBomb = true;
|
||||||
} elseif ('blue' === $player) {
|
} elseif ('blue' === $player) {
|
||||||
$playedGame->setBlueExplodedBomb(true);
|
$playedGame->blueExplodedBomb = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$playedGame->setUpdated(new DateTime());
|
$playedGame->updated = new DateTime();
|
||||||
|
|
||||||
/** Bonus data is already persisted in calculateBonuses, but we ensure it's up to date */
|
/** Bonus data is already persisted in calculateBonuses, but we ensure it's up to date */
|
||||||
if (!empty($bonusData)) {
|
if (!empty($bonusData)) {
|
||||||
$playedGame->setRedBonusPoints($bonusData['redBonusPoints']);
|
$playedGame->redBonusPoints = $bonusData['redBonusPoints'];
|
||||||
$playedGame->setBlueBonusPoints($bonusData['blueBonusPoints']);
|
$playedGame->blueBonusPoints = $bonusData['blueBonusPoints'];
|
||||||
$playedGame->setRedBonusStats($bonusData['redBonusStats']);
|
$playedGame->redBonusStats = $bonusData['redBonusStats'];
|
||||||
$playedGame->setBlueBonusStats($bonusData['blueBonusStats']);
|
$playedGame->blueBonusStats = $bonusData['blueBonusStats'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->em->persist($playedGame);
|
$this->em->persist($playedGame);
|
||||||
@@ -658,11 +658,11 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
try {
|
try {
|
||||||
if ($count === 1) {
|
if ($count === 1) {
|
||||||
$random = random_int(0, 1);
|
$random = random_int(0, 1);
|
||||||
!$random ? $playedGame->setRed($user) : $playedGame->setBlue($user);
|
!$random ? $playedGame->red = $user : $playedGame->blue = $user;
|
||||||
} else {
|
} else {
|
||||||
null === $playedGame->getRed() && null === $playedGame->getRedAnon()
|
null === $playedGame->red && null === $playedGame->redAnon
|
||||||
? $playedGame->setRed($user)
|
? $playedGame->red = $user
|
||||||
: $playedGame->setBlue($user);
|
: $playedGame->blue = $user;
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->logger->error($e->getMessage());
|
$this->logger->error($e->getMessage());
|
||||||
@@ -673,21 +673,21 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$anon = new Gamer();
|
$anon = new Gamer();
|
||||||
$anon->setUserName($userName);
|
$anon->userName = $userName;
|
||||||
$anon->setIp($this->requestStack->getCurrentRequest()->getClientIp());
|
$anon->ip = $this->requestStack->getCurrentRequest()->getClientIp();
|
||||||
$anon->setCountry($this->extractCountry());
|
$anon->country = $this->extractCountry();
|
||||||
$anon->setUserAgent($this->requestStack->getCurrentRequest()->headers->get('User-Agent'));
|
$anon->userAgent = $this->requestStack->getCurrentRequest()->headers->get('User-Agent');
|
||||||
$anon->setConnTimestamp(new DateTime());
|
$anon->connTimestamp = new DateTime();
|
||||||
|
|
||||||
$this->em->persist($anon);
|
$this->em->persist($anon);
|
||||||
|
|
||||||
if ($count === 1) {
|
if ($count === 1) {
|
||||||
$random = random_int(0, 1);
|
$random = random_int(0, 1);
|
||||||
!$random ? $playedGame->setRedAnon($anon) : $playedGame->setBlueAnon($anon);
|
!$random ? $playedGame->redAnon = $anon : $playedGame->blueAnon = $anon;
|
||||||
} else {
|
} else {
|
||||||
null === $playedGame->getRed() && null === $playedGame->getRedAnon()
|
null === $playedGame->red && null === $playedGame->redAnon
|
||||||
? $playedGame->setRedAnon($anon)
|
? $playedGame->redAnon = $anon
|
||||||
: $playedGame->setBlueAnon($anon);
|
: $playedGame->blueAnon = $anon;
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->logger->error($e->getMessage());
|
$this->logger->error($e->getMessage());
|
||||||
@@ -696,19 +696,19 @@ readonly class TopicManager implements TopicManagerInterface
|
|||||||
|
|
||||||
private function getUserCollection(PlayedGame $playedGame): array
|
private function getUserCollection(PlayedGame $playedGame): array
|
||||||
{
|
{
|
||||||
$redUser = $playedGame->getRed();
|
$redUser = $playedGame->red;
|
||||||
$blueUser = $playedGame->getBlue();
|
$blueUser = $playedGame->blue;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'red' => null !== $redUser ? $redUser->getUsername() : '',
|
'red' => null !== $redUser ? $redUser->getUsername() : '',
|
||||||
'blue' => null !== $blueUser ? $blueUser->getUsername() : '',
|
'blue' => null !== $blueUser ? $blueUser->getUsername() : '',
|
||||||
'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '',
|
'redAnon' => null !== $playedGame->redAnon ? $playedGame->redAnon->userName : '',
|
||||||
'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : '',
|
'blueAnon' => null !== $playedGame->blueAnon ? $playedGame->blueAnon->userName : '',
|
||||||
'redAvatar' => null !== $redUser && null !== $redUser->getAvatarPath()
|
'redAvatar' => null !== $redUser && null !== $redUser->avatarPath
|
||||||
? $this->cacheManager->generateUrl($redUser->getAvatarPath(), 'avatar_thumb')
|
? $this->cacheManager->generateUrl($redUser->avatarPath, 'avatar_thumb')
|
||||||
: null,
|
: null,
|
||||||
'blueAvatar' => null !== $blueUser && null !== $blueUser->getAvatarPath()
|
'blueAvatar' => null !== $blueUser && null !== $blueUser->avatarPath
|
||||||
? $this->cacheManager->generateUrl($blueUser->getAvatarPath(), 'avatar_thumb')
|
? $this->cacheManager->generateUrl($blueUser->avatarPath, 'avatar_thumb')
|
||||||
: null,
|
: null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user