lol #1

Merged
lubiana merged 1 commit from simplify into main 2024-06-10 17:14:23 +00:00
90 changed files with 2842 additions and 6060 deletions
Showing only changes of commit e2a33be4f9 - Show all commits

2
.env
View file

@ -16,7 +16,7 @@
###> symfony/framework-bundle ### ###> symfony/framework-bundle ###
APP_ENV=dev APP_ENV=dev
APP_SECRET=4293c0675d5638816d9140f45bd2515b APP_SECRET=baf2f8a94d398f52a7baf90b23b730d9
###< symfony/framework-bundle ### ###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ### ###> doctrine/doctrine-bundle ###

6
.env.test Normal file
View file

@ -0,0 +1,6 @@
# define your env variables for the test env here
KERNEL_CLASS='App\Kernel'
APP_SECRET='$ecretf0rt3st'
SYMFONY_DEPRECATIONS_HELPER=999999
PANTHER_APP_ENV=panther
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots

View file

@ -0,0 +1,37 @@
on: [pull_request]
jobs:
ls:
runs-on: docker
container:
image: git.php.fail/lubiana/container/php:ci
steps:
- name: Manually checkout
env:
REPO: '${{ github.repository }}'
TOKEN: '${{ secrets.GITHUB_TOKEN }}'
GIT_SERVER: 'hannover.ccc.de/gitlab'
run: |
git clone --branch $GITHUB_HEAD_REF https://${TOKEN}@${GIT_SERVER}/${REPO}.git .
git fetch
git checkout $GITHUB_HEAD_REF
- name: composer install
env:
COMPOSER_CACHE_DIR: /opt/hostedtoolcache/.composer/cache/files
run: |
mkdir -p ${{ env.COMPOSER_CACHE_DIR }}
composer install
- name: lint
run: composer lint
- name: test
run: composer test
- name: GIT commit and push all changed files
env:
CI_COMMIT_MESSAGE: Continuous Integration Fixes
CI_COMMIT_AUTHOR: Continuous Integration
run: |
if [[ -n "$(git status -s)" ]]; then
git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}"
git config --global user.email "gitbot@users.noreply.php.fail"
git commit -am "${{ env.CI_COMMIT_MESSAGE }}"
git push
fi

View file

@ -0,0 +1,41 @@
on:
push:
branches:
- 'main'
jobs:
ls:
runs-on: docker
container:
image: git.php.fail/lubiana/container/php:ci
steps:
- name: Manually checkout
env:
REPO: '${{ github.repository }}'
TOKEN: '${{ secrets.GITHUB_TOKEN }}'
BRANCH: '${{ env.GITHUB_REF_NAME }}'
GIT_SERVER: 'hannover.ccc.de/gitlab'
run: |
git clone --branch $GITHUB_REF_NAME https://${TOKEN}@${GIT_SERVER}/${REPO}.git .
git fetch
git checkout ${{ github.head_ref }}
- name: composer install
env:
COMPOSER_CACHE_DIR: /opt/hostedtoolcache/.composer/cache/files
run: |
mkdir -p ${{ env.COMPOSER_CACHE_DIR }}
composer install
- name: lint
run: composer lint
- name: test
run: composer test
- name: GIT commit and push all changed files
env:
CI_COMMIT_MESSAGE: Continuous Integration Fixes
CI_COMMIT_AUTHOR: Continuous Integration
run: |
if [[ -n "$(git status -s)" ]]; then
git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}"
git config --global user.email "gitbot@users.noreply.php.fail"
git commit -am "${{ env.CI_COMMIT_MESSAGE }}"
git push
fi

16
.gitignore vendored
View file

@ -8,9 +8,15 @@
/var/ /var/
/vendor/ /vendor/
###< symfony/framework-bundle ### ###< symfony/framework-bundle ###
/.php-styler.cache
###> squizlabs/php_codesniffer ### ###> symfony/phpunit-bridge ###
/.phpcs-cache .phpunit.result.cache
/phpcs.xml /phpunit.xml
###< squizlabs/php_codesniffer ### ###< symfony/phpunit-bridge ###
###> phpunit/phpunit ###
/phpunit.xml
.phpunit.result.cache
###< phpunit/phpunit ###
.idea/

8
.idea/.gitignore vendored
View file

@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Codeception">
<option name="configurations">
<list>
<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>
<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>
<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>
<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>
</project>

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="data.db" uuid="a97e0c0d-1a88-4e27-b1c3-36b7079cc563">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/var/data.db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

View file

@ -1,91 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/dealerdirect/phpcodesniffer-composer-installer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/lubiana/code-quality" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpstan/phpdoc-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpstan/phpstan" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/event-dispatcher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
<excludeFolder url="file://$MODULE_DIR$/vendor/rector/rector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/slevomat/coding-standard" />
<excludeFolder url="file://$MODULE_DIR$/vendor/squizlabs/php_codesniffer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/cache-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/config" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dependency-injection" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dotenv" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/error-handler" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/filesystem" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/finder" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/flex" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/framework-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-kernel" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/routing" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/runtime" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-exporter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/yaml" />
<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/dbal" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/deprecations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/event-manager" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/inflector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/instantiator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/migrations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/orm" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/persistence" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/sql-formatter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nikic/php-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/pmjones/auto-shell" />
<excludeFolder url="file://$MODULE_DIR$/vendor/pmjones/php-styler" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/doctrine-bridge" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/form" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/maker-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/options-resolver" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/password-hasher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-icu" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/process" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-access" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-info" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-core" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-csrf" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stopwatch" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/twig-bridge" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/twig-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/validator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/twig" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/data-fixtures" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/fakerphp/faker" />
<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" />
</component>
</module>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/futtern.iml" filepath="$PROJECT_DIR$/.idea/futtern.iml" />
</modules>
</component>
</project>

View file

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpDockerContainerSettings">
<list>
<map>
<entry key="de9b5aa7-e4b3-472b-9be8-63313022c875">
<value>
<DockerContainerSettings>
<option name="version" value="1" />
<option name="volumeBindings">
<list>
<DockerVolumeBindingImpl>
<option name="containerPath" value="/opt/project" />
<option name="hostPath" value="$PROJECT_DIR$" />
</DockerVolumeBindingImpl>
</list>
</option>
</DockerContainerSettings>
</value>
</entry>
</map>
</list>
</component>
</project>

View file

@ -1,116 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpCodeSniffer">
<phpcs_settings>
<PhpCSConfiguration beautifier_path="$PROJECT_DIR$/vendor/bin/phpcbf" tool_path="$PROJECT_DIR$/vendor/bin/phpcs" />
</phpcs_settings>
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/rector/rector" />
<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/deprecations" />
<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/doctrine/doctrine-migrations-bundle" />
<path value="$PROJECT_DIR$/vendor/doctrine/migrations" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.3" />
<component name="PhpStan">
<PhpStan_settings>
<PhpStanConfiguration tool_path="$PROJECT_DIR$/vendor/bin/phpstan" />
</PhpStan_settings>
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" />
</phpunit_settings>
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

View file

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PHPSpec">
<suites>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<PhpSpecSuiteConfiguration>
<option name="myPath" value="$PROJECT_DIR$" />
</PhpSpecSuiteConfiguration>
<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>

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PHPUnit">
<option name="directories">
<list>
<option value="$PROJECT_DIR$/tests" />
</list>
</option>
</component>
</project>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Symfony2PluginSettings">
<option name="pluginEnabled" value="true" />
</component>
</project>

View file

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

View file

View file

@ -4,6 +4,10 @@
use App\Kernel; use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_dir(dirname(__DIR__).'/vendor')) {
throw new LogicException('Dependencies are missing. Try running "composer install".');
}
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) { if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".'); throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
} }

23
bin/phpunit Executable file
View file

@ -0,0 +1,23 @@
#!/usr/bin/env php
<?php
if (!ini_get('date.timezone')) {
ini_set('date.timezone', 'UTC');
}
if (is_file(dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit')) {
if (PHP_VERSION_ID >= 80000) {
require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit';
} else {
define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php');
require PHPUNIT_COMPOSER_INSTALL;
PHPUnit\TextUI\Command::main();
}
} else {
if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
exit(1);
}
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
}

View file

@ -4,30 +4,29 @@
"minimum-stability": "stable", "minimum-stability": "stable",
"prefer-stable": true, "prefer-stable": true,
"require": { "require": {
"php": ">=8.3", "php": ">=8.2",
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"doctrine/doctrine-bundle": "^2.11", "doctrine/dbal": "^3",
"doctrine/doctrine-bundle": "^2.12",
"doctrine/doctrine-migrations-bundle": "^3.3", "doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^2.18", "doctrine/orm": "^3.2",
"symfony/console": "7.0.*", "symfony/console": "7.1.*",
"symfony/dotenv": "7.0.*", "symfony/dotenv": "7.1.*",
"symfony/flex": "^2", "symfony/flex": "^2",
"symfony/form": "7.0.*", "symfony/framework-bundle": "7.1.*",
"symfony/framework-bundle": "7.0.*", "symfony/runtime": "7.1.*",
"symfony/runtime": "7.0.*", "symfony/uid": "7.1.*",
"symfony/security-csrf": "7.0.*", "symfony/yaml": "7.1.*"
"symfony/twig-bundle": "7.0.*",
"symfony/uid": "7.0.*",
"symfony/validator": "7.0.*",
"symfony/yaml": "7.0.*"
}, },
"require-dev": { "require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.5", "lubiana/code-quality": "^1.7",
"fakerphp/faker": "^1.23", "phpunit/phpunit": "^9.5",
"pmjones/php-styler": "0.x-dev", "symfony/browser-kit": "7.1.*",
"lubiana/code-quality": "^1.5", "symfony/css-selector": "7.1.*",
"symfony/maker-bundle": "^1.54" "symfony/maker-bundle": "^1.60",
"symfony/phpunit-bridge": "^7.1",
"symplify/config-transformer": "^12.3"
}, },
"config": { "config": {
"allow-plugins": { "allow-plugins": {
@ -56,11 +55,7 @@
"symfony/polyfill-php74": "*", "symfony/polyfill-php74": "*",
"symfony/polyfill-php80": "*", "symfony/polyfill-php80": "*",
"symfony/polyfill-php81": "*", "symfony/polyfill-php81": "*",
"symfony/polyfill-php82": "*", "symfony/polyfill-php82": "*"
"symfony/polyfill-php83": "*",
"symfony/polyfill-intl-grapheme": "*",
"symfony/polyfill-intl-normalizer": "*",
"symfony/polyfill-intl-mbstring": "*"
}, },
"scripts": { "scripts": {
"auto-scripts": { "auto-scripts": {
@ -68,17 +63,17 @@
"assets:install %PUBLIC_DIR%": "symfony-cmd" "assets:install %PUBLIC_DIR%": "symfony-cmd"
}, },
"post-install-cmd": [ "post-install-cmd": [
"@auto-scripts" "@auto-scripts",
"config-transformer switch-format config"
], ],
"post-update-cmd": [ "post-update-cmd": [
"@auto-scripts" "@auto-scripts"
], ],
"lint": [ "lint": [
"rector", "rector",
"php-styler apply", "ecs --fix || ecs --fix"
"ecs --fix", ],
"ecs --fix" "test": "bin/phpunit"
]
}, },
"conflict": { "conflict": {
"symfony/symfony": "*" "symfony/symfony": "*"
@ -86,7 +81,7 @@
"extra": { "extra": {
"symfony": { "symfony": {
"allow-contrib": false, "allow-contrib": false,
"require": "7.0.*" "require": "7.1.*"
} }
} }
} }

4177
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,30 +1,21 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
use Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle;
use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle; use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\MakerBundle\MakerBundle; use Symfony\Bundle\MakerBundle\MakerBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
return [ return [
FrameworkBundle::class => [ FrameworkBundle::class => [
'all' => true, 'all' => true,
], ],
MakerBundle::class => [
'dev' => true,
],
DoctrineBundle::class => [ DoctrineBundle::class => [
'all' => true, 'all' => true,
], ],
DoctrineMigrationsBundle::class => [ DoctrineMigrationsBundle::class => [
'all' => true, 'all' => true,
], ],
MakerBundle::class => [
'dev' => true,
],
TwigBundle::class => [
'all' => true,
],
DoctrineFixturesBundle::class => [
'dev' => true,
'test' => true,
],
]; ];

View file

@ -3,76 +3,66 @@
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void { return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension( $containerConfigurator->extension('doctrine', [
'doctrine', 'dbal' => [
[ 'url' => '%env(resolve:DATABASE_URL)%',
'dbal' => [ 'profiling_collect_backtrace' => '%kernel.debug%',
'url' => '%env(resolve:DATABASE_URL)%', 'use_savepoints' => true,
'profiling_collect_backtrace' => '%kernel.debug%', ],
], 'orm' => [
'orm' => [ 'auto_generate_proxy_classes' => true,
'auto_generate_proxy_classes' => true, 'enable_lazy_ghost_objects' => true,
'enable_lazy_ghost_objects' => true, 'report_fields_where_declared' => true,
'report_fields_where_declared' => true, 'validate_xml_mapping' => true,
'validate_xml_mapping' => true, 'naming_strategy' => 'doctrine.orm.naming_strategy.underscore_number_aware',
'naming_strategy' => 'doctrine.orm.naming_strategy.underscore_number_aware', 'auto_mapping' => true,
'auto_mapping' => true, 'mappings' => [
'mappings' => [ 'App' => [
'App' => [ 'type' => 'attribute',
'type' => 'attribute', 'is_bundle' => false,
'is_bundle' => false, 'dir' => '%kernel.project_dir%/src/Entity',
'dir' => '%kernel.project_dir%/src/Entity', 'prefix' => 'App\Entity',
'prefix' => 'App\Entity', 'alias' => 'App',
'alias' => 'App',
],
], ],
], ],
'controller_resolver' => [
'auto_mapping' => false,
],
], ],
); ]);
if ($containerConfigurator->env() === 'test') { if ($containerConfigurator->env() === 'test') {
$containerConfigurator->extension( $containerConfigurator->extension('doctrine', [
'doctrine', 'dbal' => [
[ 'dbname_suffix' => '_test%env(default::TEST_TOKEN)%',
'dbal' => [
'dbname_suffix' => '_test%env(default::TEST_TOKEN)%',
],
], ],
); ]);
} }
if ($containerConfigurator->env() === 'prod') { if ($containerConfigurator->env() === 'prod') {
$containerConfigurator->extension( $containerConfigurator->extension('doctrine', [
'doctrine', 'orm' => [
[ 'auto_generate_proxy_classes' => false,
'orm' => [ 'proxy_dir' => '%kernel.build_dir%/doctrine/orm/Proxies',
'auto_generate_proxy_classes' => false, 'query_cache_driver' => [
'proxy_dir' => '%kernel.build_dir%/doctrine/orm/Proxies', 'type' => 'pool',
'query_cache_driver' => [ 'pool' => 'doctrine.system_cache_pool',
'type' => 'pool', ],
'pool' => 'doctrine.system_cache_pool', 'result_cache_driver' => [
'type' => 'pool',
'pool' => 'doctrine.result_cache_pool',
],
],
]);
$containerConfigurator->extension('framework', [
'cache' => [
'pools' => [
'doctrine.result_cache_pool' => [
'adapter' => 'cache.app',
], ],
'result_cache_driver' => [ 'doctrine.system_cache_pool' => [
'type' => 'pool', 'adapter' => 'cache.system',
'pool' => 'doctrine.result_cache_pool',
], ],
], ],
], ],
); ]);
$containerConfigurator->extension(
'framework',
[
'cache' => [
'pools' => [
'doctrine.result_cache_pool' => [
'adapter' => 'cache.app',
],
'doctrine.system_cache_pool' => [
'adapter' => 'cache.system',
],
],
],
],
);
} }
}; };

View file

@ -3,13 +3,10 @@
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void { return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension( $containerConfigurator->extension('doctrine_migrations', [
'doctrine_migrations', 'migrations_paths' => [
[ 'DoctrineMigrations' => '%kernel.project_dir%/migrations',
'migrations_paths' => [
'DoctrineMigrations' => '%kernel.project_dir%/migrations',
],
'enable_profiler' => false,
], ],
); 'enable_profiler' => false,
]);
}; };

View file

@ -3,23 +3,16 @@
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void { return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension( $containerConfigurator->extension('framework', [
'framework', 'secret' => '%env(APP_SECRET)%',
[ 'session' => true,
'secret' => '%env(APP_SECRET)%', ]);
'session' => true,
],
);
if ($containerConfigurator->env() === 'test') { if ($containerConfigurator->env() === 'test') {
$containerConfigurator->extension( $containerConfigurator->extension('framework', [
'framework', 'test' => true,
[ 'session' => [
'test' => true, 'storage_factory_id' => 'session.storage.factory.mock_file',
'session' => [
'storage_factory_id' => 'session.storage.factory.mock_file',
],
], ],
); ]);
} }
}; };

View file

@ -6,15 +6,11 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('framework', [ $containerConfigurator->extension('framework', [
'router' => null, 'router' => null,
]); ]);
if ($containerConfigurator->env() === 'prod') { if ($containerConfigurator->env() === 'prod') {
$containerConfigurator->extension( $containerConfigurator->extension('framework', [
'framework', 'router' => [
[ 'strict_requirements' => null,
'router' => [
'strict_requirements' => null,
],
], ],
); ]);
} }
}; };

View file

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

View file

@ -1,20 +0,0 @@
<?php declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('framework', [
'validation' => null,
]);
if ($containerConfigurator->env() === 'test') {
$containerConfigurator->extension(
'framework',
[
'validation' => [
'not_compromised_password' => false,
],
],
);
}
};

View file

@ -1,9 +1,5 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
if ( if (file_exists(dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php')) {
file_exists(
dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php',
)
) {
require dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php'; require dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php';
} }

View file

@ -3,11 +3,8 @@
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return static function (RoutingConfigurator $routingConfigurator): void { return static function (RoutingConfigurator $routingConfigurator): void {
$routingConfigurator->import( $routingConfigurator->import([
[ 'path' => '../src/Controller/',
'path' => '../src/Controller/', 'namespace' => 'App\Controller',
'namespace' => 'App\Controller', ], 'attribute');
],
'attribute',
);
}; };

View file

@ -4,8 +4,7 @@ use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return static function (RoutingConfigurator $routingConfigurator): void { return static function (RoutingConfigurator $routingConfigurator): void {
if ($routingConfigurator->env() === 'dev') { if ($routingConfigurator->env() === 'dev') {
$routingConfigurator $routingConfigurator->import('@FrameworkBundle/Resources/config/routing/errors.xml')
->import('@FrameworkBundle/Resources/config/routing/errors.xml')
->prefix('/_error'); ->prefix('/_error');
} }
}; };

View file

@ -1,19 +1,18 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
use Symfony\Bridge\Twig\AppVariable;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void { return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services(); $services = $containerConfigurator->services();
$services->defaults() $services->defaults()
->autowire() ->autowire()
->autoconfigure(); ->autoconfigure();
$services
->load('App\\', __DIR__ . '/../src/') $services->load('App\\', __DIR__ . '/../src/')
->exclude([ ->exclude([
__DIR__ . '/../src/DependencyInjection/', __DIR__ . '/../src/DependencyInjection/',
__DIR__ . '/../src/Entity/', __DIR__ . '/../src/Entity/',
__DIR__ . '/../src/Kernel.php', __DIR__ . '/../src/Kernel.php',
]); ]);
$services->alias(AppVariable::class, 'twig.app_variable');
}; };

13
ecs.php
View file

@ -1,18 +1,17 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
use Lubiana\CodeQuality\LubiSetList; use Lubiana\CodeQuality\LubiSetList;
use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer; use PhpCsFixer\Fixer\ClassNotation\FinalClassFixer;
use Symplify\EasyCodingStandard\Config\ECSConfig; use Symplify\EasyCodingStandard\Config\ECSConfig;
return ECSConfig::configure() return ECSConfig::configure()
->withPaths([ ->withPaths([
__DIR__ . '/config', __DIR__ . '/bin',
__DIR__ . '/public', __DIR__ . '/public',
__DIR__ . '/src', __DIR__ . '/src',
__DIR__ . '/config',
__DIR__ . '/tests',
]) ])
->withRootFiles() ->withRootFiles()
->withSets([ ->withRules([FinalClassFixer::class])
LubiSetList::ECS, ->withSets([LubiSetList::ECS]);
])
->withSkip([LineLengthFixer::class])
;

View file

@ -1,67 +0,0 @@
<?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 Version20240213204922 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 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('CREATE INDEX IDX_4485672F603EE73 ON food_order (vendor_id)');
$this->addSql('CREATE TABLE item_extra (id BLOB NOT NULL --(DC2Type:ulid)
, menu_item_id BLOB NOT NULL --(DC2Type:ulid)
, name VARCHAR(50) NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_679816B59AB44FE0 FOREIGN KEY (menu_item_id) REFERENCES menu_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('CREATE INDEX IDX_679816B59AB44FE0 ON item_extra (menu_item_id)');
$this->addSql('CREATE TABLE menu_item (id BLOB NOT NULL --(DC2Type:ulid)
, vendor_id BLOB NOT NULL --(DC2Type:ulid)
, 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(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 TABLE order_item_item_extra (order_item_id BLOB NOT NULL --(DC2Type:ulid)
, item_extra_id BLOB NOT NULL --(DC2Type:ulid)
, PRIMARY KEY(order_item_id, item_extra_id), CONSTRAINT FK_1120FDE3E415FB15 FOREIGN KEY (order_item_id) REFERENCES order_item (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_1120FDE34798570D FOREIGN KEY (item_extra_id) REFERENCES item_extra (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('CREATE INDEX IDX_1120FDE3E415FB15 ON order_item_item_extra (order_item_id)');
$this->addSql('CREATE INDEX IDX_1120FDE34798570D ON order_item_item_extra (item_extra_id)');
$this->addSql('CREATE TABLE vendor (id BLOB NOT NULL --(DC2Type:ulid)
, name VARCHAR(50) NOT NULL, PRIMARY KEY(id))');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE food_order');
$this->addSql('DROP TABLE item_extra');
$this->addSql('DROP TABLE menu_item');
$this->addSql('DROP TABLE menu_item_alias');
$this->addSql('DROP TABLE order_item');
$this->addSql('DROP TABLE order_item_item_extra');
$this->addSql('DROP TABLE vendor');
}
}

View file

@ -5,7 +5,16 @@ use PhpStyler\Files;
use PhpStyler\Styler; use PhpStyler\Styler;
return new Config( return new Config(
files: new Files(__DIR__ . '/src', __DIR__ . '/config', __DIR__ . '/public'), styler: new Styler(lineLen: 79),
styler: new Styler, files: new Files(
__DIR__ . '/bin',
__DIR__ . '/public',
__DIR__ . '/src',
__DIR__ . '/config',
__DIR__ . '/tests',
__DIR__ . '/php-styler.php',
__DIR__ . '/ecs.php',
__DIR__ . '/rector.php',
),
cache: __DIR__ . '/.php-styler.cache', cache: __DIR__ . '/.php-styler.cache',
); );

View file

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

39
phpunit.xml.dist Normal file
View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="tests/bootstrap.php"
convertDeprecationsToExceptions="false"
>
<php>
<ini name="display_errors" value="1" />
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
<server name="SYMFONY_PHPUNIT_VERSION" value="9.6" />
<server name="KERNEL_CLASS" value="App\Kernel" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
</listeners>
<extensions>
</extensions>
</phpunit>

File diff suppressed because one or more lines are too long

View file

@ -1,8 +0,0 @@
/**
* 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 */

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -3,5 +3,5 @@
use App\Kernel; use App\Kernel;
require_once dirname(__DIR__) . '/vendor/autoload_runtime.php'; require_once dirname(__DIR__) . '/vendor/autoload_runtime.php';
return static fn(array $context): Kernel
=> new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); return static fn(array $context): Kernel => new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);

File diff suppressed because one or more lines are too long

View file

@ -1,15 +1,19 @@
<?php declare(strict_types=1); <?php declare(strict_types=1);
use Lubiana\CodeQuality\LubiSetList; use Lubiana\CodeQuality\LubiSetList;
use Rector\CodingStyle\Rector\Closure\StaticClosureRector;
use Rector\Config\RectorConfig; use Rector\Config\RectorConfig;
return RectorConfig::configure() return RectorConfig::configure()
->withPaths([ ->withPaths([
__DIR__ . '/config', __DIR__ . '/bin',
__DIR__ . '/public', __DIR__ . '/public',
__DIR__ . '/src', __DIR__ . '/src',
__DIR__ . '/config',
__DIR__ . '/tests',
]) ])
->withRootFiles() ->withRootFiles()
->withSets([ ->withSkip([
LubiSetList::RECTOR, StaticClosureRector::class => [__DIR__ . '/tests'],
]); ])
->withSets([LubiSetList::RECTOR]);

View file

@ -1,214 +0,0 @@
<?php declare(strict_types=1);
namespace App\Controller;
use App\Entity\FoodOrder;
use App\Entity\ItemExtra;
use App\Entity\MenuItem;
use App\Entity\MenuItemAlias;
use App\Entity\OrderItem;
use App\Form\ItemExtraType;
use App\Form\MenuItemType;
use App\Form\OrderItemType;
use App\Repository\ItemExtraRepository;
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;
#[Route('/order')]
class FoodOrderController extends AbstractController
{
final public const APP_FOOD_ORDER_SHOW = 'app_food_order_show';
final public const APP_FOODORDER_ADD_ITEM = 'app_foodorder_add_item';
final public const APP_FOODORDER_CLOSE = 'app_foodorder_close';
final public const APP_FOODORDER_COPY_ITEM = 'app_foodorder_item_copy';
final public const APP_FOODORDER_REMOVE_ITEM = 'app_foodorder_item_remove';
#[Route(
'/{id}',
name: self::APP_FOOD_ORDER_SHOW,
methods: [Request::METHOD_GET, Request::METHOD_POST],
)]
public function show(
FoodOrder $foodOrder,
Request $request,
EntityManagerInterface $entityManager,
): Response {
$newItem = new MenuItem;
$newItem->setVendor($foodOrder->getVendor());
$newItem->setPrice(0);
$newItemForm = $this->createForm(MenuItemType::class, $newItem);
$newItemForm->handleRequest($request);
if ($newItemForm->isSubmitted() && $newItemForm->isValid()) {
$name = (string) $newItemForm->get('name')
->getData();
$alias = new MenuItemAlias;
$alias->setName($name);
$alias->setMenuItem($newItem);
$entityManager->persist($newItem);
$entityManager->persist($alias);
$entityManager->flush();
return $this->redirectToRoute(
self::APP_FOOD_ORDER_SHOW,
[
'id' => $foodOrder->getId(),
],
);
}
return $this->render(
'food_order/show.html.twig',
[
'food_order' => $foodOrder,
'menu_items' => $foodOrder->getVendor()
->getMenuItems(),
'form' => $newItemForm,
],
);
}
#[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}',
name: self::APP_FOODORDER_ADD_ITEM,
methods: [Request::METHOD_GET, Request::METHOD_POST],
)]
public function add(
FoodOrder $foodOrder,
MenuItem $menuItem,
EntityManagerInterface $entityManager,
ItemExtraRepository $extraRepository,
Request $request,
): Response {
$orderItem = new OrderItem;
$orderItem->setFoodOrder($foodOrder);
$orderItem->setMenuItem($menuItem);
$form = $this->createForm(
OrderItemType::class,
$orderItem,
[
'menuItem' => $menuItem,
],
);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($orderItem);
$entityManager->flush();
return $this->redirectToRoute(
self::APP_FOOD_ORDER_SHOW,
[
'id' => $foodOrder->getId(),
],
Response::HTTP_SEE_OTHER,
);
}
$newExtra = new ItemExtra;
$newExtra->setMenuItem($menuItem);
$extraForm = $this->createForm(
ItemExtraType::class,
$newExtra,
[
'menuItem' => $menuItem,
],
);
$extraForm->handleRequest($request);
if ($extraForm->isSubmitted() && $extraForm->isValid()) {
$entityManager->persist($newExtra);
$entityManager->flush();
return $this->redirectToRoute(
self::APP_FOODORDER_ADD_ITEM,
[
'foodOrder' => $foodOrder->getId(),
'menuItem' => $menuItem->getId(),
],
Response::HTTP_SEE_OTHER,
);
}
return $this->render(
'food_order/orderitem.html.twig',
[
'form' => $form,
'extraForm' => $extraForm,
'extras' => $extraRepository->getUniqueNames(),
],
);
}
#[Route(
'/item/remove/{orderItem}',
name: self::APP_FOODORDER_REMOVE_ITEM,
methods: [Request::METHOD_GET],
)]
public function remove(
OrderItem $orderItem,
EntityManagerInterface $entityManager,
): Response {
$orderId = $orderItem->getFoodOrder()
->getId();
$entityManager->remove($orderItem);
$entityManager->flush();
return $this->redirectToRoute(
self::APP_FOOD_ORDER_SHOW,
[
'id' => $orderId,
],
Response::HTTP_SEE_OTHER,
);
}
#[Route(
'/item/copy/{orderItem}',
name: self::APP_FOODORDER_COPY_ITEM,
methods: [Request::METHOD_GET],
)]
public function copyItem(
OrderItem $orderItem,
EntityManagerInterface $entityManager,
): Response {
$newItem = new OrderItem;
$newItem->setFoodOrder($orderItem->getFoodOrder());
$newItem->setMenuItem($orderItem->getMenuItem());
foreach ($orderItem->getExtras() as $extra) {
$newItem->getExtras()
->add($extra);
}
$entityManager->persist($newItem);
$entityManager->flush();
return $this->redirectToRoute(
self::APP_FOOD_ORDER_SHOW,
[
'id' => $orderItem->getFoodOrder()
->getId(),
],
);
}
}

15
src/Controller/Home.php Normal file
View file

@ -0,0 +1,15 @@
<?php declare(strict_types=1);
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
final class Home
{
#[Route('/', name: 'home')]
public function home(): Response
{
return new Response('<h1>Halloo</h1>');
}
}

View file

@ -1,77 +0,0 @@
<?php declare(strict_types=1);
namespace App\Controller;
use App\Entity\FoodOrder;
use App\Form\FoodOrderType;
use App\Repository\FoodOrderRepository;
use App\Service\WhoAreYou;
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('/', name: 'app_index')]
public function index(
FoodOrderRepository $foodOrderRepository,
EntityManagerInterface $em,
Request $request,
): Response {
$openOrders = $foodOrderRepository->findOpenOrders();
$order = new FoodOrder;
$form = $this->createForm(FoodOrderType::class, $order);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($order);
$em->flush();
return $this->redirectToRoute(
FoodOrderController::APP_FOOD_ORDER_SHOW,
[
'id' => $order->getId(),
],
Response::HTTP_SEE_OTHER,
);
}
return $this->render(
'start/index.html.twig',
[
'orders' => $openOrders,
'form' => $form,
],
);
}
#[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

@ -1,109 +0,0 @@
<?php declare(strict_types=1);
namespace App\Controller;
use App\Entity\Vendor;
use App\Form\VendorType;
use App\Repository\VendorRepository;
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;
#[Route('/vendor')]
class VendorController extends AbstractController
{
#[Route('/', name: 'app_vendor_index', methods: ['GET'])]
public function index(VendorRepository $vendorRepository): Response
{
return $this->render(
'vendor/index.html.twig',
[
'vendors' => $vendorRepository->findAll(),
],
);
}
#[Route('/new', name: 'app_vendor_new', methods: ['GET', 'POST'])]
public function new(
Request $request,
EntityManagerInterface $entityManager,
): Response {
$vendor = new Vendor;
$form = $this->createForm(VendorType::class, $vendor);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($vendor);
$entityManager->flush();
return $this->redirectToRoute(
'app_vendor_index',
[],
Response::HTTP_SEE_OTHER,
);
}
return $this->render(
'vendor/new.html.twig',
[
'vendor' => $vendor,
'form' => $form,
],
);
}
#[Route('/{id}', name: 'app_vendor_show', methods: ['GET'])]
public function show(Vendor $vendor): Response
{
return $this->render('vendor/show.html.twig', [
'vendor' => $vendor,
]);
}
#[Route('/{id}/edit', name: 'app_vendor_edit', methods: ['GET', 'POST'])]
public function edit(
Request $request,
Vendor $vendor,
EntityManagerInterface $entityManager,
): Response {
$form = $this->createForm(VendorType::class, $vendor);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
return $this->redirectToRoute(
'app_vendor_index',
[],
Response::HTTP_SEE_OTHER,
);
}
return $this->render(
'vendor/edit.html.twig',
[
'vendor' => $vendor,
'form' => $form,
],
);
}
#[Route('/{id}', name: 'app_vendor_delete', methods: ['POST'])]
public function delete(
Request $request,
Vendor $vendor,
EntityManagerInterface $entityManager,
): Response {
if (
$this->isCsrfTokenValid(
'delete' . $vendor->getId(),
$request->request->get('_token'),
)
) {
$entityManager->remove($vendor);
$entityManager->flush();
}
return $this->redirectToRoute('app_vendor_index', [], Response::HTTP_SEE_OTHER);
}
}

View file

@ -1,78 +0,0 @@
<?php declare(strict_types=1);
namespace App\DataFixtures;
use App\Entity\ItemExtra;
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;
final class AppFixture extends Fixture
{
private Generator $faker;
#[Override]
public function load(ObjectManager $manager): void
{
$this->faker = Factory::create();
foreach (range(0, 20) as $vendorCount) {
$this->createVendorAndMenuItems($manager);
}
$manager->flush();
}
public function addMenuItemAliases(
MenuItem $menuItem,
ObjectManager $manager,
): void {
$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);
}
public function addMenuItemExtras(MenuItem $menuItem, ObjectManager $manager): void
{
foreach (range(0, random_int(0, 5)) as $dispose) {
$itemExtra = new ItemExtra;
$itemExtra->setName($this->faker->word);
$menuItem->addItemExtra($itemExtra);
$manager->persist($itemExtra);
}
}
public function createMenuItem(Vendor $vendor, ObjectManager $manager): void
{
$menuItem = new MenuItem;
$menuItem->setVendor($vendor);
$menuItem->setPrice(random_int(500, 2000));
$manager->persist($menuItem);
$this->addMenuItemAliases($menuItem, $manager);
$this->addMenuItemExtras($menuItem, $manager);
}
public function createVendorAndMenuItems(ObjectManager $manager): void
{
$vendor = new Vendor;
$vendor->setName($this->faker->name);
$manager->persist($vendor);
foreach (range(0, 10) as $itemCount) {
$this->createMenuItem($vendor, $manager);
}
}
}

View file

@ -1,143 +0,0 @@
<?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 function iterator_to_array;
#[ORM\Entity(repositoryClass: FoodOrderRepository::class)]
class FoodOrder
{
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
#[ORM\Column(nullable: true)]
private DateTimeImmutable|null $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|null $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)) {
$this->orderItems->add($orderItem);
$orderItem->setFoodOrder($this);
}
return $this;
}
public function removeOrderItem(OrderItem $orderItem): static
{
// set the owning side to null (unless already changed)
if (
$this->orderItems->removeElement($orderItem)
&& $orderItem->getFoodOrder() === $this
) {
$orderItem->setFoodOrder(null);
}
return $this;
}
public function getVendor(): Vendor|null
{
return $this->vendor;
}
public function setVendor(Vendor|null $vendor): static
{
$this->vendor = $vendor;
return $this;
}
public function groupedOrderItems(): Collection
{
$iterator = $this->orderItems->getIterator();
$orderFunction = static fn(OrderItem $a, OrderItem $b): int
=> $a->getMenuItem()
->getId()
->compare($b->getMenuItem()->getId());
$iterator->uasort($orderFunction);
return new ArrayCollection(iterator_to_array($iterator));
}
}

View file

@ -1,53 +0,0 @@
<?php declare(strict_types=1);
namespace App\Entity;
use App\Repository\ItemExtraRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: ItemExtraRepository::class)]
class ItemExtra
{
public function __construct(
#[ORM\Column(length: 50)]
private string|null $name = null,
#[ORM\ManyToOne(inversedBy: 'itemExtras')]
#[ORM\JoinColumn(nullable: false)]
private 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 = 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

@ -1,138 +0,0 @@
<?php declare(strict_types=1);
namespace App\Entity;
use App\Repository\MenuItemRepository;
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;
#[ORM\Entity(repositoryClass: MenuItemRepository::class)]
class MenuItem
{
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
#[ORM\ManyToOne(inversedBy: 'menuItems')]
#[ORM\JoinColumn(nullable: false)]
private Vendor $vendor;
#[ORM\Column]
private int $price;
#[ORM\OneToMany(
mappedBy: 'menuItem',
targetEntity: MenuItemAlias::class,
orphanRemoval: true,
)]
private Collection $menuItemAliases;
#[ORM\OneToMany(
mappedBy: 'menuItem',
targetEntity: ItemExtra::class,
orphanRemoval: true,
)]
private Collection $itemExtras;
public function __construct()
{
$this->id = new Ulid;
$this->menuItemAliases = new ArrayCollection;
$this->itemExtras = new ArrayCollection;
}
public function getId(): Ulid
{
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 function removeMenuItemAlias(MenuItemAlias $menuItemAlias): static
{
// set the owning side to null (unless already changed)
if (
$this->menuItemAliases->removeElement($menuItemAlias)
&& $menuItemAlias->getMenuItem() === $this
) {
$menuItemAlias->setMenuItem(null);
}
return $this;
}
/**
* @return Collection<int, ItemExtra>
*/
public function getItemExtras(): Collection
{
return $this->itemExtras;
}
public function addItemExtra(ItemExtra $itemExtra): static
{
if (! $this->itemExtras->contains($itemExtra)) {
$this->itemExtras->add($itemExtra);
$itemExtra->setMenuItem($this);
}
return $this;
}
public function removeItemExtra(ItemExtra $itemExtra): static
{
// set the owning side to null (unless already changed)
if (
$this->itemExtras->removeElement($itemExtra)
&& $itemExtra->getMenuItem() === $this
) {
$itemExtra->setMenuItem(null);
}
return $this;
}
}

View file

@ -1,58 +0,0 @@
<?php declare(strict_types=1);
namespace App\Entity;
use App\Repository\MenuItemAliasRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;
#[ORM\Entity(repositoryClass: MenuItemAliasRepository::class)]
class MenuItemAlias
{
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
#[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()
{
$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

@ -1,88 +0,0 @@
<?php declare(strict_types=1);
namespace App\Entity;
use App\Repository\OrderItemRepository;
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;
#[ORM\Entity(repositoryClass: OrderItemRepository::class)]
class OrderItem
{
#[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\ManyToOne]
#[ORM\JoinColumn(nullable: false)]
private MenuItem|null $menuItem = null;
#[ORM\ManyToMany(targetEntity: ItemExtra::class, cascade: ['persist'])]
private Collection $extras;
public function __construct()
{
$this->id = new Ulid;
$this->extras = new ArrayCollection;
}
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|null $menuItem): static
{
$this->menuItem = $menuItem;
return $this;
}
/**
* @return Collection<int, ItemExtra>
*/
public function getExtras(): Collection
{
return $this->extras;
}
public function addExtra(ItemExtra $extra): static
{
if (! $this->extras->contains($extra)) {
$this->extras->add($extra);
}
return $this;
}
public function removeExtra(ItemExtra $extra): static
{
$this->extras->removeElement($extra);
return $this;
}
}

View file

@ -1,84 +0,0 @@
<?php declare(strict_types=1);
namespace App\Entity;
use App\Repository\VendorRepository;
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;
#[ORM\Entity(repositoryClass: VendorRepository::class)]
class Vendor
{
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
private Ulid $id;
#[ORM\Column(length: 50)]
private string|null $name = null;
#[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->setVendor($this);
}
return $this;
}
public function removeMenuItem(MenuItem $menuItem): static
{
// set the owning side to null (unless already changed)
if (
$this->menuItems->removeElement($menuItem)
&& $menuItem->getVendor() === $this
) {
$menuItem->setVendor(null);
}
return $this;
}
}

View file

@ -1,46 +0,0 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\FoodOrder;
use App\Entity\Vendor;
use App\Service\WhoAreYou;
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('startedBy', TextType::class, [
'data' => $this->who->username,
])
->add(
'vendor',
EntityType::class,
[
'class' => Vendor::class,
'choice_label' => 'name',
'multiple' => false,
],
);
}
#[Override]
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => FoodOrder::class,
]);
}
}

View file

@ -1,31 +0,0 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\ItemExtra;
use App\Entity\MenuItem;
use Override;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ItemExtraType extends AbstractType
{
#[Override]
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add(child: 'name', options: [
'label' => 'custom extra',
]);
}
#[Override]
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ItemExtra::class,
]);
$resolver->setRequired('menuItem');
$resolver->setAllowedTypes('menuItem', MenuItem::class);
}
}

View file

@ -1,39 +0,0 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\ItemExtra;
use Override;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class MenuItemExtraType extends AbstractType
{
#[Override]
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('name');
$builder->add(
'customextra',
TextType::class,
[
'label' => 'Add a new extra option',
'mapped' => false,
'required' => false,
'attr' => [
'list' => 'item-extra-list',
],
],
);
}
#[Override]
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ItemExtra::class,
]);
}
}

View file

@ -1,43 +0,0 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\MenuItem;
use Override;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
class MenuItemType extends AbstractType
{
#[Override]
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add(child: 'name', type: TextType::class, options: [
'mapped' => false,
])
->add(
child: 'price',
options: [
'label' => 'Price in cents',
'constraints' => [
new GreaterThanOrEqual([
'value' => 0,
'message' => 'The price must be a positive number or zero.',
]),
],
],
);
}
#[Override]
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => MenuItem::class,
]);
}
}

View file

@ -1,45 +0,0 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\ItemExtra;
use App\Entity\MenuItem;
use App\Entity\OrderItem;
use Override;
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
{
/**
* @param array{menuItem: MenuItem} $options
*/
#[Override]
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add(
'extras',
EntityType::class,
[
'class' => ItemExtra::class,
'choices' => $options['menuItem']->getItemExtras(),
'choice_label' => 'name', // Change this for the field you want to display
'multiple' => true,
'expanded' => true,
],
);
}
#[Override]
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => OrderItem::class,
]);
$resolver->setRequired('menuItem');
$resolver->setAllowedTypes('menuItem', MenuItem::class);
}
}

View file

@ -1,26 +0,0 @@
<?php declare(strict_types=1);
namespace App\Form;
use App\Entity\Vendor;
use Override;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class VendorType extends AbstractType
{
#[Override]
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('name');
}
#[Override]
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Vendor::class,
]);
}
}

View file

@ -5,7 +5,7 @@ namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel; use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel final class Kernel extends BaseKernel
{ {
use MicroKernelTrait; use MicroKernelTrait;
} }

View file

@ -1,35 +0,0 @@
<?php declare(strict_types=1);
namespace App\Repository;
use App\Entity\FoodOrder;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<FoodOrder>
*
* @method FoodOrder|null find($id, $lockMode = null, $lockVersion = null)
* @method FoodOrder|null findOneBy(array $criteria, array $orderBy = null)
* @method FoodOrder[] findAll()
* @method FoodOrder[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class FoodOrderRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, FoodOrder::class);
}
/**
* @return FoodOrder[] Returns an array of FoodOrder objects
*/
public function findOpenOrders(): array
{
return $this
->createQueryBuilder('f')
->andWhere('f.closedAt IS NULL')
->getQuery()
->getResult();
}
}

View file

@ -1,32 +0,0 @@
<?php declare(strict_types=1);
namespace App\Repository;
use App\Entity\ItemExtra;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<ItemExtra>
*
* @method ItemExtra|null find($id, $lockMode = null, $lockVersion = null)
* @method ItemExtra|null findOneBy(array $criteria, array $orderBy = null)
* @method ItemExtra[] findAll()
* @method ItemExtra[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ItemExtraRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, ItemExtra::class);
}
public function getUniqueNames(): Collection
{
$qb = $this->createQueryBuilder('p');
$qb->groupBy('p.name');
return new ArrayCollection($qb->getQuery()->getResult());
}
}

View file

@ -1,47 +0,0 @@
<?php declare(strict_types=1);
namespace App\Repository;
use App\Entity\MenuItemAlias;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<MenuItemAlias>
*
* @method MenuItemAlias|null find($id, $lockMode = null, $lockVersion = null)
* @method MenuItemAlias|null findOneBy(array $criteria, array $orderBy = null)
* @method MenuItemAlias[] findAll()
* @method MenuItemAlias[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class MenuItemAliasRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, MenuItemAlias::class);
}
// /**
// * @return MenuItemAlias[] Returns an array of MenuItemAlias objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('m')
// ->andWhere('m.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('m.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?MenuItemAlias
// {
// return $this->createQueryBuilder('m')
// ->andWhere('m.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View file

@ -1,47 +0,0 @@
<?php declare(strict_types=1);
namespace App\Repository;
use App\Entity\MenuItem;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<MenuItem>
*
* @method MenuItem|null find($id, $lockMode = null, $lockVersion = null)
* @method MenuItem|null findOneBy(array $criteria, array $orderBy = null)
* @method MenuItem[] findAll()
* @method MenuItem[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class MenuItemRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, MenuItem::class);
}
// /**
// * @return MenuItem[] Returns an array of MenuItem objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('m')
// ->andWhere('m.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('m.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?MenuItem
// {
// return $this->createQueryBuilder('m')
// ->andWhere('m.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View file

@ -1,47 +0,0 @@
<?php declare(strict_types=1);
namespace App\Repository;
use App\Entity\OrderItem;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<OrderItem>
*
* @method OrderItem|null find($id, $lockMode = null, $lockVersion = null)
* @method OrderItem|null findOneBy(array $criteria, array $orderBy = null)
* @method OrderItem[] findAll()
* @method OrderItem[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class OrderItemRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, OrderItem::class);
}
// /**
// * @return OrderItem[] Returns an array of OrderItem objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('o')
// ->andWhere('o.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('o.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?OrderItem
// {
// return $this->createQueryBuilder('o')
// ->andWhere('o.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View file

@ -1,47 +0,0 @@
<?php declare(strict_types=1);
namespace App\Repository;
use App\Entity\Vendor;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Vendor>
*
* @method Vendor|null find($id, $lockMode = null, $lockVersion = null)
* @method Vendor|null findOneBy(array $criteria, array $orderBy = null)
* @method Vendor[] findAll()
* @method Vendor[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class VendorRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Vendor::class);
}
// /**
// * @return Vendor[] Returns an array of Vendor objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('v')
// ->andWhere('v.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('v.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Vendor
// {
// return $this->createQueryBuilder('v')
// ->andWhere('v.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View file

@ -1,29 +0,0 @@
<?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;
}
}

View file

@ -1,24 +0,0 @@
<?php declare(strict_types=1);
namespace App\Twig;
use Override;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use function number_format;
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

@ -1,11 +1,11 @@
{ {
"doctrine/doctrine-bundle": { "doctrine/doctrine-bundle": {
"version": "2.11", "version": "2.12",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "2.10", "version": "2.12",
"ref": "c170ded8fc587d6bd670550c43dafcf093762245" "ref": "7266981c201efbbe02ae53c87f8bb378e3f825ae"
}, },
"files": [ "files": [
"config/packages/doctrine.yaml", "config/packages/doctrine.yaml",
@ -13,18 +13,6 @@
"src/Repository/.gitignore" "src/Repository/.gitignore"
] ]
}, },
"doctrine/doctrine-fixtures-bundle": {
"version": "3.5",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "1f5514cfa15b947298df4d771e694e578d4c204d"
},
"files": [
"src/DataFixtures/AppFixtures.php"
]
},
"doctrine/doctrine-migrations-bundle": { "doctrine/doctrine-migrations-bundle": {
"version": "3.3", "version": "3.3",
"recipe": { "recipe": {
@ -39,7 +27,7 @@
] ]
}, },
"phpstan/phpstan": { "phpstan/phpstan": {
"version": "1.10", "version": "1.11",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes-contrib", "repo": "github.com/symfony/recipes-contrib",
"branch": "main", "branch": "main",
@ -47,8 +35,22 @@
"ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767" "ref": "5e490cc197fb6bb1ae22e5abbc531ddc633b6767"
} }
}, },
"phpunit/phpunit": {
"version": "9.6",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "9.6",
"ref": "7364a21d87e658eb363c5020c072ecfdc12e2326"
},
"files": [
".env.test",
"phpunit.xml.dist",
"tests/bootstrap.php"
]
},
"squizlabs/php_codesniffer": { "squizlabs/php_codesniffer": {
"version": "3.8", "version": "3.10",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes-contrib", "repo": "github.com/symfony/recipes-contrib",
"branch": "main", "branch": "main",
@ -57,12 +59,12 @@
} }
}, },
"symfony/console": { "symfony/console": {
"version": "7.0", "version": "7.1",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "5.3", "version": "5.3",
"ref": "da0c8be8157600ad34f10ff0c9cc91232522e047" "ref": "1781ff40d8a17d87cf53f8d4cf0c8346ed2bb461"
}, },
"files": [ "files": [
"bin/console" "bin/console"
@ -81,7 +83,7 @@
] ]
}, },
"symfony/framework-bundle": { "symfony/framework-bundle": {
"version": "7.0", "version": "7.1",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -100,7 +102,7 @@
] ]
}, },
"symfony/maker-bundle": { "symfony/maker-bundle": {
"version": "1.54", "version": "1.60",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -108,8 +110,23 @@
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
} }
}, },
"symfony/phpunit-bridge": {
"version": "7.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "a411a0480041243d97382cac7984f7dce7813c08"
},
"files": [
".env.test",
"bin/phpunit",
"phpunit.xml.dist",
"tests/bootstrap.php"
]
},
"symfony/routing": { "symfony/routing": {
"version": "7.0", "version": "7.1",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
@ -121,38 +138,13 @@
"config/routes.yaml" "config/routes.yaml"
] ]
}, },
"symfony/twig-bundle": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "cab5fd2a13a45c266d45a7d9337e28dee6272877"
},
"files": [
"config/packages/twig.yaml",
"templates/base.html.twig"
]
},
"symfony/uid": { "symfony/uid": {
"version": "7.0", "version": "7.1",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "7.0", "version": "7.0",
"ref": "0df5844274d871b37fc3816c57a768ffc60a43a5" "ref": "0df5844274d871b37fc3816c57a768ffc60a43a5"
} }
},
"symfony/validator": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd"
},
"files": [
"config/packages/validator.yaml"
]
} }
} }

View file

@ -1,4 +0,0 @@
{{ form_start(form) }}
{{ form_widget(form) }}
<button class="btn">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}

View file

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<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/water.css">
</head>
<body>
<header>
<p>
Futtern |
Henlo {{ username }} (<a href="{{ url('app_name') }}">change name</a>) |
<a href="{{ url('app_index') }}">index</a>
</p>
<hr />
</header>
<main>
{% block body %}{% endblock %}
</main>
</body>
</html>

View file

@ -1,4 +0,0 @@
<form method="post" action="{{ path('app_food_order_delete', {'id': food_order.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ food_order.id) }}">
<button class="btn">Delete</button>
</form>

View file

@ -1,4 +0,0 @@
{{ form_start(form) }}
{{ form_widget(form) }}
<button class="btn">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}

View file

@ -1,13 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Edit FoodOrder{% endblock %}
{% block body %}
<h1>Edit FoodOrder</h1>
{{ include('food_order/_form.html.twig', {'button_label': 'Update'}) }}
<a href="{{ path('app_food_order_index') }}">back to list</a>
{{ include('food_order/_delete_form.html.twig') }}
{% endblock %}

View file

@ -1,39 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}FoodOrder index{% endblock %}
{% block body %}
<h1>FoodOrder index</h1>
<table class="table">
<thead>
<tr>
<th>StartedByName</th>
<th>Id</th>
<th>StartedAt</th>
<th>ClosedAt</th>
<th>actions</th>
</tr>
</thead>
<tbody>
{% for food_order in food_orders %}
<tr>
<td>{{ food_order.startedByName }}</td>
<td>{{ food_order.id }}</td>
<td>{{ food_order.startedAt ? food_order.startedAt|date('Y-m-d H:i:s') : '' }}</td>
<td>{{ food_order.closedAt ? food_order.closedAt|date('Y-m-d H:i:s') : '' }}</td>
<td>
<a href="{{ path('app_food_order_show', {'id': food_order.id}) }}">show</a>
<a href="{{ path('app_food_order_edit', {'id': food_order.id}) }}">edit</a>
</td>
</tr>
{% else %}
<tr>
<td colspan="5">no records found</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="{{ path('app_food_order_new') }}">Create new</a>
{% endblock %}

View file

@ -1,11 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}New FoodOrder{% endblock %}
{% block body %}
<h1>Create new FoodOrder</h1>
{{ include('food_order/_form.html.twig') }}
<a href="{{ path('app_food_order_index') }}">back to list</a>
{% endblock %}

View file

@ -1,12 +0,0 @@
{% extends 'base.html.twig' %}
{% block body %}
{% include('_form.html.twig') %}
{% include('_form.html.twig') with {'form': extraForm, 'button_label': 'add extra'} only %}
<datalist id="item-extra-list">
{% for item in extras %}
<option value="{{ item.name }}"></option>
{% endfor %}
</datalist>
{% endblock %}

View file

@ -1,111 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}FoodOrder{% endblock %}
{% block body %}
<h1>FoodOrder</h1>
<table class="table">
<tbody>
<tr>
<th>StartedByName</th>
<td>{{ food_order.startedBy }}</td>
</tr>
<tr>
<th>Id</th>
<td>{{ food_order.id }}</td>
</tr>
<tr>
<th>StartedAt</th>
<td>{{ food_order.startedAt ? food_order.startedAt|date('Y-m-d H:i:s') : '' }}</td>
</tr>
<tr>
<th>ClosedAt</th>
<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>
<table class="table">
<thead>
<tr>
<th>Name(s)</th>
<th>Extra(s)</th>
<th>possible price</th>
<th>actions</th>
</tr>
</thead>
<tbody>
{% for orderItem in food_order.groupedOrderItems %}
<tr>
<td>
{{ orderItem.menuItem.menuItemAliases|map(i => i.name)|join(' / ') }}
</td>
<td>
{{ orderItem.extras|map(i => i.name)|join(' / ') }}
</td>
<td>
{{ orderItem.menuItem.price|cents_to_eur }}
</td>
<td>
<a
href="{{ path(
'app_foodorder_item_copy',
{
'orderItem': orderItem.id
}
) }}"
>+1</a> |
<a
href="{{ path(
'app_foodorder_item_remove',
{
'orderItem': orderItem.id
}
) }}"
>del</a> |
</td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table">
<thead>
<tr>
<th>Name(s)</th>
<th>possible price</th>
<th>actions</th>
</tr>
</thead>
{% for item in menu_items %}
<tr>
<td>
{{ item.menuItemAliases|map(i => i.name)|join(' / ') }}
</td>
<td>
{{ item.price|cents_to_eur }}
</td>
<td>
{% if food_order.closedAt is null %}
<a
href="{{ path(
'app_foodorder_add_item',
{
foodOrder: food_order.id,
menuItem: item.id
}
) }}"
>add</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% include('_form.html.twig') %}
{% endblock %}

View file

@ -1,35 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Futtern{% endblock %}
{% block body %}
<h1>Open Orders</h1>
<table class="table">
<thead>
<tr>
<th>StartedBy</th>
<th>Vendor</th>
<th>StartedAt</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for order in orders %}
<tr>
<td>{{ order.startedBy }}</td>
<td>{{ order.vendor.name }}</td>
<td>{{ order.startedAt|date("Y-m-d H:i") }}</td>
<td><a href="{{ path('app_food_order_show', {'id': order.id}) }}">show</a></td>
</tr>
{% else %}
<tr>
<td colspan="4">no records found</td>
</tr>
{% endfor %}
</tbody>
</table>
<h2>New Order:</h2>
{{ include('_form.html.twig') }}
{% endblock %}

View file

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

View file

@ -1,4 +0,0 @@
<form method="post" action="{{ path('app_vendor_delete', {'id': vendor.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ vendor.id) }}">
<button class="btn">Delete</button>
</form>

View file

@ -1,4 +0,0 @@
{{ form_start(form) }}
{{ form_widget(form) }}
<button class="btn">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}

View file

@ -1,13 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Edit Vendor{% endblock %}
{% block body %}
<h1>Edit Vendor</h1>
{{ include('vendor/_form.html.twig', {'button_label': 'Update'}) }}
<a href="{{ path('app_vendor_index') }}">back to list</a>
{{ include('vendor/_delete_form.html.twig') }}
{% endblock %}

View file

@ -1,35 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Vendor index{% endblock %}
{% block body %}
<h1>Vendor index</h1>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>actions</th>
</tr>
</thead>
<tbody>
{% for vendor in vendors %}
<tr>
<td>{{ vendor.id }}</td>
<td>{{ vendor.name }}</td>
<td>
<a href="{{ path('app_vendor_show', {'id': vendor.id}) }}">show</a>
<a href="{{ path('app_vendor_edit', {'id': vendor.id}) }}">edit</a>
</td>
</tr>
{% else %}
<tr>
<td colspan="3">no records found</td>
</tr>
{% endfor %}
</tbody>
</table>
<a href="{{ path('app_vendor_new') }}">Create new</a>
{% endblock %}

View file

@ -1,11 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}New Vendor{% endblock %}
{% block body %}
<h1>Create new Vendor</h1>
{{ include('vendor/_form.html.twig') }}
<a href="{{ path('app_vendor_index') }}">back to list</a>
{% endblock %}

View file

@ -1,26 +0,0 @@
{% extends 'base.html.twig' %}
{% block title %}Vendor{% endblock %}
{% block body %}
<h1>Vendor</h1>
<table class="table">
<tbody>
<tr>
<th>Id</th>
<td>{{ vendor.id }}</td>
</tr>
<tr>
<th>Name</th>
<td>{{ vendor.name }}</td>
</tr>
</tbody>
</table>
<a href="{{ path('app_vendor_index') }}">back to list</a>
<a href="{{ path('app_vendor_edit', {'id': vendor.id}) }}">edit</a>
{{ include('vendor/_delete_form.html.twig') }}
{% endblock %}

View file

@ -0,0 +1,17 @@
<?php declare(strict_types=1);
namespace App\Tests\Controler;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
final class HomeTest extends WebTestCase
{
public function testSomething(): void
{
$client = static::createClient();
$client->request('GET', '/');
$this->assertResponseIsSuccessful();
$this->assertSelectorTextContains('h1', 'Halloo');
}
}

13
tests/bootstrap.php Normal file
View file

@ -0,0 +1,13 @@
<?php declare(strict_types=1);
use Symfony\Component\Dotenv\Dotenv;
require dirname(__DIR__) . '/vendor/autoload.php';
if (method_exists(Dotenv::class, 'bootEnv')) {
(new Dotenv)->bootEnv(dirname(__DIR__) . '/.env');
}
if ($_SERVER['APP_DEBUG']) {
umask(0o000);
}