This commit is contained in:
Jonas 2024-02-12 22:03:17 +01:00
parent 203233d2ed
commit 93fa2da696
45 changed files with 2633 additions and 550 deletions

5
.gitignore vendored
View file

@ -9,3 +9,8 @@
/vendor/
###< symfony/framework-bundle ###
/.php-styler.cache
###> squizlabs/php_codesniffer ###
/.phpcs-cache
/phpcs.xml
###< squizlabs/php_codesniffer ###

View file

@ -27,6 +27,12 @@
<Configuration>
<option name="path" value="$PROJECT_DIR$/tests" />
</Configuration>
<Configuration>
<option name="path" value="$PROJECT_DIR$/tests" />
</Configuration>
<Configuration>
<option name="path" value="$PROJECT_DIR$/tests" />
</Configuration>
</list>
</option>
</component>

View file

@ -43,7 +43,6 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/symplify/easy-coding-standard" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/collections" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/common" />
<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" />
@ -82,6 +81,7 @@
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-uuid" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/uid" />
<excludeFolder url="file://$MODULE_DIR$/var" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/common" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />

View file

@ -17,83 +17,83 @@
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/psr/cache" />
<path value="$PROJECT_DIR$/vendor/rector/rector" />
<path value="$PROJECT_DIR$/vendor/lubiana/code-quality" />
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/symfony/runtime" />
<path value="$PROJECT_DIR$/vendor/symfony/dotenv" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpdoc-parser" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan" />
<path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/dependency-injection" />
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/symfony/config" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/symfony/framework-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
<path value="$PROJECT_DIR$/vendor/symfony/cache" />
<path value="$PROJECT_DIR$/vendor/symfony/var-exporter" />
<path value="$PROJECT_DIR$/vendor/symfony/flex" />
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
<path value="$PROJECT_DIR$/vendor/symfony/string" />
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/slevomat/coding-standard" />
<path value="$PROJECT_DIR$/vendor/symplify/easy-coding-standard" />
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/dealerdirect/phpcodesniffer-composer-installer" />
<path value="$PROJECT_DIR$/vendor/squizlabs/php_codesniffer" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-icu" />
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
<path value="$PROJECT_DIR$/vendor/symfony/property-access" />
<path value="$PROJECT_DIR$/vendor/symfony/property-info" />
<path value="$PROJECT_DIR$/vendor/symfony/form" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
<path value="$PROJECT_DIR$/vendor/doctrine/migrations" />
<path value="$PROJECT_DIR$/vendor/doctrine/collections" />
<path value="$PROJECT_DIR$/vendor/doctrine/common" />
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
<path value="$PROJECT_DIR$/vendor/doctrine/sql-formatter" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-bundle" />
<path value="$PROJECT_DIR$/vendor/doctrine/cache" />
<path value="$PROJECT_DIR$/vendor/doctrine/orm" />
<path value="$PROJECT_DIR$/vendor/pmjones/auto-shell" />
<path value="$PROJECT_DIR$/vendor/pmjones/php-styler" />
<path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
<path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpdoc-parser" />
<path value="$PROJECT_DIR$/vendor/doctrine/cache" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan" />
<path value="$PROJECT_DIR$/vendor/twig/twig" />
<path value="$PROJECT_DIR$/vendor/symfony/dependency-injection" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
<path value="$PROJECT_DIR$/vendor/doctrine/sql-formatter" />
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
<path value="$PROJECT_DIR$/vendor/doctrine/persistence" />
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/symfony/string" />
<path value="$PROJECT_DIR$/vendor/doctrine/data-fixtures" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
<path value="$PROJECT_DIR$/vendor/symfony/uid" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/flex" />
<path value="$PROJECT_DIR$/vendor/symfony/property-access" />
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-icu" />
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
<path value="$PROJECT_DIR$/vendor/squizlabs/php_codesniffer" />
<path value="$PROJECT_DIR$/vendor/symfony/property-info" />
<path value="$PROJECT_DIR$/vendor/symfony/twig-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
<path value="$PROJECT_DIR$/vendor/symfony/cache" />
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
<path value="$PROJECT_DIR$/vendor/symfony/runtime" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-uuid" />
<path value="$PROJECT_DIR$/vendor/symfony/twig-bridge" />
<path value="$PROJECT_DIR$/vendor/doctrine/collections" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/symfony/security-csrf" />
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
<path value="$PROJECT_DIR$/vendor/doctrine/orm" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/vendor/symfony/dotenv" />
<path value="$PROJECT_DIR$/vendor/symfony/security-core" />
<path value="$PROJECT_DIR$/vendor/symfony/var-exporter" />
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
<path value="$PROJECT_DIR$/vendor/symfony/config" />
<path value="$PROJECT_DIR$/vendor/doctrine/persistence" />
<path value="$PROJECT_DIR$/vendor/fakerphp/faker" />
<path value="$PROJECT_DIR$/vendor/lubiana/code-quality" />
<path value="$PROJECT_DIR$/vendor/dealerdirect/phpcodesniffer-composer-installer" />
<path value="$PROJECT_DIR$/vendor/symfony/form" />
<path value="$PROJECT_DIR$/vendor/slevomat/coding-standard" />
<path value="$PROJECT_DIR$/vendor/symfony/framework-bundle" />
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/symplify/easy-coding-standard" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/psr/cache" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/doctrine/common" />
<path value="$PROJECT_DIR$/vendor/symfony/maker-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/process" />
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/maker-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/twig-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
<path value="$PROJECT_DIR$/vendor/symfony/security-core" />
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/security-csrf" />
<path value="$PROJECT_DIR$/vendor/symfony/twig-bridge" />
<path value="$PROJECT_DIR$/vendor/twig/twig" />
<path value="$PROJECT_DIR$/vendor/pmjones/php-styler" />
<path value="$PROJECT_DIR$/vendor/pmjones/auto-shell" />
<path value="$PROJECT_DIR$/vendor/doctrine/data-fixtures" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
<path value="$PROJECT_DIR$/vendor/fakerphp/faker" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-uuid" />
<path value="$PROJECT_DIR$/vendor/symfony/uid" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
<path value="$PROJECT_DIR$/vendor/doctrine/migrations" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.3" />

View file

@ -26,6 +26,12 @@
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
</suites>
</component>
</project>

6
.idea/vcs.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -9,7 +9,7 @@
"ext-iconv": "*",
"doctrine/doctrine-bundle": "^2.11",
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^2.17",
"doctrine/orm": "^2.18",
"lubiana/code-quality": "^1.4",
"symfony/console": "7.0.*",
"symfony/dotenv": "7.0.*",
@ -27,7 +27,7 @@
"doctrine/doctrine-fixtures-bundle": "^3.5",
"fakerphp/faker": "^1.23",
"pmjones/php-styler": "0.x-dev",
"symfony/maker-bundle": "^1.53"
"symfony/maker-bundle": "^1.54"
},
"config": {
"allow-plugins": {

202
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "819ccb5535c468b5a449a26b029fbb73",
"content-hash": "72b8eb151eaf7da0138e53c9ebce0cee",
"packages": [
{
"name": "dealerdirect/phpcodesniffer-composer-installer",
@ -356,16 +356,16 @@
},
{
"name": "doctrine/dbal",
"version": "3.8.0",
"version": "3.8.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "d244f2e6e6bf32bff5174e6729b57214923ecec9"
"reference": "c9ea252cdce4da324ede3d6c5913dd89f769afd2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/d244f2e6e6bf32bff5174e6729b57214923ecec9",
"reference": "d244f2e6e6bf32bff5174e6729b57214923ecec9",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/c9ea252cdce4da324ede3d6c5913dd89f769afd2",
"reference": "c9ea252cdce4da324ede3d6c5913dd89f769afd2",
"shasum": ""
},
"require": {
@ -381,9 +381,9 @@
"doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.1",
"phpstan/phpstan": "1.10.56",
"phpstan/phpstan": "1.10.57",
"phpstan/phpstan-strict-rules": "^1.5",
"phpunit/phpunit": "9.6.15",
"phpunit/phpunit": "9.6.16",
"psalm/plugin-phpunit": "0.18.4",
"slevomat/coding-standard": "8.13.1",
"squizlabs/php_codesniffer": "3.8.1",
@ -449,7 +449,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/3.8.0"
"source": "https://github.com/doctrine/dbal/tree/3.8.1"
},
"funding": [
{
@ -465,7 +465,7 @@
"type": "tidelift"
}
],
"time": "2024-01-25T21:44:02+00:00"
"time": "2024-02-03T17:33:49+00:00"
},
{
"name": "doctrine/deprecations",
@ -516,16 +516,16 @@
},
{
"name": "doctrine/doctrine-bundle",
"version": "2.11.1",
"version": "2.11.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/DoctrineBundle.git",
"reference": "4089f1424b724786c062aea50aae5f773449b94b"
"reference": "fb22c9320383caa2829c32dc3b84c1b5e0f1ceaf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/4089f1424b724786c062aea50aae5f773449b94b",
"reference": "4089f1424b724786c062aea50aae5f773449b94b",
"url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/fb22c9320383caa2829c32dc3b84c1b5e0f1ceaf",
"reference": "fb22c9320383caa2829c32dc3b84c1b5e0f1ceaf",
"shasum": ""
},
"require": {
@ -546,18 +546,18 @@
},
"conflict": {
"doctrine/annotations": ">=3.0",
"doctrine/orm": "<2.14 || >=4.0",
"doctrine/orm": "<2.17 || >=4.0",
"twig/twig": "<1.34 || >=2.0 <2.4"
},
"require-dev": {
"doctrine/annotations": "^1 || ^2",
"doctrine/coding-standard": "^12",
"doctrine/deprecations": "^1.0",
"doctrine/orm": "^2.14 || ^3.0",
"doctrine/orm": "^2.17 || ^3.0",
"friendsofphp/proxy-manager-lts": "^1.0",
"phpunit/phpunit": "^9.5.26 || ^10.0",
"phpunit/phpunit": "^9.5.26",
"psalm/plugin-phpunit": "^0.18.4",
"psalm/plugin-symfony": "^4",
"psalm/plugin-symfony": "^5",
"psr/log": "^1.1.4 || ^2.0 || ^3.0",
"symfony/phpunit-bridge": "^6.1 || ^7.0",
"symfony/property-info": "^5.4 || ^6.0 || ^7.0",
@ -570,7 +570,7 @@
"symfony/web-profiler-bundle": "^5.4 || ^6.0 || ^7.0",
"symfony/yaml": "^5.4 || ^6.0 || ^7.0",
"twig/twig": "^1.34 || ^2.12 || ^3.0",
"vimeo/psalm": "^4.30"
"vimeo/psalm": "^5.15"
},
"suggest": {
"doctrine/orm": "The Doctrine ORM integration is optional in the bundle.",
@ -615,7 +615,7 @@
],
"support": {
"issues": "https://github.com/doctrine/DoctrineBundle/issues",
"source": "https://github.com/doctrine/DoctrineBundle/tree/2.11.1"
"source": "https://github.com/doctrine/DoctrineBundle/tree/2.11.2"
},
"funding": [
{
@ -631,7 +631,7 @@
"type": "tidelift"
}
],
"time": "2023-11-15T20:01:50+00:00"
"time": "2024-02-06T15:41:25+00:00"
},
{
"name": "doctrine/doctrine-migrations-bundle",
@ -978,28 +978,27 @@
},
{
"name": "doctrine/lexer",
"version": "2.1.0",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
"reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124"
"reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124",
"reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124",
"url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
"reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
"shasum": ""
},
"require": {
"doctrine/deprecations": "^1.0",
"php": "^7.1 || ^8.0"
"php": "^8.1"
},
"require-dev": {
"doctrine/coding-standard": "^9 || ^10",
"phpstan/phpstan": "^1.3",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
"doctrine/coding-standard": "^12",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.5",
"psalm/plugin-phpunit": "^0.18.3",
"vimeo/psalm": "^4.11 || ^5.0"
"vimeo/psalm": "^5.21"
},
"type": "library",
"autoload": {
@ -1036,7 +1035,7 @@
],
"support": {
"issues": "https://github.com/doctrine/lexer/issues",
"source": "https://github.com/doctrine/lexer/tree/2.1.0"
"source": "https://github.com/doctrine/lexer/tree/3.0.1"
},
"funding": [
{
@ -1052,7 +1051,7 @@
"type": "tidelift"
}
],
"time": "2022-12-14T08:49:07+00:00"
"time": "2024-02-05T11:56:58+00:00"
},
{
"name": "doctrine/migrations",
@ -1158,16 +1157,16 @@
},
{
"name": "doctrine/orm",
"version": "2.17.4",
"version": "2.18.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/orm.git",
"reference": "ccfc97c32f63aaa0988ac6aa42e71c5590bb794d"
"reference": "f2176a9ce56cafdfd1624d54bfdb076819083d5b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/orm/zipball/ccfc97c32f63aaa0988ac6aa42e71c5590bb794d",
"reference": "ccfc97c32f63aaa0988ac6aa42e71c5590bb794d",
"url": "https://api.github.com/repos/doctrine/orm/zipball/f2176a9ce56cafdfd1624d54bfdb076819083d5b",
"reference": "f2176a9ce56cafdfd1624d54bfdb076819083d5b",
"shasum": ""
},
"require": {
@ -1180,7 +1179,7 @@
"doctrine/event-manager": "^1.2 || ^2",
"doctrine/inflector": "^1.4 || ^2.0",
"doctrine/instantiator": "^1.3 || ^2",
"doctrine/lexer": "^2",
"doctrine/lexer": "^2 || ^3",
"doctrine/persistence": "^2.4 || ^3",
"ext-ctype": "*",
"php": "^7.1 || ^8.0",
@ -1216,7 +1215,7 @@
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\ORM\\": "lib/Doctrine/ORM"
"Doctrine\\ORM\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@ -1253,9 +1252,9 @@
],
"support": {
"issues": "https://github.com/doctrine/orm/issues",
"source": "https://github.com/doctrine/orm/tree/2.17.4"
"source": "https://github.com/doctrine/orm/tree/2.18.0"
},
"time": "2024-01-26T19:41:16+00:00"
"time": "2024-01-31T15:53:12+00:00"
},
{
"name": "doctrine/persistence",
@ -1749,16 +1748,16 @@
},
{
"name": "rector/rector",
"version": "0.19.5",
"version": "0.19.8",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "89c895d127b9d248d2af007068a824b5348ef81f"
"reference": "de3b3bb159abd704b144aa86fb244f7f1f4ac947"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/89c895d127b9d248d2af007068a824b5348ef81f",
"reference": "89c895d127b9d248d2af007068a824b5348ef81f",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/de3b3bb159abd704b144aa86fb244f7f1f4ac947",
"reference": "de3b3bb159abd704b144aa86fb244f7f1f4ac947",
"shasum": ""
},
"require": {
@ -1793,7 +1792,7 @@
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/0.19.5"
"source": "https://github.com/rectorphp/rector/tree/0.19.8"
},
"funding": [
{
@ -1801,7 +1800,7 @@
"type": "github"
}
],
"time": "2024-01-29T23:53:47+00:00"
"time": "2024-02-05T10:59:13+00:00"
},
{
"name": "slevomat/coding-standard",
@ -2975,16 +2974,16 @@
},
{
"name": "symfony/flex",
"version": "v2.4.3",
"version": "v2.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/flex.git",
"reference": "6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1"
"reference": "bec213c39511eda66663baa2ee7440c65f89c695"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/flex/zipball/6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1",
"reference": "6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1",
"url": "https://api.github.com/repos/symfony/flex/zipball/bec213c39511eda66663baa2ee7440c65f89c695",
"reference": "bec213c39511eda66663baa2ee7440c65f89c695",
"shasum": ""
},
"require": {
@ -3020,7 +3019,7 @@
"description": "Composer plugin for Symfony",
"support": {
"issues": "https://github.com/symfony/flex/issues",
"source": "https://github.com/symfony/flex/tree/v2.4.3"
"source": "https://github.com/symfony/flex/tree/v2.4.4"
},
"funding": [
{
@ -3036,7 +3035,7 @@
"type": "tidelift"
}
],
"time": "2024-01-02T11:08:32+00:00"
"time": "2024-02-05T18:04:53+00:00"
},
{
"name": "symfony/form",
@ -3610,16 +3609,16 @@
},
{
"name": "symfony/polyfill-intl-icu",
"version": "v1.28.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-icu.git",
"reference": "e46b4da57951a16053cd751f63f4a24292788157"
"reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/e46b4da57951a16053cd751f63f4a24292788157",
"reference": "e46b4da57951a16053cd751f63f4a24292788157",
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/07094a28851a49107f3ab4f9120ca2975a64b6e1",
"reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1",
"shasum": ""
},
"require": {
@ -3630,9 +3629,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -3677,7 +3673,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.28.0"
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.29.0"
},
"funding": [
{
@ -3693,20 +3689,20 @@
"type": "tidelift"
}
],
"time": "2023-03-21T17:27:24+00:00"
"time": "2024-01-29T20:12:16+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.28.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "42292d99c55abe617799667f454222c54c60e229"
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
"reference": "42292d99c55abe617799667f454222c54c60e229",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"shasum": ""
},
"require": {
@ -3720,9 +3716,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -3760,7 +3753,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
},
"funding": [
{
@ -3776,20 +3769,20 @@
"type": "tidelift"
}
],
"time": "2023-07-28T09:04:16+00:00"
"time": "2024-01-29T20:11:03+00:00"
},
{
"name": "symfony/polyfill-uuid",
"version": "v1.28.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-uuid.git",
"reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e"
"reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9c44518a5aff8da565c8a55dbe85d2769e6f630e",
"reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e",
"url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853",
"reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853",
"shasum": ""
},
"require": {
@ -3803,9 +3796,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -3842,7 +3832,7 @@
"uuid"
],
"support": {
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.0"
"source": "https://github.com/symfony/polyfill-uuid/tree/v1.29.0"
},
"funding": [
{
@ -3858,7 +3848,7 @@
"type": "tidelift"
}
],
"time": "2023-01-26T09:26:14+00:00"
"time": "2024-01-29T20:11:03+00:00"
},
{
"name": "symfony/property-access",
@ -5229,16 +5219,16 @@
},
{
"name": "symplify/easy-coding-standard",
"version": "12.1.8",
"version": "12.1.10",
"source": {
"type": "git",
"url": "https://github.com/easy-coding-standard/easy-coding-standard.git",
"reference": "7962c810a8eebc4174a38d7dff673f1999e61595"
"reference": "67f643befd6997961aa6bd759b4529e94bb18b53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/7962c810a8eebc4174a38d7dff673f1999e61595",
"reference": "7962c810a8eebc4174a38d7dff673f1999e61595",
"url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/67f643befd6997961aa6bd759b4529e94bb18b53",
"reference": "67f643befd6997961aa6bd759b4529e94bb18b53",
"shasum": ""
},
"require": {
@ -5271,7 +5261,7 @@
],
"support": {
"issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues",
"source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.1.8"
"source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.1.10"
},
"funding": [
{
@ -5283,7 +5273,7 @@
"type": "github"
}
],
"time": "2024-01-16T22:56:06+00:00"
"time": "2024-02-05T10:58:24+00:00"
},
{
"name": "twig/twig",
@ -5757,44 +5747,44 @@
},
{
"name": "symfony/maker-bundle",
"version": "v1.53.0",
"version": "v1.54.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/maker-bundle.git",
"reference": "8d2f3f96704766837548d177fe3ae39ae94822d9"
"reference": "a8523cf35d777bf2d8cf5703fa73f378fdc27125"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/maker-bundle/zipball/8d2f3f96704766837548d177fe3ae39ae94822d9",
"reference": "8d2f3f96704766837548d177fe3ae39ae94822d9",
"url": "https://api.github.com/repos/symfony/maker-bundle/zipball/a8523cf35d777bf2d8cf5703fa73f378fdc27125",
"reference": "a8523cf35d777bf2d8cf5703fa73f378fdc27125",
"shasum": ""
},
"require": {
"doctrine/inflector": "^2.0",
"nikic/php-parser": "^4.18|^5.0",
"php": ">=8.1",
"symfony/config": "^6.3|^7.0",
"symfony/console": "^6.3|^7.0",
"symfony/dependency-injection": "^6.3|^7.0",
"symfony/config": "^6.4|^7.0",
"symfony/console": "^6.4|^7.0",
"symfony/dependency-injection": "^6.4|^7.0",
"symfony/deprecation-contracts": "^2.2|^3",
"symfony/filesystem": "^6.3|^7.0",
"symfony/finder": "^6.3|^7.0",
"symfony/framework-bundle": "^6.3|^7.0",
"symfony/http-kernel": "^6.3|^7.0",
"symfony/process": "^6.3|^7.0"
"symfony/filesystem": "^6.4|^7.0",
"symfony/finder": "^6.4|^7.0",
"symfony/framework-bundle": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/process": "^6.4|^7.0"
},
"conflict": {
"doctrine/doctrine-bundle": "<2.4",
"doctrine/orm": "<2.10"
"doctrine/doctrine-bundle": "<2.10",
"doctrine/orm": "<2.15"
},
"require-dev": {
"composer/semver": "^3.0",
"doctrine/doctrine-bundle": "^2.5.0",
"doctrine/orm": "^2.10.0",
"symfony/http-client": "^6.3|^7.0",
"symfony/phpunit-bridge": "^6.3|^7.0",
"symfony/security-core": "^6.3|^7.0",
"symfony/yaml": "^6.3|^7.0",
"doctrine/orm": "^2.15|^3",
"symfony/http-client": "^6.4|^7.0",
"symfony/phpunit-bridge": "^6.4.1|^7.0",
"symfony/security-core": "^6.4|^7.0",
"symfony/yaml": "^6.4|^7.0",
"twig/twig": "^3.0|^4.x-dev"
},
"type": "symfony-bundle",
@ -5829,7 +5819,7 @@
],
"support": {
"issues": "https://github.com/symfony/maker-bundle/issues",
"source": "https://github.com/symfony/maker-bundle/tree/v1.53.0"
"source": "https://github.com/symfony/maker-bundle/tree/v1.54.0"
},
"funding": [
{
@ -5845,7 +5835,7 @@
"type": "tidelift"
}
],
"time": "2024-02-01T10:05:38+00:00"
"time": "2024-02-06T21:23:55+00:00"
},
{
"name": "symfony/process",

View file

@ -0,0 +1,49 @@
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%'
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
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

View file

@ -0,0 +1,10 @@
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

View file

@ -1,15 +1,18 @@
<?php declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
// config/packages/twig.php
use Symfony\Config\TwigConfig;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('twig', [
'file_name_pattern' => '*.twig',
]);
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
if ($containerConfigurator->env() === 'test') {
$containerConfigurator->extension('twig', [
'strict_variables' => true,
]);
use App\Service\WhoAreYou;
return static function (TwigConfig $twig): void {
$twig
->fileNamePattern('*.twig')
->global('username', service(WhoAreYou::class));
if ($_SERVER['APP_ENV'] === 'test') {
$twig->strictVariables(true);
}
};

View file

@ -0,0 +1,6 @@
twig:
file_name_pattern: '*.twig'
when@test:
twig:
strict_variables: true

View file

@ -0,0 +1,11 @@
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

5
config/routes.yaml Normal file
View file

@ -0,0 +1,5 @@
controllers:
resource:
path: ../src/Controller/
namespace: App\Controller
type: attribute

View file

@ -0,0 +1,4 @@
when@dev:
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error

View file

@ -1,6 +1,7 @@
<?php declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Bridge\Twig\AppVariable;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
@ -14,4 +15,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
__DIR__ . '/../src/Entity/',
__DIR__ . '/../src/Kernel.php',
]);
$services->alias(AppVariable::class, 'twig.app_variable');
};

View file

@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240203164757 extends AbstractMigration
final class Version20240212201659 extends AbstractMigration
{
public function getDescription(): string
{
@ -21,27 +21,25 @@ final class Version20240203164757 extends AbstractMigration
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL --(DC2Type:ulid)
, vendor_id BLOB NOT NULL --(DC2Type:ulid)
, started_by_name VARCHAR(255) NOT NULL, closed_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
, started_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
, PRIMARY KEY(id), CONSTRAINT FK_4485672F603EE73 FOREIGN KEY (vendor_id) REFERENCES vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('CREATE INDEX IDX_4485672F603EE73 ON food_order (vendor_id)');
, closed_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
, started_by VARCHAR(30) NOT NULL, started_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE menu_item (id BLOB NOT NULL --(DC2Type:ulid)
, vendor_id BLOB NOT NULL --(DC2Type:ulid)
, price INTEGER DEFAULT NULL, PRIMARY KEY(id), CONSTRAINT FK_D754D550F603EE73 FOREIGN KEY (vendor_id) REFERENCES vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
, price INTEGER NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_D754D550F603EE73 FOREIGN KEY (vendor_id) REFERENCES vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('CREATE INDEX IDX_D754D550F603EE73 ON menu_item (vendor_id)');
$this->addSql('CREATE TABLE menu_item_alias (id BLOB NOT NULL --(DC2Type:ulid)
, menu_item_id BLOB NOT NULL --(DC2Type:ulid)
, name VARCHAR(255) NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_EA66C4969AB44FE0 FOREIGN KEY (menu_item_id) REFERENCES menu_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
, name VARCHAR(50) NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_EA66C4969AB44FE0 FOREIGN KEY (menu_item_id) REFERENCES menu_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('CREATE INDEX IDX_EA66C4969AB44FE0 ON menu_item_alias (menu_item_id)');
$this->addSql('CREATE TABLE order_item (id BLOB NOT NULL --(DC2Type:ulid)
, food_order_id BLOB NOT NULL --(DC2Type:ulid)
, menu_item_id BLOB NOT NULL --(DC2Type:ulid)
, PRIMARY KEY(id), CONSTRAINT FK_52EA1F09A5D24A7A FOREIGN KEY (food_order_id) REFERENCES food_order (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_52EA1F099AB44FE0 FOREIGN KEY (menu_item_id) REFERENCES menu_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('CREATE INDEX IDX_52EA1F09A5D24A7A ON order_item (food_order_id)');
$this->addSql('CREATE INDEX IDX_52EA1F099AB44FE0 ON order_item (menu_item_id)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_52EA1F099AB44FE0 ON order_item (menu_item_id)');
$this->addSql('CREATE TABLE vendor (id BLOB NOT NULL --(DC2Type:ulid)
, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
, name VARCHAR(50) NOT NULL, PRIMARY KEY(id))');
}
public function down(Schema $schema): void

View file

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240212202919 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TEMPORARY TABLE __temp__food_order AS SELECT id, closed_at, started_by, started_at FROM food_order');
$this->addSql('DROP TABLE food_order');
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL --(DC2Type:ulid)
, vendor_id BLOB NOT NULL --(DC2Type:ulid)
, closed_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
, started_by VARCHAR(30) NOT NULL, started_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
, PRIMARY KEY(id), CONSTRAINT FK_4485672F603EE73 FOREIGN KEY (vendor_id) REFERENCES vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('INSERT INTO food_order (id, closed_at, started_by, started_at) SELECT id, closed_at, started_by, started_at FROM __temp__food_order');
$this->addSql('DROP TABLE __temp__food_order');
$this->addSql('CREATE INDEX IDX_4485672F603EE73 ON food_order (vendor_id)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TEMPORARY TABLE __temp__food_order AS SELECT id, closed_at, started_by, started_at FROM food_order');
$this->addSql('DROP TABLE food_order');
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL --(DC2Type:ulid)
, closed_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
, started_by VARCHAR(30) NOT NULL, started_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
, PRIMARY KEY(id))');
$this->addSql('INSERT INTO food_order (id, closed_at, started_by, started_at) SELECT id, closed_at, started_by, started_at FROM __temp__food_order');
$this->addSql('DROP TABLE __temp__food_order');
}
}

19
phpcs.xml.dist Normal file
View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
<arg name="basepath" value="."/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<arg name="extensions" value="php"/>
<rule ref="PSR12"/>
<file>bin/</file>
<file>config/</file>
<file>public/</file>
<file>src/</file>
<file>tests/</file>
</ruleset>

1
public/css/missing.css Normal file

File diff suppressed because one or more lines are too long

8
public/css/new.min.css vendored Normal file
View file

@ -0,0 +1,8 @@
/**
* Minified by jsDelivr using clean-css v4.2.1.
* Original file: /npm/@exampledev/new.css@1.1.2/new.css
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
:root{--nc-font-sans:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--nc-font-mono:Consolas,monaco,'Ubuntu Mono','Liberation Mono','Courier New',Courier,monospace;--nc-tx-1:#000000;--nc-tx-2:#1A1A1A;--nc-bg-1:#FFFFFF;--nc-bg-2:#F6F8FA;--nc-bg-3:#E5E7EB;--nc-lk-1:#0070F3;--nc-lk-2:#0366D6;--nc-lk-tx:#FFFFFF;--nc-ac-1:#79FFE1;--nc-ac-tx:#0C4047}@media (prefers-color-scheme:dark){:root{--nc-tx-1:#ffffff;--nc-tx-2:#eeeeee;--nc-bg-1:#000000;--nc-bg-2:#111111;--nc-bg-3:#222222;--nc-lk-1:#3291FF;--nc-lk-2:#0070F3;--nc-lk-tx:#FFFFFF;--nc-ac-1:#7928CA;--nc-ac-tx:#FFFFFF}}*{margin:0;padding:0}address,area,article,aside,audio,blockquote,datalist,details,dl,fieldset,figure,form,iframe,img,input,meter,nav,ol,optgroup,option,output,p,pre,progress,ruby,section,table,textarea,ul,video{margin-bottom:1rem}button,html,input,select{font-family:var(--nc-font-sans)}body{margin:0 auto;max-width:750px;padding:2rem;border-radius:6px;overflow-x:hidden;word-break:break-word;overflow-wrap:break-word;background:var(--nc-bg-1);color:var(--nc-tx-2);font-size:1.03rem;line-height:1.5}::selection{background:var(--nc-ac-1);color:var(--nc-ac-tx)}h1,h2,h3,h4,h5,h6{line-height:1;color:var(--nc-tx-1);padding-top:.875rem}h1,h2,h3{color:var(--nc-tx-1);padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid var(--nc-bg-2)}h4,h5,h6{margin-bottom:.3rem}h1{font-size:2.25rem}h2{font-size:1.85rem}h3{font-size:1.55rem}h4{font-size:1.25rem}h5{font-size:1rem}h6{font-size:.875rem}a{color:var(--nc-lk-1)}a:hover{color:var(--nc-lk-2)}abbr:hover{cursor:help}blockquote{padding:1.5rem;background:var(--nc-bg-2);border-left:5px solid var(--nc-bg-3)}abbr{cursor:help}blockquote :last-child{padding-bottom:0;margin-bottom:0}header{background:var(--nc-bg-2);border-bottom:1px solid var(--nc-bg-3);padding:2rem 1.5rem;margin:-2rem calc(0px - (50vw - 50%)) 2rem;padding-left:calc(50vw - 50%);padding-right:calc(50vw - 50%)}header h1,header h2,header h3{padding-bottom:0;border-bottom:0}header>:first-child{margin-top:0;padding-top:0}header>:last-child{margin-bottom:0}a button,button,input[type=button],input[type=reset],input[type=submit]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:var(--nc-lk-1);color:var(--nc-lk-tx);border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:var(--nc-lk-tx)}a button[disabled],button[disabled],input[type=button][disabled],input[type=reset][disabled],input[type=submit][disabled]{cursor:default;opacity:.5;cursor:not-allowed}.button:focus,.button:hover,button:focus,button:hover,input[type=button]:focus,input[type=button]:hover,input[type=reset]:focus,input[type=reset]:hover,input[type=submit]:focus,input[type=submit]:hover{background:var(--nc-lk-2)}code,kbd,pre,samp{font-family:var(--nc-font-mono)}code,kbd,pre,samp{background:var(--nc-bg-2);border:1px solid var(--nc-bg-3);border-radius:4px;padding:3px 6px;font-size:.9rem}kbd{border-bottom:3px solid var(--nc-bg-3)}pre{padding:1rem 1.4rem;max-width:100%;overflow:auto}pre code{background:inherit;font-size:inherit;color:inherit;border:0;padding:0;margin:0}code pre{display:inline;background:inherit;font-size:inherit;color:inherit;border:0;padding:0;margin:0}details{padding:.6rem 1rem;background:var(--nc-bg-2);border:1px solid var(--nc-bg-3);border-radius:4px}summary{cursor:pointer;font-weight:700}details[open]{padding-bottom:.75rem}details[open] summary{margin-bottom:6px}details[open]>:last-child{margin-bottom:0}dt{font-weight:700}dd::before{content:'→ '}hr{border:0;border-bottom:1px solid var(--nc-bg-3);margin:1rem auto}fieldset{margin-top:1rem;padding:2rem;border:1px solid var(--nc-bg-3);border-radius:4px}legend{padding:auto .5rem}table{border-collapse:collapse;width:100%}td,th{border:1px solid var(--nc-bg-3);text-align:left;padding:.5rem}th{background:var(--nc-bg-2)}tr:nth-child(even){background:var(--nc-bg-2)}table caption{font-weight:700;margin-bottom:.5rem}textarea{max-width:100%}ol,ul{padding-left:2rem}li{margin-top:.4rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}mark{padding:3px 6px;background:var(--nc-ac-1);color:var(--nc-ac-tx)}input,select,textarea{padding:6px 12px;margin-bottom:.5rem;background:var(--nc-bg-2);color:var(--nc-tx-2);border:1px solid var(--nc-bg-3);border-radius:4px;box-shadow:none;box-sizing:border-box}img{max-width:100%}
/*# sourceMappingURL=/sm/4a51164882967d28a74fabce02685c18fa45a529b77514edc75d708f04dd08b9.map */

1689
public/css/water.css Normal file

File diff suppressed because it is too large Load diff

1
public/js/htmx.org.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -5,13 +5,12 @@ namespace App\Controller;
use App\Entity\FoodOrder;
use App\Entity\MenuItem;
use App\Entity\OrderItem;
use App\Form\FoodOrderType;
use App\Repository\FoodOrderRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use DateTimeImmutable;
#[Route('/order')]
class FoodOrderController extends AbstractController
@ -20,82 +19,48 @@ class FoodOrderController extends AbstractController
final public const APP_FOODORDER_ADD_ITEM = 'app_foodorder_add_item';
#[Route('/', name: 'app_food_order_index', methods: ['GET'])]
public function index(FoodOrderRepository $foodOrderRepository): Response
{
return $this->render(
'food_order/index.html.twig',
[
'food_orders' => $foodOrderRepository->findAll(),
],
);
}
#[Route(
'/new',
name: 'app_food_order_new',
methods: [Request::METHOD_GET, Request::METHOD_POST],
)]
public function new(
Request $request,
EntityManagerInterface $entityManager,
): Response {
$foodOrder = new FoodOrder;
$form = $this->createForm(FoodOrderType::class, $foodOrder);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($foodOrder);
$entityManager->flush();
return $this->redirectToRoute(
'app_food_order_index',
[],
Response::HTTP_SEE_OTHER,
);
}
return $this->render(
'food_order/new.html.twig',
[
'food_order' => $foodOrder,
'form' => $form,
],
);
}
final public const APP_FOODORDER_CLOSE = 'app_foodorder_close';
#[Route('/{id}', name: self::APP_FOOD_ORDER_SHOW, methods: ['GET'])]
public function show(FoodOrder $foodOrder): Response
{
$menuItems = $foodOrder->vendor->menuItems;
return $this->render(
'food_order/show.html.twig',
[
'food_order' => $foodOrder,
'menu_items' => $menuItems,
'menu_items' => $foodOrder->getVendor()->getMenuItems(),
],
);
}
#[Route('/close/{id}', name: self::APP_FOODORDER_CLOSE, methods: ['GET'])]
public function close(
FoodOrder $foodOrder,
EntityManagerInterface $entityManager,
): Response {
$foodOrder->setClosedAt();
$entityManager->persist($foodOrder);
$entityManager->flush();
return $this->redirectToRoute(
self::APP_FOOD_ORDER_SHOW,
[
'id' => $foodOrder->getId(),
],
Response::HTTP_SEE_OTHER,
);
}
#[Route(
'/{foodOrder}/add/{menuItem}',
'/{foodOrder}/add',
name: self::APP_FOODORDER_ADD_ITEM,
methods: [Request::METHOD_GET],
methods: [Request::METHOD_GET, Request::METHOD_POST],
)]
public function add(
FoodOrder $foodOrder,
MenuItem $menuItem,
EntityManagerInterface $entityManager,
): Response {
$orderItem = new OrderItem(foodOrder: $foodOrder, menuItem: $menuItem);
$entityManager->persist($orderItem);
$entityManager->flush();
return $this->redirectToRoute(
self::APP_FOOD_ORDER_SHOW,
[
'id' => $foodOrder->id,
],
Response::HTTP_SEE_OTHER,
);
return new Response('lol');
}
#[Route(
@ -118,50 +83,4 @@ class FoodOrderController extends AbstractController
Response::HTTP_SEE_OTHER,
);
}
#[Route('/{id}/edit', name: 'app_food_order_edit', methods: ['GET', 'POST'])]
public function edit(
Request $request,
FoodOrder $foodOrder,
EntityManagerInterface $entityManager,
): Response {
$form = $this->createForm(FoodOrderType::class, $foodOrder);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
return $this->redirectToRoute(''[], Response::HTTP_SEE_OTHER);
}
return $this->render(
'food_order/edit.html.twig',
[
'food_order' => $foodOrder,
'form' => $form,
],
);
}
#[Route('/{id}', name: 'app_food_order_delete', methods: ['POST'])]
public function delete(
Request $request,
FoodOrder $foodOrder,
EntityManagerInterface $entityManager,
): Response {
if (
$this->isCsrfTokenValid(
'delete' . $foodOrder->id ?? '',
$request->request->get('_token'),
)
) {
$entityManager->remove($foodOrder);
$entityManager->flush();
}
return $this->redirectToRoute(
'app_food_order_index',
[],
Response::HTTP_SEE_OTHER,
);
}
}

View file

@ -2,25 +2,28 @@
namespace App\Controller;
use App\Entity\FoodOrder;
use App\Form\FoodOrderType;
use App\Repository\FoodOrderRepository;
use App\Service\WhoAreYou;
use App\Entity\FoodOrder;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
final class Start extends AbstractController
{
#[Route('/')]
#[Route('/', name: 'app_index')]
public function index(
FoodOrderRepository $foodOrderRepository,
EntityManagerInterface $em,
Request $request,
): Response {
$openOrders = $foodOrderRepository->findOpen();
$order = new FoodOrder('');
$openOrders = $foodOrderRepository->findOpenOrders();
$order = new FoodOrder();
$form = $this->createForm(FoodOrderType::class, $order);
$form->handleRequest($request);
@ -28,8 +31,10 @@ final class Start extends AbstractController
$em->persist($order);
$em->flush();
return $this->redirectToRoute(
'app_food_order_index',
[],
FoodOrderController::APP_FOOD_ORDER_SHOW,
[
'id' => $order->getId(),
],
Response::HTTP_SEE_OTHER,
);
}
@ -42,4 +47,31 @@ final class Start extends AbstractController
],
);
}
#[Route(
'/name',
name: 'app_name',
methods: [Request::METHOD_GET, Request::METHOD_POST],
)]
public function name(Request $request, WhoAreYou $who): Response
{
$form = $this
->createFormBuilder()
->add('name', TextType::class, [
'data' => $who->username,
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$name = $form->getData()['name'];
$response = $this->redirectToRoute('app_index');
$response->headers->setCookie(new Cookie('username', $name));
return $response;
}
return $this->render('start/name.html.twig', [
'form' => $form->createView(),
]);
}
}

View file

@ -2,9 +2,9 @@
namespace App\Controller;
use App\Entity\Vendor;
use App\Form\VendorType;
use App\Repository\VendorRepository;
use App\Entity\Vendor;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;

View file

@ -0,0 +1,42 @@
<?php declare(strict_types=1);
namespace App\DataFixtures;
use App\Entity\MenuItem;
use App\Entity\MenuItemAlias;
use App\Entity\Vendor;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Faker\Generator;
final class AppFixture extends Fixture
{
private Generator $faker;
public function load(ObjectManager $manager)
{
$this->faker = \Faker\Factory::create();
foreach (range(0, 20) as $vendorCount) {
$vendor = new Vendor();
$vendor->setName($this->faker->name);
$manager->persist($vendor);
foreach (range(0, 10) as $itemCount) {
$menuItem = new MenuItem();
$menuItem->setVendor($vendor);
$menuItem->setPrice(random_int(500, 2000));
$manager->persist($menuItem);
$menuItemAliasOne = new MenuItemAlias();
$menuItemAliasOne->setName($this->faker->word);
$menuItem->addMenuItemAlias($menuItemAliasOne);
$manager->persist($menuItemAliasOne);
$menuItemAliasTwo = new MenuItemAlias();
$menuItemAliasTwo->setName($this->faker->word);
$menuItem->addMenuItemAlias($menuItemAliasTwo);
$manager->persist($menuItemAliasTwo);
}
}
$manager->flush();
}
}

View file

@ -1,51 +0,0 @@
<?php declare(strict_types=1);
namespace App\DataFixtures;
use App\Entity\MenuItem;
use App\Entity\MenuItemAlias;
use App\Entity\Vendor;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Faker\Factory;
use Faker\Generator;
use Override;
use function random_int;
use function range;
class AppFixtures extends Fixture
{
private readonly Generator $faker;
public function __construct()
{
$this->faker = Factory::create();
}
#[Override]
public function load(ObjectManager $manager): void
{
foreach (range(0, 10) as $counter) {
$vendor = new Vendor(name: $this->faker->company());
$this->addMenuItemsToVendor($vendor, $manager);
$manager->persist($vendor);
}
$manager->flush();
}
private function addMenuItemsToVendor(Vendor $vendor, ObjectManager $manager): void
{
foreach (range(0, 100) as $counter) {
$aliasOne = MenuItemAlias::new($this->faker->lastName());
$aliasTwo = MenuItemAlias::new($this->faker->lastName());
$manager->persist($aliasOne);
$manager->persist($aliasTwo);
$item = MenuItem::new([$aliasOne, $aliasTwo]);
$item->price = random_int(500, 2000);
$manager->persist($item);
$vendor->addMenuItem($item);
}
}
}

View file

@ -1,51 +1,105 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace App\Entity;
use App\Repository\FoodOrderRepository;
use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;
use DateTimeImmutable;
#[ORM\Entity(repositoryClass: FoodOrderRepository::class)]
class FoodOrder
{
public function __construct(
#[ORM\Column]
public string $startedByName,
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
public Ulid $id = new Ulid,
#[ORM\Column(nullable: true)]
public DateTimeImmutable|null $closedAt = null,
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
/** @var Collection<int, OrderItem> $orderItems */
#[ORM\OneToMany(
mappedBy: 'foodOrder',
targetEntity: OrderItem::class,
orphanRemoval: true,
)]
public Collection $orderItems = new ArrayCollection,
#[ORM\ManyToOne(inversedBy: 'foodOrders')]
#[ORM\JoinColumn(nullable: false)]
public Vendor|null $vendor = null,
#[ORM\Column]
public DateTimeImmutable $startedAt = new DateTimeImmutable,
)
#[ORM\Column(nullable: true)]
private ?DateTimeImmutable $closedAt = null;
#[ORM\Column(length: 30)]
private string|null $startedBy = null;
#[ORM\Column]
private DateTimeImmutable $startedAt;
#[ORM\OneToMany(
mappedBy: 'foodOrder',
targetEntity: OrderItem::class,
orphanRemoval: true,
)]
private Collection $orderItems;
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
private ?Vendor $vendor = null;
public function __construct()
{
$this->id = new Ulid;
$this->orderItems = new ArrayCollection;
$this->startedAt = new DateTimeImmutable;
}
public function getId(): Ulid
{
return $this->id;
}
public function getClosedAt(): \DateTimeImmutable|null
{
return $this->closedAt;
}
public function setClosedAt(\DateTimeImmutable $closedAt = new DateTimeImmutable()): static
{
$this->closedAt = $closedAt;
return $this;
}
public function getStartedBy(): string|null
{
return $this->startedBy;
}
public function setStartedBy(string $startedBy): static
{
$this->startedBy = $startedBy;
return $this;
}
public function getStartedAt(): \DateTimeImmutable
{
return $this->startedAt;
}
public function setStartedAt(\DateTimeImmutable $startedAt): static
{
$this->startedAt = $startedAt;
return $this;
}
/**
* @return Collection<int, OrderItem>
*/
public function getOrderItems(): Collection
{
return $this->orderItems;
}
public function addOrderItem(OrderItem $orderItem): static
{
if (!$this->orderItems->contains($orderItem)) {
if (! $this->orderItems->contains($orderItem)) {
$this->orderItems->add($orderItem);
$orderItem->foodOrder = $this;
$orderItem->setFoodOrder($this);
}
return $this;
@ -56,19 +110,31 @@ class FoodOrder
// set the owning side to null (unless already changed)
if (
$this->orderItems->removeElement($orderItem)
&& $orderItem->foodOrder === $this
&& $orderItem->getFoodOrder() === $this
) {
$orderItem->foodOrder = null;
$orderItem->setFoodOrder(null);
}
return $this;
}
public function getVendor(): ?Vendor
{
return $this->vendor;
}
public function setVendor(?Vendor $vendor): static
{
$this->vendor = $vendor;
return $this;
}
public function groupedOrderItems(): array
{
return $this->orderItems->reduce(
function (array $carry, OrderItem $item): array {
$menuItemStringId = (string)$item->menuItem->id;
$menuItemStringId = (string)$item->getMenuItem()->getId();
if (isset($carry[$menuItemStringId])) {
$carry[$menuItemStringId]['amount']++;
} else {
@ -82,4 +148,6 @@ class FoodOrder
[]
);
}
}

View file

@ -13,55 +13,87 @@ use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: MenuItemRepository::class)]
class MenuItem
{
public function __construct(
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
public Ulid $id = new Ulid,
#[ORM\ManyToOne(inversedBy: 'menuItems')]
#[ORM\JoinColumn(nullable: false)]
public Vendor|null $vendor = null,
#[ORM\Column(nullable: true)]
public int|null $price = null,
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
/** @var Collection<int, MenuItemAlias> $aliases */
#[ORM\OneToMany(
mappedBy: 'menuItem',
targetEntity: MenuItemAlias::class,
orphanRemoval: true,
)]
public Collection $aliases = new ArrayCollection,
) {}
#[ORM\ManyToOne(inversedBy: 'menuItems')]
#[ORM\JoinColumn(nullable: false)]
private Vendor $vendor;
public function addAlias(MenuItemAlias $alias): static
#[ORM\Column]
private int $price;
#[ORM\OneToMany(
mappedBy: 'menuItem',
targetEntity: MenuItemAlias::class,
orphanRemoval: true,
)]
private Collection $menuItemAliases;
public function __construct()
{
if (! $this->aliases->contains($alias)) {
$this->aliases->add($alias);
$alias->menuItem = $this;
}
return false;
$this->id = new Ulid;
$this->menuItemAliases = new ArrayCollection;
}
public function removeAlias(MenuItemAlias $alias): static
public function getId(): Ulid
{
// set the owning side to null (unless already changed)
if ($this->aliases->removeElement($alias) && $alias->menuItem === $this) {
$alias->menuItem = null;
return $this->id;
}
public function getVendor(): Vendor
{
return $this->vendor;
}
public function setVendor(Vendor$vendor): static
{
$this->vendor = $vendor;
return $this;
}
public function getPrice(): int|null
{
return $this->price;
}
public function setPrice(int $price): static
{
$this->price = $price;
return $this;
}
/**
* @return Collection<int, MenuItemAlias>
*/
public function getMenuItemAliases(): Collection
{
return $this->menuItemAliases;
}
public function addMenuItemAlias(MenuItemAlias $menuItemAlias): static
{
if (! $this->menuItemAliases->contains($menuItemAlias)) {
$this->menuItemAliases->add($menuItemAlias);
$menuItemAlias->setMenuItem($this);
}
return $this;
}
public static function new(array $aliases): self
public function removeMenuItemAlias(MenuItemAlias $menuItemAlias): static
{
$menuItem = new self;
foreach ($aliases as $alias) {
$menuItem->addAlias($alias);
// set the owning side to null (unless already changed)
if (
$this->menuItemAliases->removeElement($menuItemAlias)
&& $menuItemAlias->getMenuItem() === $this
) {
$menuItemAlias->setMenuItem(null);
}
return $menuItem;
return $this;
}
}

View file

@ -1,4 +1,5 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace App\Entity;
@ -11,23 +12,48 @@ use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: MenuItemAliasRepository::class)]
class MenuItemAlias
{
public function __construct(
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
public Ulid $id = new Ulid,
#[ORM\ManyToOne(inversedBy: 'aliases')]
#[ORM\JoinColumn(nullable: false)]
public MenuItem|null $menuItem = null,
#[ORM\Column(length: 255)]
public string|null $name = null,
) {}
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
public static function new(string $name): self
#[ORM\Column(length: 50)]
private string|null $name = null;
#[ORM\ManyToOne(inversedBy: 'menuItemAliases')]
#[ORM\JoinColumn(nullable: false)]
private MenuItem|null $menuItem = null;
public function __construct()
{
$new = new self;
$new->name = $name;
return $new;
$this->id = new Ulid;
}
public function getId(): Ulid
{
return $this->id;
}
public function getName(): string|null
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function getMenuItem(): MenuItem|null
{
return $this->menuItem;
}
public function setMenuItem(MenuItem|null $menuItem): static
{
$this->menuItem = $menuItem;
return $this;
}
}

View file

@ -11,17 +11,49 @@ use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: OrderItemRepository::class)]
class OrderItem
{
public function __construct(
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
public Ulid $id = new Ulid,
#[ORM\ManyToOne(inversedBy: 'orderItems')]
#[ORM\JoinColumn(nullable: false)]
public FoodOrder|null $foodOrder = null,
#[ORM\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
public MenuItem|null $menuItem = null,
) {}
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
#[ORM\ManyToOne(inversedBy: 'orderItems')]
#[ORM\JoinColumn(nullable: false)]
private FoodOrder|null $foodOrder = null;
#[ORM\OneToOne(cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(nullable: false)]
private MenuItem|null $menuItem = null;
public function __construct()
{
$this->id = new Ulid;
}
public function getId(): Ulid
{
return $this->id;
}
public function getFoodOrder(): FoodOrder|null
{
return $this->foodOrder;
}
public function setFoodOrder(FoodOrder|null $foodOrder): static
{
$this->foodOrder = $foodOrder;
return $this;
}
public function getMenuItem(): MenuItem|null
{
return $this->menuItem;
}
public function setMenuItem(MenuItem $menuItem): static
{
$this->menuItem = $menuItem;
return $this;
}
}

View file

@ -1,4 +1,5 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace App\Entity;
@ -13,33 +14,58 @@ use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: VendorRepository::class)]
class Vendor
{
public function __construct(
#[ORM\Column]
public string $name,
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
public Ulid $id = new Ulid,
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
/** @var Collection<int, MenuItem> $menuItems */
#[ORM\OneToMany(mappedBy: 'vendor', targetEntity: MenuItem::class)]
public Collection $menuItems = new ArrayCollection,
#[ORM\Column(length: 50)]
private string|null $name = null;
/** @var Collection<int, FoodOrder> $foodOrders */
#[ORM\OneToMany(
mappedBy: 'vendor',
targetEntity: FoodOrder::class,
orphanRemoval: true,
)]
private Collection $foodOrders = new ArrayCollection,
) {}
#[ORM\OneToMany(
mappedBy: 'vendor',
targetEntity: MenuItem::class,
orphanRemoval: true,
)]
private Collection $menuItems;
public function __construct()
{
$this->id = new Ulid;
$this->menuItems = new ArrayCollection;
}
public function getId(): Ulid
{
return $this->id;
}
public function getName(): string|null
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
/**
* @return Collection<int, MenuItem>
*/
public function getMenuItems(): Collection
{
return $this->menuItems;
}
public function addMenuItem(MenuItem $menuItem): static
{
if (! $this->menuItems->contains($menuItem)) {
$this->menuItems->add($menuItem);
$menuItem->vendor = $this;
$menuItem->setVendor($this);
}
return $this;
@ -48,29 +74,11 @@ class Vendor
public function removeMenuItem(MenuItem $menuItem): static
{
// set the owning side to null (unless already changed)
if ($this->menuItems->removeElement($menuItem) && $menuItem->vendor === $this) {
$menuItem->vendor = null;
}
return $this;
}
public function addFoodOrder(FoodOrder $foodOrder): static
{
if (! $this->foodOrders->contains($foodOrder)) {
$this->foodOrders->add($foodOrder);
$foodOrder->vendor = $this;
}
return $this;
}
public function removeFoodOrder(FoodOrder $foodOrder): static
{
if (
$this->foodOrders->removeElement($foodOrder) && $foodOrder->vendor === $this
$this->menuItems->removeElement($menuItem)
&& $menuItem->getVendor() === $this
) {
$foodOrder->vendor = null;
$menuItem->setVendor(null);
}
return $this;

View file

@ -2,21 +2,29 @@
namespace App\Form;
use App\Service\WhoAreYou;
use App\Entity\FoodOrder;
use App\Entity\Vendor;
use Override;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class FoodOrderType extends AbstractType
{
public function __construct(
private readonly WhoAreYou $who
) {}
#[Override]
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('startedByName')
->add('startedBy', TextType::class, [
'data' => $this->who->username,
])
->add(
'vendor',
EntityType::class,

View file

@ -0,0 +1,35 @@
<?php
namespace App\Form;
use App\Entity\FoodOrder;
use App\Entity\MenuItem;
use App\Entity\OrderItem;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class OrderItemType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('foodOrder', EntityType::class, [
'class' => FoodOrder::class,
'choice_label' => 'id',
])
->add('menuItem', EntityType::class, [
'class' => MenuItem::class,
'choice_label' => 'id',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => OrderItem::class,
]);
}
}

View file

@ -1,12 +1,10 @@
<?php declare(strict_types=1);
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\FoodOrder;
use DateTime;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Persistence\ManagerRegistry;
/**
@ -25,17 +23,13 @@ class FoodOrderRepository extends ServiceEntityRepository
}
/**
* @return Collection<int, FoodOrder>
* @return FoodOrder[] Returns an array of FoodOrder objects
*/
public function findOpen(int $limit = 10): Collection
public function findOpenOrders(): array
{
$yesterday = new DateTime;
$yesterday->modify('-1 day');
$queryBuilder = $this->createQueryBuilder('e');
$queryBuilder
->where('e.closedAt IS NULL')
->andWhere($queryBuilder->expr()->gte('e.startedAt', ':yesterday'))
->setParameter('yesterday', $yesterday);
return new ArrayCollection($queryBuilder->getQuery()->getResult());
return $this->createQueryBuilder('f')
->andWhere('f.closedAt IS NULL')
->getQuery()
->getResult();
}
}

View file

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

View file

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

29
src/Service/WhoAreYou.php Normal file
View file

@ -0,0 +1,29 @@
<?php declare(strict_types=1);
namespace App\Service;
use Override;
use Stringable;
use Symfony\Bridge\Twig\AppVariable;
final class WhoAreYou implements Stringable
{
public string $username = '';
public function __construct(AppVariable $appVariable)
{
$this->username = $appVariable->getRequest()?->cookies?->get('username', '')
?? '';
}
public function isKnown(): bool
{
return $this->username !== '';
}
#[Override]
public function __toString(): string
{
return $this->username;
}
}

26
src/Twig/AppExtension.php Normal file
View file

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use function number_format;
use Override;
final class AppExtension extends AbstractExtension
{
#[Override]
public function getFilters(): array
{
return [new TwigFilter('cents_to_eur', $this->formatCentsToEur(...))];
}
public function formatCentsToEur(int $cents): string
{
$euros = $cents / 100;
return number_format($euros, 2, ',', '') . ' EUR';
}
}

View file

@ -25,19 +25,6 @@
"src/DataFixtures/AppFixtures.php"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "3.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.1",
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"phpstan/phpstan": {
"version": "1.10",
"recipe": {
@ -99,15 +86,6 @@
"src/Kernel.php"
]
},
"symfony/maker-bundle": {
"version": "1.53",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
"symfony/routing": {
"version": "7.0",
"recipe": {

View file

@ -4,7 +4,7 @@
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
<link rel="stylesheet" href="/css/simple.min.css">
<link rel="stylesheet" href="/css/water.css">
{% block stylesheets %}
{% endblock %}
@ -12,6 +12,15 @@
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
<header>
<p>
Futtern |
Henlo {{ username }} (<a href="{{ url('app_name') }}">change name</a>) |
<a href="{{ url('app_index') }}">index</a>
</p>
</header>
<main>
{% block body %}{% endblock %}
</main>
</body>
</html>

View file

@ -9,7 +9,7 @@
<tbody>
<tr>
<th>StartedByName</th>
<td>{{ food_order.startedByName }}</td>
<td>{{ food_order.startedBy }}</td>
</tr>
<tr>
<th>Id</th>
@ -21,7 +21,13 @@
</tr>
<tr>
<th>ClosedAt</th>
<td>{{ food_order.closedAt ? food_order.closedAt|date('Y-m-d H:i:s') : '' }}</td>
<td>
{% if food_order.closedAt is not null%}
{{ food_order.closedAt|date('Y-m-d H:i:s') }}
{% else %}
<a href="{{ path('app_foodorder_close', {id: food_order.id}) }}">close</a>
{% endif %}
</td>
</tr>
</tbody>
</table>
@ -41,7 +47,7 @@
{{ lel.item.menuItem.aliases|map(i => i.name)|join(' / ') }}
</td>
<td>
{{ lel.item.menuItem.price }}
{{ lel.item.menuItem.price|cents_to_eur }}
</td>
<td>
{{ lel.amount }} |
@ -65,21 +71,37 @@
{% for item in menu_items %}
<tr>
<td>
{{ item.aliases|map(i => i.name)|join(' / ') }}
{{ item.menuItemAliases|map(i => i.name)|join(' / ') }}
</td>
<td>
{{ item.price }}
{{ item.price|cents_to_eur }}
</td>
<td>
<a href="{{ path('app_foodorder_add_item', {foodOrder: food_order.id, menuItem: item.id}) }}">join</a>
{% if food_order.closedAt is null %}
<a
href="#"
data-menuitem-id="{{ item.id }}"
>add</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<script>
document.querySelectorAll('a[data-menuitem-id]').forEach((link) => {
link.addEventListener('click', (event) => {
// Prevent the default action of the link
event.preventDefault();
<a href="{{ path('app_food_order_index') }}">back to list</a>
// Get the `data-menuitem-id` attribute of the clicked link
let menuItemId = link.getAttribute('data-menuitem-id');
<a href="{{ path('app_food_order_edit', {'id': food_order.id}) }}">edit</a>
// Select the corresponding dialog with the same `data-menuitem-id`. Assuming each dialog's id is the same as `data-menuitem-id`, please update the code to use proper id or class as needed.
let dialog = document.querySelector(`dialog[data-menuitem-id="${menuItemId}"]` );
{{ include('food_order/_delete_form.html.twig') }}
// Open the dialog
dialog.showModal();
});
});
</script>
{% endblock %}

View file

@ -23,7 +23,7 @@
</tr>
{% else %}
<tr>
<td colspan="3">no records found</td>
<td colspan="4">no records found</td>
</tr>
{% endfor %}
</tbody>

View file

@ -0,0 +1,6 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ include('_form.html.twig') }}
{% endblock %}