Compare commits

...

13 Commits

27 changed files with 223 additions and 64 deletions

View File

@ -34,10 +34,14 @@ max_line_length = 120
indent_size = 4
max_line_length = off
[/website/config/routes/*.yaml]
[/website/config/modules/*.yaml]
indent_size = 4
max_line_length = off
[/website/config/packages/*.yaml]
indent_size = 4
max_line_length = off
[/website/config/routes/*.yaml]
indent_size = 4
max_line_length = off

View File

@ -41,9 +41,10 @@ This project is published to multiple core-sharing portals:
## Directory structure
- [core](core/README.md): core engine of the game
- [doc](doc/README.md): developer documentation
- [legacy](legacy/README.md): History and source code of previous versions of
the game
- [modules/core](modules/core/README.md): core engine of the game
- [modules/storage](modules/storage/README.md): storage module for the game
- `tools`: developer tools
- [website](website/README.md): website and UI

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace Quintolin\Core;
final class HealthCheck
{
public function __invoke(): bool
{
return true;
}
}

2
modules/storage/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/vendor
composer.lock

View File

@ -0,0 +1,6 @@
# Quintolin: storage module
This directory contains **storage module** of Quintolin game.
The engine is intended to be an abstract PHP library,
independent of any framework or execution environment.

View File

@ -0,0 +1,32 @@
{
"name": "quintolin/storage",
"description": "Storage module for Quintolin PBBG",
"version": "0.0.1",
"type": "library",
"keywords": [
"game",
"pbbg"
],
"homepage": "https://www.shintolin.com/",
"readme": "README.md",
"license": "AGPL-3.0-or-later",
"authors": [
{
"name": "Krzysztof Sikorski",
"homepage": "https://zerozero.pl/",
"role": "Developer"
}
],
"support": {
"chat": "https://discord.gg/ZKTSKne"
},
"require": {
"php": "^8.3",
"symfony/finder": "^7.0"
},
"autoload": {
"psr-4": {
"Quintolin\\Storage\\": "src/"
}
}
}

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace Quintolin\Storage;
final class HealthCheck
{
public function __invoke(): bool
{
return true;
}
}

View File

@ -2,11 +2,10 @@
declare(strict_types=1);
namespace App\Service\Query;
namespace Quintolin\Storage\Query;
use App\DTO\QueryResult\ReleaseNote;
use DateTimeImmutable;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Quintolin\Storage\QueryResult\ReleaseNote;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
@ -15,7 +14,6 @@ use function sprintf;
abstract readonly class AbstractReleaseNotesQuery
{
public function __construct(
#[Autowire('%kernel.project_dir%/data/release-notes')]
private string $projectDir,
) {}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Quintolin\Storage\Query;
use Quintolin\Storage\QueryResult\ReleaseNote;
final readonly class LatestReleaseNoteQuery extends AbstractReleaseNotesQuery
{
public function __invoke(): null | ReleaseNote
{
$notes = $this->fetch(maxCount: 1);
return $notes[0] ?? null;
}
}

View File

@ -2,9 +2,9 @@
declare(strict_types=1);
namespace App\Service\Query;
namespace Quintolin\Storage\Query;
use App\DTO\QueryResult\ReleaseNote;
use Quintolin\Storage\QueryResult\ReleaseNote;
final readonly class ReleaseNotesQuery extends AbstractReleaseNotesQuery
{
@ -13,6 +13,6 @@ final readonly class ReleaseNotesQuery extends AbstractReleaseNotesQuery
*/
public function __invoke(): array
{
return parent::fetch(maxCount: null);
return $this->fetch(maxCount: null);
}
}

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\DTO\QueryResult;
namespace Quintolin\Storage\QueryResult;
use DateTimeImmutable;

View File

@ -25,6 +25,7 @@
"ext-ctype": "*",
"ext-iconv": "*",
"quintolin/core": "^0.0.1",
"quintolin/storage": "^0.0.1",
"symfony/asset": "7.0.*",
"symfony/asset-mapper": "7.0.*",
"symfony/cache": "7.0.*",
@ -71,7 +72,11 @@
"repositories": [
{
"type": "path",
"url": "../core"
"url": "../modules/core"
},
{
"type": "path",
"url": "../modules/storage"
}
],
"config": {

45
website/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ed3529ad1366e7b682b2a133c9597403",
"content-hash": "eafe42c282ea9b4550d687735901053f",
"packages": [
{
"name": "composer/semver",
@ -342,7 +342,7 @@
"version": "0.0.1",
"dist": {
"type": "path",
"url": "../core",
"url": "../modules/core",
"reference": "71ff64c8723e825a1437cadc00f1229e262a1490"
},
"require": {
@ -377,6 +377,47 @@
"relative": true
}
},
{
"name": "quintolin/storage",
"version": "0.0.1",
"dist": {
"type": "path",
"url": "../modules/storage",
"reference": "40dd747426f7ffba283e67e03ffada0a9622ff11"
},
"require": {
"php": "^8.3",
"symfony/finder": "^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Quintolin\\Storage\\": "src/"
}
},
"license": [
"AGPL-3.0-or-later"
],
"authors": [
{
"name": "Krzysztof Sikorski",
"homepage": "https://zerozero.pl/",
"role": "Developer"
}
],
"description": "Storage module for Quintolin PBBG",
"homepage": "https://www.shintolin.com/",
"keywords": [
"game",
"pbbg"
],
"support": {
"chat": "https://discord.gg/ZKTSKne"
},
"transport-options": {
"relative": true
}
},
{
"name": "symfony/asset",
"version": "v7.0.0",

View File

@ -0,0 +1,18 @@
services:
_defaults:
autowire: true
autoconfigure: true
Quintolin\Storage\Query\:
resource: '../../../modules/storage/src/Query/'
Quintolin\Storage\Query\AbstractReleaseNotesQuery:
abstract: true
arguments:
$projectDir: '%kernel.project_dir%/data/release-notes'
Quintolin\Storage\Query\LatestReleaseNoteQuery:
parent: Quintolin\Storage\Query\AbstractReleaseNotesQuery
Quintolin\Storage\Query\ReleaseNotesQuery:
parent: Quintolin\Storage\Query\AbstractReleaseNotesQuery

View File

@ -2,19 +2,12 @@
framework:
secret: '%env(APP_SECRET)%'
#csrf_protection: true
handle_all_throwables: true
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: null
cookie_secure: auto
cookie_samesite: lax
# Note that the session will be started ONLY if you read or write from it.
session: true
#esi: true
#fragments: true
php_errors:
log: true
when@test:
framework:

View File

@ -1,7 +1,5 @@
framework:
router:
utf8: true
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
#default_uri: http://localhost

View File

@ -1,4 +1,5 @@
twig:
file_name_pattern: '*.twig'
default_path: '%kernel.project_dir%/templates'
globals:
app_clock: '@Psr\Clock\ClockInterface'

View File

@ -1,3 +1,6 @@
imports:
- {resource: 'modules/storage.yaml'}
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace App\Controller;
use Quintolin\Core\HealthCheck as CoreHealthCheck;
use Quintolin\Storage\HealthCheck as StorageHealthCheck;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route;
#[AsController]
#[Route(path: '/health', name: 'app_health', methods: [Request::METHOD_GET])]
final readonly class HealthController
{
public function __invoke(): Response
{
$coreChecker = new CoreHealthCheck();
$storageChecker = new StorageHealthCheck();
return new JsonResponse(data: [
'core' => $coreChecker(),
'storage' => $storageChecker(),
]);
}
}

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Controller\Website;
use App\Service\Query\LatestReleaseNoteQuery;
use Quintolin\Storage\Query\LatestReleaseNoteQuery;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\AsController;

View File

@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Controller\Website;
use App\Service\Query\ReleaseNotesQuery;
use Quintolin\Storage\Query\ReleaseNotesQuery;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\AsController;

View File

@ -1,16 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Service\Query;
use App\DTO\QueryResult\ReleaseNote;
final readonly class LatestReleaseNoteQuery extends AbstractReleaseNotesQuery
{
public function __invoke(): ReleaseNote
{
$notes = parent::fetch(maxCount: 1);
return $notes[0];
}
}

View File

@ -5,7 +5,7 @@
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "8a0d17c04c791b3d7bdd083e1e2b2a53439dc3b0"
"ref": "7824128ef0da56f09a376539d00a17e23e9b5054"
},
"files": [
"config/packages/asset_mapper.yaml",
@ -42,7 +42,7 @@
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "de6e1b3e2bbbe69e36262d72c3f3db858b1ab391"
"ref": "6356c19b9ae08e7763e4ba2d9ae63043efc75db5"
},
"files": [
"config/packages/cache.yaml",
@ -69,8 +69,8 @@
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.2",
"ref": "e0a11b4ccb8c9e70b574ff5ad3dfdcd41dec5aa6"
"version": "7.0",
"ref": "21b72649d5622d8f7da329ffb5afb232a023619d"
},
"files": [
"config/packages/routing.yaml",
@ -82,8 +82,8 @@
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "b7772eb20e92f3fb4d4fe756e7505b4ba2ca1a2c"
"version": "6.4",
"ref": "cab5fd2a13a45c266d45a7d9337e28dee6272877"
},
"files": [
"config/packages/twig.yaml",

View File

@ -98,23 +98,25 @@
</div>
</div>
<article id="release-notes">
<div class="container">
<div class="row">
<div class="col-12">
<h2>Recently Released!</h2>
<h3>
<a href="{{ path('app_website_release_notes', {_fragment: latestReleaseNote.id}) }}">
{{ latestReleaseNote.createdAt|format_date(dateFormat='relative_full') }}
</a>
</h3>
<div class="note">{{ latestReleaseNote.htmlContent|raw }}</div>
<p class="older">
<a href="{{ path('app_website_release_notes') }}" class="btn btn-light">Read Older Release Notes</a>
</p>
{% if latestReleaseNote %}
<article id="release-notes">
<div class="container">
<div class="row">
<div class="col-12">
<h2>Recently Released!</h2>
<h3>
<a href="{{ path('app_website_release_notes', {_fragment: latestReleaseNote.id}) }}">
{{ latestReleaseNote.createdAt|format_date(dateFormat='relative_full') }}
</a>
</h3>
<div class="note">{{ latestReleaseNote.htmlContent|raw }}</div>
<p class="older">
<a href="{{ path('app_website_release_notes') }}" class="btn btn-light">Read Older Release Notes</a>
</p>
</div>
</div>
</div>
</div>
</article>
</article>
{% endif %}
{% endblock %}