diff --git a/.idea/app-sf.iml b/.idea/app-sf.iml index 82e1e39..ec1057e 100644 --- a/.idea/app-sf.iml +++ b/.idea/app-sf.iml @@ -5,7 +5,10 @@ + + + @@ -199,6 +202,7 @@ + diff --git a/.idea/php.xml b/.idea/php.xml index aa2a1b7..b6046de 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -219,6 +219,7 @@ + diff --git a/composer.json b/composer.json index af12525..2ef7a93 100644 --- a/composer.json +++ b/composer.json @@ -146,6 +146,7 @@ "symfony/phpunit-bridge": "7.3.*", "symfony/stopwatch": "7.3.*", "symfony/web-profiler-bundle": "7.3.*", + "symplify/config-transformer": "^12.3", "vincentlanglet/twig-cs-fixer": "dev-main" } } diff --git a/composer.lock b/composer.lock index f65026a..419ec2a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f459ad30f7f54194e3f29cb05fec14fb", + "content-hash": "07dda2568d49823e168caac24aced4cd", "packages": [ { "name": "composer/semver", @@ -904,12 +904,12 @@ "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "9e3ae34de52dd65590c4277d5cdde8f39f12418b" + "reference": "a9e64e5ea80184e14a66c262e5bcf3c2cb4a94d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/9e3ae34de52dd65590c4277d5cdde8f39f12418b", - "reference": "9e3ae34de52dd65590c4277d5cdde8f39f12418b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a9e64e5ea80184e14a66c262e5bcf3c2cb4a94d7", + "reference": "a9e64e5ea80184e14a66c262e5bcf3c2cb4a94d7", "shasum": "" }, "require": { @@ -922,8 +922,7 @@ "phpbench/phpbench": "^1.2", "phpstan/phpstan": "^1.9.4", "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.4" + "phpunit/phpunit": "^10.5" }, "default-branch": true, "type": "library", @@ -967,7 +966,7 @@ "type": "tidelift" } ], - "time": "2024-11-25T19:21:52+00:00" + "time": "2024-12-02T21:34:17+00:00" }, { "name": "doctrine/lexer", @@ -1343,12 +1342,12 @@ "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "b4068e8d1a5168769ce65410bab76a8362e04da0" + "reference": "579b67954ca6817a4d5a0a785c654fb7bc849b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/b4068e8d1a5168769ce65410bab76a8362e04da0", - "reference": "b4068e8d1a5168769ce65410bab76a8362e04da0", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/579b67954ca6817a4d5a0a785c654fb7bc849b2e", + "reference": "579b67954ca6817a4d5a0a785c654fb7bc849b2e", "shasum": "" }, "require": { @@ -1358,8 +1357,7 @@ "doctrine/coding-standard": "^12", "ergebnis/phpunit-slow-test-detector": "^2.14", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.24" + "phpunit/phpunit": "^10.5" }, "default-branch": true, "bin": [ @@ -1392,7 +1390,7 @@ "issues": "https://github.com/doctrine/sql-formatter/issues", "source": "https://github.com/doctrine/sql-formatter/tree/1.5.x" }, - "time": "2024-11-25T11:48:05+00:00" + "time": "2024-12-02T22:10:47+00:00" }, { "name": "easycorp/easyadmin-bundle", @@ -1400,12 +1398,12 @@ "source": { "type": "git", "url": "https://github.com/EasyCorp/EasyAdminBundle.git", - "reference": "2307da58ccfd0569f65943b9a01d49a4f3a71d7d" + "reference": "2b49b51ccd128ac3983ef1c585d74d60ee5c6efa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/EasyCorp/EasyAdminBundle/zipball/2307da58ccfd0569f65943b9a01d49a4f3a71d7d", - "reference": "2307da58ccfd0569f65943b9a01d49a4f3a71d7d", + "url": "https://api.github.com/repos/EasyCorp/EasyAdminBundle/zipball/2b49b51ccd128ac3983ef1c585d74d60ee5c6efa", + "reference": "2b49b51ccd128ac3983ef1c585d74d60ee5c6efa", "shasum": "" }, "require": { @@ -1489,7 +1487,7 @@ "type": "github" } ], - "time": "2024-11-29T18:27:19+00:00" + "time": "2024-12-02T19:53:15+00:00" }, { "name": "egulias/email-validator", @@ -1893,12 +1891,12 @@ "source": { "type": "git", "url": "https://github.com/meilisearch/meilisearch-symfony.git", - "reference": "d46b2da1865ef228aaca67eeac9e6851022dbeaf" + "reference": "345bb2b18ec0a962a8a12d0ae0e8088c2ebf0641" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/meilisearch/meilisearch-symfony/zipball/d46b2da1865ef228aaca67eeac9e6851022dbeaf", - "reference": "d46b2da1865ef228aaca67eeac9e6851022dbeaf", + "url": "https://api.github.com/repos/meilisearch/meilisearch-symfony/zipball/345bb2b18ec0a962a8a12d0ae0e8088c2ebf0641", + "reference": "345bb2b18ec0a962a8a12d0ae0e8088c2ebf0641", "shasum": "" }, "require": { @@ -1963,9 +1961,9 @@ ], "support": { "issues": "https://github.com/meilisearch/meilisearch-symfony/issues", - "source": "https://github.com/meilisearch/meilisearch-symfony/tree/main" + "source": "https://github.com/meilisearch/meilisearch-symfony/tree/v0.15.7" }, - "time": "2024-12-01T18:32:28+00:00" + "time": "2024-12-03T12:49:45+00:00" }, { "name": "monolog/monolog", @@ -3300,12 +3298,12 @@ "source": { "type": "git", "url": "https://github.com/php-runtime/frankenphp-symfony.git", - "reference": "38a5dfa1b1e40d8e0b3bbc91d84a03cf4e65fcf4" + "reference": "34b8c25e4b1043dec2a51dfebbc776260acf1921" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-runtime/frankenphp-symfony/zipball/38a5dfa1b1e40d8e0b3bbc91d84a03cf4e65fcf4", - "reference": "38a5dfa1b1e40d8e0b3bbc91d84a03cf4e65fcf4", + "url": "https://api.github.com/repos/php-runtime/frankenphp-symfony/zipball/34b8c25e4b1043dec2a51dfebbc776260acf1921", + "reference": "34b8c25e4b1043dec2a51dfebbc776260acf1921", "shasum": "" }, "require": { @@ -3345,7 +3343,7 @@ "type": "github" } ], - "time": "2024-06-14T20:56:26+00:00" + "time": "2024-12-03T16:13:06+00:00" }, { "name": "sensiolabs/typescript-bundle", @@ -10442,12 +10440,12 @@ "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "f8d27d5b81b23d9b679ca2ccac09261c461a15f4" + "reference": "927be0d98b92d1b0636d78e95bf9a7ba6042a5c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f8d27d5b81b23d9b679ca2ccac09261c461a15f4", - "reference": "f8d27d5b81b23d9b679ca2ccac09261c461a15f4", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/927be0d98b92d1b0636d78e95bf9a7ba6042a5c8", + "reference": "927be0d98b92d1b0636d78e95bf9a7ba6042a5c8", "shasum": "" }, "require": { @@ -10493,7 +10491,7 @@ "type": "github" } ], - "time": "2024-12-02T07:51:15+00:00" + "time": "2024-12-03T14:24:47+00:00" }, { "name": "phpstan/phpstan-doctrine", @@ -13151,6 +13149,48 @@ ], "time": "2024-11-19T10:12:55+00:00" }, + { + "name": "symplify/config-transformer", + "version": "12.3.4", + "source": { + "type": "git", + "url": "https://github.com/symplify/config-transformer.git", + "reference": "9fb4f5acf7ec4261ba426bee9eb7aeed174eb600" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symplify/config-transformer/zipball/9fb4f5acf7ec4261ba426bee9eb7aeed174eb600", + "reference": "9fb4f5acf7ec4261ba426bee9eb7aeed174eb600", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "bin": [ + "bin/config-transformer" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Prefixed version of Symfony YAML/XML to PHP/YAML config converter", + "support": { + "issues": "https://github.com/symplify/config-transformer/issues", + "source": "https://github.com/symplify/config-transformer/tree/12.3.4" + }, + "funding": [ + { + "url": "https://www.paypal.me/rectorphp", + "type": "custom" + }, + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2024-01-15T21:58:26+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.3", diff --git a/config/packages/asset_mapper.php b/config/packages/asset_mapper.php new file mode 100644 index 0000000..04de67d --- /dev/null +++ b/config/packages/asset_mapper.php @@ -0,0 +1,15 @@ +assetMapper() + ->path('assets/', '') + ->path('vendor/twbs/bootstrap/', '') + ->excludedPatterns([ + '*/assets/styles/_*.scss', + '*/assets/styles/**/_*.scss', + ]); +}; diff --git a/config/packages/asset_mapper.yaml b/config/packages/asset_mapper.yaml deleted file mode 100644 index 03dc576..0000000 --- a/config/packages/asset_mapper.yaml +++ /dev/null @@ -1,13 +0,0 @@ -framework: - asset_mapper: - # The paths to make available to the asset mapper. - paths: - - assets/ - - vendor/twbs/bootstrap/ - excluded_patterns: - - "*/assets/styles/_*.scss" - - "*/assets/styles/**/_*.scss" -sensiolabs_typescript: - source_dir: - - "%kernel.project_dir%/assets/app" - - "%kernel.project_dir%/assets/controllers" diff --git a/config/packages/cache.php b/config/packages/cache.php new file mode 100644 index 0000000..e2a2091 --- /dev/null +++ b/config/packages/cache.php @@ -0,0 +1,14 @@ +cache() + ->prefixSeed('database_playground/app') + ->app('cache.adapter.redis_tag_aware') + ->defaultRedisProvider(param('app.redis_uri')); +}; diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml deleted file mode 100644 index 5236446..0000000 --- a/config/packages/cache.yaml +++ /dev/null @@ -1,23 +0,0 @@ -framework: - cache: - prefix_seed: "database_playground/app" - - app: cache.adapter.redis_tag_aware - default_redis_provider: "%app.redis_uri%" - # 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 diff --git a/config/packages/csrf.php b/config/packages/csrf.php new file mode 100644 index 0000000..352483f --- /dev/null +++ b/config/packages/csrf.php @@ -0,0 +1,16 @@ +form() + ->csrfProtection() + ->tokenId('submit'); + + $frameworkConfig + ->csrfProtection() + ->statelessTokenIds(['submit', 'authenticate', 'logout']); +}; diff --git a/config/packages/csrf.yaml b/config/packages/csrf.yaml deleted file mode 100644 index dd07de8..0000000 --- a/config/packages/csrf.yaml +++ /dev/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 diff --git a/config/packages/debug.php b/config/packages/debug.php new file mode 100644 index 0000000..457cce8 --- /dev/null +++ b/config/packages/debug.php @@ -0,0 +1,16 @@ +env()) { + // 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. + $debugConfig->dumpDestination('tcp://'.env('VAR_DUMPER_SERVER')); + } +}; diff --git a/config/packages/debug.yaml b/config/packages/debug.yaml deleted file mode 100644 index ce519f3..0000000 --- a/config/packages/debug.yaml +++ /dev/null @@ -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)%" diff --git a/config/packages/doctrine.php b/config/packages/doctrine.php new file mode 100644 index 0000000..5979af8 --- /dev/null +++ b/config/packages/doctrine.php @@ -0,0 +1,117 @@ +dbal(); + $dbalConfig + ->connection('default') + ->url(env('DATABASE_URL')->resolve()) + ->profilingCollectBacktrace(param('kernel.debug')) + ->useSavepoints(true); + + $ormConfig = $doctrineConfig->orm(); + $ormConfig + ->autoGenerateProxyClasses(true) + ->enableLazyGhostObjects(true); + + $entityManager = $ormConfig->entityManager('default'); + $entityManager + ->reportFieldsWhereDeclared(true) + ->validateXmlMapping(true) + ->namingStrategy('doctrine.orm.naming_strategy.underscore_number_aware') + ->autoMapping(true) + ->mapping('App', [ + 'type' => 'attribute', + 'is_bundle' => false, + 'dir' => '%kernel.project_dir%/src/Entity', + 'prefix' => 'App\Entity', + 'alias' => 'App', + ]); + + $ormConfig + ->controllerResolver() + ->autoMapping(true); + + $entityManager->dql() + ->datetimeFunction('date', SimpleFunction::class) + ->datetimeFunction('time', SimpleFunction::class) + ->datetimeFunction('timestamp', SimpleFunction::class) + ->datetimeFunction('convert_tz', ConvertTz::class) + ->numericFunction('timestampdiff', TimestampDiff::class) + ->numericFunction('dayofyear', SimpleFunction::class) + ->numericFunction('dayofmonth', SimpleFunction::class) + ->numericFunction('dayofweek', SimpleFunction::class) + ->numericFunction('week', SimpleFunction::class) + ->numericFunction('day', SimpleFunction::class) + ->numericFunction('hour', SimpleFunction::class) + ->numericFunction('minute', SimpleFunction::class) + ->numericFunction('month', SimpleFunction::class) + ->numericFunction('quarter', SimpleFunction::class) + ->numericFunction('second', SimpleFunction::class) + ->numericFunction('year', SimpleFunction::class) + ->numericFunction('sign', Sign::class) + ->numericFunction('pow', Pow::class) + ->numericFunction('round', Round::class) + ->numericFunction('ceil', SimpleFunction::class) + ->stringFunction('md5', SimpleFunction::class) + ->stringFunction('group_concat', GroupConcat::class) + ->stringFunction('concat_ws', ConcatWs::class) + ->stringFunction('cast', Cast::class) + ->stringFunction('replace', Replace::class) + ->stringFunction('date_format', DateFormat::class); + + if ('test' === $containerConfigurator->env()) { + $dbalConfig + ->connection('default') + // "TEST_TOKEN" is typically set by ParaTest + ->dbnameSuffix('_test.%env(default::TEST_TOKEN)%'); + } + + if ('prod' === $containerConfigurator->env()) { + $systemCachePool = 'doctrine.system_cache_pool'; + $resultCachePool = 'doctrine.result_cache_pool'; + + $ormConfig + ->autoGenerateProxyClasses(false) + ->proxyDir('%kernel.build_dir%/doctrine/orm/Proxies'); + + $entityManager + ->queryCacheDriver([ + 'type' => 'pool', + 'pool' => $systemCachePool, + ]); + + $entityManager + ->resultCacheDriver([ + 'type' => 'pool', + 'pool' => $resultCachePool, + ]); + + $cache = $frameworkConfig->cache(); + $cache->pool($systemCachePool, [ + 'adapter' => 'cache.system', + ]); + $cache->pool($resultCachePool, [ + 'adapter' => 'cache.app', + ]); + } +}; diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml deleted file mode 100644 index 4c49cfc..0000000 --- a/config/packages/doctrine.yaml +++ /dev/null @@ -1,82 +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/Entity" - prefix: 'App\Entity' - alias: App - controller_resolver: - auto_mapping: false - dql: - datetime_functions: - date: Oro\ORM\Query\AST\Functions\SimpleFunction - time: Oro\ORM\Query\AST\Functions\SimpleFunction - timestamp: Oro\ORM\Query\AST\Functions\SimpleFunction - convert_tz: Oro\ORM\Query\AST\Functions\DateTime\ConvertTz - numeric_functions: - timestampdiff: Oro\ORM\Query\AST\Functions\Numeric\TimestampDiff - dayofyear: Oro\ORM\Query\AST\Functions\SimpleFunction - dayofmonth: Oro\ORM\Query\AST\Functions\SimpleFunction - dayofweek: Oro\ORM\Query\AST\Functions\SimpleFunction - week: Oro\ORM\Query\AST\Functions\SimpleFunction - day: Oro\ORM\Query\AST\Functions\SimpleFunction - hour: Oro\ORM\Query\AST\Functions\SimpleFunction - minute: Oro\ORM\Query\AST\Functions\SimpleFunction - month: Oro\ORM\Query\AST\Functions\SimpleFunction - quarter: Oro\ORM\Query\AST\Functions\SimpleFunction - second: Oro\ORM\Query\AST\Functions\SimpleFunction - year: Oro\ORM\Query\AST\Functions\SimpleFunction - sign: Oro\ORM\Query\AST\Functions\Numeric\Sign - pow: Oro\ORM\Query\AST\Functions\Numeric\Pow - round: Oro\ORM\Query\AST\Functions\Numeric\Round - ceil: Oro\ORM\Query\AST\Functions\SimpleFunction - string_functions: - md5: Oro\ORM\Query\AST\Functions\SimpleFunction - group_concat: Oro\ORM\Query\AST\Functions\String\GroupConcat - concat_ws: Oro\ORM\Query\AST\Functions\String\ConcatWs - cast: Oro\ORM\Query\AST\Functions\Cast - replace: Oro\ORM\Query\AST\Functions\String\Replace - date_format: Oro\ORM\Query\AST\Functions\String\DateFormat - -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 diff --git a/config/packages/doctrine_migrations.php b/config/packages/doctrine_migrations.php new file mode 100644 index 0000000..1927c51 --- /dev/null +++ b/config/packages/doctrine_migrations.php @@ -0,0 +1,15 @@ +enableProfiler(false); + + $doctrineMigrationsConfig + // namespace is arbitrary but should be different from App\Migrations + // as migrations classes should NOT be autoloaded + ->migrationsPath('DoctrineMigrations', '%kernel.project_dir%/migrations'); +}; diff --git a/config/packages/doctrine_migrations.yaml b/config/packages/doctrine_migrations.yaml deleted file mode 100644 index 9300c9b..0000000 --- a/config/packages/doctrine_migrations.yaml +++ /dev/null @@ -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 diff --git a/config/packages/framework.php b/config/packages/framework.php new file mode 100644 index 0000000..0f2b85e --- /dev/null +++ b/config/packages/framework.php @@ -0,0 +1,34 @@ +session(); + assert($sessionConfig instanceof SessionConfig); + + $frameworkConfig->secret(env('APP_SECRET')); + + // Note that the session will be started ONLY if you read or write from it. + $sessionConfig->handlerId(env('REDIS_URI')); + + // proxy configuration for Zeabur + $frameworkConfig->trustedProxies('private_ranges'); + $frameworkConfig->trustedHeaders([ + 'x-forwarded-for', + 'x-forwarded-host', + 'x-forwarded-proto', + 'x-forwarded-port', + 'x-forwarded-prefix', + ]); + + if ('test' === $containerConfigurator->env()) { + $frameworkConfig->test(true); + $sessionConfig->storageFactoryId('session.storage.factory.mock_file'); + } +}; diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml deleted file mode 100644 index 2f9aceb..0000000 --- a/config/packages/framework.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# see https://symfony.com/doc/current/reference/configuration/framework.html -framework: - secret: "%env(APP_SECRET)%" - #csrf_protection: true - - # Note that the session will be started ONLY if you read or write from it. - session: - handler_id: "%env(REDIS_URI)%" - - #esi: true - #fragments: true - - # proxy configuration for Zeabur - trusted_proxies: "private_ranges" - trusted_headers: [ - "x-forwarded-for", - "x-forwarded-host", - "x-forwarded-proto", - "x-forwarded-port", - "x-forwarded-prefix", - ] - -when@test: - framework: - test: true - session: - storage_factory_id: session.storage.factory.mock_file diff --git a/config/packages/http_discovery.php b/config/packages/http_discovery.php new file mode 100644 index 0000000..303701a --- /dev/null +++ b/config/packages/http_discovery.php @@ -0,0 +1,22 @@ +services() + ->alias(RequestFactoryInterface::class, Psr17Factory::class) + ->alias(ResponseFactoryInterface::class, Psr17Factory::class) + ->alias(ServerRequestFactoryInterface::class, Psr17Factory::class) + ->alias(StreamFactoryInterface::class, Psr17Factory::class) + ->alias(UploadedFileFactoryInterface::class, Psr17Factory::class) + ->alias(UriFactoryInterface::class, Psr17Factory::class); +}; diff --git a/config/packages/http_discovery.yaml b/config/packages/http_discovery.yaml deleted file mode 100644 index 3e7ef4b..0000000 --- a/config/packages/http_discovery.yaml +++ /dev/null @@ -1,10 +0,0 @@ -services: - Psr\Http\Message\RequestFactoryInterface: "@http_discovery.psr17_factory" - Psr\Http\Message\ResponseFactoryInterface: "@http_discovery.psr17_factory" - Psr\Http\Message\ServerRequestFactoryInterface: "@http_discovery.psr17_factory" - Psr\Http\Message\StreamFactoryInterface: "@http_discovery.psr17_factory" - Psr\Http\Message\UploadedFileFactoryInterface: "@http_discovery.psr17_factory" - Psr\Http\Message\UriFactoryInterface: "@http_discovery.psr17_factory" - - http_discovery.psr17_factory: - class: Http\Discovery\Psr17Factory diff --git a/config/packages/lock.yaml b/config/packages/lock.yaml deleted file mode 100644 index 6c7aa58..0000000 --- a/config/packages/lock.yaml +++ /dev/null @@ -1,2 +0,0 @@ -framework: - lock: "%env(LOCK_DSN)%" diff --git a/config/packages/mailer.php b/config/packages/mailer.php new file mode 100644 index 0000000..e9df49e --- /dev/null +++ b/config/packages/mailer.php @@ -0,0 +1,12 @@ +mailer() + ->dsn(env('MAILER_DSN')); +}; diff --git a/config/packages/mailer.yaml b/config/packages/mailer.yaml deleted file mode 100644 index 813f6e1..0000000 --- a/config/packages/mailer.yaml +++ /dev/null @@ -1,3 +0,0 @@ -framework: - mailer: - dsn: "%env(MAILER_DSN)%" diff --git a/config/packages/meilisearch.php b/config/packages/meilisearch.php new file mode 100644 index 0000000..df18cf2 --- /dev/null +++ b/config/packages/meilisearch.php @@ -0,0 +1,27 @@ +url(env('MEILISEARCH_URL')) + ->apiKey(env('MEILISEARCH_API_KEY')) + ->indices() + ->name('questions') + ->class(Question::class) + ->enableSerializerGroups(true) + ->settings([ + 'filterableAttributes' => [ + 'type', + 'difficulty', + ], + 'sortableAttributes' => [ + 'id', + ], + ]); +}; diff --git a/config/packages/meilisearch.yaml b/config/packages/meilisearch.yaml deleted file mode 100644 index 1b9d805..0000000 --- a/config/packages/meilisearch.yaml +++ /dev/null @@ -1,17 +0,0 @@ -meilisearch: - url: "%env(MEILISEARCH_URL)%" # URL of the Meilisearch server (mandatory) - api_key: "%env(MEILISEARCH_API_KEY)%" # API key to access the Meilisearch server (mandatory) - indices: - - name: questions - class: App\Entity\Question - enable_serializer_groups: true - settings: - filterableAttributes: - - type - - difficulty - sortableAttributes: - - id - -when@preprod: - meilisearch: - prefix: prod_ diff --git a/config/packages/messenger.php b/config/packages/messenger.php new file mode 100644 index 0000000..716d872 --- /dev/null +++ b/config/packages/messenger.php @@ -0,0 +1,40 @@ +messenger(); + + $messenger->failureTransport('failed'); + + $asyncTransport = $messenger->transport('async'); + assert($asyncTransport instanceof TransportConfig); + $asyncTransport->dsn(env('MESSENGER_TRANSPORT_DSN')); + /* @phpstan-ignore-next-line argument.type https://github.com/symfony/symfony/issues/18988 */ + $asyncTransport->options([ + 'use_notify' => true, + 'check_delayed_interval' => 60000, + ]); + $asyncTransport->retryStrategy() + ->maxRetries(3) + ->multiplier(2); + + $failedTransport = $messenger->transport('failed'); + assert($failedTransport instanceof TransportConfig); + $failedTransport->dsn('doctrine://default?queue_name=failed'); + + $messenger->bus('messenger.bus.default'); + $messenger->defaultBus('messenger.bus.default'); + + $routingConfig = $messenger->routing(SendEmailMessage::class); + assert($routingConfig instanceof RoutingConfig); + $routingConfig->senders(['async']); +}; diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml deleted file mode 100644 index fd7f8cd..0000000 --- a/config/packages/messenger.yaml +++ /dev/null @@ -1,27 +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 - - # Route your messages to the transports - # 'App\Message\YourMessage': async diff --git a/config/packages/monolog.php b/config/packages/monolog.php new file mode 100644 index 0000000..51dfa3d --- /dev/null +++ b/config/packages/monolog.php @@ -0,0 +1,67 @@ +channels(['deprecation']); + + if ('dev' === $containerConfigurator->env()) { + $monologConfig->handler('main') + ->type('stream') + ->path('%kernel.logs_dir%/%kernel.environment%.log') + ->level('debug') + ->channels() + ->elements(['!event']); + $monologConfig->handler('console') + ->type('console') + ->processPsr3Messages(false) + ->channels() + ->elements(['!event', '!doctrine', '!console']); + } + + if ('test' === $containerConfigurator->env()) { + $monologConfig->handler('main') + ->type('fingers_crossed') + ->actionLevel('error') + ->handler('nested') + ->excludedHttpCode(404) + ->excludedHttpCode(405) + ->channels() + ->elements(['!event']); + $monologConfig->handler('nested') + ->type('stream') + ->path('%kernel.logs_dir%/%kernel.environment%.log') + ->level('debug'); + } + + if ('prod' === $containerConfigurator->env()) { + $monologConfig->handler('main') + ->type('fingers_crossed') + ->actionLevel('error') + ->handler('nested') + ->excludedHttpCode(404) + ->excludedHttpCode(405) + // How many messages should be saved? Prevent memory leaks + ->bufferSize(50); + $monologConfig->handler('nested') + ->type('stream') + ->path('php://stderr') + ->level('debug') + ->formatter('monolog.formatter.json'); + $monologConfig->handler('console') + ->type('console') + ->processPsr3Messages(false) + ->channels() + ->elements(['!event', '!doctrine']); + $monologConfig->handler('deprecation') + ->type('stream') + ->path('php://stderr') + ->formatter('monolog.formatter.json') + ->channels() + ->elements(['deprecation']); + } +}; diff --git a/config/packages/monolog.yaml b/config/packages/monolog.yaml deleted file mode 100644 index c2da281..0000000 --- a/config/packages/monolog.yaml +++ /dev/null @@ -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 diff --git a/config/packages/notifier.php b/config/packages/notifier.php new file mode 100644 index 0000000..e321b1f --- /dev/null +++ b/config/packages/notifier.php @@ -0,0 +1,15 @@ +notifier(); + + $notifierConfig->chatterTransport('linenotify', env('LINE_NOTIFY_DSN')); + $notifierConfig->adminRecipient()->email('dbplay@pan93.com'); +}; diff --git a/config/packages/notifier.yaml b/config/packages/notifier.yaml deleted file mode 100644 index 8d4eff7..0000000 --- a/config/packages/notifier.yaml +++ /dev/null @@ -1,12 +0,0 @@ -framework: - notifier: - chatter_transports: - linenotify: "%env(LINE_NOTIFY_DSN)%" - texter_transports: - channel_policy: - urgent: ["chat/linenotify"] - high: ["chat/linenotify"] - medium: ["chat/linenotify"] - low: ["chat/linenotify"] - admin_recipients: - - { email: dbplay@pan93.com } diff --git a/config/packages/routing.php b/config/packages/routing.php new file mode 100644 index 0000000..71c1387 --- /dev/null +++ b/config/packages/routing.php @@ -0,0 +1,18 @@ +router(); + assert($routerConfig instanceof RouterConfig); // workaround for PHPStan support + + $routerConfig->strictRequirements(true); + + if ('prod' === $containerConfigurator->env()) { + $routerConfig->strictRequirements(null); + } +}; diff --git a/config/packages/routing.yaml b/config/packages/routing.yaml deleted file mode 100644 index 5969ced..0000000 --- a/config/packages/routing.yaml +++ /dev/null @@ -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 diff --git a/config/packages/security.php b/config/packages/security.php new file mode 100644 index 0000000..566c37b --- /dev/null +++ b/config/packages/security.php @@ -0,0 +1,87 @@ +passwordHasher(PasswordAuthenticatedUserInterface::class, 'auto'); + + // used to reload user from session & other features (e.g. switch_user) + $securityConfig + ->provider('app_user_provider') + ->entity() + ->class(User::class) + ->property('email'); + + $securityConfig + ->firewall('dev') + ->pattern('^/(_(profiler|wdt)|css|images|js)/') + ->security(false); + + $mainFirewall = $securityConfig->firewall('main'); + + $mainFirewall + ->lazy(true) + ->provider('app_user_provider'); + + $mainFirewall + ->formLogin() + ->loginPath('app_login') + ->checkPath('app_login') + ->enableCsrf(true); + + $mainFirewall + ->logout() + ->path('app_logout') + ->target('app_home'); + + $mainFirewall + ->rememberMe() + ->secret(param('kernel.secret')) + ->lifetime(604800 /* 1 week in seconds */); + + // https://symfony.com/doc/current/security/impersonating_user.html + $mainFirewall->switchUser(); + + // Allow anonymous access to the login form. + $securityConfig + ->accessControl() + ->route('app_login') + ->roles('PUBLIC_ACCESS'); + + // Allow anonymous access to the feedback form. + $securityConfig + ->accessControl() + ->route('app_feedback') + ->roles('PUBLIC_ACCESS'); + + // Admin + $securityConfig + ->accessControl() + ->path('^/admin') + ->roles('ROLE_ADMIN'); + + // Others (for example, apps) + $securityConfig + ->accessControl() + ->path('^/') + ->roles('ROLE_USER'); + + if ('test' === $containerConfigurator->env()) { + $passwordHasher = $securityConfig->passwordHasher(PasswordAuthenticatedUserInterface::class); + assert($passwordHasher instanceof PasswordHasherConfig); + + $passwordHasher + ->algorithm('auto') + ->cost(4) + ->timeCost(3) + ->memoryCost(10); + } +}; diff --git a/config/packages/security.yaml b/config/packages/security.yaml deleted file mode 100644 index 6a6fdee..0000000 --- a/config/packages/security.yaml +++ /dev/null @@ -1,64 +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: - # used to reload user from session & other features (e.g. switch_user) - app_user_provider: - entity: - class: App\Entity\User - property: email - firewalls: - dev: - pattern: ^/(_(profiler|wdt)|css|images|js)/ - security: false - main: - lazy: true - provider: app_user_provider - form_login: - login_path: app_login - check_path: app_login - enable_csrf: true - logout: - path: app_logout - target: app_home - remember_me: - secret: "%kernel.secret%" # required - lifetime: 604800 # 1 week in seconds - - # https://symfony.com/doc/current/security/impersonating_user.html - switch_user: true - - # activate different ways to authenticate - # https://symfony.com/doc/current/security.html#the-firewall - - # Easy way to control access for large sections of your site - # Note: Only the *first* access control that matches will be used - access_control: - # login page - - { route: app_login, roles: PUBLIC_ACCESS } - - # feedback page - # Note that we provide the feedback form in login page, - # so we need to allow public access to this page. - - { route: app_feedback, roles: PUBLIC_ACCESS } - - # admin - - { path: ^/admin, roles: ROLE_ADMIN } - - # others (for example, apps) - - { path: ^/, 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 diff --git a/config/packages/sensiolabs_typescript.php b/config/packages/sensiolabs_typescript.php new file mode 100644 index 0000000..20830b9 --- /dev/null +++ b/config/packages/sensiolabs_typescript.php @@ -0,0 +1,13 @@ +swcBinary('node_modules/.bin/swc'); + $config->sourceDir([ + '%kernel.project_dir%/assets/app', + '%kernel.project_dir%/assets/controllers', + ]); +}; diff --git a/config/packages/sensiolabs_typescript.yaml b/config/packages/sensiolabs_typescript.yaml deleted file mode 100644 index 604fcbc..0000000 --- a/config/packages/sensiolabs_typescript.yaml +++ /dev/null @@ -1,2 +0,0 @@ -sensiolabs_typescript: - swc_binary: "node_modules/.bin/swc" diff --git a/config/packages/translation.php b/config/packages/translation.php new file mode 100644 index 0000000..d9ec9b0 --- /dev/null +++ b/config/packages/translation.php @@ -0,0 +1,16 @@ +defaultLocale('zh_TW') + ->enabledLocales(['zh_TW']); + + $config + ->translator() + ->defaultPath('%kernel.project_dir%/translations') + ->fallbacks(['zh_TW']); +}; diff --git a/config/packages/translation.yaml b/config/packages/translation.yaml deleted file mode 100644 index 6fdb6e9..0000000 --- a/config/packages/translation.yaml +++ /dev/null @@ -1,8 +0,0 @@ -framework: - default_locale: zh_TW - enabled_locales: ["zh_TW"] - translator: - default_path: "%kernel.project_dir%/translations" - fallbacks: - - zh_TW - providers: diff --git a/config/packages/twig.php b/config/packages/twig.php new file mode 100644 index 0000000..15f19b3 --- /dev/null +++ b/config/packages/twig.php @@ -0,0 +1,19 @@ +fileNamePattern('*.twig') + ->formThemes(['bootstrap_5_layout.html.twig']) + ->global('umami_domain', env('UMAMI_DOMAIN')) + ->global('umami_website_id', env('UMAMI_WEBSITE_ID')) + ->strictVariables(true) + ->global('app_features_hint', param('app.features.hint')) + ->global('app_features_comment', param('app.features.comment')); +}; diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml deleted file mode 100644 index 4af147b..0000000 --- a/config/packages/twig.yaml +++ /dev/null @@ -1,13 +0,0 @@ -twig: - file_name_pattern: "*.twig" - form_themes: ["bootstrap_5_layout.html.twig"] - globals: - umami_domain: "%env(UMAMI_DOMAIN)%" - umami_website_id: "%env(UMAMI_WEBSITE_ID)%" - appfeatures: - hint: "%app.features.hint%" - comment: "%app.features.comment%" - -when@test: - twig: - strict_variables: true diff --git a/config/packages/twig_component.php b/config/packages/twig_component.php new file mode 100644 index 0000000..42605b9 --- /dev/null +++ b/config/packages/twig_component.php @@ -0,0 +1,11 @@ +anonymousTemplateDirectory('components/') + ->defaults('App\Twig\Components\\', 'components/'); +}; diff --git a/config/packages/twig_component.yaml b/config/packages/twig_component.yaml deleted file mode 100644 index 7b4b5eb..0000000 --- a/config/packages/twig_component.yaml +++ /dev/null @@ -1,5 +0,0 @@ -twig_component: - anonymous_template_directory: "components/" - defaults: - # Namespace & directory for components - App\Twig\Components\: "components/" diff --git a/config/packages/validator.php b/config/packages/validator.php new file mode 100644 index 0000000..c4f1adc --- /dev/null +++ b/config/packages/validator.php @@ -0,0 +1,11 @@ +validation()->notCompromisedPassword(); + $notCompromisedPassword->enabled('test' !== $containerConfigurator->env()); +}; diff --git a/config/packages/validator.yaml b/config/packages/validator.yaml deleted file mode 100644 index 7b5d7d5..0000000 --- a/config/packages/validator.yaml +++ /dev/null @@ -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 diff --git a/config/packages/web_profiler.php b/config/packages/web_profiler.php new file mode 100644 index 0000000..d46eba3 --- /dev/null +++ b/config/packages/web_profiler.php @@ -0,0 +1,32 @@ +profiler(); + assert($frameworkProfilerConfig instanceof ProfilerConfig); + + switch ($containerConfigurator->env()) { + case 'dev': + $webProfilerConfig->toolbar(true); + $webProfilerConfig->interceptRedirects(false); + $frameworkProfilerConfig + ->onlyExceptions(false) + ->collectSerializerData(true); + break; + case 'test': + $webProfilerConfig->toolbar(false); + $webProfilerConfig->interceptRedirects(false); + $frameworkProfilerConfig->collect(false); + break; + } +}; diff --git a/config/packages/web_profiler.yaml b/config/packages/web_profiler.yaml deleted file mode 100644 index a529921..0000000 --- a/config/packages/web_profiler.yaml +++ /dev/null @@ -1,17 +0,0 @@ -when@dev: - web_profiler: - toolbar: true - intercept_redirects: false - - framework: - profiler: - only_exceptions: false - collect_serializer_data: true - -when@test: - web_profiler: - toolbar: false - intercept_redirects: false - - framework: - profiler: { collect: false } diff --git a/config/routes.php b/config/routes.php new file mode 100644 index 0000000..d3a5ab6 --- /dev/null +++ b/config/routes.php @@ -0,0 +1,12 @@ +import([ + 'path' => '../src/Controller/', + 'namespace' => 'App\Controller', + ], 'attribute'); +}; diff --git a/config/routes.yaml b/config/routes.yaml deleted file mode 100644 index 2d0ef99..0000000 --- a/config/routes.yaml +++ /dev/null @@ -1,5 +0,0 @@ -controllers: - resource: - path: ../src/Controller/ - namespace: App\Controller - type: attribute diff --git a/config/routes/easyadmin.php b/config/routes/easyadmin.php new file mode 100644 index 0000000..ddb8599 --- /dev/null +++ b/config/routes/easyadmin.php @@ -0,0 +1,9 @@ +import('.', 'easyadmin.routes'); +}; diff --git a/config/routes/easyadmin.yaml b/config/routes/easyadmin.yaml deleted file mode 100644 index f409de2..0000000 --- a/config/routes/easyadmin.yaml +++ /dev/null @@ -1,3 +0,0 @@ -easyadmin: - resource: . - type: easyadmin.routes diff --git a/config/routes/framework.php b/config/routes/framework.php new file mode 100644 index 0000000..455101b --- /dev/null +++ b/config/routes/framework.php @@ -0,0 +1,12 @@ +env()) { + $routingConfigurator->import('@FrameworkBundle/Resources/config/routing/errors.xml') + ->prefix('/_error'); + } +}; diff --git a/config/routes/framework.yaml b/config/routes/framework.yaml deleted file mode 100644 index cce01c1..0000000 --- a/config/routes/framework.yaml +++ /dev/null @@ -1,4 +0,0 @@ -when@dev: - _errors: - resource: "@FrameworkBundle/Resources/config/routing/errors.xml" - prefix: /_error diff --git a/config/routes/security.php b/config/routes/security.php new file mode 100644 index 0000000..cd2c44f --- /dev/null +++ b/config/routes/security.php @@ -0,0 +1,9 @@ +import('security.route_loader.logout', 'service'); +}; diff --git a/config/routes/security.yaml b/config/routes/security.yaml deleted file mode 100644 index 3cb5ef0..0000000 --- a/config/routes/security.yaml +++ /dev/null @@ -1,3 +0,0 @@ -_security_logout: - resource: security.route_loader.logout - type: service diff --git a/config/routes/ux_live_component.php b/config/routes/ux_live_component.php new file mode 100644 index 0000000..e7cb167 --- /dev/null +++ b/config/routes/ux_live_component.php @@ -0,0 +1,10 @@ +import('@LiveComponentBundle/config/routes.php') + ->prefix('/_components'); +}; diff --git a/config/routes/ux_live_component.yaml b/config/routes/ux_live_component.yaml deleted file mode 100644 index b062f61..0000000 --- a/config/routes/ux_live_component.yaml +++ /dev/null @@ -1,5 +0,0 @@ -live_component: - resource: "@LiveComponentBundle/config/routes.php" - prefix: "/_components" - # adjust prefix to add localization to your components - #prefix: '/{_locale}/_components' diff --git a/config/routes/web_profiler.php b/config/routes/web_profiler.php new file mode 100644 index 0000000..63bbf5f --- /dev/null +++ b/config/routes/web_profiler.php @@ -0,0 +1,14 @@ +env()) { + $routingConfigurator->import('@WebProfilerBundle/Resources/config/routing/wdt.xml') + ->prefix('/_wdt'); + $routingConfigurator->import('@WebProfilerBundle/Resources/config/routing/profiler.xml') + ->prefix('/_profiler'); + } +}; diff --git a/config/routes/web_profiler.yaml b/config/routes/web_profiler.yaml deleted file mode 100644 index e004603..0000000 --- a/config/routes/web_profiler.yaml +++ /dev/null @@ -1,8 +0,0 @@ -when@dev: - web_profiler_wdt: - resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" - prefix: /_wdt - - web_profiler_profiler: - resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" - prefix: /_profiler diff --git a/config/services.php b/config/services.php new file mode 100644 index 0000000..cf9fd95 --- /dev/null +++ b/config/services.php @@ -0,0 +1,41 @@ +parameters() + ->set('app.sqlrunner_url', env('SQLRUNNER_URL')) + ->set('app.redis_uri', env('REDIS_URI')) + ->set('app.openai_api_key', env('OPENAI_API_KEY')) + ->set('app.features.hint', true) + ->set('app.features.editable-profile', true) + ->set('app.features.comment', true); + + $services = $containerConfigurator->services(); + + $services->defaults() + ->autowire() + ->autoconfigure(); + + $services->load('App\\', __DIR__.'/../src/') + ->exclude([ + __DIR__.'/../src/DependencyInjection/', + __DIR__.'/../src/Entity/', + __DIR__.'/../src/Kernel.php', + __DIR__.'/../src/Service/Processes/', + __DIR__.'/../src/Service/Types/', + __DIR__.'/../src/Twig/Components/Challenge/EventConstant.php', + ]); + + $services->set(PromptService::class) + ->arg('$apiKey', '%app.openai_api_key%'); + + $services->set(SqlRunnerService::class) + ->arg('$baseUrl', '%app.sqlrunner_url%'); +}; diff --git a/config/services.yaml b/config/services.yaml deleted file mode 100644 index 0641d8b..0000000 --- a/config/services.yaml +++ /dev/null @@ -1,41 +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: - app.sqlrunner_url: "%env(SQLRUNNER_URL)%" - app.redis_uri: "%env(REDIS_URI)%" - app.openai_api_key: "%env(OPENAI_API_KEY)%" - - app.features.hint: true - app.features.editable-profile: true - app.features.comment: true - -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/" - exclude: - - "../src/DependencyInjection/" - - "../src/Entity/" - - "../src/Kernel.php" - - "../src/Service/Processes/" - - "../src/Service/Types/" - - "../src/Twig/Components/Challenge/EventConstant.php" - - # add more service definitions when explicit configuration is needed - # please note that last definitions always *replace* previous ones - App\Service\PromptService: - arguments: - $apiKey: "%app.openai_api_key%" - - App\Service\SqlRunnerService: - arguments: - $baseUrl: "%app.sqlrunner_url%" diff --git a/devenv.lock b/devenv.lock index 6b5f771..61f5c0f 100644 --- a/devenv.lock +++ b/devenv.lock @@ -53,10 +53,10 @@ }, "nixpkgs": { "locked": { - "lastModified": 1733064805, + "lastModified": 1733097829, "owner": "nixos", "repo": "nixpkgs", - "rev": "31d66ae40417bb13765b0ad75dd200400e98de84", + "rev": "2c15aa59df0017ca140d9ba302412298ab4bf22a", "type": "github" }, "original": { diff --git a/frankenphp/docker-entrypoint.sh b/frankenphp/docker-entrypoint.sh index 5af3f41..e8023a0 100644 --- a/frankenphp/docker-entrypoint.sh +++ b/frankenphp/docker-entrypoint.sh @@ -7,8 +7,8 @@ if [ "$1" = 'frankenphp' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then fi if [ -z "$(ls -A 'node_modules/' 2>/dev/null)" ]; then - corepnpm prepare && pnpm install --prod --prefer-frozen-lockfile - fi + corepack prepare && pnpm install --prod --prefer-frozen-lockfile + fi if grep -q ^DATABASE_URL= .env; then echo "Waiting for database to be ready..." diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 2469fa7..f0afb3f 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -6,5 +6,10 @@ parameters: - public/ - src/ - tests/ + scanDirectories: + - var/cache/dev/Symfony/Config + scanFiles: + - vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php symfony: consoleApplicationLoader: tests/console-application.php + containerXmlPath: var/cache/dev/App_KernelDevDebugContainer.xml diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b10269e..42325b8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1635,9 +1635,9 @@ packages: } engines: { node: ">= 8" } - streamx@2.20.2: + streamx@2.21.0: resolution: { - integrity: sha512-aDGDLU+j9tJcUdPGOaHmVF1u/hhI+CsGkT02V3OKlHDV7IukOI+nTWAGkiZEKCO35rWN1wIr4tS7YFr1f4qSvA==, + integrity: sha512-Qz6MsDZXJ6ur9u+b+4xCG18TluU7PGlRfXVAAjNiGsFrBUt/ioyLkxbFaKJygoPs+/kW4VyBj0bSj89Qu0IGyg==, } strip-dirs@3.0.0: @@ -2820,7 +2820,7 @@ snapshots: source-map@0.7.4: {} - streamx@2.20.2: + streamx@2.21.0: dependencies: fast-fifo: 1.3.2 queue-tick: 1.0.1 @@ -2852,7 +2852,7 @@ snapshots: dependencies: b4a: 1.6.7 fast-fifo: 1.3.2 - streamx: 2.20.2 + streamx: 2.21.0 text-decoder@1.2.1: {} diff --git a/src/Controller/CommentsController.php b/src/Controller/CommentsController.php index 8cee2a1..b7ddd9a 100644 --- a/src/Controller/CommentsController.php +++ b/src/Controller/CommentsController.php @@ -99,11 +99,6 @@ public function likes( private function isCommentFeatureEnabled(): bool { - $comment = $this->getParameter('app.features.comment'); - if (!\is_bool($comment)) { - throw new \RuntimeException('The "app.features.comment" parameter must be a boolean.'); - } - - return $comment; + return $this->getParameter('app.features.comment'); } } diff --git a/src/Controller/ProfileController.php b/src/Controller/ProfileController.php index ffc4b97..a24c34f 100644 --- a/src/Controller/ProfileController.php +++ b/src/Controller/ProfileController.php @@ -21,10 +21,7 @@ class ProfileController extends AbstractController { public function isProfileEditable(): bool { - $isProfileEditable = $this->getParameter('app.features.editable-profile'); - \assert(\is_bool($isProfileEditable)); - - return $isProfileEditable; + return $this->getParameter('app.features.editable-profile'); } #[Route('/profile', name: 'app_profile')] diff --git a/src/Twig/Components/Challenge/Comments/CommentForm.php b/src/Twig/Components/Challenge/Comments/CommentForm.php index 10cd494..3e98188 100644 --- a/src/Twig/Components/Challenge/Comments/CommentForm.php +++ b/src/Twig/Components/Challenge/Comments/CommentForm.php @@ -57,8 +57,6 @@ protected function instantiateForm(): FormInterface public function save(EntityManagerInterface $entityManager, ParameterBagInterface $parameterBag): void { $appFeatureComment = $parameterBag->get('app.features.comment'); - \assert(\is_bool($appFeatureComment)); - if (!$appFeatureComment) { throw new BadRequestHttpException('Comment feature is disabled.'); } diff --git a/src/Twig/Components/Challenge/Instruction/Modal.php b/src/Twig/Components/Challenge/Instruction/Modal.php index 04677b2..10d2cb6 100644 --- a/src/Twig/Components/Challenge/Instruction/Modal.php +++ b/src/Twig/Components/Challenge/Instruction/Modal.php @@ -67,8 +67,6 @@ public function instruct( ParameterBagInterface $parameterBag, ): void { $appFeatureHint = $parameterBag->get('app.features.hint'); - \assert(\is_bool($appFeatureHint)); - if (!$appFeatureHint) { throw new BadRequestHttpException('Hint feature is disabled.'); } diff --git a/templates/components/Challenge/Comments.html.twig b/templates/components/Challenge/Comments.html.twig index 54f5b7f..20b1037 100644 --- a/templates/components/Challenge/Comments.html.twig +++ b/templates/components/Challenge/Comments.html.twig @@ -1,5 +1,5 @@ -
- {% if appfeatures.comment %} +
+ {% if app_features_comment %}
diff --git a/templates/components/Challenge/Ui.html.twig b/templates/components/Challenge/Ui.html.twig index 39ade25..de3d888 100644 --- a/templates/components/Challenge/Ui.html.twig +++ b/templates/components/Challenge/Ui.html.twig @@ -3,7 +3,7 @@ {% if question.solutionVideo %} {% endif %} - {% if appfeatures.hint %} + {% if app_features_hint %} {% endif %} @@ -15,7 +15,7 @@
- {% if appfeatures.hint %} + {% if app_features_hint %} {% endif %} {% if question.solutionVideo %} @@ -35,7 +35,7 @@
- {% if appfeatures.comment %} + {% if app_features_comment %}

留言區

diff --git a/templates/components/Navbar.html.twig b/templates/components/Navbar.html.twig index 0d9bc31..5a05e0e 100644 --- a/templates/components/Navbar.html.twig +++ b/templates/components/Navbar.html.twig @@ -20,7 +20,7 @@ name: '留言一覽', icon: 'bi bi-chat-left-text-fill', path: path('app_comments'), - disabled: not appfeatures.comment, + disabled: not app_features_comment, }, { pageId: 'complementary',