Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e999027eac |
@@ -1,17 +0,0 @@
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{compose.yaml,compose.*.yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,63 +0,0 @@
|
||||
# In all environments, the following files are loaded if they exist,
|
||||
# the latter taking precedence over the former:
|
||||
#
|
||||
# * .env contains default values for the environment variables needed by the app
|
||||
# * .env.local uncommitted file with local overrides
|
||||
# * .env.$APP_ENV committed environment-specific defaults
|
||||
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
||||
#
|
||||
# Real environment variables win over .env files.
|
||||
#
|
||||
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||
# https://symfony.com/doc/current/configuration/secrets.html
|
||||
#
|
||||
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
APP_ENV=dev
|
||||
APP_SECRET=
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||
#
|
||||
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data_%kernel.environment%.db"
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
|
||||
DATABASE_URL="mysql://app:!ChangeMe!@database:3306/app?serverVersion=8.0.32&charset=utf8mb4"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> symfony/messenger ###
|
||||
# Choose one of the transports below
|
||||
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
||||
###< symfony/messenger ###
|
||||
|
||||
###> symfony/mailer ###
|
||||
# Development: use Mailpit (docker compose override provides service `mailer` on port 1025)
|
||||
MAILER_DSN=smtp://mailer:1025
|
||||
# Production/Stage (uncomment and set SENDGRID_API_KEY in real env or secrets):
|
||||
# MAILER_DSN=sendgrid+api://%env(SENDGRID_API_KEY)%
|
||||
# Alternatively, via SMTP (no extra package needed):
|
||||
# MAILER_DSN="smtp://apikey:%env(SENDGRID_API_KEY)%@smtp.sendgrid.net:587?encryption=tls"
|
||||
# Optional default sender (used by test command if --from not passed):
|
||||
# MAILER_FROM=no-reply@your-domain.tld
|
||||
# SENDGRID_API_KEY=your_real_key_goes_here # Do NOT commit this; set in .env.local or deployment env
|
||||
###< symfony/mailer ###
|
||||
|
||||
###> symfony/sendgrid-mailer ###
|
||||
# MAILER_DSN=sendgrid://KEY@default
|
||||
###< symfony/sendgrid-mailer ###
|
||||
|
||||
###> mercure ###
|
||||
# Internal hub URL used by the PHP app (reachable from the php container)
|
||||
MERCURE_URL=http://mercure/.well-known/mercure
|
||||
# Public hub URL used by browsers
|
||||
MERCURE_PUBLIC_URL=http://localhost:8090/.well-known/mercure
|
||||
# Shared secret for signing JWTs (dev only). In prod, set via real env/secrets.
|
||||
MERCURE_JWT_SECRET=!ChangeThisMercureJWT!
|
||||
# Base URL for Mercure topics. Use .dev in development; override to .com in prod via .env.prod or real env.
|
||||
MERCURE_TOPIC_BASE=https://escapepage.dev
|
||||
###< mercure ###
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
APP_SECRET=620e9ce5f88a714b636179eb39d5be4f
|
||||
###< symfony/framework-bundle ###
|
||||
@@ -1,9 +0,0 @@
|
||||
### Compiled or real environment variables should be used in production.
|
||||
### Configure MAILER_DSN to use SendGrid API transport.
|
||||
### Prefer storing SENDGRID_API_KEY using Symfony Secrets or real env vars.
|
||||
|
||||
###> symfony/mailer ###
|
||||
# Example using SendGrid API key (replace with real secret via vault/secrets):
|
||||
# SENDGRID_API_KEY=SG.xxxxx
|
||||
MAILER_DSN=sendgrid+api://%env(resolve:SENDGRID_API_KEY)%@default
|
||||
###< symfony/mailer ###
|
||||
@@ -1,3 +0,0 @@
|
||||
# define your env variables for the test env here
|
||||
KERNEL_CLASS='App\Kernel'
|
||||
APP_SECRET='$ecretf0rt3st'
|
||||
+48
-21
@@ -1,27 +1,54 @@
|
||||
# ---> Symfony
|
||||
# Cache and logs (Symfony2)
|
||||
/app/cache/*
|
||||
/app/logs/*
|
||||
!app/cache/.gitkeep
|
||||
!app/logs/.gitkeep
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
/.env.local
|
||||
/.env.local.php
|
||||
/.env.*.local
|
||||
/config/secrets/prod/prod.decrypt.private.php
|
||||
/public/bundles/
|
||||
/var/
|
||||
# Email spool folder
|
||||
/app/spool/*
|
||||
|
||||
# Cache, session files and logs (Symfony3)
|
||||
/var/cache/*
|
||||
/var/logs/*
|
||||
/var/sessions/*
|
||||
!var/cache/.gitkeep
|
||||
!var/logs/.gitkeep
|
||||
!var/sessions/.gitkeep
|
||||
|
||||
# Logs (Symfony4)
|
||||
/var/log/*
|
||||
!var/log/.gitkeep
|
||||
|
||||
# Parameters
|
||||
/app/config/parameters.yml
|
||||
/app/config/parameters.ini
|
||||
|
||||
# Managed by Composer
|
||||
/app/bootstrap.php.cache
|
||||
/var/bootstrap.php.cache
|
||||
/bin/*
|
||||
!bin/console
|
||||
!bin/symfony_requirements
|
||||
/vendor/
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> phpunit/phpunit ###
|
||||
# Assets and user uploads
|
||||
/web/bundles/
|
||||
/web/uploads/
|
||||
|
||||
# PHPUnit
|
||||
/app/phpunit.xml
|
||||
/phpunit.xml
|
||||
/.phpunit.cache/
|
||||
###< phpunit/phpunit ###
|
||||
|
||||
###> symfony/asset-mapper ###
|
||||
/public/assets/
|
||||
/assets/vendor/
|
||||
###< symfony/asset-mapper ###
|
||||
# Build data
|
||||
/build/
|
||||
|
||||
# Composer PHAR
|
||||
/composer.phar
|
||||
|
||||
# Backup entities generated with doctrine:generate:entities command
|
||||
**/Entity/*~
|
||||
|
||||
# Embedded web-server pid file
|
||||
/.web-server-pid
|
||||
|
||||
###> symfony/webpack-encore-bundle ###
|
||||
/node_modules/
|
||||
/public/build/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
###< symfony/webpack-encore-bundle ###
|
||||
|
||||
Generated
-8
@@ -1,8 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
-2525
File diff suppressed because it is too large
Load Diff
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="framework" type="frameworkType"/>
|
||||
<xs:complexType name="commandType">
|
||||
<xs:all>
|
||||
<xs:element type="xs:string" name="name" minOccurs="1" maxOccurs="1"/>
|
||||
<xs:element type="xs:string" name="params" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element type="optionsBeforeType" name="optionsBefore" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="frameworkType">
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="extraData" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element type="commandType" name="command" maxOccurs="unbounded" minOccurs="0"/>
|
||||
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:string" name="name" use="required"/>
|
||||
<xs:attribute type="xs:string" name="invoke" use="required"/>
|
||||
<xs:attribute type="xs:string" name="alias" use="required"/>
|
||||
<xs:attribute type="xs:boolean" name="enabled" use="required"/>
|
||||
<xs:attribute type="xs:integer" name="version" use="required"/>
|
||||
<xs:attribute type="xs:string" name="frameworkId" use="optional"/>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="optionsBeforeType">
|
||||
<xs:sequence>
|
||||
<xs:element type="optionType" name="option" maxOccurs="unbounded" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="optionType">
|
||||
<xs:sequence>
|
||||
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute type="xs:string" name="name" use="required"/>
|
||||
<xs:attribute type="xs:string" name="shortcut" use="optional"/>
|
||||
<xs:attribute name="pattern" use="optional">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="space"/>
|
||||
<xs:enumeration value="equals"/>
|
||||
<xs:enumeration value="unknown"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
Generated
-145
@@ -1,145 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/collections" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/dbal" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/deprecations" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/event-manager" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/inflector" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/instantiator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/migrations" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/orm" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/persistence" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/sql-formatter" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/egulias/email-validator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/masterminds/html5" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/monolog/monolog" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/deep-copy" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/nikic/php-parser" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-common" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-docblock" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/type-resolver" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpstan/phpdoc-parser" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-file-iterator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-invoker" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/clock" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/event-dispatcher" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/link" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/cli-parser" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/comparator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/complexity" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/diff" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/environment" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/exporter" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/global-state" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/lines-of-code" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-enumerator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-reflector" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/recursion-context" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/type" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/staabm/side-effects-detector" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/asset" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/asset-mapper" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/browser-kit" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/cache-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/clock" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/config" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/css-selector" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/debug-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dependency-injection" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/doctrine-bridge" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/doctrine-messenger" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dom-crawler" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dotenv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/error-handler" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/expression-language" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/filesystem" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/finder" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/flex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/form" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/framework-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-client" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-client-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-kernel" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/intl" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mailer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/maker-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/messenger" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mime" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/monolog-bridge" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/monolog-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/notifier" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/options-resolver" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/password-hasher" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-icu" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php83" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php84" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/process" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-access" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-info" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/routing" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/runtime" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-core" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-csrf" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-http" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/serializer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stimulus-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stopwatch" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation-contracts" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/twig-bridge" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/twig-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/type-info" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/ux-turbo" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/validator" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-exporter" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/web-link" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/web-profiler-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/yaml" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/theseer/tokenizer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/extra-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/twig" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/webmozart/assert" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/lcobucci/jwt" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mercure" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mercure-bundle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/sendgrid-mailer" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/webpack-encore-bundle" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
-8
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="InertiaPackage">
|
||||
<option name="directoryPaths">
|
||||
<list />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
Generated
-8
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/escapepage.iml" filepath="$PROJECT_DIR$/.idea/escapepage.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
-180
@@ -1,180 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MessDetectorOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PHPCSFixerOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PHPCodeSnifferOptionsConfiguration">
|
||||
<option name="highlightLevel" value="WARNING" />
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PhpCodeSniffer">
|
||||
<phpcs_settings>
|
||||
<phpcs_by_interpreter asDefaultInterpreter="true" interpreter_id="5505d524-8d4c-4fe7-a2cb-82e334156ed6" timeout="30000" />
|
||||
</phpcs_settings>
|
||||
</component>
|
||||
<component name="PhpIncludePathManager">
|
||||
<include_path>
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/config" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/var-exporter" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php83" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/flex" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/console" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/runtime" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/string" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/composer" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/cache" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/log" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/container" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/dependency-injection" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/cache" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/framework-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/dotenv" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/link" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/clock" />
|
||||
<path value="$PROJECT_DIR$/vendor/twig/twig" />
|
||||
<path value="$PROJECT_DIR$/vendor/twig/extra-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/security-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/browser-kit" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php84" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/dom-crawler" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-client-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/property-access" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/monolog-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-icu" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-bridge" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/asset-mapper" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/twig-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-messenger" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/clock" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/mailer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/security-csrf" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/expression-language" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/maker-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/security-core" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/security-http" />
|
||||
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/web-link" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/web-profiler-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/serializer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/ux-turbo" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/stimulus-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/type-info" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/debug-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/staabm/side-effects-detector" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/notifier" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/property-info" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/process" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/intl" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/twig-bridge" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/collections" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-client" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/orm" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/form" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/messenger" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/migrations" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/monolog-bridge" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/asset" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/persistence" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/sql-formatter" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
|
||||
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
|
||||
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
|
||||
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
|
||||
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
|
||||
<path value="$PROJECT_DIR$/vendor/phpstan/phpdoc-parser" />
|
||||
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
|
||||
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
|
||||
<path value="$PROJECT_DIR$/vendor/monolog/monolog" />
|
||||
<path value="$PROJECT_DIR$/vendor/masterminds/html5" />
|
||||
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/sendgrid-mailer" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/webpack-encore-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/mercure" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/mercure-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/lcobucci/jwt" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.5.1">
|
||||
<option name="suggestChangeDefaultLanguageLevel" value="false" />
|
||||
</component>
|
||||
<component name="PhpStan">
|
||||
<PhpStan_settings>
|
||||
<phpstan_by_interpreter asDefaultInterpreter="true" interpreter_id="5505d524-8d4c-4fe7-a2cb-82e334156ed6" timeout="60000" />
|
||||
</PhpStan_settings>
|
||||
</component>
|
||||
<component name="PhpStanOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
<component name="PhpUnit">
|
||||
<phpunit_settings>
|
||||
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" />
|
||||
</phpunit_settings>
|
||||
</component>
|
||||
<component name="Psalm">
|
||||
<Psalm_settings>
|
||||
<psalm_fixer_by_interpreter asDefaultInterpreter="true" interpreter_id="5505d524-8d4c-4fe7-a2cb-82e334156ed6" timeout="60000" />
|
||||
</Psalm_settings>
|
||||
</component>
|
||||
<component name="PsalmOptionsConfiguration">
|
||||
<option name="transferred" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
-6
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,119 +1,3 @@
|
||||
# EscapePage — Online Escape Room
|
||||
# Escapepage
|
||||
|
||||
This repository contains a Symfony 7.3 (PHP >= 8.5.1) application for a collaborative online escape room experience.
|
||||
|
||||
- Start here: doc/FILES.md — quick file index.
|
||||
- Development standards and workflows: doc/CONTRIBUTING.md
|
||||
- All documentation is located under the doc/ directory.
|
||||
|
||||
## Getting Started (brief)
|
||||
- Local machine (no Docker):
|
||||
1. Copy `.env` to `.env.local` and set database and `APP_SECRET`.
|
||||
2. Install PHP deps: `composer install`
|
||||
3. Create database and run migrations (when present): `php bin/console doctrine:database:create --if-not-exists && php bin/console doctrine:migrations:migrate -n`
|
||||
4. Install/import JS deps: `php bin/console importmap:install`
|
||||
5. Run the server: `symfony server:start -d` (or your preferred web server)
|
||||
6. Run tests: `vendor/bin/phpunit`
|
||||
|
||||
- With Docker:
|
||||
1. From `docker/`: `docker compose up -d`
|
||||
2. Install vendors inside the PHP container:
|
||||
- `docker compose exec php bash`
|
||||
- `composer install`
|
||||
3. Initialize DB:
|
||||
- `php bin/console doctrine:database:create --if-not-exists`
|
||||
- `php bin/console doctrine:migrations:migrate -n`
|
||||
4. App is at http://localhost:8080
|
||||
|
||||
## Email (Mailpit in dev, SendGrid for prod)
|
||||
- Dev: a `mailer` service (Mailpit) runs in Docker.
|
||||
- SMTP DSN in `.env`: `MAILER_DSN=smtp://mailer:1025`
|
||||
- Mailpit UI: http://localhost:8025
|
||||
- Send a test mail: `php bin/console app:mail:test you@example.com`
|
||||
- Staging/Prod: use SendGrid.
|
||||
- Require package (already in composer): `symfony/sendgrid-mailer`.
|
||||
- Set environment variables (do NOT commit secrets):
|
||||
- `MAILER_DSN=sendgrid+api://%env(SENDGRID_API_KEY)%`
|
||||
- `SENDGRID_API_KEY=YOUR_REAL_KEY`
|
||||
- Optional: `MAILER_FROM=no-reply@your-domain.tld`
|
||||
- Alternatively via SMTP (no extra package):
|
||||
- `MAILER_DSN="smtp://apikey:%env(SENDGRID_API_KEY)%@smtp.sendgrid.net:587?encryption=tls"`
|
||||
|
||||
Troubleshooting:
|
||||
- If emails don’t appear in dev, open Mailpit at http://localhost:8025 and verify messages.
|
||||
- In prod, check logs for HTTP 2xx responses from SendGrid and verify sender domain is verified in SendGrid.
|
||||
|
||||
## Frontend assets with Webpack Encore
|
||||
We use Webpack Encore to build and minify JS/CSS from the `assets/` directory into `public/build/`.
|
||||
|
||||
Install Node dependencies (on your host machine):
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Common commands:
|
||||
```
|
||||
# One-time dev build
|
||||
npm run dev
|
||||
|
||||
# Watch & rebuild on changes
|
||||
npm run watch
|
||||
|
||||
# Production build (minified, versioned filenames)
|
||||
npm run build
|
||||
```
|
||||
|
||||
How it’s wired:
|
||||
- Entry file: `assets/app.js` (imports `assets/styles/app.css`).
|
||||
- Webpack config: `webpack.config.js` outputs to `public/build/`.
|
||||
- Twig template includes built assets via Encore:
|
||||
- In `templates/base.html.twig`:
|
||||
- `{{ encore_entry_link_tags('app') }}` (CSS)
|
||||
- `{{ encore_entry_script_tags('app') }}` (JS)
|
||||
|
||||
Notes:
|
||||
- The PHP Docker image does not include Node. Run the build commands on your host, or ask to add a Node build container if you prefer fully containerized builds.
|
||||
- Built files are ignored by git except for `public/build/.gitignore` to keep the directory.
|
||||
|
||||
See doc/CONTRIBUTING.md for code style and more details.
|
||||
|
||||
## Real‑time updates with Mercure
|
||||
We use a Mercure hub (Docker service) to push server updates to browsers via Server‑Sent Events (SSE).
|
||||
|
||||
Quick start (dev):
|
||||
1. Start Docker stack from `docker/`:
|
||||
```
|
||||
docker compose up -d
|
||||
```
|
||||
This starts `mercure` at http://localhost:8090 and the app at http://localhost:8080.
|
||||
2. Install PHP deps inside the PHP container if you haven't yet:
|
||||
```
|
||||
docker compose exec php bash
|
||||
composer install
|
||||
```
|
||||
3. Open the Game Hub page in your browser: http://localhost:8080/game
|
||||
- The page subscribes to a demo topic and logs messages in the console.
|
||||
4. Publish a test update (in the PHP container):
|
||||
```
|
||||
php bin/console app:mercure:publish
|
||||
```
|
||||
You should see a console log like `[Mercure] Update received: { ... }` on the Game Hub page.
|
||||
|
||||
Configuration:
|
||||
- Env vars (defined in `.env`, override in `.env.local` as needed):
|
||||
- `MERCURE_URL=http://mercure/.well-known/mercure` (internal URL from PHP to the hub)
|
||||
- `MERCURE_PUBLIC_URL=http://localhost:8090/.well-known/mercure` (browser URL)
|
||||
- `MERCURE_JWT_SECRET=!ChangeThisMercureJWT!` (dev secret; do not use in prod)
|
||||
- `MERCURE_TOPIC_BASE=https://escapepage.dev` (base topic URL)
|
||||
- Docker service `mercure` is based on `dunglas/mercure` and allows anonymous subscribers in dev.
|
||||
|
||||
Topics:
|
||||
- Topics must be URLs. We use `MERCURE_TOPIC_BASE` to control the domain per environment.
|
||||
- Dev: `.env` sets `https://escapepage.dev`
|
||||
- Prod: set `MERCURE_TOPIC_BASE=https://escapepage.com`
|
||||
- The Game Hub demo topic is `${MERCURE_TOPIC_BASE}/game/hub`.
|
||||
|
||||
Production notes:
|
||||
- Disable anonymous subscribers and require JWTs for subscriptions (configure the Mercure container accordingly).
|
||||
- Use a strong, rotated `MERCURE_JWT_SECRET` and keep it out of VCS (use real env/secrets).
|
||||
- Serve Mercure over HTTPS and set proper CORS/allowed origins for your production domain(s).
|
||||
De Escapepage
|
||||
@@ -1,6 +0,0 @@
|
||||
/*
|
||||
* Welcome to your app's main JavaScript file!
|
||||
*/
|
||||
import './styles/app.css';
|
||||
|
||||
console.log('This log comes from assets/app.js built by Webpack Encore! 🎉');
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
import { startStimulusApp } from '@symfony/stimulus-bundle';
|
||||
|
||||
const app = startStimulusApp();
|
||||
// register any custom, 3rd party controllers here
|
||||
// app.register('some_controller_name', SomeImportedController);
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"controllers": {
|
||||
"@symfony/ux-turbo": {
|
||||
"turbo-core": {
|
||||
"enabled": true,
|
||||
"fetch": "eager"
|
||||
},
|
||||
"mercure-turbo-stream": {
|
||||
"enabled": false,
|
||||
"fetch": "eager"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entrypoints": []
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
const nameCheck = /^[-_a-zA-Z0-9]{4,22}$/;
|
||||
const tokenCheck = /^[-_/+a-zA-Z0-9]{24,}$/;
|
||||
|
||||
// Generate and double-submit a CSRF token in a form field and a cookie, as defined by Symfony's SameOriginCsrfTokenManager
|
||||
document.addEventListener('submit', function (event) {
|
||||
generateCsrfToken(event.target);
|
||||
}, true);
|
||||
|
||||
// When @hotwired/turbo handles form submissions, send the CSRF token in a header in addition to a cookie
|
||||
// The `framework.csrf_protection.check_header` config option needs to be enabled for the header to be checked
|
||||
document.addEventListener('turbo:submit-start', function (event) {
|
||||
const h = generateCsrfHeaders(event.detail.formSubmission.formElement);
|
||||
Object.keys(h).map(function (k) {
|
||||
event.detail.formSubmission.fetchRequest.headers[k] = h[k];
|
||||
});
|
||||
});
|
||||
|
||||
// When @hotwired/turbo handles form submissions, remove the CSRF cookie once a form has been submitted
|
||||
document.addEventListener('turbo:submit-end', function (event) {
|
||||
removeCsrfToken(event.detail.formSubmission.formElement);
|
||||
});
|
||||
|
||||
export function generateCsrfToken (formElement) {
|
||||
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||
|
||||
if (!csrfField) {
|
||||
return;
|
||||
}
|
||||
|
||||
let csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||
let csrfToken = csrfField.value;
|
||||
|
||||
if (!csrfCookie && nameCheck.test(csrfToken)) {
|
||||
csrfField.setAttribute('data-csrf-protection-cookie-value', csrfCookie = csrfToken);
|
||||
csrfField.defaultValue = csrfToken = btoa(String.fromCharCode.apply(null, (window.crypto || window.msCrypto).getRandomValues(new Uint8Array(18))));
|
||||
}
|
||||
csrfField.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
|
||||
if (csrfCookie && tokenCheck.test(csrfToken)) {
|
||||
const cookie = csrfCookie + '_' + csrfToken + '=' + csrfCookie + '; path=/; samesite=strict';
|
||||
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
|
||||
}
|
||||
}
|
||||
|
||||
export function generateCsrfHeaders (formElement) {
|
||||
const headers = {};
|
||||
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||
|
||||
if (!csrfField) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||
|
||||
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
|
||||
headers[csrfCookie] = csrfField.value;
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
export function removeCsrfToken (formElement) {
|
||||
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||
|
||||
if (!csrfField) {
|
||||
return;
|
||||
}
|
||||
|
||||
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||
|
||||
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
|
||||
const cookie = csrfCookie + '_' + csrfField.value + '=0; path=/; samesite=strict; max-age=0';
|
||||
|
||||
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
|
||||
}
|
||||
}
|
||||
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default 'csrf-protection-controller';
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
/*
|
||||
* This is an example Stimulus controller!
|
||||
*
|
||||
* Any element with a data-controller="hello" attribute will cause
|
||||
* this controller to be executed. The name "hello" comes from the filename:
|
||||
* hello_controller.js -> "hello"
|
||||
*
|
||||
* Delete this file or adapt it for your use!
|
||||
*/
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
|
||||
}
|
||||
}
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
/* Game1 entry point built with Webpack Encore */
|
||||
import './styles/game1.css';
|
||||
|
||||
function subscribeToMercure(mercurePublicUrl, topic) {
|
||||
try {
|
||||
const url = mercurePublicUrl + '?topic=' + encodeURIComponent(topic);
|
||||
const es = new EventSource(url);
|
||||
|
||||
es.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
console.log('[Mercure][game1] Update:', data);
|
||||
} catch (e) {
|
||||
console.log('[Mercure][game1] Raw event:', event.data);
|
||||
}
|
||||
};
|
||||
|
||||
es.onerror = (err) => {
|
||||
console.warn('[Mercure][game1] EventSource error:', err);
|
||||
};
|
||||
|
||||
console.log('[Mercure][game1] Subscribed to', url);
|
||||
} catch (e) {
|
||||
console.error('[Mercure][game1] Failed to subscribe:', e);
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchJson(url, options = {}) {
|
||||
const opts = { ...options };
|
||||
const headers = new Headers(opts.headers || {});
|
||||
headers.set('Accept', 'application/json');
|
||||
if (opts.body !== undefined && typeof opts.body !== 'string') {
|
||||
headers.set('Content-Type', 'application/json');
|
||||
opts.body = JSON.stringify(opts.body);
|
||||
}
|
||||
// Useful convention for server-side checks
|
||||
if (!headers.has('X-Requested-With')) {
|
||||
headers.set('X-Requested-With', 'XMLHttpRequest');
|
||||
}
|
||||
opts.headers = headers;
|
||||
const res = await fetch(url, opts);
|
||||
const text = await res.text();
|
||||
let data;
|
||||
try { data = text ? JSON.parse(text) : null; } catch (e) { data = text; }
|
||||
if (!res.ok) {
|
||||
const err = new Error('HTTP ' + res.status + ' ' + res.statusText);
|
||||
console.error('[API][game1]', err, data);
|
||||
throw err;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
// Simple boot log so you can verify it in the browser console
|
||||
// and confirm this specific bundle is loaded on the Game Hub page.
|
||||
console.log('Game1 bundle loaded');
|
||||
|
||||
// Example: add a CSS class to <body> so page-specific styles can apply
|
||||
document.body.classList.add('game1-page');
|
||||
|
||||
// Look for config injected by Twig in the page
|
||||
const cfgEl = document.getElementById('mercure-config');
|
||||
if (!cfgEl) {
|
||||
console.warn('[Mercure][game1] #mercure-config element not found on page');
|
||||
return;
|
||||
}
|
||||
|
||||
const mercurePublicUrl = cfgEl.dataset.mercurePublicUrl;
|
||||
const topic = cfgEl.dataset.topic;
|
||||
const apiPingUrl = cfgEl.dataset.apiPingUrl;
|
||||
const apiEchoUrl = cfgEl.dataset.apiEchoUrl;
|
||||
|
||||
if (mercurePublicUrl && topic) {
|
||||
subscribeToMercure(mercurePublicUrl, topic);
|
||||
} else {
|
||||
console.warn('[Mercure][game1] Missing data attributes on #mercure-config');
|
||||
}
|
||||
|
||||
// Demo API calls
|
||||
try {
|
||||
if (apiPingUrl) {
|
||||
const ping = await fetchJson(apiPingUrl);
|
||||
console.log('[API][game1] ping →', ping);
|
||||
} else {
|
||||
console.warn('[API][game1] data-api-ping-url missing');
|
||||
}
|
||||
|
||||
if (apiEchoUrl) {
|
||||
const echo = await fetchJson(apiEchoUrl, {
|
||||
method: 'POST',
|
||||
body: { hello: 'from game1.js', ts: new Date().toISOString() },
|
||||
});
|
||||
console.log('[API][game1] echo →', echo);
|
||||
} else {
|
||||
console.warn('[API][game1] data-api-echo-url missing');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[API][game1] Request failed:', e);
|
||||
}
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
body {
|
||||
background-color: skyblue;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/* Styles specific to Game1 */
|
||||
|
||||
/* page-level indicator to confirm CSS is loaded */
|
||||
body.game1-page {
|
||||
/* subtle background tint so you can visually confirm on /game */
|
||||
background-color: #f9fbff;
|
||||
}
|
||||
|
||||
/* example component style */
|
||||
.game1-banner {
|
||||
padding: 1rem 1.25rem;
|
||||
border: 1px solid #cfe2ff;
|
||||
background: #e9f2ff;
|
||||
color: #0b5ed7;
|
||||
border-radius: 8px;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use App\Kernel;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
|
||||
if (!is_dir(dirname(__DIR__).'/vendor')) {
|
||||
throw new LogicException('Dependencies are missing. Try running "composer install".');
|
||||
}
|
||||
|
||||
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
|
||||
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
|
||||
return new Application($kernel);
|
||||
};
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
if (!ini_get('date.timezone')) {
|
||||
ini_set('date.timezone', 'UTC');
|
||||
}
|
||||
|
||||
if (is_file(dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit')) {
|
||||
if (PHP_VERSION_ID >= 80000) {
|
||||
require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit';
|
||||
} else {
|
||||
define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php');
|
||||
require PHPUNIT_COMPOSER_INSTALL;
|
||||
PHPUnit\TextUI\Command::main();
|
||||
}
|
||||
} else {
|
||||
if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
|
||||
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
services:
|
||||
###> symfony/mercure-bundle ###
|
||||
mercure:
|
||||
ports:
|
||||
- "80"
|
||||
###< symfony/mercure-bundle ###
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
services:
|
||||
###> symfony/mercure-bundle ###
|
||||
mercure:
|
||||
image: dunglas/mercure
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
# Uncomment the following line to disable HTTPS,
|
||||
#SERVER_NAME: ':80'
|
||||
MERCURE_PUBLISHER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
|
||||
MERCURE_SUBSCRIBER_JWT_KEY: '!ChangeThisMercureHubJWTSecretKey!'
|
||||
# Set the URL of your Symfony project (without trailing slash!) as value of the cors_origins directive
|
||||
MERCURE_EXTRA_DIRECTIVES: |
|
||||
cors_origins http://127.0.0.1:8000
|
||||
# Comment the following line to disable the development mode
|
||||
command: /usr/bin/caddy run --config /etc/caddy/dev.Caddyfile
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "https://localhost/healthz"]
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 60s
|
||||
volumes:
|
||||
- mercure_data:/data
|
||||
- mercure_config:/config
|
||||
###< symfony/mercure-bundle ###
|
||||
|
||||
volumes:
|
||||
###> symfony/mercure-bundle ###
|
||||
mercure_data:
|
||||
mercure_config:
|
||||
###< symfony/mercure-bundle ###
|
||||
-111
@@ -1,111 +0,0 @@
|
||||
{
|
||||
"type": "project",
|
||||
"license": "proprietary",
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=8.5.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"doctrine/dbal": "^3",
|
||||
"doctrine/doctrine-bundle": "^2.16",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.4",
|
||||
"doctrine/orm": "^3.5",
|
||||
"phpdocumentor/reflection-docblock": "^5.6",
|
||||
"phpstan/phpdoc-parser": "^2.3",
|
||||
"symfony/asset": "7.3.*",
|
||||
"symfony/asset-mapper": "7.3.*",
|
||||
"symfony/console": "7.3.*",
|
||||
"symfony/doctrine-messenger": "7.3.*",
|
||||
"symfony/dotenv": "7.3.*",
|
||||
"symfony/expression-language": "7.3.*",
|
||||
"symfony/flex": "^2",
|
||||
"symfony/form": "7.3.*",
|
||||
"symfony/framework-bundle": "7.3.*",
|
||||
"symfony/http-client": "7.3.*",
|
||||
"symfony/intl": "7.3.*",
|
||||
"symfony/mailer": "7.3.*",
|
||||
"symfony/mime": "7.3.*",
|
||||
"symfony/sendgrid-mailer": "7.3.*",
|
||||
"symfony/monolog-bundle": "^3.0",
|
||||
"symfony/notifier": "7.3.*",
|
||||
"symfony/process": "7.3.*",
|
||||
"symfony/property-access": "7.3.*",
|
||||
"symfony/property-info": "7.3.*",
|
||||
"symfony/runtime": "7.3.*",
|
||||
"symfony/security-bundle": "7.3.*",
|
||||
"symfony/serializer": "7.3.*",
|
||||
"symfony/stimulus-bundle": "^2.30",
|
||||
"symfony/string": "7.3.*",
|
||||
"symfony/translation": "7.3.*",
|
||||
"symfony/twig-bundle": "7.3.*",
|
||||
"symfony/ux-turbo": "^2.30",
|
||||
"symfony/validator": "7.3.*",
|
||||
"symfony/web-link": "7.3.*",
|
||||
"symfony/yaml": "7.3.*",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0",
|
||||
"symfony/webpack-encore-bundle": "^2.1",
|
||||
"symfony/mercure-bundle": "^0.3"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"php-http/discovery": true,
|
||||
"symfony/flex": true,
|
||||
"symfony/runtime": true
|
||||
},
|
||||
"bump-after-update": true,
|
||||
"sort-packages": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"replace": {
|
||||
"symfony/polyfill-ctype": "*",
|
||||
"symfony/polyfill-iconv": "*",
|
||||
"symfony/polyfill-php72": "*",
|
||||
"symfony/polyfill-php73": "*",
|
||||
"symfony/polyfill-php74": "*",
|
||||
"symfony/polyfill-php80": "*",
|
||||
"symfony/polyfill-php81": "*",
|
||||
"symfony/polyfill-php82": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"cache:clear": "symfony-cmd",
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd",
|
||||
"importmap:install": "symfony-cmd"
|
||||
},
|
||||
"post-install-cmd": [
|
||||
"@auto-scripts"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@auto-scripts"
|
||||
]
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"extra": {
|
||||
"symfony": {
|
||||
"allow-contrib": false,
|
||||
"require": "7.3.*"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.5",
|
||||
"symfony/browser-kit": "7.3.*",
|
||||
"symfony/css-selector": "7.3.*",
|
||||
"symfony/debug-bundle": "7.3.*",
|
||||
"symfony/maker-bundle": "^1.0",
|
||||
"symfony/stopwatch": "7.3.*",
|
||||
"symfony/web-profiler-bundle": "7.3.*"
|
||||
}
|
||||
}
|
||||
Generated
-10511
File diff suppressed because it is too large
Load Diff
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||
Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true],
|
||||
Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
|
||||
];
|
||||
@@ -1,11 +0,0 @@
|
||||
framework:
|
||||
asset_mapper:
|
||||
# The paths to make available to the asset mapper.
|
||||
paths:
|
||||
- assets/
|
||||
missing_import_mode: strict
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
asset_mapper:
|
||||
missing_import_mode: warn
|
||||
@@ -1,19 +0,0 @@
|
||||
framework:
|
||||
cache:
|
||||
# Unique name of your app: used to compute stable namespaces for cache keys.
|
||||
#prefix_seed: your_vendor_name/app_name
|
||||
|
||||
# The "app" cache stores to the filesystem by default.
|
||||
# The data in this cache should persist between deploys.
|
||||
# Other options include:
|
||||
|
||||
# Redis
|
||||
#app: cache.adapter.redis
|
||||
#default_redis_provider: redis://localhost
|
||||
|
||||
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
|
||||
#app: cache.adapter.apcu
|
||||
|
||||
# Namespaced pools use the above "app" backend by default
|
||||
#pools:
|
||||
#my.dedicated.cache: null
|
||||
@@ -1,11 +0,0 @@
|
||||
# Enable stateless CSRF protection for forms and logins/logouts
|
||||
framework:
|
||||
form:
|
||||
csrf_protection:
|
||||
token_id: submit
|
||||
|
||||
csrf_protection:
|
||||
stateless_token_ids:
|
||||
- submit
|
||||
- authenticate
|
||||
- logout
|
||||
@@ -1,5 +0,0 @@
|
||||
when@dev:
|
||||
debug:
|
||||
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
|
||||
# See the "server:dump" command to start a new server.
|
||||
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
|
||||
@@ -1,50 +0,0 @@
|
||||
doctrine:
|
||||
dbal:
|
||||
url: '%env(resolve:DATABASE_URL)%'
|
||||
|
||||
# IMPORTANT: You MUST configure your server version,
|
||||
# either here or in the DATABASE_URL env var (see .env file)
|
||||
#server_version: '16'
|
||||
|
||||
profiling_collect_backtrace: '%kernel.debug%'
|
||||
use_savepoints: true
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
enable_lazy_ghost_objects: true
|
||||
report_fields_where_declared: true
|
||||
validate_xml_mapping: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
auto_mapping: true
|
||||
mappings:
|
||||
App:
|
||||
type: attribute
|
||||
is_bundle: false
|
||||
dir: '%kernel.project_dir%/src'
|
||||
prefix: 'App'
|
||||
alias: App
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
dbal:
|
||||
# "TEST_TOKEN" is typically set by ParaTest
|
||||
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
|
||||
|
||||
when@prod:
|
||||
doctrine:
|
||||
orm:
|
||||
auto_generate_proxy_classes: false
|
||||
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
|
||||
query_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.system_cache_pool
|
||||
result_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.result_cache_pool
|
||||
|
||||
framework:
|
||||
cache:
|
||||
pools:
|
||||
doctrine.result_cache_pool:
|
||||
adapter: cache.app
|
||||
doctrine.system_cache_pool:
|
||||
adapter: cache.system
|
||||
@@ -1,6 +0,0 @@
|
||||
doctrine_migrations:
|
||||
migrations_paths:
|
||||
# namespace is arbitrary but should be different from App\Migrations
|
||||
# as migrations classes should NOT be autoloaded
|
||||
'DoctrineMigrations': '%kernel.project_dir%/migrations'
|
||||
enable_profiler: false
|
||||
@@ -1,20 +0,0 @@
|
||||
# see https://symfony.com/doc/current/reference/configuration/framework.html
|
||||
framework:
|
||||
secret: '%env(APP_SECRET)%'
|
||||
|
||||
default_locale: 'en'
|
||||
translator:
|
||||
default_path: '%kernel.project_dir%/translations'
|
||||
fallbacks: ['en', 'nl']
|
||||
|
||||
# Note that the session will be started ONLY if you read or write from it.
|
||||
session: true
|
||||
|
||||
#esi: true
|
||||
#fragments: true
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
test: true
|
||||
session:
|
||||
storage_factory_id: session.storage.factory.mock_file
|
||||
@@ -1,3 +0,0 @@
|
||||
framework:
|
||||
mailer:
|
||||
dsn: '%env(MAILER_DSN)%'
|
||||
@@ -1,6 +0,0 @@
|
||||
mercure:
|
||||
hubs:
|
||||
default:
|
||||
url: '%env(MERCURE_URL)%'
|
||||
public_url: '%env(MERCURE_PUBLIC_URL)%'
|
||||
jwt: '%env(MERCURE_JWT_SECRET)%'
|
||||
@@ -1,29 +0,0 @@
|
||||
framework:
|
||||
messenger:
|
||||
failure_transport: failed
|
||||
|
||||
transports:
|
||||
# https://symfony.com/doc/current/messenger.html#transport-configuration
|
||||
async:
|
||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||
options:
|
||||
use_notify: true
|
||||
check_delayed_interval: 60000
|
||||
retry_strategy:
|
||||
max_retries: 3
|
||||
multiplier: 2
|
||||
failed: 'doctrine://default?queue_name=failed'
|
||||
# sync: 'sync://'
|
||||
|
||||
default_bus: messenger.bus.default
|
||||
|
||||
buses:
|
||||
messenger.bus.default: []
|
||||
|
||||
routing:
|
||||
Symfony\Component\Mailer\Messenger\SendEmailMessage: async
|
||||
Symfony\Component\Notifier\Message\ChatMessage: async
|
||||
Symfony\Component\Notifier\Message\SmsMessage: async
|
||||
|
||||
# Route your messages to the transports
|
||||
# 'App\Message\YourMessage': async
|
||||
@@ -1,62 +0,0 @@
|
||||
monolog:
|
||||
channels:
|
||||
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
|
||||
|
||||
when@dev:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
channels: ["!event"]
|
||||
# uncomment to get logging in your browser
|
||||
# you may have to allow bigger header sizes in your Web server configuration
|
||||
#firephp:
|
||||
# type: firephp
|
||||
# level: info
|
||||
#chromephp:
|
||||
# type: chromephp
|
||||
# level: info
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine", "!console"]
|
||||
|
||||
when@test:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
channels: ["!event"]
|
||||
nested:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
|
||||
when@prod:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
|
||||
nested:
|
||||
type: stream
|
||||
path: php://stderr
|
||||
level: debug
|
||||
formatter: monolog.formatter.json
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine"]
|
||||
deprecation:
|
||||
type: stream
|
||||
channels: [deprecation]
|
||||
path: php://stderr
|
||||
formatter: monolog.formatter.json
|
||||
@@ -1,13 +0,0 @@
|
||||
framework:
|
||||
notifier:
|
||||
chatter_transports:
|
||||
texter_transports:
|
||||
sendgrid: '%env(MAILER_DSN)%'
|
||||
channel_policy:
|
||||
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
|
||||
urgent: ['email']
|
||||
high: ['email']
|
||||
medium: ['email']
|
||||
low: ['email']
|
||||
admin_recipients:
|
||||
- { email: admin@example.com }
|
||||
@@ -1,3 +0,0 @@
|
||||
framework:
|
||||
property_info:
|
||||
with_constructor_extractor: true
|
||||
@@ -1,10 +0,0 @@
|
||||
framework:
|
||||
router:
|
||||
# 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
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
router:
|
||||
strict_requirements: null
|
||||
@@ -1,39 +0,0 @@
|
||||
security:
|
||||
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
|
||||
password_hashers:
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
|
||||
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
|
||||
providers:
|
||||
users_in_memory: { memory: null }
|
||||
firewalls:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
main:
|
||||
lazy: true
|
||||
provider: users_in_memory
|
||||
|
||||
# activate different ways to authenticate
|
||||
# https://symfony.com/doc/current/security.html#the-firewall
|
||||
|
||||
# https://symfony.com/doc/current/security/impersonating_user.html
|
||||
# switch_user: true
|
||||
|
||||
# Easy way to control access for large sections of your site
|
||||
# Note: Only the *first* access control that matches will be used
|
||||
access_control:
|
||||
# - { path: ^/admin, roles: ROLE_ADMIN }
|
||||
# - { path: ^/profile, roles: ROLE_USER }
|
||||
|
||||
when@test:
|
||||
security:
|
||||
password_hashers:
|
||||
# By default, password hashers are resource intensive and take time. This is
|
||||
# important to generate secure password hashes. In tests however, secure hashes
|
||||
# are not important, waste resources and increase test times. The following
|
||||
# reduces the work factor to the lowest possible values.
|
||||
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
|
||||
algorithm: auto
|
||||
cost: 4 # Lowest possible value for bcrypt
|
||||
time_cost: 3 # Lowest possible value for argon
|
||||
memory_cost: 10 # Lowest possible value for argon
|
||||
@@ -1,5 +0,0 @@
|
||||
framework:
|
||||
default_locale: en
|
||||
translator:
|
||||
default_path: '%kernel.project_dir%/translations'
|
||||
providers:
|
||||
@@ -1,4 +0,0 @@
|
||||
twig:
|
||||
globals:
|
||||
mercure_public_url: '%env(MERCURE_PUBLIC_URL)%'
|
||||
mercure_topic_base: '%env(MERCURE_TOPIC_BASE)%'
|
||||
@@ -1,4 +0,0 @@
|
||||
# Enable stateless CSRF protection for forms and logins/logouts
|
||||
framework:
|
||||
csrf_protection:
|
||||
check_header: true
|
||||
@@ -1,11 +0,0 @@
|
||||
framework:
|
||||
validation:
|
||||
# Enables validator auto-mapping support.
|
||||
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
|
||||
#auto_mapping:
|
||||
# App\Entity\: []
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
validation:
|
||||
not_compromised_password: false
|
||||
@@ -1,13 +0,0 @@
|
||||
when@dev:
|
||||
web_profiler:
|
||||
toolbar: true
|
||||
|
||||
framework:
|
||||
profiler:
|
||||
collect_serializer_data: true
|
||||
|
||||
when@test:
|
||||
framework:
|
||||
profiler:
|
||||
collect: false
|
||||
collect_serializer_data: true
|
||||
@@ -1,45 +0,0 @@
|
||||
webpack_encore:
|
||||
# The path where Encore is building the assets - i.e. Encore.setOutputPath()
|
||||
output_path: '%kernel.project_dir%/public/build'
|
||||
# If multiple builds are defined (as shown below), you can disable the default build:
|
||||
# output_path: false
|
||||
|
||||
# Set attributes that will be rendered on all script and link tags
|
||||
script_attributes:
|
||||
defer: true
|
||||
# Uncomment (also under link_attributes) if using Turbo Drive
|
||||
# https://turbo.hotwired.dev/handbook/drive#reloading-when-assets-change
|
||||
# 'data-turbo-track': reload
|
||||
# link_attributes:
|
||||
# Uncomment if using Turbo Drive
|
||||
# 'data-turbo-track': reload
|
||||
|
||||
# If using Encore.enableIntegrityHashes() and need the crossorigin attribute (default: false, or use 'anonymous' or 'use-credentials')
|
||||
# crossorigin: 'anonymous'
|
||||
|
||||
# Preload all rendered script and link tags automatically via the HTTP/2 Link header
|
||||
# preload: true
|
||||
|
||||
# Throw an exception if the entrypoints.json file is missing or an entry is missing from the data
|
||||
# strict_mode: false
|
||||
|
||||
# If you have multiple builds:
|
||||
# builds:
|
||||
# frontend: '%kernel.project_dir%/public/frontend/build'
|
||||
|
||||
# pass the build name as the 3rd argument to the Twig functions
|
||||
# {{ encore_entry_script_tags('entry1', null, 'frontend') }}
|
||||
|
||||
framework:
|
||||
assets:
|
||||
json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'
|
||||
|
||||
#when@prod:
|
||||
# webpack_encore:
|
||||
# # Cache the entrypoints.json (rebuild Symfony's cache when entrypoints.json changes)
|
||||
# # Available in version 1.2
|
||||
# cache: true
|
||||
|
||||
#when@test:
|
||||
# webpack_encore:
|
||||
# strict_mode: false
|
||||
@@ -1,5 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
|
||||
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
# Attribute-based routing imports for controllers in subnamespaces
|
||||
|
||||
website_controllers:
|
||||
resource:
|
||||
path: ../src/Website/Controller/
|
||||
namespace: App\Website\Controller
|
||||
type: attribute
|
||||
|
||||
game_controllers:
|
||||
resource:
|
||||
path: ../src/Game/Controller/
|
||||
namespace: App\Game\Controller
|
||||
type: attribute
|
||||
prefix: /game
|
||||
|
||||
# Uncomment when you add base controllers
|
||||
# base_controllers:
|
||||
# resource:
|
||||
# path: ../src/Base/Controller/
|
||||
# namespace: App\Base\Controller
|
||||
# type: attribute
|
||||
# # Set a prefix if desired, e.g., "/base" or leave empty to mount at root
|
||||
# # prefix: /base
|
||||
@@ -1,13 +0,0 @@
|
||||
website:
|
||||
resource: ../../src/Website/Controller/
|
||||
type: attribute
|
||||
prefix:
|
||||
en: '/'
|
||||
nl: '/nl'
|
||||
|
||||
game:
|
||||
resource: ../../src/Game/Controller/
|
||||
type: attribute
|
||||
prefix:
|
||||
en: '/game'
|
||||
nl: '/nl/game'
|
||||
@@ -1,4 +0,0 @@
|
||||
when@dev:
|
||||
_errors:
|
||||
resource: '@FrameworkBundle/Resources/config/routing/errors.php'
|
||||
prefix: /_error
|
||||
@@ -1,3 +0,0 @@
|
||||
_security_logout:
|
||||
resource: security.route_loader.logout
|
||||
type: service
|
||||
@@ -1,8 +0,0 @@
|
||||
when@dev:
|
||||
web_profiler_wdt:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/wdt.php'
|
||||
prefix: /_wdt
|
||||
|
||||
web_profiler_profiler:
|
||||
resource: '@WebProfilerBundle/Resources/config/routing/profiler.php'
|
||||
prefix: /_profiler
|
||||
@@ -1,20 +0,0 @@
|
||||
# This file is the entry point to configure your own services.
|
||||
# Files in the packages/ subdirectory configure your dependencies.
|
||||
|
||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||
parameters:
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
_defaults:
|
||||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
resource: '../src/'
|
||||
|
||||
# add more service definitions when explicit configuration is needed
|
||||
# please note that last definitions always *replace* previous ones
|
||||
@@ -1,138 +0,0 @@
|
||||
# Contribution & Code Style Guide
|
||||
|
||||
This document is for Junie (and humans) to keep our code style consistent and to quickly find the files we’ll reference during development of the Online Escape Room platform.
|
||||
|
||||
Project type: Symfony 7.3, PHP >= 8.5.1, Doctrine ORM 3, Twig, Stimulus (UX), Importmap/Asset Mapper, PHPUnit 11.
|
||||
|
||||
|
||||
## 1. Repository Conventions
|
||||
- PHP version: 8.5.1+ (composer.json enforces ">=8.5.1").
|
||||
- Framework: Symfony 7.3.* (see composer.json).
|
||||
- Architecture: MVC with Controllers in `src/Controller`, Entities in `src/Entity`, Repositories in `src/Repository`, Templates in `templates`.
|
||||
- Env files: `.env`, `.env.local` (ignored), and environment overrides like `.env.test.local`.
|
||||
- Routes: annotation/attributes in controllers or YAML/PHP in `config/routes`.
|
||||
- Documentation location: All documentation must live under the `doc/` directory. New docs requested by the team will be added there.
|
||||
|
||||
|
||||
## 2. Coding Standards
|
||||
|
||||
### 2.1 PHP
|
||||
- Standard: PSR-12 (line length soft cap 120; prefer multi-line for long signatures/arrays).
|
||||
- Strict types at top of new files: `declare(strict_types=1);`
|
||||
- Type-hint everything (params, returns, properties). Prefer readonly where applicable.
|
||||
- Visibility: declare on all properties and methods.
|
||||
- Exceptions: throw domain-specific exceptions for game logic; do not return null where an exception is appropriate.
|
||||
- Controllers: keep thin; delegate to services. Use DTOs/Form types to validate input.
|
||||
- Dependency Injection: constructor injection; avoid container-aware services.
|
||||
- Naming: Services suffixed with `...Service`, commands with `...Command`, event listeners with `...Listener`/`...Subscriber`.
|
||||
- Logging: use `Psr\Log\LoggerInterface` where meaningful.
|
||||
|
||||
### 2.2 Twig
|
||||
- Keep templates lean; no heavy logic. Use filters/functions and view models if needed.
|
||||
- Use `trans` for strings that will be localized.
|
||||
- Partial templates/components: place in `templates/_partials` or `templates/components`.
|
||||
|
||||
### 2.3 JavaScript (Stimulus / vanilla)
|
||||
- Use ES modules via Importmap/Asset Mapper.
|
||||
- Controllers in `assets/controllers`. Name as `something_controller.js` following Stimulus conventions.
|
||||
- Prefer small, focused controllers. Keep DOM queries scoped to controller element.
|
||||
- Avoid global state; communicate via events or Turbo streams when appropriate.
|
||||
|
||||
### 2.4 Styles (CSS/SCSS)
|
||||
- Keep styles in `assets/styles`. Use BEM naming for classes.
|
||||
- Prefer CSS variables for theme colors, spacing scale, z-index scale.
|
||||
|
||||
### 2.5 YAML / Config
|
||||
- 2-space indentation, no tabs.
|
||||
- Use parameters and env vars (`env()`) instead of hardcoding secrets.
|
||||
|
||||
### 2.6 Git & Commits
|
||||
- Branch naming: `feature/<short-name>`, `fix/<short-name>`, `chore/<short-name>`.
|
||||
- Commit messages:
|
||||
- Conventional commits style: `feat: ...`, `fix: ...`, `chore: ...`, `docs: ...`, `test: ...`, `refactor: ...`.
|
||||
- First line ≤ 72 chars; add body when needed with rationale.
|
||||
|
||||
|
||||
## 3. Linting, Tests, and Quality
|
||||
|
||||
### 3.1 PHP
|
||||
- Use PHP-CS-Fixer or PHP_CodeSniffer (PHPCS) with PSR-12. If not yet installed, proposed composer scripts (to add later):
|
||||
- `composer require --dev friendsofphp/php-cs-fixer`
|
||||
- Script: `php-cs-fixer fix --allow-risky=yes`
|
||||
- Static analysis: PHPStan level 6–8 recommended:
|
||||
- `composer require --dev phpstan/phpstan`
|
||||
- Run: `vendor/bin/phpstan analyse src tests` (configure `phpstan.neon` later)
|
||||
|
||||
### 3.2 Symfony
|
||||
- Cache and debug:
|
||||
- `php bin/console cache:clear`
|
||||
- `php bin/console debug:router`
|
||||
- `php bin/console debug:container`
|
||||
|
||||
### 3.3 Tests
|
||||
- PHPUnit (already required):
|
||||
- Run tests: `vendor/bin/phpunit`
|
||||
- Tests location: `tests/`
|
||||
- Config: `phpunit.dist.xml`
|
||||
|
||||
### 3.4 Frontend
|
||||
- Stimulus/UX: controllers auto-registered via `symfony/stimulus-bundle`.
|
||||
- Asset Mapper/Importmap:
|
||||
- Install deps: `php bin/console importmap:install`
|
||||
- Dev server (if using symfony local server): `symfony server:start -d`
|
||||
|
||||
|
||||
## 4. Project File Map (Quick Reference)
|
||||
- App kernel: `src/Kernel.php`
|
||||
- Controllers: `src/Controller/`
|
||||
- Domain entities: `src/Entity/`
|
||||
- Repositories: `src/Repository/`
|
||||
- Migrations: `migrations/`
|
||||
- Templates: `templates/`
|
||||
- Translations: `translations/`
|
||||
- Assets entry: `assets/app.js`, styles in `assets/styles/`
|
||||
- Stimulus controllers: `assets/controllers/`
|
||||
- Routes: `config/routes/`
|
||||
- Packages config: `config/packages/`
|
||||
- Env vars: `.env` (base), `.env.local` (local overrides)
|
||||
- Public web root: `public/`
|
||||
- Tests: `tests/`
|
||||
|
||||
|
||||
## 5. How We Build Features (Checklist)
|
||||
1) Create branch: `feature/<name>`.
|
||||
2) Describe the task in an issue with acceptance criteria.
|
||||
3) Implement backend (entities/services/controllers) with tests.
|
||||
4) Implement templates and Stimulus controller if interactive.
|
||||
5) Add/adjust routes and translations.
|
||||
6) Run: linters, phpstan, phpunit; ensure green.
|
||||
7) Open PR; request review.
|
||||
|
||||
|
||||
## 6. Escape Room Domain Notes (early)
|
||||
- Core concepts likely: Game, Room, Puzzle, Session, Player, Team, Hint, Timer.
|
||||
- Consider events (Domain Events) for puzzle solved, hint requested, time warnings.
|
||||
- Real-time collaboration options: Symfony Mercure, WebSockets, or Turbo Streams.
|
||||
- Persist immutable audit trail for gameplay.
|
||||
|
||||
|
||||
## 7. Editor Configuration
|
||||
- Recommend EditorConfig. If we add `.editorconfig` later, set:
|
||||
- Indent 4 spaces for PHP, 2 for YAML/Twig/JS/CSS.
|
||||
- LF line endings, UTF-8, insert final newline, trim trailing whitespace.
|
||||
|
||||
|
||||
## 8. Security & Secrets
|
||||
- Never commit secrets. Use environment variables or Symfony Vault.
|
||||
- Review `APP_ENV`, `APP_SECRET`, database DSN in `.env` and `.env.local`.
|
||||
|
||||
|
||||
## 9. Release & Environments
|
||||
- Envs: `dev`, `test`, `prod`.
|
||||
- Build steps: run migrations, warmup cache, compile assets if using.
|
||||
|
||||
|
||||
## 10. References
|
||||
- Symfony Best Practices: https://symfony.com/doc/current/best_practices.html
|
||||
- Doctrine ORM 3 Docs: https://www.doctrine-project.org/projects/doctrine-orm/en/current/
|
||||
- Stimulus: https://stimulus.hotwired.dev/
|
||||
@@ -1,51 +0,0 @@
|
||||
# Project File Index (Quick Reference)
|
||||
|
||||
Use this index to quickly locate files and directories during development and in discussions.
|
||||
|
||||
## Top-Level
|
||||
- docker/compose.yaml / docker/compose.override.yaml — Docker services.
|
||||
- docker/ — Docker build contexts and configs (php Dockerfile, nginx vhost, compose files).
|
||||
- composer.json / composer.lock — Dependencies and scripts.
|
||||
- importmap.php — Importmap configuration for JS dependencies.
|
||||
- phpunit.dist.xml — PHPUnit configuration.
|
||||
- public/ — Web root (index.php, assets, static files).
|
||||
- var/ — Cache and logs.
|
||||
- vendor/ — Composer dependencies.
|
||||
|
||||
## Application Source (src/)
|
||||
- src/Kernel.php — Symfony Kernel bootstrapping.
|
||||
- src/Website/ — Marketing/public website area (controllers, templates under templates/website/).
|
||||
- src/Game/ — Game area (controllers, templates under templates/game/).
|
||||
- src/Entity/ — Doctrine ORM entities.
|
||||
- src/Repository/ — Doctrine repositories.
|
||||
|
||||
## Configuration (config/)
|
||||
- config/packages/ — Symfony bundles configuration (framework.yaml, cache.yaml, etc.).
|
||||
- config/routes/ — Routing configuration files.
|
||||
- config/routes/app.yaml — Imports attribute routes for both sites (Website and Game).
|
||||
|
||||
## Data & DB
|
||||
- migrations/ — Doctrine migrations.
|
||||
|
||||
## Presentation
|
||||
- templates/ — Twig templates.
|
||||
- templates/website — Views for the public website.
|
||||
- templates/game — Views for the game area.
|
||||
- translations/ — i18n message files.
|
||||
|
||||
## Frontend Assets
|
||||
- assets/app.js — Main JS entry (imports Stimulus, styles, etc.).
|
||||
- assets/controllers/ — Stimulus controllers.
|
||||
- assets/styles/ — Global styles.
|
||||
- assets/vendor/ — Vendor frontend assets if any.
|
||||
|
||||
## Tests
|
||||
- tests/ — Test suites for PHPUnit.
|
||||
|
||||
## Environment
|
||||
- .env — Base environment configuration.
|
||||
- .env.local — Local overrides (ignored).
|
||||
|
||||
## Notes
|
||||
- Follow doc/CONTRIBUTING.md for code style and workflows.
|
||||
- Email setup: see doc/email.md for dev Mailpit and production SendGrid configuration.
|
||||
@@ -1,10 +0,0 @@
|
||||
# Project Documentation
|
||||
|
||||
This directory contains all project documentation for EscapePage.
|
||||
|
||||
- Code Style & Contribution Guide: CONTRIBUTING.md
|
||||
- Project File Index: FILES.md
|
||||
|
||||
Policy: All new and existing documentation must be placed in this doc/ directory. If you ask Junie to add docs in the future, they will be created under doc/.
|
||||
|
||||
Additional docs can be added here as the project grows (architecture decisions, API docs, gameplay design, onboarding, etc.).
|
||||
@@ -1,60 +0,0 @@
|
||||
# Docker Setup
|
||||
|
||||
This app can run fully in Docker using docker compose with PHP-FPM, Nginx and MySQL.
|
||||
|
||||
## Services
|
||||
- php: PHP 8.5.1 FPM with required extensions and Composer
|
||||
- nginx: Serves the Symfony app from public/ and proxies PHP to php-fpm
|
||||
- database: MySQL 8.0 (data persisted in a volume)
|
||||
- mailer (dev only via compose.override.yaml): Mailpit (SMTP/UI)
|
||||
|
||||
## Prerequisites
|
||||
- Docker and Docker Compose (v2)
|
||||
|
||||
## Usage
|
||||
|
||||
### 1) Build and start
|
||||
```
|
||||
./docker/setup.sh
|
||||
```
|
||||
App will be served at http://localhost:8080
|
||||
|
||||
Alternatively (manual):
|
||||
```
|
||||
docker compose -f docker/compose.yaml -f docker/compose.override.yaml up -d --build
|
||||
```
|
||||
|
||||
### 2) Install dependencies
|
||||
The setup script already runs composer install. To run manually:
|
||||
```
|
||||
docker compose -f docker/compose.yaml -f docker/compose.override.yaml exec php composer install
|
||||
```
|
||||
|
||||
### 3) Prepare DB
|
||||
The setup script already prepares the DB. To run manually:
|
||||
```
|
||||
docker compose -f docker/compose.yaml -f docker/compose.override.yaml exec php php bin/console doctrine:database:create --if-not-exists
|
||||
docker compose -f docker/compose.yaml -f docker/compose.override.yaml exec php php bin/console doctrine:migrations:migrate -n
|
||||
```
|
||||
|
||||
### 4) Run tests
|
||||
```
|
||||
docker compose -f docker/compose.yaml -f docker/compose.override.yaml exec php vendor/bin/phpunit
|
||||
```
|
||||
|
||||
### 5) Logs
|
||||
```
|
||||
docker compose -f docker/compose.yaml -f docker/compose.override.yaml logs -f nginx
|
||||
docker compose -f docker/compose.yaml -f docker/compose.override.yaml logs -f php
|
||||
```
|
||||
|
||||
### 6) Stop
|
||||
```
|
||||
docker compose -f docker/compose.yaml -f docker/compose.override.yaml down
|
||||
```
|
||||
|
||||
## Notes
|
||||
- .env already points DATABASE_URL to the `database` service hostname.
|
||||
- Nginx listens on port 8080 (mapped from container 80) to avoid conflicts.
|
||||
- Source is bind-mounted; changes on host reflect inside containers.
|
||||
- For production images, create a separate Dockerfile with build steps (composer install --no-dev, cache warmup) and avoid bind mounts.
|
||||
@@ -1,45 +0,0 @@
|
||||
# Email Delivery: Dev Mailcatcher & Production SendGrid
|
||||
|
||||
This application uses Symfony Mailer. We separate development and production delivery:
|
||||
|
||||
- Development: Mailpit (mailcatcher) via SMTP in Docker.
|
||||
- Production: SendGrid via API transport.
|
||||
|
||||
## Development (Mailpit)
|
||||
|
||||
- Service is defined in `compose.override.yaml` as `mailer` (axllent/mailpit).
|
||||
- Ports:
|
||||
- SMTP: 1025 (mapped to host 1025)
|
||||
- Web UI: 8025 (mapped to host 8025)
|
||||
- Default DSN for dev is set in `.env`:
|
||||
|
||||
```
|
||||
MAILER_DSN=smtp://mailer:1025
|
||||
```
|
||||
|
||||
- Usage:
|
||||
1. Start stack: `docker compose up -d`
|
||||
2. Send an email from the app.
|
||||
3. Open http://localhost:8025 to view captured emails.
|
||||
|
||||
## Production (SendGrid)
|
||||
|
||||
Use the SendGrid API transport. Do not commit secrets.
|
||||
|
||||
- Example configuration is in `.env.prod`:
|
||||
|
||||
```
|
||||
MAILER_DSN=sendgrid+api://%env(resolve:SENDGRID_API_KEY)%@default
|
||||
```
|
||||
|
||||
- Provide `SENDGRID_API_KEY` via:
|
||||
- Real environment variable on the server/container, or
|
||||
- Symfony secrets: `php bin/console secrets:set SENDGRID_API_KEY` (and dump for prod), or
|
||||
- Orchestration secret stores (e.g., Docker/K8s).
|
||||
|
||||
### Notes
|
||||
- No Mailpit container is defined in the base `compose.yaml`, only in `compose.override.yaml`. This ensures it is used in development only.
|
||||
- To test email locally without Docker, you can:
|
||||
- Run Mailpit on your host (ports 1025/8025) and set `MAILER_DSN=smtp://127.0.0.1:1025` in `.env.local`.
|
||||
- If you need to use SendGrid SMTP instead of API, a DSN example:
|
||||
`smtp://apikey:YOUR_SENDGRID_API_KEY@smtp.sendgrid.net:587`.
|
||||
@@ -1,26 +0,0 @@
|
||||
|
||||
services:
|
||||
php:
|
||||
environment:
|
||||
XDEBUG_MODE: off
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
depends_on:
|
||||
- mailer
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
database:
|
||||
ports:
|
||||
- "3306"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> symfony/mailer ###
|
||||
mailer:
|
||||
image: axllent/mailpit
|
||||
ports:
|
||||
- "1025:1025"
|
||||
- "8025:8025"
|
||||
environment:
|
||||
MP_SMTP_AUTH_ACCEPT_ANY: 1
|
||||
MP_SMTP_AUTH_ALLOW_INSECURE: 1
|
||||
###< symfony/mailer ###
|
||||
@@ -1,96 +0,0 @@
|
||||
|
||||
version: '3.7'
|
||||
|
||||
services:
|
||||
php:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: php/Dockerfile
|
||||
container_name: escapepage-php
|
||||
volumes:
|
||||
- ../:/var/www/html:delegated
|
||||
environment:
|
||||
APP_ENV: dev
|
||||
depends_on:
|
||||
- database
|
||||
- mercure
|
||||
networks:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
|
||||
nginx:
|
||||
image: nginx:1.29.4-alpine
|
||||
container_name: escapepage-nginx
|
||||
ports:
|
||||
- "8080:80"
|
||||
volumes:
|
||||
- ../:/var/www/html:ro
|
||||
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
depends_on:
|
||||
- php
|
||||
networks:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
|
||||
mailer:
|
||||
image: axllent/mailpit:latest
|
||||
container_name: escapepage-mailer
|
||||
ports:
|
||||
- "8025:8025"
|
||||
networks:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
|
||||
mercure:
|
||||
image: dunglas/mercure:v0.21
|
||||
container_name: escapepage-mercure
|
||||
environment:
|
||||
SERVER_NAME: ":80"
|
||||
MERCURE_PUBLISHER_JWT_KEY: ${MERCURE_JWT_SECRET:-!ChangeThisMercureJWT!}
|
||||
MERCURE_SUBSCRIBER_JWT_KEY: ${MERCURE_JWT_SECRET:-!ChangeThisMercureJWT!}
|
||||
MERCURE_CORS_ALLOWED_ORIGINS: http://localhost:8080
|
||||
MERCURE_PUBLISH_ALLOWED_ORIGINS: http://localhost:8080
|
||||
MERCURE_EXTRA_DIRECTIVES: |
|
||||
cors_origins http://localhost:8080
|
||||
# Allow anonymous subscribers in dev only
|
||||
anonymous
|
||||
ports:
|
||||
- "8090:80"
|
||||
networks:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
database:
|
||||
image: mysql:8.0
|
||||
container_name: escapepage-db
|
||||
environment:
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-app}
|
||||
MYSQL_USER: ${MYSQL_USER:-app}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-!ChangeMe!}
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root}
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-p${MYSQL_ROOT_PASSWORD:-root}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 30s
|
||||
command: ["--default-authentication-plugin=mysql_native_password", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
|
||||
volumes:
|
||||
- database_data:/var/lib/mysql:rw
|
||||
# Uncomment the two lines below if you need to access MySQL from your host (workbench, etc.)
|
||||
# ports:
|
||||
# - "3306:3306"
|
||||
networks:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
volumes:
|
||||
###> doctrine/doctrine-bundle ###
|
||||
database_data:
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
networks:
|
||||
backend:
|
||||
driver: bridge
|
||||
@@ -1,28 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
root /var/www/html/public;
|
||||
index index.php index.html;
|
||||
|
||||
access_log /var/log/nginx/access.log;
|
||||
error_log /var/log/nginx/error.log;
|
||||
|
||||
location / {
|
||||
try_files $uri /index.php$is_args$args;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_read_timeout 120;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
|
||||
client_max_body_size 32m;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
FROM php:8.5.1-fpm-alpine3.23
|
||||
|
||||
# Install system deps
|
||||
RUN apk add --no-cache bash git icu-dev libzip-dev oniguruma-dev
|
||||
|
||||
# Install PHP extensions
|
||||
RUN docker-php-ext-configure intl \
|
||||
&& docker-php-ext-install -j$(nproc) intl pdo pdo_mysql opcache
|
||||
|
||||
# Install composer
|
||||
ENV COMPOSER_ALLOW_SUPERUSER=1 \
|
||||
COMPOSER_HOME=/tmp/composer
|
||||
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||
|
||||
# Configure PHP
|
||||
COPY php.ini $PHP_INI_DIR/conf.d/zz-custom.ini
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
# Default command
|
||||
CMD ["php-fpm"]
|
||||
@@ -1,9 +0,0 @@
|
||||
memory_limit=512M
|
||||
post_max_size=32M
|
||||
upload_max_filesize=32M
|
||||
max_execution_time=60
|
||||
; For Symfony dev
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.validate_timestamps=1
|
||||
opcache.revalidate_freq=0
|
||||
-126
@@ -1,126 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Simple setup script to bootstrap the Dockerized dev stack for this project.
|
||||
# - Builds and starts containers (php, nginx, mariadb, mailpit via override)
|
||||
# - Installs composer dependencies
|
||||
# - Ensures APP_SECRET is set (generates if empty)
|
||||
# - Creates and migrates the database
|
||||
# - Installs/imports JS dependencies
|
||||
# - Prints helpful info on success
|
||||
|
||||
# Usage:
|
||||
# ./docker/setup.sh # full setup
|
||||
# ./docker/setup.sh --no-build # skip image rebuild
|
||||
# ./docker/setup.sh --down # stop and remove containers (down)
|
||||
# ./docker/setup.sh --recreate # force recreate containers
|
||||
|
||||
ROOT_DIR=$(cd "$(dirname "$0")"/.. && pwd)
|
||||
DOCKER_DIR="$ROOT_DIR/docker"
|
||||
# Determine the docker compose command (V2 'docker compose' or V1 'docker-compose')
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
DOCKER_COMPOSE="docker compose"
|
||||
elif command -v docker-compose >/dev/null 2>&1; then
|
||||
DOCKER_COMPOSE="docker-compose"
|
||||
else
|
||||
echo "Error: Neither 'docker compose' nor 'docker-compose' was found. Please install Docker Compose." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Helper to run docker compose from the docker/ directory
|
||||
dc() { (cd "$DOCKER_DIR" && $DOCKER_COMPOSE -f compose.yaml "$@"); }
|
||||
|
||||
REBUILD=1
|
||||
RECREATE=0
|
||||
DOWN_ONLY=0
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--no-build) REBUILD=0 ;;
|
||||
--recreate) RECREATE=1 ;;
|
||||
--down) DOWN_ONLY=1 ;;
|
||||
*) echo "Unknown option: $arg" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
need() { command -v "$1" >/dev/null 2>&1 || { echo "Error: '$1' is required but not installed." >&2; exit 1; }; }
|
||||
|
||||
need docker
|
||||
|
||||
if [ "$DOWN_ONLY" -eq 1 ]; then
|
||||
dc down
|
||||
exit 0
|
||||
fi
|
||||
|
||||
BUILD_ARGS=()
|
||||
if [ "$REBUILD" -eq 1 ]; then
|
||||
BUILD_ARGS+=("--build")
|
||||
fi
|
||||
if [ "$RECREATE" -eq 1 ]; then
|
||||
BUILD_ARGS+=("--force-recreate")
|
||||
fi
|
||||
|
||||
# Start stack
|
||||
dc up "${BUILD_ARGS[@]}"
|
||||
|
||||
# Helper to run commands in php container
|
||||
pexec() { dc exec -T php "$@"; }
|
||||
|
||||
# Wait for database to be healthy (mariadb)
|
||||
printf "Waiting for database to be healthy..."
|
||||
# Use docker inspect health status
|
||||
DB_HEALTH=""
|
||||
for i in {1..60}; do
|
||||
DB_HEALTH=$(docker inspect -f '{{.State.Health.Status}}' "$(docker ps --filter name=_database_ --format '{{.ID}}' | head -n1)" 2>/dev/null || true)
|
||||
if [ "$DB_HEALTH" = "healthy" ]; then
|
||||
echo " OK"
|
||||
break
|
||||
fi
|
||||
printf "."
|
||||
sleep 2
|
||||
if [ "$i" -eq 60 ]; then
|
||||
echo "\nWarning: database health check not healthy yet, continuing anyway."
|
||||
fi
|
||||
done
|
||||
|
||||
# Ensure composer is available and install dependencies
|
||||
pexec composer install --no-interaction
|
||||
|
||||
# Ensure APP_SECRET is set
|
||||
if grep -q '^APP_SECRET=$' "$ROOT_DIR/.env" 2>/dev/null; then
|
||||
echo "Generating APP_SECRET in .env.local..."
|
||||
mkdir -p "$ROOT_DIR"
|
||||
SECRET=$(openssl rand -hex 16)
|
||||
# Write to .env.local so we don't commit it
|
||||
if [ ! -f "$ROOT_DIR/.env.local" ]; then
|
||||
printf "APP_SECRET=%s\n" "$SECRET" > "$ROOT_DIR/.env.local"
|
||||
elif ! grep -q '^APP_SECRET=' "$ROOT_DIR/.env.local"; then
|
||||
printf "APP_SECRET=%s\n" "$SECRET" >> "$ROOT_DIR/.env.local"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prepare DB
|
||||
pexec php bin/console doctrine:database:create --if-not-exists || true
|
||||
pexec php bin/console doctrine:migrations:migrate -n || true
|
||||
|
||||
# Import JS deps (Importmap/Asset Mapper)
|
||||
pexec php bin/console importmap:install || true
|
||||
|
||||
APP_URL=http://localhost:8080
|
||||
MAILPIT_URL=http://localhost:8025
|
||||
|
||||
cat <<EOT
|
||||
|
||||
Setup complete!
|
||||
|
||||
Open the app: $APP_URL
|
||||
Mailpit (dev): $MAILPIT_URL
|
||||
|
||||
Common commands:
|
||||
(cd docker && $DOCKER_COMPOSE logs -f nginx)
|
||||
(cd docker && $DOCKER_COMPOSE logs -f php)
|
||||
(cd docker && $DOCKER_COMPOSE exec php bash)
|
||||
(cd docker && $DOCKER_COMPOSE down)
|
||||
|
||||
You can re-run this script any time. Use --no-build to skip rebuilding images.
|
||||
EOT
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Returns the importmap for this application.
|
||||
*
|
||||
* - "path" is a path inside the asset mapper system. Use the
|
||||
* "debug:asset-map" command to see the full list of paths.
|
||||
*
|
||||
* - "entrypoint" (JavaScript only) set to true for any module that will
|
||||
* be used as an "entrypoint" (and passed to the importmap() Twig function).
|
||||
*
|
||||
* The "importmap:require" command can be used to add new entries to this file.
|
||||
*/
|
||||
return [
|
||||
'app' => [
|
||||
'path' => './assets/app.js',
|
||||
'entrypoint' => true,
|
||||
],
|
||||
'@hotwired/stimulus' => [
|
||||
'version' => '3.2.2',
|
||||
],
|
||||
'@symfony/stimulus-bundle' => [
|
||||
'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js',
|
||||
],
|
||||
'@hotwired/turbo' => [
|
||||
'version' => '7.3.0',
|
||||
],
|
||||
];
|
||||
Generated
-8205
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "escapepage",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "EscapePage Symfony app assets built with Webpack Encore",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"dev": "encore dev",
|
||||
"watch": "encore dev --watch",
|
||||
"build": "encore production"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.0",
|
||||
"@babel/preset-env": "^7.25.0",
|
||||
"@symfony/webpack-encore": "^4.6.1",
|
||||
"babel-loader": "^9.1.3",
|
||||
"core-js": "^3.37.1",
|
||||
"css-loader": "^7.1.2",
|
||||
"mini-css-extract-plugin": "^2.9.2",
|
||||
"regenerator-runtime": "^0.14.1",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-notifier": "^1.15.0"
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
failOnDeprecation="true"
|
||||
failOnNotice="true"
|
||||
failOnWarning="true"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
cacheDirectory=".phpunit.cache"
|
||||
>
|
||||
<php>
|
||||
<ini name="display_errors" value="1" />
|
||||
<ini name="error_reporting" value="-1" />
|
||||
<server name="APP_ENV" value="test" force="true" />
|
||||
<server name="SHELL_VERBOSITY" value="-1" />
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="Project Test Suite">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<source ignoreSuppressionOfDeprecations="true"
|
||||
ignoreIndirectDeprecations="true"
|
||||
restrictNotices="true"
|
||||
restrictWarnings="true"
|
||||
>
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
|
||||
<deprecationTrigger>
|
||||
<method>Doctrine\Deprecations\Deprecation::trigger</method>
|
||||
<method>Doctrine\Deprecations\Deprecation::delegateTriggerToBackend</method>
|
||||
<function>trigger_deprecation</function>
|
||||
</deprecationTrigger>
|
||||
</source>
|
||||
|
||||
<extensions>
|
||||
</extensions>
|
||||
</phpunit>
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Kernel;
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
};
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\HttpClient\HttpClient;
|
||||
use Symfony\Component\Mercure\HubInterface;
|
||||
use Symfony\Component\Mercure\Update;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'app:mercure:publish',
|
||||
description: 'Publishes a test update to the Mercure hub.'
|
||||
)]
|
||||
final class MercurePublishCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly HubInterface $hub)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addArgument('topic', InputArgument::OPTIONAL, 'Topic URL to publish to', $_ENV['MERCURE_TOPIC_BASE'] . '/game/hub')
|
||||
->addOption('type', null, InputOption::VALUE_REQUIRED, 'Update type (for clients to filter)', 'game.event')
|
||||
->addOption('data', null, InputOption::VALUE_REQUIRED, 'JSON payload to send', '{"message":"Hello from Mercure!"}')
|
||||
->addOption('private', null, InputOption::VALUE_NONE, 'Mark the update as private');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$topic = (string) $input->getArgument('topic');
|
||||
$type = (string) $input->getOption('type');
|
||||
$data = (string) $input->getOption('data');
|
||||
$isPrivate = (bool) $input->getOption('private');
|
||||
|
||||
// Validate JSON
|
||||
$decoded = json_decode($data, true);
|
||||
if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) {
|
||||
$output->writeln('<error>Invalid JSON provided for --data.</error>');
|
||||
return Command::FAILURE;
|
||||
}
|
||||
|
||||
$update = new Update(
|
||||
topics: $topic,
|
||||
data: json_encode([
|
||||
'type' => $type,
|
||||
'payload' => $decoded,
|
||||
'ts' => date('c'),
|
||||
], JSON_THROW_ON_ERROR),
|
||||
private: $isPrivate
|
||||
);
|
||||
|
||||
$this->hub->publish($update);
|
||||
|
||||
$output->writeln('<info>Published update to topic:</info> ' . $topic);
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'app:mail:test',
|
||||
description: 'Sends a simple test email using the configured mail transport (SendGrid in prod).'
|
||||
)]
|
||||
final class TestEmailCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly MailerInterface $mailer)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->addArgument('to', InputArgument::REQUIRED, 'Recipient email address')
|
||||
->addOption('subject', null, InputOption::VALUE_REQUIRED, 'Email subject', 'EscapePage mailer test')
|
||||
->addOption('from', null, InputOption::VALUE_REQUIRED, 'Sender email address (defaults to MAILER_FROM if set)')
|
||||
->addOption('from-name', null, InputOption::VALUE_REQUIRED, 'Sender name', 'EscapePage');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$to = (string) $input->getArgument('to');
|
||||
$subject = (string) $input->getOption('subject');
|
||||
$fromEmail = (string) ($input->getOption('from') ?? ($_ENV['MAILER_FROM'] ?? $_SERVER['MAILER_FROM'] ?? 'no-reply@example.com'));
|
||||
$fromName = (string) $input->getOption('from-name');
|
||||
|
||||
$email = (new Email())
|
||||
->from(new Address($fromEmail, $fromName))
|
||||
->to($to)
|
||||
->subject($subject)
|
||||
->html('<p>This is a test email sent at ' . date('c') . '.</p><p>If you see this, your mailer setup works.</p>')
|
||||
->text('This is a test email sent at ' . date('c') . ". If you see this, your mailer setup works.");
|
||||
|
||||
$this->mailer->send($email);
|
||||
|
||||
$output->writeln('<info>Test email sent to ' . $to . '.</info>');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Game\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
#[Route('/game/api', name: 'game_api_')]
|
||||
final class GameApiController extends AbstractController
|
||||
{
|
||||
#[Route('/ping', name: 'ping', methods: ['GET'])]
|
||||
public function ping(): JsonResponse
|
||||
{
|
||||
return $this->json([
|
||||
'ok' => true,
|
||||
'service' => 'game-api',
|
||||
'ts' => date('c'),
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/echo', name: 'echo', methods: ['POST'])]
|
||||
public function echo(Request $request): JsonResponse
|
||||
{
|
||||
$raw = (string) $request->getContent();
|
||||
$data = null;
|
||||
if ($raw !== '') {
|
||||
try {
|
||||
/** @var array<string,mixed>|null $decoded */
|
||||
$decoded = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
|
||||
$data = $decoded;
|
||||
} catch (\Throwable $e) {
|
||||
return $this->json([
|
||||
'ok' => false,
|
||||
'error' => 'Invalid JSON: ' . $e->getMessage(),
|
||||
], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->json([
|
||||
'ok' => true,
|
||||
'received' => $data,
|
||||
'ts' => date('c'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Game\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
final class GameController extends AbstractController
|
||||
{
|
||||
#[Route(path: '', name: 'game')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('game/index.html.twig');
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
|
||||
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||
|
||||
class Kernel extends BaseKernel
|
||||
{
|
||||
use MicroKernelTrait;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Website\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
final class HomeController extends AbstractController
|
||||
{
|
||||
#[Route(path: '', name: 'website_home')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render(
|
||||
'website/home/index.html.twig');
|
||||
}
|
||||
}
|
||||
-362
@@ -1,362 +0,0 @@
|
||||
{
|
||||
"doctrine/deprecations": {
|
||||
"version": "1.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "87424683adc81d7dc305eefec1fced883084aab9"
|
||||
}
|
||||
},
|
||||
"doctrine/doctrine-bundle": {
|
||||
"version": "2.16",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.13",
|
||||
"ref": "620b57f496f2e599a6015a9fa222c2ee0a32adcb"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/doctrine.yaml",
|
||||
"src/Entity/.gitignore",
|
||||
"src/Repository/.gitignore"
|
||||
]
|
||||
},
|
||||
"doctrine/doctrine-migrations-bundle": {
|
||||
"version": "3.4",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "3.1",
|
||||
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/doctrine_migrations.yaml",
|
||||
"migrations/.gitignore"
|
||||
]
|
||||
},
|
||||
"phpunit/phpunit": {
|
||||
"version": "11.5",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "11.1",
|
||||
"ref": "c6658a60fc9d594805370eacdf542c3d6b5c0869"
|
||||
},
|
||||
"files": [
|
||||
".env.test",
|
||||
"phpunit.dist.xml",
|
||||
"tests/bootstrap.php",
|
||||
"bin/phpunit"
|
||||
]
|
||||
},
|
||||
"symfony/asset-mapper": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.4",
|
||||
"ref": "5ad1308aa756d58f999ffbe1540d1189f5d7d14a"
|
||||
},
|
||||
"files": [
|
||||
"assets/app.js",
|
||||
"assets/styles/app.css",
|
||||
"config/packages/asset_mapper.yaml",
|
||||
"importmap.php"
|
||||
]
|
||||
},
|
||||
"symfony/console": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "5.3",
|
||||
"ref": "1781ff40d8a17d87cf53f8d4cf0c8346ed2bb461"
|
||||
},
|
||||
"files": [
|
||||
"bin/console"
|
||||
]
|
||||
},
|
||||
"symfony/debug-bundle": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "5.3",
|
||||
"ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/debug.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/flex": {
|
||||
"version": "2.8",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.4",
|
||||
"ref": "52e9754527a15e2b79d9a610f98185a1fe46622a"
|
||||
},
|
||||
"files": [
|
||||
".env",
|
||||
".env.dev"
|
||||
]
|
||||
},
|
||||
"symfony/form": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.2",
|
||||
"ref": "7d86a6723f4a623f59e2bf966b6aad2fc461d36b"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/csrf.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/framework-bundle": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.3",
|
||||
"ref": "5a1497d539f691b96afd45ae397ce5fe30beb4b9"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/cache.yaml",
|
||||
"config/packages/framework.yaml",
|
||||
"config/preload.php",
|
||||
"config/routes/framework.yaml",
|
||||
"config/services.yaml",
|
||||
"public/index.php",
|
||||
"src/Controller/.gitignore",
|
||||
"src/Kernel.php",
|
||||
".editorconfig"
|
||||
]
|
||||
},
|
||||
"symfony/mailer": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "4.3",
|
||||
"ref": "09051cfde49476e3c12cd3a0e44289ace1c75a4f"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/mailer.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/maker-bundle": {
|
||||
"version": "1.64",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
|
||||
}
|
||||
},
|
||||
"symfony/mercure-bundle": {
|
||||
"version": "0.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "0.3",
|
||||
"ref": "528285147494380298f8f991ee8c47abebaf79db"
|
||||
},
|
||||
"files": [
|
||||
"./config/packages/mercure.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/messenger": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.0",
|
||||
"ref": "ba1ac4e919baba5644d31b57a3284d6ba12d52ee"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/messenger.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/monolog-bundle": {
|
||||
"version": "3.10",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "3.7",
|
||||
"ref": "aff23899c4440dd995907613c1dd709b6f59503f"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/monolog.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/notifier": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "5.0",
|
||||
"ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/notifier.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/property-info": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.3",
|
||||
"ref": "dae70df71978ae9226ae915ffd5fad817f5ca1f7"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/property_info.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/routing": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.0",
|
||||
"ref": "21b72649d5622d8f7da329ffb5afb232a023619d"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/routing.yaml",
|
||||
"config/routes.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/security-bundle": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.4",
|
||||
"ref": "2ae08430db28c8eb4476605894296c82a642028f"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/security.yaml",
|
||||
"config/routes/security.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/sendgrid-mailer": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "4.4",
|
||||
"ref": "224aedffb66812dc2b0965dabc14d5f800941da6"
|
||||
}
|
||||
},
|
||||
"symfony/stimulus-bundle": {
|
||||
"version": "2.30",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.20",
|
||||
"ref": "c30f782a8910ae9f12e7a1399db607d172d23da6"
|
||||
},
|
||||
"files": [
|
||||
"assets/bootstrap.js",
|
||||
"assets/controllers.json",
|
||||
"assets/controllers/csrf_protection_controller.js",
|
||||
"assets/controllers/hello_controller.js"
|
||||
]
|
||||
},
|
||||
"symfony/translation": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.3",
|
||||
"ref": "620a1b84865ceb2ba304c8f8bf2a185fbf32a843"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/translation.yaml",
|
||||
"translations/.gitignore"
|
||||
]
|
||||
},
|
||||
"symfony/twig-bundle": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.4",
|
||||
"ref": "cab5fd2a13a45c266d45a7d9337e28dee6272877"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/twig.yaml",
|
||||
"templates/base.html.twig"
|
||||
]
|
||||
},
|
||||
"symfony/ux-turbo": {
|
||||
"version": "2.30",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.20",
|
||||
"ref": "287f7c6eb6e9b65e422d34c00795b360a787380b"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/ux_turbo.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/validator": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.0",
|
||||
"ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/validator.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/web-profiler-bundle": {
|
||||
"version": "7.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.3",
|
||||
"ref": "a363460c1b0b4a4d0242f2ce1a843ca0f6ac9026"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/web_profiler.yaml",
|
||||
"config/routes/web_profiler.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/webapp-pack": {
|
||||
"version": "1.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.0",
|
||||
"ref": "7d5c5e282f7e2c36a2c3bbb1504f78456c352407"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/messenger.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/webpack-encore-bundle": {
|
||||
"version": "2.4",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "2.0",
|
||||
"ref": "719f6110345acb6495e496601fc1b4977d7102b3"
|
||||
},
|
||||
"files": [
|
||||
"./assets/app.js",
|
||||
"./assets/styles/app.css",
|
||||
"./config/packages/webpack_encore.yaml",
|
||||
"./package.json",
|
||||
"./webpack.config.js"
|
||||
]
|
||||
},
|
||||
"twig/extra-bundle": {
|
||||
"version": "v3.21.0"
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ app.request.locale|default(app.request.defaultLocale|default('en')) }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}{{ 'site.name'|trans }}{% endblock %}</title>
|
||||
{% block stylesheets %}
|
||||
{{ encore_entry_link_tags('app') }}
|
||||
{{ encore_entry_link_tags('app') }}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
{% set pathinfo = app.request.pathinfo %}
|
||||
<a href="/">{{ 'nav.home'|trans }}</a> |
|
||||
<a href="/game">{{ 'nav.game'|trans }}</a>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
{% block body %}{% endblock %}
|
||||
</main>
|
||||
<footer>
|
||||
<small>© {{ "now"|date("Y") }} {{ 'site.name'|trans }}</small>
|
||||
</footer>
|
||||
{% block javascripts %}
|
||||
{{ encore_entry_script_tags('app') }}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,32 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}{{ 'game.title'|trans({'%site%': ('site.name'|trans)}) }}{% endblock %}
|
||||
|
||||
{# Include Game1-specific CSS in addition to the base app assets #}
|
||||
{% block stylesheets %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('game1') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>{{ 'game.h1'|trans }}</h1>
|
||||
<p>{{ 'game.description'|trans }}</p>
|
||||
<div class="game1-banner">Game 1 assets are active. Enjoy the challenge!</div>
|
||||
|
||||
{# Hidden config element read by assets/game1.js #}
|
||||
<div id="mercure-config"
|
||||
data-mercure-public-url="{{ mercure_public_url|e('html_attr') }}"
|
||||
data-topic="{{ (mercure_topic_base ~ '/game/hub')|e('html_attr') }}"
|
||||
data-api-ping-url="{{ path('game_api_ping')|e('html_attr') }}"
|
||||
data-api-echo-url="{{ path('game_api_echo')|e('html_attr') }}"
|
||||
style="display:none">
|
||||
</div>
|
||||
|
||||
<p><a href="{{ path('website_home') }}">{{ 'link.back_to_website'|trans }}</a></p>
|
||||
{% endblock %}
|
||||
|
||||
{# Include Game1-specific JS in addition to the base app assets #}
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_script_tags('game1') }}
|
||||
{% endblock %}
|
||||
@@ -1,9 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}{{ 'home.title'|trans({'%site%': ('site.name'|trans)}) }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>{{ 'home.h1'|trans({'%site%': ('site.name'|trans)}) }}</h1>
|
||||
<p>{{ 'home.description'|trans }}</p>
|
||||
<p><a href="{{ path('game_hub') }}">{{ 'link.enter_game'|trans }}</a></p>
|
||||
{% endblock %}
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\Dotenv\Dotenv;
|
||||
|
||||
require dirname(__DIR__).'/vendor/autoload.php';
|
||||
|
||||
if (method_exists(Dotenv::class, 'bootEnv')) {
|
||||
(new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
|
||||
}
|
||||
|
||||
if ($_SERVER['APP_DEBUG']) {
|
||||
umask(0000);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
# General
|
||||
site.name: EscapePage
|
||||
nav.home: Home
|
||||
nav.game: Game
|
||||
link.enter_game: Enter the Game Area
|
||||
link.back_to_website: Back to Website
|
||||
|
||||
# Home page
|
||||
home.title: "Welcome | EscapePage"
|
||||
home.h1: "Welcome to EscapePage"
|
||||
home.description: "This is the public website. Minimal interaction, information about the game, and links."
|
||||
|
||||
# Game hub
|
||||
game.title: "Game Hub | EscapePage"
|
||||
game.h1: "Game Area"
|
||||
game.description: "This is the game hub. Interactive components will be built here."
|
||||
@@ -1,16 +0,0 @@
|
||||
# Algemeen
|
||||
site.name: EscapePage
|
||||
nav.home: Start
|
||||
nav.game: Spel
|
||||
link.enter_game: Ga naar het Speelgedeelte
|
||||
link.back_to_website: Terug naar Website
|
||||
|
||||
# Home pagina
|
||||
home.title: "Welkom | %{site}%"
|
||||
home.h1: "Welkom bij %{site}%"
|
||||
home.description: "Dit is de publieke website. Beperkte interactie, informatie over het spel en links."
|
||||
|
||||
# Spel hub
|
||||
game.title: "Spel Hub | %{site}%"
|
||||
game.h1: "Speelgedeelte"
|
||||
game.description: "Dit is de spelhub. Interactieve componenten worden hier later gebouwd."
|
||||
@@ -1,34 +0,0 @@
|
||||
const Encore = require('@symfony/webpack-encore');
|
||||
|
||||
if (!Encore.isRuntimeEnvironmentConfigured()) {
|
||||
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
|
||||
}
|
||||
|
||||
Encore
|
||||
// where compiled assets will be stored
|
||||
.setOutputPath('public/build/')
|
||||
// public path used by the web server to access the output path
|
||||
.setPublicPath('/build')
|
||||
// clean output before build
|
||||
.cleanupOutputBeforeBuild()
|
||||
// main entry for your app
|
||||
.addEntry('app', './assets/app.js')
|
||||
.addEntry('game1', './assets/game1.js')
|
||||
// split entry chunks for better caching
|
||||
.splitEntryChunks()
|
||||
// will require an extra script tag for runtime.js
|
||||
.enableSingleRuntimeChunk()
|
||||
// features
|
||||
.enableSourceMaps(!Encore.isProduction())
|
||||
.enableVersioning(Encore.isProduction())
|
||||
// Babel config for wide browser support
|
||||
.configureBabelPresetEnv((options) => {
|
||||
options.useBuiltIns = 'usage';
|
||||
options.corejs = 3;
|
||||
options.bugfixes = true;
|
||||
})
|
||||
.autoProvidejQuery(false)
|
||||
.enableBuildNotifications()
|
||||
;
|
||||
|
||||
module.exports = Encore.getWebpackConfig();
|
||||
Reference in New Issue
Block a user