Private
Public Access
1
0

chg: pkg: make a massive refactor to the backend and remove all unnecessary deps - and make small refactors for the frontend too #4

This commit is contained in:
2026-04-09 20:21:01 +02:00
parent 23547f4237
commit b55c223d8a
55 changed files with 1567 additions and 4398 deletions

View File

@@ -6,7 +6,7 @@ class MineSeeker extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
let gameAssoc = '' !== props.gameId ? props.gameId : this.makeGameAssoc(50); let gameAssoc = '' !== props.gameId ? props.gameId : crypto.randomUUID();
let channel = 'mineseeker/channel/' + gameAssoc; let channel = 'mineseeker/channel/' + gameAssoc;
this.state = { this.state = {
@@ -23,15 +23,6 @@ class MineSeeker extends React.Component {
}; };
} }
makeGameAssoc(len) {
let text = '';
let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < len; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
currectGridSize() { currectGridSize() {
let $field = $('#mine-wrapper .grid'); let $field = $('#mine-wrapper .grid');
$field.height($field.width()); $field.height($field.width());
@@ -174,27 +165,6 @@ class MineSeeker extends React.Component {
} }
} }
/**
* @see https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus
* @see https://developers.facebook.com/docs/sharing/reference/send-dialog
* @see https://developers.facebook.com/docs/plugins/share-button/
*/
clickFBShare() {
let display = 'popup';
FB.getLoginStatus(function(response) {
display = 'connected' === response.status
? 'dialog'
: 'popup';
});
FB.ui({
method: 'send',
display: display,
link: window.location.href + '/' + this.state.gameAssoc,
});
}
wInit(session, gridServer, gridClient) { wInit(session, gridServer, gridClient) {
this.setState({ session: session }); this.setState({ session: session });
@@ -227,15 +197,10 @@ class MineSeeker extends React.Component {
<div className="clippy"> <div className="clippy">
<input <input
id="foo" id="foo"
defaultValue={window.location.href + '/' + this.state.gameAssoc} defaultValue={`${window.location.href}/${this.state.gameAssoc}`}
/> />
</div> </div>
{'dev' !== this.state.env <a href={`/play/${this.state.gameAssoc}`} target="_blank">Play w/ me!</a>
&& <a onClick={this.clickFBShare.bind(this)}>Share in Facebook message</a>
}
{'dev' === this.state.env
&& <a href={'/play/' + this.state.gameAssoc} target="_blank">Play w/ me!</a>
}
</div> </div>
) : '', ) : '',
renderGridFields: this.state.gameAssoc, renderGridFields: this.state.gameAssoc,

View File

@@ -24,11 +24,7 @@ class Grid extends React.Component {
createSet(obj) { createSet(obj) {
for (let i = 0, j = this.state.row * this.state.col; i < j; i++) { for (let i = 0, j = this.state.row * this.state.col; i < j; i++) {
obj.push( obj.push(0 < this.state.mines ? 'm' : 'w');
0 < this.state.mines
? 'm'
: 'w',
);
this.state.mines--; this.state.mines--;
} }
@@ -61,15 +57,8 @@ class Grid extends React.Component {
return grid; return grid;
} }
checkMine(field, i, j) {
return 'undefined' !== typeof field[i] && 'undefined' !== typeof field[i][j] && 'm' === field[i][j];
}
isThereMine(obj, row, col) { isThereMine(obj, row, col) {
if (this.checkMine(obj, row, col)) { return 'm' === obj?.[row]?.[col] ? 1 : 0;
return 1;
}
return 0;
} }
numberingGrid(obj) { numberingGrid(obj) {

View File

@@ -5,28 +5,28 @@
"php": ">=8.1", "php": ">=8.1",
"ext-iconv": "*", "ext-iconv": "*",
"ext-json": "*", "ext-json": "*",
"doctrine/doctrine-migrations-bundle": "^2.0", "doctrine/dbal": "^3.7",
"doctrine/doctrine-bundle": ">=2.11 <2.14",
"doctrine/doctrine-migrations-bundle": "^3.0",
"doctrine/orm": "^2.6", "doctrine/orm": "^2.6",
"gos/web-socket-bundle": "^3.0", "gos/web-socket-bundle": "^3.0",
"sensio/framework-extra-bundle": "^6.0", "symfony/console": "6.4.*",
"sonata-project/admin-bundle": "^4.0",
"sonata-project/doctrine-orm-admin-bundle": "^4.0",
"sonata-project/user-bundle": "^5.0",
"symfony/console": "5.4.*",
"symfony/flex": "^2.10.0", "symfony/flex": "^2.10.0",
"symfony/framework-bundle": "5.4.*", "symfony/framework-bundle": "6.4.*",
"symfony/mailer": "5.4.*", "symfony/mailer": "6.4.*",
"symfony/monolog-bundle": "^3.8", "symfony/monolog-bundle": "^3.8",
"symfony/orm-pack": "^2.0", "symfony/security-bundle": "6.4.*",
"symfony/twig-bundle": "5.4.*", "symfony/translation": "6.4.*",
"symfony/twig-bundle": "6.4.*",
"symfony/webpack-encore-bundle": "^1.0", "symfony/webpack-encore-bundle": "^1.0",
"symfony/yaml": "5.4.*" "symfony/yaml": "6.4.*"
}, },
"require-dev": { "require-dev": {
"roave/security-advisories": "dev-master", "roave/security-advisories": "dev-master",
"symfony/dotenv": "5.4.*", "symfony/dotenv": "6.4.*",
"symfony/profiler-pack": "^1.0", "symfony/maker-bundle": "^1.5",
"symfony/maker-bundle": "^1.5" "symfony/stopwatch": "6.4.*",
"symfony/web-profiler-bundle": "6.4.*"
}, },
"config": { "config": {
"preferred-install": { "preferred-install": {
@@ -75,7 +75,7 @@
"extra": { "extra": {
"symfony": { "symfony": {
"allow-contrib": false, "allow-contrib": false,
"require": "5.4.*" "require": "6.4.*"
} }
} }
} }

3672
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,19 +8,8 @@ return [
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Knp\Bundle\MenuBundle\KnpMenuBundle::class => ['all' => true],
Sonata\Doctrine\Bridge\Symfony\SonataDoctrineBundle::class => ['all' => true],
Sonata\Exporter\Bridge\Symfony\SonataExporterBundle::class => ['all' => true],
Sonata\Form\Bridge\Symfony\Bundle\SonataFormBundle::class => ['all' => true],
Sonata\Twig\Bridge\Symfony\SonataTwigBundle::class => ['all' => true],
Sonata\BlockBundle\SonataBlockBundle::class => ['all' => true],
Sonata\AdminBundle\SonataAdminBundle::class => ['all' => true],
Sonata\UserBundle\SonataUserBundle::class => ['all' => true],
App\Application\Sonata\UserBundle\ApplicationSonataUserBundle::class => ['all' => true],
Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle::class => ['all' => true],
Gos\Bundle\PubSubRouterBundle\GosPubSubRouterBundle::class => ['all' => true], Gos\Bundle\PubSubRouterBundle\GosPubSubRouterBundle::class => ['all' => true],
Gos\Bundle\WebSocketBundle\GosWebSocketBundle::class => ['all' => true], Gos\Bundle\WebSocketBundle\GosWebSocketBundle::class => ['all' => true],
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true], Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
]; ];

View File

@@ -16,8 +16,7 @@ doctrine:
collate: utf8mb4_unicode_ci collate: utf8mb4_unicode_ci
url: '%env(resolve:DATABASE_URL)%' url: '%env(resolve:DATABASE_URL)%'
types:
json: Sonata\Doctrine\Types\JsonType
orm: orm:
auto_generate_proxy_classes: '%kernel.debug%' auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore naming_strategy: doctrine.orm.naming_strategy.underscore
@@ -25,9 +24,7 @@ doctrine:
mappings: mappings:
App: App:
is_bundle: false is_bundle: false
type: annotation type: attribute
dir: '%kernel.project_dir%/src/Entity' dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity' prefix: 'App\Entity'
alias: App alias: App
SonataUserBundle: ~
ApplicationSonataUserBundle: ~

View File

@@ -1,26 +1,14 @@
doctrine: doctrine:
orm: orm:
metadata_cache_driver: metadata_cache_driver:
type: service type: pool
id: doctrine.system_cache_provider pool: doctrine.system_cache_pool
query_cache_driver: query_cache_driver:
type: service type: pool
id: doctrine.system_cache_provider pool: doctrine.system_cache_pool
result_cache_driver: result_cache_driver:
type: service type: pool
id: doctrine.result_cache_provider pool: doctrine.result_cache_pool
services:
doctrine.result_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.result_cache_pool'
doctrine.system_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.system_cache_pool'
framework: framework:
cache: cache:

View File

@@ -1,7 +1,10 @@
security: security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers: providers:
in_memory: { memory: ~ } app_user_provider:
entity:
class: App\Entity\User
property: username
firewalls: firewalls:
dev: dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/ pattern: ^/(_(profiler|wdt)|css|images|js)/

View File

@@ -1,3 +0,0 @@
sensio_framework_extra:
router:
annotations: false

View File

@@ -1,10 +0,0 @@
sonata_admin:
title: 'Sonata Admin'
dashboard:
blocks:
- { type: sonata.admin.block.admin_list, position: left }
sonata_block:
blocks:
sonata.admin.block.admin_list:
contexts: [admin]

View File

@@ -1,3 +0,0 @@
sonata_user:
class:
user: App\Application\Sonata\UserBundle\Entity\User

View File

@@ -0,0 +1,3 @@
_security_logout:
resource: security.route_loader.logout
type: service

View File

@@ -1,8 +0,0 @@
admin_area:
resource: "@SonataAdminBundle/Resources/config/routing/sonata_admin.xml"
prefix: /admin
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin

View File

@@ -1,7 +0,0 @@
sonata_user_admin_security:
resource: '@SonataUserBundle/Resources/config/routing/admin_security.xml'
prefix: /admin
sonata_user_admin_resetting:
resource: '@SonataUserBundle/Resources/config/routing/admin_resetting.xml'
prefix: /admin/resetting

View File

@@ -22,13 +22,13 @@ services:
# this creates a service per class whose id is the fully-qualified class name # this creates a service per class whose id is the fully-qualified class name
App\: App\:
resource: '../src/*' resource: '../src/*'
exclude: '../src/{Entity,Migrations,Tests,Kernel.php,Periodic}' exclude: '../src/{Command/WebsocketServerCommand.php,Entity,Migrations,Tests,Kernel.php,Periodic}'
# controllers are imported separately to make sure services can be injected # controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class # as action arguments even if you don't extend any base controller class
App\Controller\: App\Controller\:
resource: '../src/Controller' resource: '../src/Controller'
tags: ['controller.service_arguments'] tags: [ 'controller.service_arguments' ]
# add more service definitions when explicit configuration is needed # add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones # please note that last definitions always *replace* previous ones
@@ -44,6 +44,17 @@ services:
tags: tags:
- { name: gos_web_socket.rpc } - { name: gos_web_socket.rpc }
# Override gos WebsocketServerCommand to avoid --profile conflict with Symfony 6.4 global option
gos_web_socket.command.websocket_server:
class: App\Command\WebsocketServerCommand
arguments:
- '@gos_web_socket.server.launcher'
- '%gos_web_socket.server.host%'
- '%gos_web_socket.server.port%'
- '@gos_web_socket.registry.server'
tags:
- { name: console.command, command: 'gos:websocket:server' }
gos_web_socket_server.client_event.listener: gos_web_socket_server.client_event.listener:
class: App\EventListener\MineseekerClientEventListener class: App\EventListener\MineseekerClientEventListener
tags: tags:

View File

@@ -1,7 +0,0 @@
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>

View File

View File

@@ -1,24 +0,0 @@
<?php
namespace App\Application\Sonata\UserBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* This file has been generated by the SonataEasyExtendsBundle.
*
* @link https://sonata-project.org/easy-extends
*
* References:
* @link http://symfony.com/doc/current/book/bundles.html
*/
class ApplicationSonataUserBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return 'SonataUserBundle';
}
}

View File

@@ -1,31 +0,0 @@
<?php
namespace App\Application\Sonata\UserBundle\Document;
use Sonata\UserBundle\Document\BaseUser as BaseUser;
/**
* This file has been generated by the SonataEasyExtendsBundle.
*
* @link https://sonata-project.org/easy-extends
*
* References:
* @link http://www.doctrine-project.org/docs/mongodb_odm/1.0/en/reference/working-with-objects.html
*/
class User extends BaseUser
{
/**
* @var int $id
*/
protected $id;
/**
* Get id.
*
* @return int $id
*/
public function getId()
{
return $this->id;
}
}

View File

@@ -1,31 +0,0 @@
<?php
namespace App\Application\Sonata\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
/**
* This file has been generated by the SonataEasyExtendsBundle.
*
* @link https://sonata-project.org/easy-extends
*
* References:
* @link http://www.doctrine-project.org/projects/orm/2.0/docs/reference/working-with-objects/en
*/
class User extends BaseUser
{
/**
* @var int $id
*/
protected $id;
/**
* Get id.
*
* @return int $id
*/
public function getId()
{
return $this->id;
}
}

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping
http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd">
<document name="App\Application\Sonata\UserBundle\Document\User" collection="fos_user_user" customId="true">
<field fieldName="id" id="true" strategy="INCREMENT" />
</document>
</doctrine-mongo-mapping>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="App\Application\Sonata\UserBundle\Entity\User" table="fos_user_user">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
</entity>
</doctrine-mapping>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
<!-- This file has been generated by the SonataEasyExtendsBundle: https://sonata-project.org/bundles/easy-extends -->
<class name="App\Application\Sonata\UserBundle\Document\User" exclusion-policy="all" xml-root-name="_user">
<property xml-attribute-map="true" name="id" type="integer" expose="true" since-version="1.0" groups="sonata_api_read,sonata_api_write,sonata_search"/>
</class>
</serializer>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
<!-- This file has been generated by the SonataEasyExtendsBundle: https://sonata-project.org/bundles/easy-extends -->
<class name="App\Application\Sonata\UserBundle\Entity\User" exclusion-policy="all" xml-root-name="_user">
<property xml-attribute-map="true" name="id" type="integer" expose="true" since-version="1.0" groups="sonata_api_read,sonata_api_write,sonata_search"/>
</class>
</serializer>

View File

@@ -0,0 +1,79 @@
<?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\Command;
use Gos\Bundle\WebSocketBundle\Server\App\Registry\ServerRegistry;
use Gos\Bundle\WebSocketBundle\Server\ServerLauncherInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Replaces gos WebsocketServerCommand to avoid the --profile option conflict
* introduced when Symfony 6.4 added --profile as a global console option.
*/
#[AsCommand(name: 'gos:websocket:server', description: 'Starts the websocket server')]
final class WebsocketServerCommand extends Command
{
public function __construct(
private readonly ServerLauncherInterface $serverLauncher,
private readonly string $host,
private readonly int $port,
private readonly ?ServerRegistry $serverRegistry = null,
) {
parent::__construct();
}
protected function configure(): void
{
$this
->addArgument('name', InputArgument::OPTIONAL, 'Name of the server to start, launches the first registered server if not specified')
->addOption('ws-profile', 'm', InputOption::VALUE_NONE, 'Enable profiling of the websocket server')
->addOption('host', 'a', InputOption::VALUE_OPTIONAL, 'The hostname of the websocket server')
->addOption('port', 'p', InputOption::VALUE_OPTIONAL, 'The port of the websocket server');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
/** @var string $name */
$name = $input->getArgument('name');
/** @var string $host */
$host = null === $input->getOption('host') ? $this->host : $input->getOption('host');
/** @var int|string $port */
$port = null === $input->getOption('port') ? $this->port : $input->getOption('port');
if (!is_numeric($port)) {
throw new InvalidArgumentException('The port option must be a numeric value.');
}
/** @var bool $profile */
$profile = (bool) $input->getOption('ws-profile');
$this->serverLauncher->launch($name, $host, (int) $port, $profile);
return 0;
}
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestArgumentValuesFor('name') && null !== $this->serverRegistry) {
$suggestions->suggestValues(array_keys($this->serverRegistry->getServers()));
}
}
}

View File

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -12,83 +12,56 @@ namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
/** /**
* Class GameController * Class GameController
* *
* @package App\Controller * @package App\Controller
* @author system7 <https://www.splendidbear.org> * @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. 09.
*/ */
class GameController extends AbstractController class GameController extends AbstractController
{ {
public function __construct( public function __construct(
#[Autowire(env: 'APP_ENV')] #[Autowire(env: 'APP_ENV')]
private readonly string $env, private readonly string $env,
private readonly RequestStack $request,
) { ) {
} }
/**
* It is the homepage
*
* @return Response
*/
public function index(): Response public function index(): Response
{ {
return $this->render('Game/index.html.twig'); return $this->render('Game/index.html.twig');
} }
/** public function play(): Response
* It is the game itself
*
* @param Request $request
*
* @return Response
*/
public function play(Request $request): Response
{ {
return $this->render('Game/play.html.twig', array( return $this->render('Game/play.html.twig', [
'env' => $this->env, 'env' => $this->env,
'ssl' => $request->isSecure() ? 'true' : 'false', 'ssl' => $this->request->getCurrentRequest()->isSecure() ? 'true' : 'false',
)); ]);
} }
/**
* It is the Privacy & Policy
*
* @return Response
*/
public function privacy(): Response public function privacy(): Response
{ {
return $this->render('Official/privacy.html.twig'); return $this->render('Official/privacy.html.twig');
} }
/**
* It is the Terms of Use
*
* @return Response
*/
public function terms(): Response public function terms(): Response
{ {
return $this->render('Official/terms.html.twig'); return $this->render('Official/terms.html.twig');
} }
/**
* It is the contact informations
*
* @return Response
*/
public function contact(): Response public function contact(): Response
{ {
return $this->render('Official/contact.html.twig'); return $this->render('Official/contact.html.twig');
} }
/**
* It is a landing page
*
* @return Response
*/
public function landing(): Response public function landing(): Response
{ {
return $this->render('Official/landing.html.twig'); return $this->render('Official/landing.html.twig');

View File

@@ -0,0 +1,63 @@
<?php declare(strict_types=1);
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2024 @ www.splendidbear.org
*
* For the full copyright and licence information, please view the LICENCE
* file that was distributed with this source code.
*/
namespace App\Doctrine;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Schema\PostgreSQLSchemaManager;
use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
use Doctrine\ORM\Tools\ToolEvents;
use RuntimeException;
/**
* Class FixPostgreMigrationDefaultSchemaListener
*
* @package App\Doctrine
* @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 2023. 02. 28.
*
* @see https://github.com/doctrine/dbal/issues/1110
* There is a recent bug when you create new migration, it creates a new schema even if there is no any
* changes.
*/
#[AsDoctrineListener(event: ToolEvents::postGenerateSchema, priority: 500, connection: 'default')]
final class FixPostgreMigrationDefaultSchemaListener
{
public function postGenerateSchema(GenerateSchemaEventArgs $args): void
{
try {
$schemaManager = $args
->getEntityManager()
->getConnection()
->createSchemaManager();
if (!$schemaManager instanceof PostgreSqlSchemaManager) {
return;
}
$schema = $args->getSchema();
foreach ($schemaManager->getExistingSchemaSearchPaths() as $namespace) {
if ($schema->hasNamespace($namespace)) {
continue;
}
$schema->createNamespace($namespace);
}
} catch (SchemaException|Exception $e) {
throw new RuntimeException($e->getMessage());
}
}
}

View File

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -10,166 +10,97 @@
namespace App\Entity; namespace App\Entity;
use Doctrine\ORM\Mapping as ORM; use App\Repository\GamerRepository;
use DateTime;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
/** /**
* Class Gamer * Class Gamer
* *
* @package App\Entity * @package App\Entity
* @author system7 <https://www.splendidbear.org> * @author Lang <https://www.splendidbear.org>
* * @category Class
* @ORM\Entity(repositoryClass="App\Repository\GamerRepository") * @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/ */
#[Entity(repositoryClass: GamerRepository::class)]
class Gamer class Gamer
{ {
/** #[Id, GeneratedValue, Column]
* @ORM\Id() private ?int $id = null;
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/** #[Column(length: 100)]
* @var string|null private ?string $userName = null;
*
* @ORM\Column(name="user_name", type="string", length=100, nullable=false)
*/
private $userName;
/** #[Column(length: 20, nullable: true)]
* @var string|null private ?string $ip = null;
*
* @ORM\Column(name="ip", type="string", length=20, nullable=true)
*/
private $ip;
/** #[Column(length: 100, nullable: true)]
* TODO private ?string $country = null;
* $ip='0.0.0.0';
* $ip=$_SERVER['REMOTE_ADDR'];
* $clientDetails = json_decode(file_get_contents("http://ipinfo.io/$ip/json"));
* echo "You're logged in from: <b>" . $clientDetails->country . "</b>";
*
* function GetIP()
* {
* if ( getenv("HTTP_CLIENT_IP") ) {
* $ip = getenv("HTTP_CLIENT_IP");
* } elseif ( getenv("HTTP_X_FORWARDED_FOR") ) {
* $ip = getenv("HTTP_X_FORWARDED_FOR");
* if ( strstr($ip, ',') ) {
* $tmp = explode(',', $ip);
* $ip = trim($tmp[0]);
* }
* } else {
* $ip = getenv("REMOTE_ADDR");
* }
* return $ip;
* }
*/
/** #[Column(nullable: true)]
* @var string private ?string $userAgent = null;
*
* @ORM\Column(name="country", type="string", length=100, nullable=true)
*/
private $country;
/** #[Column(type: Types::DATETIME_MUTABLE)]
* @var string private ?DateTime $connTimestamp = null;
* @see http://symfony.com/doc/current/components/http_foundation.html
*
* @ORM\Column(name="user_agent", type="string", length=255, nullable=true)
*/
private $userAgent;
/**
* @var \DateTime
*
* @ORM\Column(name="conn_timestamp", type="datetime", nullable=false)
*/
private $connTimestamp;
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
} }
/**
* @return string|null
*/
public function getUserName(): ?string public function getUserName(): ?string
{ {
return $this->userName; return $this->userName;
} }
/**
* @param string|null $userName
*/
public function setUserName(?string $userName): void public function setUserName(?string $userName): void
{ {
$this->userName = $userName; $this->userName = $userName;
} }
/**
* @return string|null
*/
public function getIp(): ?string public function getIp(): ?string
{ {
return $this->ip; return $this->ip;
} }
/**
* @param string|null $ip
*/
public function setIp(?string $ip): void public function setIp(?string $ip): void
{ {
$this->ip = $ip; $this->ip = $ip;
} }
/** public function getCountry(): ?string
* @return string
*/
public function getCountry(): string
{ {
return $this->country; return $this->country;
} }
/** public function setCountry(?string $country): void
* @param string $country
*/
public function setCountry(string $country): void
{ {
$this->country = $country; $this->country = $country;
} }
/** public function getUserAgent(): ?string
* @return string
*/
public function getUserAgent(): string
{ {
return $this->userAgent; return $this->userAgent;
} }
/** public function setUserAgent(?string $userAgent): void
* @param string $userAgent
*/
public function setUserAgent(string $userAgent): void
{ {
$this->userAgent = $userAgent; $this->userAgent = $userAgent;
} }
/** public function getConnTimestamp(): ?DateTime
* @return \DateTime
*/
public function getConnTimestamp(): \DateTime
{ {
return $this->connTimestamp; return $this->connTimestamp;
} }
/** public function setConnTimestamp(?DateTime $connTimestamp): void
* @param \DateTime $connTimestamp
*/
public function setConnTimestamp(\DateTime $connTimestamp): void
{ {
$this->connTimestamp = $connTimestamp; $this->connTimestamp = $connTimestamp;
} }

View File

@@ -1,8 +1,8 @@
<?php <?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) 2019 @ www.splendidbear.org * Copyright (c) 2026 @ www.splendidbear.org
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@@ -10,74 +10,74 @@
namespace App\Entity; namespace App\Entity;
use Doctrine\ORM\Mapping as ORM; use App\Repository\GridRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\ORM\Mapping\OneToOne;
/** /**
* Class Grid * Class Grid
* *
* @package App\Entity * @package App\Entity
* @author system7 <https://www.splendidbear.org> * @author Lang <https://www.splendidbear.org>
* * @category Class
* @ORM\Entity(repositoryClass="App\Repository\GridRepository") * @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/ */
#[Entity(repositoryClass: GridRepository::class)]
class Grid class Grid
{ {
/** #[Id, GeneratedValue, Column]
* @ORM\Id() private ?int $id = null;
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/** #[OneToOne(inversedBy: 'grid', cascade: ['persist'])]
* @var PlayedGame|null private ?PlayedGame $playedGame = null;
*
* @ORM\OneToOne(targetEntity="App\Entity\PlayedGame", inversedBy="grid", cascade={"persist"})
*/
private $playedGame;
/** #[OneToMany(mappedBy: 'grid', targetEntity: GridRow::class, cascade: ['persist'])]
* @var GridRow|null #[JoinColumn(name: 'grid_row', referencedColumnName: 'id', onDelete: 'CASCADE')]
* private Collection $gridRow;
* @ORM\OneToMany(targetEntity="App\Entity\GridRow", mappedBy="grid", cascade={"persist"})
* @ORM\JoinColumn(name="grid_row", referencedColumnName="id", onDelete="CASCADE")
*/ public function __construct()
private $gridRow; {
$this->gridRow = new ArrayCollection();
}
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
} }
/** public function getPlayedGame(): ?PlayedGame
* @return PlayedGame|null
*/
public function getPlayedGame()
{ {
return $this->playedGame; return $this->playedGame;
} }
/** public function setPlayedGame(?PlayedGame $playedGame): void
* @param PlayedGame|null $playedGame
*/
public function setPlayedGame( $playedGame): void
{ {
$this->playedGame = $playedGame; $this->playedGame = $playedGame;
} }
/** public function getGridRow(): Collection
* @return GridRow|null
*/
public function getGridRow()
{ {
return $this->gridRow; return $this->gridRow;
} }
/** public function addGridRow(GridRow $gridRow): void
* @param GridRow|null $gridRow
*/
public function setGridRow( $gridRow): void
{ {
$this->gridRow = $gridRow; $this->gridRow->add($gridRow);
$gridRow->setGrid($this);
}
public function removeGridRow(GridRow $gridRow): void
{
$this->gridRow->removeElement($gridRow);
} }
} }

View File

@@ -1,8 +1,8 @@
<?php <?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) 2019 @ www.splendidbear.org * Copyright (c) 2026 @ www.splendidbear.org
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@@ -10,73 +10,60 @@
namespace App\Entity; namespace App\Entity;
use Doctrine\ORM\Mapping as ORM; use App\Repository\GridRowRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\ManyToOne;
/** /**
* Class GridRow * Class GridRow
* *
* @package App\Entity * @package App\Entity
* @author system7 <https://www.splendidbear.org> * @author Lang <https://www.splendidbear.org>
* * @category Class
* @ORM\Entity(repositoryClass="App\Repository\GridRowRepository") * @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/ */
#[Entity(repositoryClass: GridRowRepository::class)]
class GridRow class GridRow
{ {
/** #[Id, GeneratedValue, Column]
* @ORM\Id() private ?int $id = null;
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/** #[ManyToOne(cascade: ['persist'], inversedBy: 'gridRow')]
* @var Grid|null #[JoinColumn(name: 'grid', referencedColumnName: 'id', onDelete: 'CASCADE')]
* private ?Grid $grid = null;
* @ORM\ManyToOne(targetEntity="App\Entity\Grid", inversedBy="gridRow", cascade={"persist"})
* @ORM\JoinColumn(name="grid", referencedColumnName="id", onDelete="CASCADE") #[Column(name: 'grid_col', type: Types::JSON, nullable: false)]
*/ private ?array $gridCol = null;
private $grid;
/**
* @var array|null
*
* @ORM\Column(name="grid_col", type="json_array", nullable=false)
*/
private $gridCol;
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
} }
/** public function getGrid(): ?Grid
* @return Grid|null
*/
public function getGrid()
{ {
return $this->grid; return $this->grid;
} }
/** public function setGrid(?Grid $grid): void
* @param Grid|null $grid
*/
public function setGrid( $grid): void
{ {
$this->grid = $grid; $this->grid = $grid;
} }
/** public function getGridCol(): ?array
* @return array|null
*/
public function getGridCol()
{ {
return $this->gridCol; return $this->gridCol;
} }
/** public function setGridCol(?array $gridCol): void
* @param array|null $gridCol
*/
public function setGridCol($gridCol): void
{ {
$this->gridCol = $gridCol; $this->gridCol = $gridCol;
} }

View File

@@ -1,8 +1,8 @@
<?php <?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) 2019 @ www.splendidbear.org * Copyright (c) 2026 @ www.splendidbear.org
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@@ -10,355 +10,242 @@
namespace App\Entity; namespace App\Entity;
use App\Application\Sonata\UserBundle\Entity\User; use App\Repository\PlayedGameRepository;
use Doctrine\ORM\Mapping as ORM; use DateTime;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToOne;
/** /**
* Class PlayedGame * Class PlayedGame
* *
* @package App\Entity * @package App\Entity
* @author system7 <https://www.splendidbear.org> * @author Lang <https://www.splendidbear.org>
* * @category Class
* @ORM\Entity(repositoryClass="App\Repository\PlayedGameRepository") * @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/ */
#[Entity(repositoryClass: PlayedGameRepository::class)]
class PlayedGame class PlayedGame
{ {
/** #[Id, GeneratedValue, Column]
* @ORM\Id() private ?int $id = null;
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/** #[Column(length: 50)]
* @var string|null private ?string $gameAssoc = null;
*
* @ORM\Column(name="game_assoc", type="string", length=50, nullable=false)
*/
private $gameAssoc;
/** #[Column(length: 5, nullable: true)]
* @var Grid|null private ?int $redPoints = null;
*
* @ORM\OneToOne(targetEntity="App\Entity\Grid", mappedBy="playedGame", cascade={"persist"})
*/
private $grid;
/** #[Column(length: 5, nullable: true)]
* @var User|null private ?int $bluePoints = null;
*
* @ORM\ManyToOne(targetEntity="App\Application\Sonata\UserBundle\Entity\User")
* @ORM\JoinColumn(name="red_id", referencedColumnName="id", nullable=true)
*/
private $red;
/** #[Column(nullable: true)]
* @var Gamer|null private ?bool $redExplodedBomb = null;
*
* @ORM\ManyToOne(targetEntity="App\Entity\Gamer")
* @ORM\JoinColumn(name="red_anon", referencedColumnName="id", nullable=true)
*/
private $redAnon;
/** #[Column(nullable: true)]
* @var User|null private ?bool $blueExplodedBomb = null;
*
* @ORM\ManyToOne(targetEntity="App\Application\Sonata\UserBundle\Entity\User")
* @ORM\JoinColumn(name="blue_id", referencedColumnName="id", nullable=true)
*/
private $blue;
/** #[Column(length: 7, nullable: true)]
* @var Gamer|null private ?string $resign = null;
*
* @ORM\ManyToOne(targetEntity="App\Entity\Gamer")
* @ORM\JoinColumn(name="blue_anon", referencedColumnName="id", nullable=true)
*/
private $blueAnon;
/** #[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
* @var int|null private ?DateTime $created = null;
*
* @ORM\Column(name="red_points", type="integer", length=5, nullable=true)
*/
private $redPoints;
/** #[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
* @var int|null private ?DateTime $updated = null;
*
* @ORM\Column(name="blue_points", type="integer", length=5, nullable=true)
*/
private $bluePoints;
/** #[OneToOne(mappedBy: 'playedGame', cascade: ['persist'])]
* @var boolean|null private ?Grid $grid = null;
*
* @ORM\Column(name="red_exploded_bomb", type="boolean", nullable=true)
*/
private $redExplodedBomb;
/** #[ManyToOne]
* @var boolean|null #[JoinColumn(name: 'red_id', referencedColumnName: 'id', nullable: true)]
* private ?User $red = null;
* @ORM\Column(name="blue_exploded_bomb", type="boolean", nullable=true)
*/
private $blueExplodedBomb;
/** #[ManyToOne]
* @var string|null #[JoinColumn(name: 'red_anon', referencedColumnName: 'id', nullable: true)]
* private ?Gamer $redAnon = null;
* @ORM\Column(name="resign", type="string", length=7, nullable=true)
*/
private $resign;
/** #[ManyToOne]
* @var \DateTime|null #[JoinColumn(name: 'blue_id', referencedColumnName: 'id', nullable: true)]
* private ?User $blue = null;
* @ORM\Column(name="created", type="datetime", nullable=true)
*/
private $created;
/** #[ManyToOne]
* @var \DateTime|null #[JoinColumn(name: 'blue_anon', referencedColumnName: 'id', nullable: true)]
* private ?Gamer $blueAnon = null;
* @ORM\Column(name="updated", type="datetime", nullable=true)
*/ #[OneToOne(mappedBy: 'playedGame')]
private $updated; private ?Step $step = null;
/**
* @var Step|null
*
* @ORM\OneToMany(targetEntity="App\Entity\Step", mappedBy="playedGame")
* @ORM\JoinColumn(name="step", referencedColumnName="id", nullable=true)
*/
private $step;
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
} }
/** public function setId(?int $id): self
* @return string|null {
*/ $this->id = $id;
return $this;
}
public function getGameAssoc(): ?string public function getGameAssoc(): ?string
{ {
return $this->gameAssoc; return $this->gameAssoc;
} }
/** public function setGameAssoc(?string $gameAssoc): self
* @param string|null $gameAssoc
*/
public function setGameAssoc(?string $gameAssoc): void
{ {
$this->gameAssoc = $gameAssoc; $this->gameAssoc = $gameAssoc;
return $this;
} }
/**
* @return Grid|null
*/
public function getGrid()
{
return $this->grid;
}
/**
* @param Grid|null $grid
*/
public function setGrid( $grid): void
{
$this->grid = $grid;
}
/**
* @return User|null
*/
public function getRed()
{
return $this->red;
}
/**
* @param User|null $red
*/
public function setRed( $red): void
{
$this->red = $red;
}
/**
* @return Gamer|null
*/
public function getRedAnon()
{
return $this->redAnon;
}
/**
* @param Gamer|null $redAnon
*/
public function setRedAnon( $redAnon): void
{
$this->redAnon = $redAnon;
}
/**
* @return User|null
*/
public function getBlue()
{
return $this->blue;
}
/**
* @param User|null $blue
*/
public function setBlue( $blue): void
{
$this->blue = $blue;
}
/**
* @return Gamer|null
*/
public function getBlueAnon()
{
return $this->blueAnon;
}
/**
* @param Gamer|null $blueAnon
*/
public function setBlueAnon( $blueAnon): void
{
$this->blueAnon = $blueAnon;
}
/**
* @return int|null
*/
public function getRedPoints(): ?int public function getRedPoints(): ?int
{ {
return $this->redPoints; return $this->redPoints;
} }
/** public function setRedPoints(?int $redPoints): self
* @param int|null $redPoints
*/
public function setRedPoints(?int $redPoints): void
{ {
$this->redPoints = $redPoints; $this->redPoints = $redPoints;
return $this;
} }
/**
* @return int|null
*/
public function getBluePoints(): ?int public function getBluePoints(): ?int
{ {
return $this->bluePoints; return $this->bluePoints;
} }
/** public function setBluePoints(?int $bluePoints): self
* @param int|null $bluePoints
*/
public function setBluePoints(?int $bluePoints): void
{ {
$this->bluePoints = $bluePoints; $this->bluePoints = $bluePoints;
return $this;
} }
/**
* @return bool|null
*/
public function getRedExplodedBomb(): ?bool public function getRedExplodedBomb(): ?bool
{ {
return $this->redExplodedBomb; return $this->redExplodedBomb;
} }
/** public function setRedExplodedBomb(?bool $redExplodedBomb): self
* @param bool|null $redExplodedBomb
*/
public function setRedExplodedBomb(?bool $redExplodedBomb): void
{ {
$this->redExplodedBomb = $redExplodedBomb; $this->redExplodedBomb = $redExplodedBomb;
return $this;
} }
/**
* @return bool|null
*/
public function getBlueExplodedBomb(): ?bool public function getBlueExplodedBomb(): ?bool
{ {
return $this->blueExplodedBomb; return $this->blueExplodedBomb;
} }
/** public function setBlueExplodedBomb(?bool $blueExplodedBomb): self
* @param bool|null $blueExplodedBomb
*/
public function setBlueExplodedBomb(?bool $blueExplodedBomb): void
{ {
$this->blueExplodedBomb = $blueExplodedBomb; $this->blueExplodedBomb = $blueExplodedBomb;
return $this;
} }
/**
* @return string|null
*/
public function getResign(): ?string public function getResign(): ?string
{ {
return $this->resign; return $this->resign;
} }
/** public function setResign(?string $resign): self
* @param string|null $resign
*/
public function setResign(?string $resign): void
{ {
$this->resign = $resign; $this->resign = $resign;
return $this;
} }
/** public function getCreated(): ?DateTime
* @return \DateTime|null
*/
public function getCreated(): ?\DateTime
{ {
return $this->created; return $this->created;
} }
/** public function setCreated(?DateTime $created): self
* @param \DateTime|null $created
*/
public function setCreated(?\DateTime $created): void
{ {
$this->created = $created; $this->created = $created;
return $this;
} }
/** public function getUpdated(): ?DateTime
* @return \DateTime|null
*/
public function getUpdated(): ?\DateTime
{ {
return $this->updated; return $this->updated;
} }
/** public function setUpdated(?DateTime $updated): self
* @param \DateTime|null $updated
*/
public function setUpdated(?\DateTime $updated): void
{ {
$this->updated = $updated; $this->updated = $updated;
return $this;
} }
/** public function getGrid(): ?Grid
* @return Step|null {
*/ return $this->grid;
public function getStep() }
public function setGrid(?Grid $grid): self
{
$this->grid = $grid;
return $this;
}
public function getRed(): ?User
{
return $this->red;
}
public function setRed(?User $red): self
{
$this->red = $red;
return $this;
}
public function getRedAnon(): ?Gamer
{
return $this->redAnon;
}
public function setRedAnon(?Gamer $redAnon): self
{
$this->redAnon = $redAnon;
return $this;
}
public function getBlue(): ?User
{
return $this->blue;
}
public function setBlue(?User $blue): self
{
$this->blue = $blue;
return $this;
}
public function getBlueAnon(): ?Gamer
{
return $this->blueAnon;
}
public function setBlueAnon(?Gamer $blueAnon): self
{
$this->blueAnon = $blueAnon;
return $this;
}
public function getStep(): ?Step
{ {
return $this->step; return $this->step;
} }
/** public function setStep(?Step $step): self
* @param Step|null $step
*/
public function setStep( $step): void
{ {
$this->step = $step; $this->step = $step;
return $this;
} }
} }

View File

@@ -1,8 +1,8 @@
<?php <?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) 2019 @ www.splendidbear.org * Copyright (c) 2026 @ www.splendidbear.org
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
@@ -10,141 +10,98 @@
namespace App\Entity; namespace App\Entity;
use Doctrine\ORM\Mapping as ORM; use App\Repository\StepRepository;
use DateTime;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\ManyToOne;
/** /**
* Class Step * Class Step
* *
* @package App\Entity * @package App\Entity
* @author system7 <https://www.splendidbear.org> * @author Lang <https://www.splendidbear.org>
* * @category Class
* @ORM\Entity(repositoryClass="App\Repository\StepRepository") * @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/ */
#[Entity(repositoryClass: StepRepository::class)]
class Step class Step
{ {
/** #[Id, GeneratedValue, Column]
* @ORM\Id() private ?int $id = null;
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/** #[Column(length: 3)]
* @var int|null private ?int $row = null;
*
* @ORM\Column(name="row", length=3, type="integer", nullable=false)
*/
private $row;
/** #[Column(length: 3)]
* @var int|null private ?int $col = null;
*
* @ORM\Column(name="col", length=3, type="integer", nullable=false)
*/
private $col;
/** #[Column(nullable: true)]
* @var boolean|null private ?bool $wBomb = null;
*
* @ORM\Column(name="wbomb", type="boolean", nullable=true)
*/
private $wBomb;
/** #[ManyToOne(inversedBy: 'step')]
* @var PlayedGame|null private ?PlayedGame $playedGame = null;
*
* @ORM\ManyToOne(targetEntity="App\Entity\PlayedGame", inversedBy="step") #[Column(type: Types::DATETIME_MUTABLE, nullable: true)]
*/ private ?DateTime $created = null;
private $playedGame;
/**
* @var \DateTime|null
*
* @ORM\Column(name="created", type="datetime", nullable=true)
*/
private $created;
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
} }
/**
* @return int|null
*/
public function getRow(): ?int public function getRow(): ?int
{ {
return $this->row; return $this->row;
} }
/**
* @param int|null $row
*/
public function setRow(?int $row): void public function setRow(?int $row): void
{ {
$this->row = $row; $this->row = $row;
} }
/**
* @return int|null
*/
public function getCol(): ?int public function getCol(): ?int
{ {
return $this->col; return $this->col;
} }
/**
* @param int|null $col
*/
public function setCol(?int $col): void public function setCol(?int $col): void
{ {
$this->col = $col; $this->col = $col;
} }
/**
* @return bool|null
*/
public function getWBomb(): ?bool public function getWBomb(): ?bool
{ {
return $this->wBomb; return $this->wBomb;
} }
/**
* @param bool|null $wBomb
*/
public function setWBomb(?bool $wBomb): void public function setWBomb(?bool $wBomb): void
{ {
$this->wBomb = $wBomb; $this->wBomb = $wBomb;
} }
/**
* @return PlayedGame|null
*/
public function getPlayedGame(): ?PlayedGame public function getPlayedGame(): ?PlayedGame
{ {
return $this->playedGame; return $this->playedGame;
} }
/**
* @param PlayedGame|null $playedGame
*/
public function setPlayedGame(?PlayedGame $playedGame): void public function setPlayedGame(?PlayedGame $playedGame): void
{ {
$this->playedGame = $playedGame; $this->playedGame = $playedGame;
} }
/** public function getCreated(): ?DateTime
* @return \DateTime|null
*/
public function getCreated(): ?\DateTime
{ {
return $this->created; return $this->created;
} }
/** public function setCreated(?DateTime $created): void
* @param \DateTime|null $created
*/
public function setCreated(?\DateTime $created): void
{ {
$this->created = $created; $this->created = $created;
} }

95
src/Entity/User.php Normal file
View File

@@ -0,0 +1,95 @@
<?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\Entity;
use App\Repository\UserRepository;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Class User
*
* @package App\Entity
* @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. 09.
*/
#[Entity(repositoryClass: UserRepository::class)]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[Id, GeneratedValue, Column]
private ?int $id = null;
#[Column(length: 180, unique: true)]
private ?string $username = null;
#[Column]
private array $roles = [];
#[Column(nullable: true)]
private ?string $password = null;
public function getId(): ?int
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getUserIdentifier(): string
{
return (string) $this->username;
}
public function getRoles(): array
{
$roles = $this->roles;
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(?string $password): self
{
$this->password = $password;
return $this;
}
public function eraseCredentials(): void
{
}
}

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -20,21 +20,23 @@ use Gos\Bundle\WebSocketBundle\Event\ServerLaunchedEvent;
* Class MineseekerClientEventListener * Class MineseekerClientEventListener
* *
* @package App\EventListener * @package App\EventListener
* @author system7 <https://www.splendidbear.org> * @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. 09.
*/ */
class MineseekerClientEventListener class MineseekerClientEventListener
{ {
public function onClientConnect(ClientConnectedEvent $event): void public function onClientConnect(ClientConnectedEvent $event): void
{ {
$conn = $event->getConnection(); $conn = $event->getConnection();
echo $conn->resourceId . ' connected' . PHP_EOL; echo $conn->resourceId . ' connected' . PHP_EOL;
} }
public function onClientDisconnect(ClientDisconnectedEvent $event): void public function onClientDisconnect(ClientDisconnectedEvent $event): void
{ {
$conn = $event->getConnection(); $conn = $event->getConnection();
echo $conn->resourceId . ' disconnected' . PHP_EOL; echo $conn->resourceId . ' disconnected' . PHP_EOL;
} }
@@ -42,7 +44,6 @@ class MineseekerClientEventListener
{ {
$conn = $event->getConnection(); $conn = $event->getConnection();
$e = $event->getException(); $e = $event->getException();
echo 'connection error occurred: ' . $e->getMessage() . PHP_EOL; echo 'connection error occurred: ' . $e->getMessage() . PHP_EOL;
} }
@@ -54,7 +55,6 @@ class MineseekerClientEventListener
public function onClientRejected(ClientRejectedEvent $event): void public function onClientRejected(ClientRejectedEvent $event): void
{ {
$origin = $event->getOrigin(); $origin = $event->getOrigin();
echo 'connection rejected from ' . $origin . PHP_EOL; echo 'connection rejected from ' . $origin . PHP_EOL;
} }
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -8,28 +8,21 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace App\Util\Interfaces; namespace App\Interfaces;
/** /**
* Interface RpcManagerInterface * Interface RpcManagerInterface
*
* @package App\Interfaces
* @author Lang <https://www.splendidbear.org>
* @category Interface
* @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/ */
interface RpcManagerInterface interface RpcManagerInterface
{ {
/**
* Gets all connect informations
*
* @param $params
*
* @return string
*/
public function getConnectInformation($params): string; public function getConnectInformation($params): string;
/**
* It saves the whole grid table to database
*
* @param $data
*
* @return boolean
*/
public function saveGrid($data): bool; public function saveGrid($data): bool;
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -8,38 +8,26 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace App\Util\Interfaces; namespace App\Interfaces;
use Ratchet\ConnectionInterface; use Ratchet\ConnectionInterface;
use Ratchet\Wamp\Topic; use Ratchet\Wamp\Topic;
/** /**
* Interfaces TopicManagerInterface * Interface TopicManagerInterface
*
* @package App\Interfaces
* @author Lang <https://www.splendidbear.org>
* @category Interface
* @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/ */
interface TopicManagerInterface interface TopicManagerInterface
{ {
/**
* It handles the subscribe to a topic
*
* @param Topic $topic
* @param ConnectionInterface $connection
*/
public function subscribe(Topic $topic, ConnectionInterface $connection): void; public function subscribe(Topic $topic, ConnectionInterface $connection): void;
/**
* It handles the unsibscribe from the topic
*
* @param Topic $topic
* @param ConnectionInterface $connection
*/
public function unSubscribe(Topic $topic, ConnectionInterface $connection): void; public function unSubscribe(Topic $topic, ConnectionInterface $connection): void;
/**
* It publishes events on the topic
*
* @param Topic $topic
* @param ConnectionInterface $connection
* @param $event
*/
public function publish(Topic $topic, ConnectionInterface $connection, $event): void; public function publish(Topic $topic, ConnectionInterface $connection, $event): void;
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -8,21 +8,21 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace App\Util\Interfaces; namespace App\Interfaces;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
/** /**
* Interfaces WebsocketManagerInterface * Interface WebsocketManagerInterface
*
* @package App\Interfaces
* @author Lang <https://www.splendidbear.org>
* @category Interface
* @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/ */
interface WebsocketManagerInterface interface WebsocketManagerInterface
{ {
/**
* Handle prod MySQL timeout
*
* @param EntityManagerInterface $entityManager
*
* @return EntityManagerInterface|null
*/
public function reConnect(EntityManagerInterface $entityManager): ?EntityManagerInterface; public function reConnect(EntityManagerInterface $entityManager): ?EntityManagerInterface;
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
namespace App; namespace App;

View File

@@ -1,6 +1,12 @@
<?php <?php declare(strict_types=1);
/*
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; namespace App\Migrations;
@@ -8,77 +14,73 @@ use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration; use Doctrine\Migrations\AbstractMigration;
/** /**
* Auto-generated Migration: Please modify to your needs! * Class Version20260409175831
*
* @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. 09.
*/ */
final class Version20260409081936 extends AbstractMigration final class Version20260409175831 extends AbstractMigration
{ {
public function getDescription() : string public function getDescription(): string
{ {
return ''; return 'Initialize the database for 2026';
} }
public function up(Schema $schema) : void public function up(Schema $schema): void
{ {
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE SEQUENCE fos_user_user_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE gamer_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); $this->addSql('CREATE SEQUENCE gamer_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE grid_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); $this->addSql('CREATE SEQUENCE grid_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE grid_row_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); $this->addSql('CREATE SEQUENCE grid_row_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE played_game_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); $this->addSql('CREATE SEQUENCE played_game_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE step_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); $this->addSql('CREATE SEQUENCE step_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE fos_user_user (id INT NOT NULL, username VARCHAR(180) NOT NULL, username_canonical VARCHAR(180) NOT NULL, email VARCHAR(180) NOT NULL, email_canonical VARCHAR(180) NOT NULL, enabled BOOLEAN NOT NULL, salt VARCHAR(255) DEFAULT NULL, password VARCHAR(255) NOT NULL, last_login TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, confirmation_token VARCHAR(180) DEFAULT NULL, password_requested_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, roles TEXT NOT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE SEQUENCE user_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE UNIQUE INDEX UNIQ_C560D76192FC23A8 ON fos_user_user (username_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_C560D761A0D96FBF ON fos_user_user (email_canonical)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_C560D761C05FB297 ON fos_user_user (confirmation_token)');
$this->addSql('COMMENT ON COLUMN fos_user_user.roles IS \'(DC2Type:array)\'');
$this->addSql('CREATE TABLE gamer (id INT NOT NULL, user_name VARCHAR(100) NOT NULL, ip VARCHAR(20) DEFAULT NULL, country VARCHAR(100) DEFAULT NULL, user_agent VARCHAR(255) DEFAULT NULL, conn_timestamp TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE TABLE gamer (id INT NOT NULL, user_name VARCHAR(100) NOT NULL, ip VARCHAR(20) DEFAULT NULL, country VARCHAR(100) DEFAULT NULL, user_agent VARCHAR(255) DEFAULT NULL, conn_timestamp TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE grid (id INT NOT NULL, played_game_id INT DEFAULT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE TABLE grid (id INT NOT NULL, played_game_id INT DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_2E20D9375AA11DBB ON grid (played_game_id)'); $this->addSql('CREATE UNIQUE INDEX UNIQ_2E20D9375AA11DBB ON grid (played_game_id)');
$this->addSql('CREATE TABLE grid_row (id INT NOT NULL, grid INT DEFAULT NULL, grid_col JSON NOT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE TABLE grid_row (id INT NOT NULL, grid INT DEFAULT NULL, grid_col JSON NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_6FAD08EB2E20D937 ON grid_row (grid)'); $this->addSql('CREATE INDEX IDX_6FAD08EB2E20D937 ON grid_row (grid)');
$this->addSql('COMMENT ON COLUMN grid_row.grid_col IS \'(DC2Type:json_array)\'');
$this->addSql('CREATE TABLE played_game (id INT NOT NULL, red_id INT DEFAULT NULL, red_anon INT DEFAULT NULL, blue_id INT DEFAULT NULL, blue_anon INT DEFAULT NULL, game_assoc VARCHAR(50) NOT NULL, red_points INT DEFAULT NULL, blue_points INT DEFAULT NULL, red_exploded_bomb BOOLEAN DEFAULT NULL, blue_exploded_bomb BOOLEAN DEFAULT NULL, resign VARCHAR(7) DEFAULT NULL, created TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, updated TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE TABLE played_game (id INT NOT NULL, red_id INT DEFAULT NULL, red_anon INT DEFAULT NULL, blue_id INT DEFAULT NULL, blue_anon INT DEFAULT NULL, game_assoc VARCHAR(50) NOT NULL, red_points INT DEFAULT NULL, blue_points INT DEFAULT NULL, red_exploded_bomb BOOLEAN DEFAULT NULL, blue_exploded_bomb BOOLEAN DEFAULT NULL, resign VARCHAR(7) DEFAULT NULL, created TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, updated TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_54BE80398BBE8922 ON played_game (red_id)'); $this->addSql('CREATE INDEX IDX_54BE80398BBE8922 ON played_game (red_id)');
$this->addSql('CREATE INDEX IDX_54BE8039F24372EB ON played_game (red_anon)'); $this->addSql('CREATE INDEX IDX_54BE8039F24372EB ON played_game (red_anon)');
$this->addSql('CREATE INDEX IDX_54BE80395AB9393F ON played_game (blue_id)'); $this->addSql('CREATE INDEX IDX_54BE80395AB9393F ON played_game (blue_id)');
$this->addSql('CREATE INDEX IDX_54BE8039C64E7C7C ON played_game (blue_anon)'); $this->addSql('CREATE INDEX IDX_54BE8039C64E7C7C ON played_game (blue_anon)');
$this->addSql('CREATE TABLE step (id INT NOT NULL, played_game_id INT DEFAULT NULL, row INT NOT NULL, col INT NOT NULL, wbomb BOOLEAN DEFAULT NULL, created TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))'); $this->addSql('CREATE TABLE step (id INT NOT NULL, played_game_id INT DEFAULT NULL, row INT NOT NULL, col INT NOT NULL, w_bomb BOOLEAN DEFAULT NULL, created TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_43B9FE3C5AA11DBB ON step (played_game_id)'); $this->addSql('CREATE INDEX IDX_43B9FE3C5AA11DBB ON step (played_game_id)');
$this->addSql('CREATE TABLE "user" (id INT NOT NULL, username VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D649F85E0677 ON "user" (username)');
$this->addSql('ALTER TABLE grid ADD CONSTRAINT FK_2E20D9375AA11DBB FOREIGN KEY (played_game_id) REFERENCES played_game (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE grid ADD CONSTRAINT FK_2E20D9375AA11DBB FOREIGN KEY (played_game_id) REFERENCES played_game (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE grid_row ADD CONSTRAINT FK_6FAD08EB2E20D937 FOREIGN KEY (grid) REFERENCES grid (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE grid_row ADD CONSTRAINT FK_6FAD08EB2E20D937 FOREIGN KEY (grid) REFERENCES grid (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE80398BBE8922 FOREIGN KEY (red_id) REFERENCES fos_user_user (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE80398BBE8922 FOREIGN KEY (red_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE8039F24372EB FOREIGN KEY (red_anon) REFERENCES gamer (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE8039F24372EB FOREIGN KEY (red_anon) REFERENCES gamer (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE80395AB9393F FOREIGN KEY (blue_id) REFERENCES fos_user_user (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE80395AB9393F FOREIGN KEY (blue_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE8039C64E7C7C FOREIGN KEY (blue_anon) REFERENCES gamer (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE played_game ADD CONSTRAINT FK_54BE8039C64E7C7C FOREIGN KEY (blue_anon) REFERENCES gamer (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE step ADD CONSTRAINT FK_43B9FE3C5AA11DBB FOREIGN KEY (played_game_id) REFERENCES played_game (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE step ADD CONSTRAINT FK_43B9FE3C5AA11DBB FOREIGN KEY (played_game_id) REFERENCES played_game (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
} }
public function down(Schema $schema) : void public function down(Schema $schema): void
{ {
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE SCHEMA public');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE80398BBE8922');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE80395AB9393F');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE8039F24372EB');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE8039C64E7C7C');
$this->addSql('ALTER TABLE grid_row DROP CONSTRAINT FK_6FAD08EB2E20D937');
$this->addSql('ALTER TABLE grid DROP CONSTRAINT FK_2E20D9375AA11DBB');
$this->addSql('ALTER TABLE step DROP CONSTRAINT FK_43B9FE3C5AA11DBB');
$this->addSql('DROP SEQUENCE fos_user_user_id_seq CASCADE');
$this->addSql('DROP SEQUENCE gamer_id_seq CASCADE'); $this->addSql('DROP SEQUENCE gamer_id_seq CASCADE');
$this->addSql('DROP SEQUENCE grid_id_seq CASCADE'); $this->addSql('DROP SEQUENCE grid_id_seq CASCADE');
$this->addSql('DROP SEQUENCE grid_row_id_seq CASCADE'); $this->addSql('DROP SEQUENCE grid_row_id_seq CASCADE');
$this->addSql('DROP SEQUENCE played_game_id_seq CASCADE'); $this->addSql('DROP SEQUENCE played_game_id_seq CASCADE');
$this->addSql('DROP SEQUENCE step_id_seq CASCADE'); $this->addSql('DROP SEQUENCE step_id_seq CASCADE');
$this->addSql('DROP TABLE fos_user_user'); $this->addSql('DROP SEQUENCE user_id_seq CASCADE');
$this->addSql('ALTER TABLE grid DROP CONSTRAINT FK_2E20D9375AA11DBB');
$this->addSql('ALTER TABLE grid_row DROP CONSTRAINT FK_6FAD08EB2E20D937');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE80398BBE8922');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE8039F24372EB');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE80395AB9393F');
$this->addSql('ALTER TABLE played_game DROP CONSTRAINT FK_54BE8039C64E7C7C');
$this->addSql('ALTER TABLE step DROP CONSTRAINT FK_43B9FE3C5AA11DBB');
$this->addSql('DROP TABLE gamer'); $this->addSql('DROP TABLE gamer');
$this->addSql('DROP TABLE grid'); $this->addSql('DROP TABLE grid');
$this->addSql('DROP TABLE grid_row'); $this->addSql('DROP TABLE grid_row');
$this->addSql('DROP TABLE played_game'); $this->addSql('DROP TABLE played_game');
$this->addSql('DROP TABLE step'); $this->addSql('DROP TABLE step');
$this->addSql('DROP TABLE "user"');
} }
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -17,36 +17,33 @@ use Gos\Bundle\WebSocketBundle\Periodic\PeriodicInterface;
* Class MinePeriodic * Class MinePeriodic
* *
* @package App\Periodic * @package App\Periodic
* @author system7 <https://www.splendidbear.org> * @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. 09.
*
* @method MinePeriodic|null find($id, $lockMode = null, $lockVersion = null)
* @method MinePeriodic|null findOneBy(array $criteria, array $orderBy = null)
* @method MinePeriodic[] findAll()
* @method MinePeriodic[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/ */
class MinePeriodic implements PeriodicInterface class MinePeriodic implements PeriodicInterface
{ {
/** @var PdoPeriodicPing */ public function __construct(private PdoPeriodicPing $ping) { }
private $ping;
/**
* MinePeriodic constructor.
*
* @param PdoPeriodicPing $ping
*/
public function __construct(PdoPeriodicPing $ping)
{
$this->ping = $ping;
}
/** /**
* This function is executed every 5 seconds. * This function is executed every 5 seconds.
* *
* For more advanced functionality, try injecting a Topic Service to perform actions on your connections every x seconds. * For more advanced functionality, try injecting
* a Topic Service to perform actions on your
* connections every x seconds.
*/ */
public function tick(): void public function tick(): void
{ {
$this->ping->tick(); $this->ping->tick();
} }
/**
* {@inheritdoc}
*/
public function getTimeout(): int public function getTimeout(): int
{ {
return 300; return 300;

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -18,46 +18,16 @@ use Doctrine\Persistence\ManagerRegistry;
* Class GamerRepository * Class GamerRepository
* *
* @package App\Repository * @package App\Repository
* @author system7 <https://www.splendidbear.org> * @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. 09.
*/ */
class GamerRepository extends ServiceEntityRepository class GamerRepository extends ServiceEntityRepository
{ {
/**
* GamerRepository constructor.
*
* @param ManagerRegistry $registry
*/
public function __construct(ManagerRegistry $registry) public function __construct(ManagerRegistry $registry)
{ {
parent::__construct($registry, Gamer::class); parent::__construct($registry, Gamer::class);
} }
// /**
// * @return Gamer[] Returns an array of Gamer objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('g')
->andWhere('g.exampleField = :val')
->setParameter('val', $value)
->orderBy('g.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?Gamer
{
return $this->createQueryBuilder('g')
->andWhere('g.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -18,7 +18,11 @@ use Doctrine\Persistence\ManagerRegistry;
* Class GridRepository * Class GridRepository
* *
* @package App\Repository * @package App\Repository
* @author system7 <https://www.splendidbear.org> * @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. 09.
* *
* @method Grid|null find($id, $lockMode = null, $lockVersion = null) * @method Grid|null find($id, $lockMode = null, $lockVersion = null)
* @method Grid|null findOneBy(array $criteria, array $orderBy = null) * @method Grid|null findOneBy(array $criteria, array $orderBy = null)
@@ -27,42 +31,8 @@ use Doctrine\Persistence\ManagerRegistry;
*/ */
class GridRepository extends ServiceEntityRepository class GridRepository extends ServiceEntityRepository
{ {
/**
* GridRepository constructor.
*
* @param ManagerRegistry $registry
*/
public function __construct(ManagerRegistry $registry) public function __construct(ManagerRegistry $registry)
{ {
parent::__construct($registry, Grid::class); parent::__construct($registry, Grid::class);
} }
// /**
// * @return Grid[] Returns an array of Grid objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('g')
->andWhere('g.exampleField = :val')
->setParameter('val', $value)
->orderBy('g.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?Grid
{
return $this->createQueryBuilder('g')
->andWhere('g.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -18,7 +18,11 @@ use Doctrine\Persistence\ManagerRegistry;
* Class GridRowRepository * Class GridRowRepository
* *
* @package App\Repository * @package App\Repository
* @author system7 <https://www.splendidbear.org> * @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. 09.
* *
* @method GridRow|null find($id, $lockMode = null, $lockVersion = null) * @method GridRow|null find($id, $lockMode = null, $lockVersion = null)
* @method GridRow|null findOneBy(array $criteria, array $orderBy = null) * @method GridRow|null findOneBy(array $criteria, array $orderBy = null)
@@ -27,42 +31,8 @@ use Doctrine\Persistence\ManagerRegistry;
*/ */
class GridRowRepository extends ServiceEntityRepository class GridRowRepository extends ServiceEntityRepository
{ {
/**
* GridRowRepository constructor.
*
* @param ManagerRegistry $registry
*/
public function __construct(ManagerRegistry $registry) public function __construct(ManagerRegistry $registry)
{ {
parent::__construct($registry, GridRow::class); parent::__construct($registry, GridRow::class);
} }
// /**
// * @return GridRow[] Returns an array of GridRow objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('g')
->andWhere('g.exampleField = :val')
->setParameter('val', $value)
->orderBy('g.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?GridRow
{
return $this->createQueryBuilder('g')
->andWhere('g.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -18,12 +18,17 @@ use Doctrine\Persistence\ManagerRegistry;
* Class PlayedGameRepository * Class PlayedGameRepository
* *
* @package App\Repository * @package App\Repository
* @author system7 <https://www.splendidbear.org> * @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. 09.
* *
* @method PlayedGame|null find($id, $lockMode = null, $lockVersion = null) * @method PlayedGame|null find($id, $lockMode = null, $lockVersion = null)
* @method PlayedGame|null findOneBy(array $criteria, array $orderBy = null) * @method PlayedGame|null findOneBy(array $criteria, array $orderBy = null)
* @method PlayedGame[] findAll() * @method PlayedGame[] findAll()
* @method PlayedGame[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) * @method PlayedGame[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @method PlayedGame|null findOneByGameAssoc($gameAssoc)
*/ */
class PlayedGameRepository extends ServiceEntityRepository class PlayedGameRepository extends ServiceEntityRepository
{ {
@@ -36,33 +41,4 @@ class PlayedGameRepository extends ServiceEntityRepository
{ {
parent::__construct($registry, PlayedGame::class); parent::__construct($registry, PlayedGame::class);
} }
// /**
// * @return PlayedGame[] Returns an array of PlayedGame objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('p')
->andWhere('p.exampleField = :val')
->setParameter('val', $value)
->orderBy('p.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?PlayedGame
{
return $this->createQueryBuilder('p')
->andWhere('p.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -18,7 +18,11 @@ use Doctrine\Persistence\ManagerRegistry;
* Class StepRepository * Class StepRepository
* *
* @package App\Repository * @package App\Repository
* @author system7 <https://www.splendidbear.org> * @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. 09.
* *
* @method Step|null find($id, $lockMode = null, $lockVersion = null) * @method Step|null find($id, $lockMode = null, $lockVersion = null)
* @method Step|null findOneBy(array $criteria, array $orderBy = null) * @method Step|null findOneBy(array $criteria, array $orderBy = null)
@@ -27,42 +31,8 @@ use Doctrine\Persistence\ManagerRegistry;
*/ */
class StepRepository extends ServiceEntityRepository class StepRepository extends ServiceEntityRepository
{ {
/**
* StepRepository constructor.
*
* @param ManagerRegistry $registry
*/
public function __construct(ManagerRegistry $registry) public function __construct(ManagerRegistry $registry)
{ {
parent::__construct($registry, Step::class); parent::__construct($registry, Step::class);
} }
// /**
// * @return Step[] Returns an array of Step objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('s')
->andWhere('s.exampleField = :val')
->setParameter('val', $value)
->orderBy('s.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?Step
{
return $this->createQueryBuilder('s')
->andWhere('s.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
} }

View File

@@ -0,0 +1,54 @@
<?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\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
/**
* Class UserRepository
*
* @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. 09.
*
* @extends ServiceEntityRepository<User>
*/
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
public function findOneByUsername(string $username): ?User
{
return $this->findOneBy(['username' => $username]);
}
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
}
$user->setPassword($newHashedPassword);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}
}

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -11,30 +11,23 @@
namespace App\Rpc; namespace App\Rpc;
use App\Util\RpcManager; use App\Util\RpcManager;
use Ratchet\ConnectionInterface;
use Gos\Bundle\WebSocketBundle\RPC\RpcInterface;
use Gos\Bundle\WebSocketBundle\Router\WampRequest; use Gos\Bundle\WebSocketBundle\Router\WampRequest;
use Gos\Bundle\WebSocketBundle\RPC\RpcInterface;
use Ratchet\ConnectionInterface;
/** /**
* Class MineseekerRpc * Class MineseekerRpc
* *
* @package App\Rpc * @package App\Rpc
* @author system7 <https://www.splendidbear.org> * @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. 09.
*/ */
class MineseekerRpc implements RpcInterface class MineseekerRpc implements RpcInterface
{ {
/** @var RpcManager $manager */ public function __construct(private RpcManager $manager) { }
private $manager;
/**
* MineseekerRpc constructor.
*
* @param RpcManager $manager
*/
public function __construct(RpcManager $manager)
{
$this->manager = $manager;
}
/** /**
* Name of RPC, use for pubsub router (see step3) * Name of RPC, use for pubsub router (see step3)

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -11,8 +11,8 @@
namespace App\Topic; namespace App\Topic;
use App\Util\TopicManager; use App\Util\TopicManager;
use Gos\Bundle\WebSocketBundle\Topic\TopicInterface;
use Gos\Bundle\WebSocketBundle\Router\WampRequest; use Gos\Bundle\WebSocketBundle\Router\WampRequest;
use Gos\Bundle\WebSocketBundle\Topic\TopicInterface;
use Ratchet\ConnectionInterface; use Ratchet\ConnectionInterface;
use Ratchet\Wamp\Topic; use Ratchet\Wamp\Topic;
@@ -20,22 +20,15 @@ use Ratchet\Wamp\Topic;
* Class MineseekerTopic * Class MineseekerTopic
* *
* @package App\Topic * @package App\Topic
* @author system7 <https://www.splendidbear.org> * @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. 09.
*/ */
class MineseekerTopic implements TopicInterface class MineseekerTopic implements TopicInterface
{ {
/** @var TopicManager $manager */ public function __construct(private TopicManager $manager) { }
private $manager;
/**
* MineseekerTopic constructor.
*
* @param TopicManager $manager
*/
public function __construct(TopicManager $manager)
{
$this->manager = $manager;
}
/** /**
* Like RPC is will use to prefix the channel * Like RPC is will use to prefix the channel
@@ -96,8 +89,7 @@ class MineseekerTopic implements TopicInterface
$event, $event,
array $exclude, array $exclude,
array $eligible array $eligible
) ) {
{
$this->manager->publish($topic, $connection, $event); $this->manager->publish($topic, $connection, $event);
} }
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -13,9 +13,8 @@ namespace App\Util;
use App\Entity\Grid; use App\Entity\Grid;
use App\Entity\GridRow; use App\Entity\GridRow;
use App\Entity\PlayedGame; use App\Entity\PlayedGame;
use App\Util\Interfaces\RpcManagerInterface; use App\Interfaces\RpcManagerInterface;
use DateTime; use DateTime;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\ORMException; use Doctrine\ORM\ORMException;
use Exception; use Exception;
@@ -24,49 +23,34 @@ use Psr\Log\LoggerInterface;
/** /**
* Class RpcManager * Class RpcManager
* *
* @package App\Utils * @package App\Util
* @author system7 <https://www.splendidbear.org> * @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. 09.
*/ */
class RpcManager extends WebsocketManager implements RpcManagerInterface class RpcManager extends WebsocketManager implements RpcManagerInterface
{ {
/** @var EntityManager $em */ public function __construct(
protected $entityManager; private EntityManagerInterface $entityManager,
private LoggerInterface $logger,
/** @var LoggerInterface $logger */ ) {
private $logger;
/**
* MineseekerRpc constructor.
*
* @param EntityManagerInterface $entityManager
* @param LoggerInterface $logger
*/
public function __construct(EntityManagerInterface $entityManager, LoggerInterface $logger)
{
$this->entityManager = $this->reConnect($entityManager);
$this->logger = $logger;
parent::__construct($logger); parent::__construct($logger);
} }
/**
* {@inheritDoc}
*/
public function getConnectInformation($params): string public function getConnectInformation($params): string
{ {
$gameAssoc = is_array($params) ? $params[0] : $params; $gameAssoc = is_array($params) ? $params[0] : $params;
$grid = $this->getGrid($gameAssoc); $grid = $this->getGrid($gameAssoc);
$users = null !== $grid ? $this->getUsers($gameAssoc) : null; $users = null !== $grid ? $this->getUsers($gameAssoc) : null;
return base64_encode(json_encode(array( return base64_encode(json_encode([
'grid' => $grid, 'grid' => $grid,
'users' => $users 'users' => $users,
), JSON_THROW_ON_ERROR, 512)); ], JSON_THROW_ON_ERROR, 512));
} }
/**
* {@inheritDoc}
*/
public function saveGrid($data): bool public function saveGrid($data): bool
{ {
$playedGame = new PlayedGame(); $playedGame = new PlayedGame();
@@ -173,11 +157,11 @@ class RpcManager extends WebsocketManager implements RpcManagerInterface
*/ */
private function getUserCollection(PlayedGame $playedGame): array private function getUserCollection(PlayedGame $playedGame): array
{ {
return array( return [
'red' => null !== $playedGame->getRed() ? $playedGame->getRed()->getUsername() : '', 'red' => null !== $playedGame->getRed() ? $playedGame->getRed()->getUsername() : '',
'blue' => null !== $playedGame->getBlue() ? $playedGame->getBlue()->getUsername() : '', 'blue' => null !== $playedGame->getBlue() ? $playedGame->getBlue()->getUsername() : '',
'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '', 'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '',
'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : '' 'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : '',
); ];
} }
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -10,11 +10,11 @@
namespace App\Util; namespace App\Util;
use App\Application\Sonata\UserBundle\Entity\User; use App\Entity\User;
use App\Entity\Gamer; use App\Entity\Gamer;
use App\Entity\PlayedGame; use App\Entity\PlayedGame;
use App\Entity\Step; use App\Entity\Step;
use App\Util\Interfaces\TopicManagerInterface; use App\Interfaces\TopicManagerInterface;
use DateTime; use DateTime;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Exception; use Exception;
@@ -29,48 +29,24 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
* Class TopicManager * Class TopicManager
* *
* @package App\Util * @package App\Util
* @author system7 <https://www.splendidbear.org> * @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. 09.
*/ */
class TopicManager extends WebsocketManager implements TopicManagerInterface class TopicManager extends WebsocketManager implements TopicManagerInterface
{ {
/** @var ClientManipulatorInterface $clientManipulator */
protected $clientManipulator;
/** @var EntityManagerInterface $entityManager */
protected $entityManager;
/** @var RequestStack $requestStack */
protected $requestStack;
/** @var LoggerInterface $logger */
protected $logger;
/**
* TopicManager constructor.
*
* @param ClientManipulatorInterface $clientManipulator
* @param EntityManagerInterface $entityManager
* @param RequestStack $requestStack
* @param LoggerInterface $logger
*/
public function __construct( public function __construct(
ClientManipulatorInterface $clientManipulator, protected ClientManipulatorInterface $clientManipulator,
EntityManagerInterface $entityManager, protected EntityManagerInterface $entityManager,
RequestStack $requestStack, protected RequestStack $requestStack,
LoggerInterface $logger protected LoggerInterface $logger
) )
{ {
$this->clientManipulator = $clientManipulator;
$this->entityManager = $this->reConnect($entityManager);
$this->requestStack = $requestStack;
$this->logger = $logger;
parent::__construct($logger); parent::__construct($logger);
} }
/**
* {@inheritDoc}
*/
public function subscribe(Topic $topic, ConnectionInterface $connection): void public function subscribe(Topic $topic, ConnectionInterface $connection): void
{ {
/** this will broadcast the message to ALL subscribers of this topic. */ /** this will broadcast the message to ALL subscribers of this topic. */
@@ -93,18 +69,12 @@ class TopicManager extends WebsocketManager implements TopicManagerInterface
} }
} }
/**
* {@inheritDoc}
*/
public function unSubscribe(Topic $topic, ConnectionInterface $connection): void public function unSubscribe(Topic $topic, ConnectionInterface $connection): void
{ {
/** This will broadcasts the message to ALL subscribers of this topic. */ /** This will broadcasts the message to ALL subscribers of this topic. */
$topic->broadcast(array('msg' => $connection->resourceId . ' has left ' . $topic->getId())); $topic->broadcast(['msg' => $connection->resourceId . ' has left ' . $topic->getId()]);
} }
/**
* {@inheritDoc}
*/
public function publish(Topic $topic, ConnectionInterface $connection, $event): void public function publish(Topic $topic, ConnectionInterface $connection, $event): void
{ {
$user = $this->clientManipulator->getClient($connection); $user = $this->clientManipulator->getClient($connection);
@@ -319,11 +289,11 @@ class TopicManager extends WebsocketManager implements TopicManagerInterface
*/ */
private function getUserCollection(PlayedGame $playedGame): array private function getUserCollection(PlayedGame $playedGame): array
{ {
return array( return [
'red' => null !== $playedGame->getRed() ? $playedGame->getRed()->getUsername() : '', 'red' => null !== $playedGame->getRed() ? $playedGame->getRed()->getUsername() : '',
'blue' => null !== $playedGame->getBlue() ? $playedGame->getBlue()->getUsername() : '', 'blue' => null !== $playedGame->getBlue() ? $playedGame->getBlue()->getUsername() : '',
'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '', 'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '',
'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : '' 'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : ''
); ];
} }
} }

View File

@@ -1,4 +1,4 @@
<?php <?php declare(strict_types=1);
/** /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
@@ -10,35 +10,25 @@
namespace App\Util; namespace App\Util;
use App\Util\Interfaces\WebsocketManagerInterface; use App\Interfaces\WebsocketManagerInterface;
use Doctrine\DBAL\Driver\PDOException;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use RuntimeException;
/** /**
* Class WebsocketManager * Class WebsocketManager
* *
* @package App\Util * @package App\Util
* @author system7 <https://www.splendidbear.org> * @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. 09.
*/ */
class WebsocketManager implements WebsocketManagerInterface class WebsocketManager implements WebsocketManagerInterface
{ {
/** @var LoggerInterface $logger */ public function __construct(private LoggerInterface $logger) { }
private $logger;
/**
* WebsocketManager constructor.
*
* @param LoggerInterface $logger
*/
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* {@inheritDoc}
*/
public function reConnect(EntityManagerInterface $entityManager): ?EntityManagerInterface public function reConnect(EntityManagerInterface $entityManager): ?EntityManagerInterface
{ {
try { try {
@@ -48,7 +38,7 @@ class WebsocketManager implements WebsocketManagerInterface
$connection->close(); $connection->close();
$connection->connect(); $connection->connect();
} }
} catch (PDOException $e) { } catch (RuntimeException $e) {
$this->logger->error($e->getMessage()); $this->logger->error($e->getMessage());
} }

View File

@@ -5,15 +5,6 @@
"cocur/slugify": { "cocur/slugify": {
"version": "v3.1" "version": "v3.1"
}, },
"doctrine/annotations": {
"version": "1.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.0",
"ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672"
}
},
"doctrine/cache": { "doctrine/cache": {
"version": "v1.7.1" "version": "v1.7.1"
}, },
@@ -26,6 +17,15 @@
"doctrine/dbal": { "doctrine/dbal": {
"version": "v2.7.1" "version": "v2.7.1"
}, },
"doctrine/deprecations": {
"version": "1.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "fdd756167454623e21f1d769c5b814b243782a67"
}
},
"doctrine/doctrine-bundle": { "doctrine/doctrine-bundle": {
"version": "1.6", "version": "1.6",
"recipe": { "recipe": {
@@ -98,12 +98,6 @@
"jdorn/sql-formatter": { "jdorn/sql-formatter": {
"version": "v1.2.17" "version": "v1.2.17"
}, },
"knplabs/knp-menu": {
"version": "2.3.0"
},
"knplabs/knp-menu-bundle": {
"version": "v2.2.1"
},
"monolog/monolog": { "monolog/monolog": {
"version": "1.25.1" "version": "1.25.1"
}, },
@@ -164,33 +158,6 @@
"roave/security-advisories": { "roave/security-advisories": {
"version": "dev-master" "version": "dev-master"
}, },
"sensio/framework-extra-bundle": {
"version": "5.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "5.2",
"ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
},
"files": [
"config/packages/sensio_framework_extra.yaml"
]
},
"sonata-project/admin-bundle": {
"version": "3.31",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "master",
"version": "3.31",
"ref": "0e5931df1732e3dccfba42a20853049e5e9db6ae"
}
},
"sonata-project/block-bundle": {
"version": "3.12.1"
},
"sonata-project/cache": {
"version": "2.0.1"
},
"sonata-project/core-bundle": { "sonata-project/core-bundle": {
"version": "3.9", "version": "3.9",
"recipe": { "recipe": {
@@ -203,21 +170,9 @@
"sonata-project/datagrid-bundle": { "sonata-project/datagrid-bundle": {
"version": "2.3.1" "version": "2.3.1"
}, },
"sonata-project/doctrine-extensions": {
"version": "1.0.2"
},
"sonata-project/doctrine-orm-admin-bundle": {
"version": "3.6.0"
},
"sonata-project/easy-extends-bundle": { "sonata-project/easy-extends-bundle": {
"version": "2.5.0" "version": "2.5.0"
}, },
"sonata-project/exporter": {
"version": "1.9.0"
},
"sonata-project/user-bundle": {
"version": "4.2.1"
},
"swiftmailer/swiftmailer": { "swiftmailer/swiftmailer": {
"version": "v6.0.2" "version": "v6.0.2"
}, },
@@ -263,9 +218,6 @@
"symfony/event-dispatcher-contracts": { "symfony/event-dispatcher-contracts": {
"version": "v1.1.7" "version": "v1.1.7"
}, },
"symfony/expression-language": {
"version": "v4.0.9"
},
"symfony/filesystem": { "symfony/filesystem": {
"version": "v4.0.9" "version": "v4.0.9"
}, },
@@ -281,9 +233,6 @@
"ref": "cc1afd81841db36fbef982fe56b48ade6716fac4" "ref": "cc1afd81841db36fbef982fe56b48ade6716fac4"
} }
}, },
"symfony/form": {
"version": "v4.0.9"
},
"symfony/framework-bundle": { "symfony/framework-bundle": {
"version": "3.3", "version": "3.3",
"recipe": { "recipe": {
@@ -358,9 +307,6 @@
"symfony/polyfill-ctype": { "symfony/polyfill-ctype": {
"version": "v1.12.0" "version": "v1.12.0"
}, },
"symfony/polyfill-intl-icu": {
"version": "v1.8.0"
},
"symfony/polyfill-intl-idn": { "symfony/polyfill-intl-idn": {
"version": "v1.12.0" "version": "v1.12.0"
}, },
@@ -370,9 +316,6 @@
"symfony/profiler-pack": { "symfony/profiler-pack": {
"version": "v1.0.3" "version": "v1.0.3"
}, },
"symfony/property-access": {
"version": "v4.0.9"
},
"symfony/routing": { "symfony/routing": {
"version": "4.0", "version": "4.0",
"recipe": { "recipe": {
@@ -385,30 +328,25 @@
"symfony/security": { "symfony/security": {
"version": "v4.0.9" "version": "v4.0.9"
}, },
"symfony/security-acl": {
"version": "v3.0.1"
},
"symfony/security-bundle": { "symfony/security-bundle": {
"version": "3.3", "version": "6.4",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "master", "branch": "main",
"version": "3.3", "version": "6.4",
"ref": "f8a63faa0d9521526499c0a8f403c9964ecb0527" "ref": "2ae08430db28c8eb4476605894296c82a642028f"
} },
"files": [
"config/packages/security.yaml",
"config/routes/security.yaml"
]
}, },
"symfony/security-core": { "symfony/security-core": {
"version": "v4.3.5" "version": "v4.3.5"
}, },
"symfony/security-csrf": {
"version": "v4.3.5"
},
"symfony/security-guard": { "symfony/security-guard": {
"version": "v4.3.5" "version": "v4.3.5"
}, },
"symfony/security-http": {
"version": "v4.3.5"
},
"symfony/service-contracts": { "symfony/service-contracts": {
"version": "v1.1.7" "version": "v1.1.7"
}, },
@@ -419,13 +357,17 @@
"version": "v4.0.9" "version": "v4.0.9"
}, },
"symfony/translation": { "symfony/translation": {
"version": "3.3", "version": "6.4",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "master", "branch": "main",
"version": "3.3", "version": "6.3",
"ref": "6bcd6c570c017ea6ae5a7a6a027c929fd3542cd8" "ref": "620a1b84865ceb2ba304c8f8bf2a185fbf32a843"
} },
"files": [
"config/packages/translation.yaml",
"translations/.gitignore"
]
}, },
"symfony/translation-contracts": { "symfony/translation-contracts": {
"version": "v1.1.7" "version": "v1.1.7"
@@ -442,9 +384,6 @@
"ref": "f75ac166398e107796ca94cc57fa1edaa06ec47f" "ref": "f75ac166398e107796ca94cc57fa1edaa06ec47f"
} }
}, },
"symfony/validator": {
"version": "v4.0.9"
},
"symfony/var-dumper": { "symfony/var-dumper": {
"version": "v4.0.9" "version": "v4.0.9"
}, },

View File