Compare commits
No commits in common. "main" and "0.0.1" have entirely different histories.
67 changed files with 648 additions and 3502 deletions
|
@ -9,7 +9,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
REPO: '${{ github.repository }}'
|
REPO: '${{ github.repository }}'
|
||||||
TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
GIT_SERVER: 'git.hannover.ccc.de'
|
GIT_SERVER: 'hannover.ccc.de/gitlab'
|
||||||
run: |
|
run: |
|
||||||
git clone --branch $GITHUB_HEAD_REF https://${TOKEN}@${GIT_SERVER}/${REPO}.git .
|
git clone --branch $GITHUB_HEAD_REF https://${TOKEN}@${GIT_SERVER}/${REPO}.git .
|
||||||
git fetch
|
git fetch
|
||||||
|
@ -23,19 +23,7 @@ jobs:
|
||||||
- name: lint
|
- name: lint
|
||||||
run: composer lint
|
run: composer lint
|
||||||
- name: test
|
- name: test
|
||||||
run: composer mutation
|
run: composer test
|
||||||
- name: Add comment to pull request
|
|
||||||
run: |
|
|
||||||
echo '```' >> /tmp/pull-request-comment
|
|
||||||
cat var/log/infection.txt >> /tmp/pull-request-comment
|
|
||||||
cat var/log/summary.log >> /tmp/pull-request-comment
|
|
||||||
echo '```' >> /tmp/pull-request-comment
|
|
||||||
jq -n --arg msg "$(cat /tmp/pull-request-comment)" '{"body": $msg}' > /tmp/git-msg
|
|
||||||
curl -X POST \
|
|
||||||
-H "Authorization: token ${GITHUB_TOKEN}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d @/tmp/git-msg \
|
|
||||||
"${{ env.GITHUB_SERVER_URL }}/api/v1/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments"
|
|
||||||
- name: GIT commit and push all changed files
|
- name: GIT commit and push all changed files
|
||||||
env:
|
env:
|
||||||
CI_COMMIT_MESSAGE: Continuous Integration Fixes
|
CI_COMMIT_MESSAGE: Continuous Integration Fixes
|
||||||
|
|
|
@ -13,7 +13,7 @@ jobs:
|
||||||
REPO: '${{ github.repository }}'
|
REPO: '${{ github.repository }}'
|
||||||
TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
BRANCH: '${{ env.GITHUB_REF_NAME }}'
|
BRANCH: '${{ env.GITHUB_REF_NAME }}'
|
||||||
GIT_SERVER: 'git.hannover.ccc.de'
|
GIT_SERVER: 'hannover.ccc.de/gitlab'
|
||||||
run: |
|
run: |
|
||||||
git clone --branch $GITHUB_REF_NAME https://${TOKEN}@${GIT_SERVER}/${REPO}.git .
|
git clone --branch $GITHUB_REF_NAME https://${TOKEN}@${GIT_SERVER}/${REPO}.git .
|
||||||
git fetch
|
git fetch
|
||||||
|
@ -27,7 +27,7 @@ jobs:
|
||||||
- name: lint
|
- name: lint
|
||||||
run: composer lint
|
run: composer lint
|
||||||
- name: test
|
- name: test
|
||||||
run: composer mutation
|
run: composer test
|
||||||
- name: GIT commit and push all changed files
|
- name: GIT commit and push all changed files
|
||||||
env:
|
env:
|
||||||
CI_COMMIT_MESSAGE: Continuous Integration Fixes
|
CI_COMMIT_MESSAGE: Continuous Integration Fixes
|
||||||
|
|
|
@ -16,34 +16,5 @@ jobs:
|
||||||
git clone --branch $GITHUB_REF_NAME https://${TOKEN}@${GIT_SERVER}/${REPO}.git .
|
git clone --branch $GITHUB_REF_NAME https://${TOKEN}@${GIT_SERVER}/${REPO}.git .
|
||||||
git fetch
|
git fetch
|
||||||
git checkout ${{ github.head_ref }}
|
git checkout ${{ github.head_ref }}
|
||||||
- name: prepare deploy
|
- name: list
|
||||||
run: sh ./deploy/prepare-deploy.sh
|
run: ls
|
||||||
- name: deploy
|
|
||||||
env:
|
|
||||||
HOST: 'web.server.c3h'
|
|
||||||
USERNAME: 'c3h-futtern'
|
|
||||||
TARGETDIR: '/home/c3h-futtern/futtern'
|
|
||||||
HOMEDIR: '/home/c3h-futtern'
|
|
||||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.ssh/
|
|
||||||
# Print the SSH key, replacing newline characters with actual new lines
|
|
||||||
echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
|
|
||||||
# Set appropriate permissions for the SSH key
|
|
||||||
chmod 600 ~/.ssh/id_rsa
|
|
||||||
# Add the remote host's key to the known_hosts file to avoid authenticity confirmation
|
|
||||||
ssh-keyscan -H $HOST >> ~/.ssh/known_hosts
|
|
||||||
# stop services
|
|
||||||
ssh ${USERNAME}@${HOST} systemctl --user stop pod-futtern
|
|
||||||
# backup database
|
|
||||||
ssh ${USERNAME}@${HOST} "cp ${HOMEDIR}/futtern/app/var/data.db ${HOMEDIR}/backup/data.db-$(date +\"%Y%m%d%H%M%S\")"
|
|
||||||
# only keep last 10 backupts
|
|
||||||
ssh ${USERNAME}@${HOST} "find ${HOMEDIR}/backup/ -type f | sort | head -n -10 | xargs rm -f"
|
|
||||||
# SCP files to the remote host
|
|
||||||
rsync -avz --delete deploy/ ${USERNAME}@${HOST}:${TARGETDIR} --exclude=var
|
|
||||||
# run update script
|
|
||||||
ssh ${USERNAME}@${HOST} /home/c3h-futtern/futtern/update.sh
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -20,5 +20,5 @@
|
||||||
###< phpunit/phpunit ###
|
###< phpunit/phpunit ###
|
||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
|
/deploy/futtern-app/
|
||||||
/deploy/var/
|
/deploy/var/
|
||||||
/deploy/app/
|
|
||||||
|
|
|
@ -7,14 +7,13 @@
|
||||||
"php": ">=8.3",
|
"php": ">=8.3",
|
||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*",
|
"ext-iconv": "*",
|
||||||
"doctrine/dbal": "^4.1",
|
"doctrine/dbal": "^3",
|
||||||
"doctrine/doctrine-bundle": "^2.12",
|
"doctrine/doctrine-bundle": "^2.12",
|
||||||
"doctrine/doctrine-migrations-bundle": "^3.3.1",
|
"doctrine/doctrine-migrations-bundle": "^3.3",
|
||||||
"doctrine/orm": "^3.2.1",
|
"doctrine/orm": "^3.2",
|
||||||
"psr/clock": "^1.0",
|
|
||||||
"symfony/console": "7.1.*",
|
"symfony/console": "7.1.*",
|
||||||
"symfony/dotenv": "7.1.*",
|
"symfony/dotenv": "7.1.*",
|
||||||
"symfony/flex": "^2.4.6",
|
"symfony/flex": "^2",
|
||||||
"symfony/form": "7.1.*",
|
"symfony/form": "7.1.*",
|
||||||
"symfony/framework-bundle": "7.1.*",
|
"symfony/framework-bundle": "7.1.*",
|
||||||
"symfony/runtime": "7.1.*",
|
"symfony/runtime": "7.1.*",
|
||||||
|
@ -25,22 +24,20 @@
|
||||||
"symfony/yaml": "7.1.*"
|
"symfony/yaml": "7.1.*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"infection/infection": "^0.29.6",
|
"lubiana/code-quality": "^1.7",
|
||||||
"lubiana/code-quality": "^1.7.2",
|
"phpunit/phpunit": "^9.5",
|
||||||
"phpunit/phpunit": "^9.6.20",
|
|
||||||
"symfony/browser-kit": "7.1.*",
|
"symfony/browser-kit": "7.1.*",
|
||||||
"symfony/css-selector": "7.1.*",
|
"symfony/css-selector": "7.1.*",
|
||||||
"symfony/maker-bundle": "^1.60",
|
"symfony/maker-bundle": "^1.60",
|
||||||
"symfony/phpunit-bridge": "^7.1.3",
|
"symfony/phpunit-bridge": "^7.1",
|
||||||
"symplify/config-transformer": "^12.3.4"
|
"symplify/config-transformer": "^12.3"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"allow-plugins": {
|
"allow-plugins": {
|
||||||
"php-http/discovery": true,
|
"php-http/discovery": true,
|
||||||
"symfony/flex": true,
|
"symfony/flex": true,
|
||||||
"symfony/runtime": true,
|
"symfony/runtime": true,
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": true,
|
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||||
"infection/extension-installer": true
|
|
||||||
},
|
},
|
||||||
"sort-packages": true,
|
"sort-packages": true,
|
||||||
"platform": {
|
"platform": {
|
||||||
|
@ -83,8 +80,7 @@
|
||||||
"rector",
|
"rector",
|
||||||
"ecs --fix || ecs --fix"
|
"ecs --fix || ecs --fix"
|
||||||
],
|
],
|
||||||
"test": "bin/phpunit",
|
"test": "bin/phpunit"
|
||||||
"mutation": "infection --threads=8 --show-mutations"
|
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"symfony/symfony": "*"
|
"symfony/symfony": "*"
|
||||||
|
|
1862
composer.lock
generated
1862
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -5,9 +5,6 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigura
|
||||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||||
$containerConfigurator->extension('twig', [
|
$containerConfigurator->extension('twig', [
|
||||||
'file_name_pattern' => '*.twig',
|
'file_name_pattern' => '*.twig',
|
||||||
'globals' => [
|
|
||||||
'favicon' => '@App\Service\Favicon',
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
if ($containerConfigurator->env() === 'test') {
|
if ($containerConfigurator->env() === 'test') {
|
||||||
$containerConfigurator->extension('twig', [
|
$containerConfigurator->extension('twig', [
|
||||||
|
|
2
deploy/Dockerfile
Normal file
2
deploy/Dockerfile
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
FROM git.php.fail/lubiana/container/php:8.3 as phpbuild
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
[www]
|
[www]
|
||||||
|
|
||||||
user = root
|
user = nobody
|
||||||
group = root
|
group = nobody
|
||||||
listen = 9001
|
listen = 9001
|
||||||
pm = dynamic
|
pm = dynamic
|
||||||
pm.max_children = 5
|
pm.max_children = 5
|
||||||
pm.start_servers = 2
|
pm.start_servers = 2
|
||||||
pm.min_spare_servers = 1
|
pm.min_spare_servers = 1
|
||||||
pm.max_spare_servers = 3
|
pm.max_spare_servers = 3
|
||||||
env[APP_ENV]=$APP_ENV
|
|
||||||
env[APP_SECRET]=$APP_SECRET
|
|
||||||
catch_workers_output = yes
|
|
31
deploy/install.sh
Executable file
31
deploy/install.sh
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
if [ ! -d "var" ]; then
|
||||||
|
mkdir var
|
||||||
|
fi
|
||||||
|
podman pod stop futtern
|
||||||
|
podman pod rm futtern
|
||||||
|
|
||||||
|
podman pod create \
|
||||||
|
--label "io.containers.autoupdate=registry" \
|
||||||
|
--name futtern \
|
||||||
|
-p 8087:8087
|
||||||
|
|
||||||
|
podman run -d \
|
||||||
|
--pod futtern \
|
||||||
|
--name futtern-php \
|
||||||
|
--volume $(pwd)/etc/php83/php-fpm.d/www.conf:/etc/php83/php-fpm.d/www.conf \
|
||||||
|
--volume $(pwd)/futtern-app:/var/www/html \
|
||||||
|
--volume $(pwd)/var:/var/www/html/var \
|
||||||
|
--env 'APP_ENV=prod' \
|
||||||
|
git.php.fail/lubiana/container/php:8.3-fpm
|
||||||
|
|
||||||
|
podman run -d \
|
||||||
|
--pod futtern \
|
||||||
|
--name futtern-caddy \
|
||||||
|
--volume $(pwd)/etc/caddy/Caddyfile:/etc/caddy/Caddyfile \
|
||||||
|
--volume $(pwd)/futtern-app:/var/www/html \
|
||||||
|
--volume caddy_data:/data \
|
||||||
|
docker.io/caddy/caddy:alpine
|
||||||
|
|
||||||
|
echo 'yes' | podman exec -it futtern-php /var/www/html/bin/console doctrine:migrations:migrate
|
|
@ -1,10 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
export HOMEDIR='/home/c3h-futtern/'
|
|
||||||
|
|
||||||
. ./deploy/prepare-deploy.sh
|
|
||||||
ssh leitstelle-futtern 'systemctl --user stop pod-futtern'
|
|
||||||
ssh leitstelle-futtern "cp ${HOMEDIR}/futtern/app/var/data.db ${HOMEDIR}/backup/data.db-$(date +\"%Y%m%d%H%M%S\")"
|
|
||||||
ssh leitstelle-futtern "find ${HOMEDIR}/backup/ -type f | sort | head -n -10 | xargs rm -f"
|
|
||||||
rsync -avz --delete deploy/ leitstelle-futtern:futtern --exclude=var
|
|
||||||
ssh leitstelle-futtern '/home/c3h-futtern/futtern/update.sh'
|
|
15
deploy/prepare-deploy.sh
Executable file → Normal file
15
deploy/prepare-deploy.sh
Executable file → Normal file
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
TARGETDIR='deploy/app'
|
TARGETDIR='futtern-app'
|
||||||
|
|
||||||
if [ -d $TARGETDIR ]; then
|
if [ -d $TARGETDIR ]; then
|
||||||
rm -rf $TARGETDIR
|
rm -rf $TARGETDIR
|
||||||
|
@ -8,7 +8,7 @@ fi
|
||||||
mkdir $TARGETDIR
|
mkdir $TARGETDIR
|
||||||
cd $TARGETDIR || return
|
cd $TARGETDIR || return
|
||||||
|
|
||||||
pathsToCopy="public bin config migrations src templates composer.json composer.lock symfony.lock .env"
|
pathsToCopy="public bin config migrations src templates composer.json composer.lock symfony.lock .env etc"
|
||||||
|
|
||||||
for path in $pathsToCopy
|
for path in $pathsToCopy
|
||||||
do
|
do
|
||||||
|
@ -17,7 +17,14 @@ done
|
||||||
|
|
||||||
rm ./bin/phpunit
|
rm ./bin/phpunit
|
||||||
APP_ENV=prod composer install --no-dev -a
|
APP_ENV=prod composer install --no-dev -a
|
||||||
rm -rf ./var/cache
|
mkdir -p ~/.ssh/
|
||||||
|
# Print the SSH key, replacing newline characters with actual new lines
|
||||||
|
echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
|
||||||
|
# Set appropriate permissions for the SSH key
|
||||||
|
chmod 600 ~/.ssh/id_rsa
|
||||||
|
# Add the remote host's key to the known_hosts file to avoid authenticity confirmation
|
||||||
|
ssh-keyscan -H $HOST >> ~/.ssh/known_hosts
|
||||||
|
# SCP files to the remote host
|
||||||
|
rsync -avz --delete public/ ${USERNAME}@${HOST}:${TARGETDIR}
|
||||||
|
|
||||||
cd -
|
|
||||||
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
# container-futtern-caddy.service
|
|
||||||
# autogenerated by Podman 4.3.1
|
|
||||||
# Sun Jun 23 05:33:51 UTC 2024
|
|
||||||
|
|
||||||
[Unit]
|
|
||||||
Description=Podman container-futtern-caddy.service
|
|
||||||
Documentation=man:podman-generate-systemd(1)
|
|
||||||
Wants=network-online.target
|
|
||||||
After=network-online.target
|
|
||||||
RequiresMountsFor=%t/containers
|
|
||||||
BindsTo=pod-futtern.service
|
|
||||||
After=pod-futtern.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=PODMAN_SYSTEMD_UNIT=%n
|
|
||||||
Restart=on-failure
|
|
||||||
TimeoutStopSec=70
|
|
||||||
ExecStartPre=/bin/rm \
|
|
||||||
-f %t/%n.ctr-id
|
|
||||||
ExecStart=/usr/bin/podman run \
|
|
||||||
--cidfile=%t/%n.ctr-id \
|
|
||||||
--cgroups=no-conmon \
|
|
||||||
--rm \
|
|
||||||
--pod-id-file %t/pod-futtern.pod-id \
|
|
||||||
--sdnotify=conmon \
|
|
||||||
--replace \
|
|
||||||
-d \
|
|
||||||
--name futtern-caddy \
|
|
||||||
--volume %h/futtern/etc/caddy/Caddyfile:/etc/caddy/Caddyfile \
|
|
||||||
--volume %h/futtern/app:/var/www/html \
|
|
||||||
--volume caddy_data:/data docker.io/caddy/caddy:alpine
|
|
||||||
ExecStop=/usr/bin/podman stop \
|
|
||||||
--ignore -t 10 \
|
|
||||||
--cidfile=%t/%n.ctr-id
|
|
||||||
ExecStopPost=/usr/bin/podman rm \
|
|
||||||
-f \
|
|
||||||
--ignore -t 10 \
|
|
||||||
--cidfile=%t/%n.ctr-id
|
|
||||||
Type=notify
|
|
||||||
NotifyAccess=all
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
|
@ -1,46 +0,0 @@
|
||||||
# container-futtern-php.service
|
|
||||||
# autogenerated by Podman 4.3.1
|
|
||||||
# Sun Jun 23 05:33:51 UTC 2024
|
|
||||||
|
|
||||||
[Unit]
|
|
||||||
Description=Podman container-futtern-php.service
|
|
||||||
Documentation=man:podman-generate-systemd(1)
|
|
||||||
Wants=network-online.target
|
|
||||||
After=network-online.target
|
|
||||||
RequiresMountsFor=%t/containers
|
|
||||||
BindsTo=pod-futtern.service
|
|
||||||
After=pod-futtern.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=PODMAN_SYSTEMD_UNIT=%n
|
|
||||||
Restart=on-failure
|
|
||||||
TimeoutStopSec=70
|
|
||||||
ExecStartPre=/bin/rm \
|
|
||||||
-f %t/%n.ctr-id
|
|
||||||
ExecStart=/usr/bin/podman run \
|
|
||||||
--cidfile=%t/%n.ctr-id \
|
|
||||||
--cgroups=no-conmon \
|
|
||||||
--rm \
|
|
||||||
--pod-id-file %t/pod-futtern.pod-id \
|
|
||||||
--sdnotify=conmon \
|
|
||||||
--replace \
|
|
||||||
-d \
|
|
||||||
--name futtern-php \
|
|
||||||
--volume %h/futtern/etc/php83/php-fpm.d/www.conf:/etc/php83/php-fpm.d/www.conf \
|
|
||||||
--volume %h/futtern/app:/var/www/html \
|
|
||||||
--volume %h/futtern/app/var:/var/www/html/var \
|
|
||||||
--env APP_ENV=prod \
|
|
||||||
--env APP_SECRET=UwUtHiSisNotSecurePlZcHanGeMe \
|
|
||||||
git.php.fail/lubiana/container/php:8.3-fpm
|
|
||||||
ExecStop=/usr/bin/podman stop \
|
|
||||||
--ignore -t 10 \
|
|
||||||
--cidfile=%t/%n.ctr-id
|
|
||||||
ExecStopPost=/usr/bin/podman rm \
|
|
||||||
-f \
|
|
||||||
--ignore -t 10 \
|
|
||||||
--cidfile=%t/%n.ctr-id
|
|
||||||
Type=notify
|
|
||||||
NotifyAccess=all
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
|
@ -1,42 +0,0 @@
|
||||||
# pod-futtern.service
|
|
||||||
# autogenerated by Podman 4.3.1
|
|
||||||
# Sun Jun 23 05:33:51 UTC 2024
|
|
||||||
|
|
||||||
[Unit]
|
|
||||||
Description=Podman pod-futtern.service
|
|
||||||
Documentation=man:podman-generate-systemd(1)
|
|
||||||
Wants=network-online.target
|
|
||||||
After=network-online.target
|
|
||||||
RequiresMountsFor=/run/user/%U/containers
|
|
||||||
Wants=container-futtern-caddy.service container-futtern-php.service
|
|
||||||
Before=container-futtern-caddy.service container-futtern-php.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=PODMAN_SYSTEMD_UNIT=%n
|
|
||||||
Restart=on-failure
|
|
||||||
TimeoutStopSec=70
|
|
||||||
ExecStartPre=/bin/rm \
|
|
||||||
-f %t/pod-futtern.pid %t/pod-futtern.pod-id
|
|
||||||
ExecStartPre=/usr/bin/podman pod create \
|
|
||||||
--infra-conmon-pidfile %t/pod-futtern.pid \
|
|
||||||
--pod-id-file %t/pod-futtern.pod-id \
|
|
||||||
--exit-policy=stop \
|
|
||||||
--label io.containers.autoupdate=registry \
|
|
||||||
--name futtern \
|
|
||||||
-p 8087:8087 \
|
|
||||||
--replace
|
|
||||||
ExecStart=/usr/bin/podman pod start \
|
|
||||||
--pod-id-file %t/pod-futtern.pod-id
|
|
||||||
ExecStop=/usr/bin/podman pod stop \
|
|
||||||
--ignore \
|
|
||||||
--pod-id-file %t/pod-futtern.pod-id \
|
|
||||||
-t 10
|
|
||||||
ExecStopPost=/usr/bin/podman pod rm \
|
|
||||||
--ignore \
|
|
||||||
-f \
|
|
||||||
--pod-id-file %t/pod-futtern.pod-id
|
|
||||||
PIDFile=%t/pod-futtern.pid
|
|
||||||
Type=forking
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
systemctl --user stop pod-futtern
|
|
||||||
systemctl --user start pod-futtern
|
|
||||||
sleep 2
|
|
||||||
podman exec -it futtern-php /var/www/html/bin/console cache:clear
|
|
||||||
podman exec -it futtern-php /var/www/html/bin/console cache:warmup
|
|
||||||
echo 'yes' | podman exec -it futtern-php /var/www/html/bin/console doctrine:migrations:migrate
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "vendor/infection/infection/resources/schema.json",
|
|
||||||
"source": {
|
|
||||||
"directories": [
|
|
||||||
"src"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"timeout": 30,
|
|
||||||
"logs": {
|
|
||||||
"text": "var/log/infection.txt",
|
|
||||||
"summary": "var/log/summary.log",
|
|
||||||
},
|
|
||||||
"mutators": {
|
|
||||||
"@default": true,
|
|
||||||
"global-ignore": [
|
|
||||||
"App\\Service\\Favicon::__toString",
|
|
||||||
"ORM\\Column.*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +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 Version20240626175246 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 menu_item (id BLOB NOT NULL, name VARCHAR(255) NOT NULL, food_vendor_id BLOB NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_D754D5506EF983E8 FOREIGN KEY (food_vendor_id) REFERENCES food_vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('CREATE INDEX IDX_D754D5506EF983E8 ON menu_item (food_vendor_id)');
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__food_order AS SELECT id, food_vendor_id, closed_at FROM food_order');
|
|
||||||
$this->addSql('DROP TABLE food_order');
|
|
||||||
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL, food_vendor_id BLOB NOT NULL, closed_at DATETIME DEFAULT NULL, PRIMARY KEY(id), CONSTRAINT FK_44856726EF983E8 FOREIGN KEY (food_vendor_id) REFERENCES food_vendor (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('INSERT INTO food_order (id, food_vendor_id, closed_at) SELECT id, food_vendor_id, closed_at FROM __temp__food_order');
|
|
||||||
$this->addSql('DROP TABLE __temp__food_order');
|
|
||||||
$this->addSql('CREATE INDEX IDX_44856726EF983E8 ON food_order (food_vendor_id)');
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__food_vendor AS SELECT id, name FROM food_vendor');
|
|
||||||
$this->addSql('DROP TABLE food_vendor');
|
|
||||||
$this->addSql('CREATE TABLE food_vendor (id BLOB NOT NULL, name VARCHAR(50) NOT NULL, PRIMARY KEY(id))');
|
|
||||||
$this->addSql('INSERT INTO food_vendor (id, name) SELECT id, name FROM __temp__food_vendor');
|
|
||||||
$this->addSql('DROP TABLE __temp__food_vendor');
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__order_item AS SELECT id, food_order_id, name, extras FROM order_item');
|
|
||||||
$this->addSql('DROP TABLE order_item');
|
|
||||||
$this->addSql('CREATE TABLE order_item (id BLOB NOT NULL, food_order_id BLOB DEFAULT NULL, name VARCHAR(255) NOT NULL, extras VARCHAR(255) DEFAULT NULL, menu_item_id BLOB DEFAULT NULL, PRIMARY KEY(id), CONSTRAINT FK_52EA1F09A5D24A7A FOREIGN KEY (food_order_id) REFERENCES food_order (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_52EA1F099AB44FE0 FOREIGN KEY (menu_item_id) REFERENCES menu_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('INSERT INTO order_item (id, food_order_id, name, extras) SELECT id, food_order_id, name, extras FROM __temp__order_item');
|
|
||||||
$this->addSql('DROP TABLE __temp__order_item');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F09A5D24A7A ON order_item (food_order_id)');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F099AB44FE0 ON order_item (menu_item_id)');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('DROP TABLE menu_item');
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__food_order AS SELECT id, closed_at, food_vendor_id FROM food_order');
|
|
||||||
$this->addSql('DROP TABLE food_order');
|
|
||||||
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, closed_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
|
|
||||||
, food_vendor_id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, PRIMARY KEY(id), CONSTRAINT FK_44856726EF983E8 FOREIGN KEY (food_vendor_id) REFERENCES food_vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('INSERT INTO food_order (id, closed_at, food_vendor_id) SELECT id, closed_at, food_vendor_id FROM __temp__food_order');
|
|
||||||
$this->addSql('DROP TABLE __temp__food_order');
|
|
||||||
$this->addSql('CREATE INDEX IDX_44856726EF983E8 ON food_order (food_vendor_id)');
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__food_vendor AS SELECT id, name FROM food_vendor');
|
|
||||||
$this->addSql('DROP TABLE food_vendor');
|
|
||||||
$this->addSql('CREATE TABLE food_vendor (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, name VARCHAR(50) NOT NULL, PRIMARY KEY(id))');
|
|
||||||
$this->addSql('INSERT INTO food_vendor (id, name) SELECT id, name FROM __temp__food_vendor');
|
|
||||||
$this->addSql('DROP TABLE __temp__food_vendor');
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__order_item AS SELECT id, name, extras, food_order_id FROM order_item');
|
|
||||||
$this->addSql('DROP TABLE order_item');
|
|
||||||
$this->addSql('CREATE TABLE order_item (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, name VARCHAR(255) NOT NULL, extras VARCHAR(255) DEFAULT NULL, food_order_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)');
|
|
||||||
$this->addSql('INSERT INTO order_item (id, name, extras, food_order_id) SELECT id, name, extras, food_order_id FROM __temp__order_item');
|
|
||||||
$this->addSql('DROP TABLE __temp__order_item');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F09A5D24A7A ON order_item (food_order_id)');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +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 Version20240626182031 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this up() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__order_item AS SELECT id, food_order_id, name, extras, menu_item_id FROM order_item');
|
|
||||||
$this->addSql('DROP TABLE order_item');
|
|
||||||
$this->addSql('CREATE TABLE order_item (id BLOB NOT NULL, food_order_id BLOB DEFAULT NULL, name VARCHAR(255) NOT NULL, extras VARCHAR(255) DEFAULT NULL, menu_item_id BLOB NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_52EA1F09A5D24A7A FOREIGN KEY (food_order_id) REFERENCES food_order (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_52EA1F099AB44FE0 FOREIGN KEY (menu_item_id) REFERENCES menu_item (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('INSERT INTO order_item (id, food_order_id, name, extras, menu_item_id) SELECT id, food_order_id, name, extras, menu_item_id FROM __temp__order_item');
|
|
||||||
$this->addSql('DROP TABLE __temp__order_item');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F099AB44FE0 ON order_item (menu_item_id)');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F09A5D24A7A ON order_item (food_order_id)');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__order_item AS SELECT id, name, extras, food_order_id, menu_item_id FROM order_item');
|
|
||||||
$this->addSql('DROP TABLE order_item');
|
|
||||||
$this->addSql('CREATE TABLE order_item (id BLOB NOT NULL, name VARCHAR(255) NOT NULL, extras VARCHAR(255) DEFAULT NULL, food_order_id BLOB DEFAULT NULL, menu_item_id BLOB DEFAULT NULL, 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('INSERT INTO order_item (id, name, extras, food_order_id, menu_item_id) SELECT id, name, extras, food_order_id, menu_item_id FROM __temp__order_item');
|
|
||||||
$this->addSql('DROP TABLE __temp__order_item');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F09A5D24A7A ON order_item (food_order_id)');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F099AB44FE0 ON order_item (menu_item_id)');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +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 Version20240627212849 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('ALTER TABLE food_order ADD COLUMN created_by VARCHAR(255) DEFAULT \'nobody\' NOT NULL');
|
|
||||||
$this->addSql('ALTER TABLE order_item ADD COLUMN created_by VARCHAR(255) DEFAULT \'nobody\' NOT NULL');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__food_order AS SELECT id, closed_at, food_vendor_id FROM food_order');
|
|
||||||
$this->addSql('DROP TABLE food_order');
|
|
||||||
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL, closed_at DATETIME DEFAULT NULL, food_vendor_id BLOB NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_44856726EF983E8 FOREIGN KEY (food_vendor_id) REFERENCES food_vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('INSERT INTO food_order (id, closed_at, food_vendor_id) SELECT id, closed_at, food_vendor_id FROM __temp__food_order');
|
|
||||||
$this->addSql('DROP TABLE __temp__food_order');
|
|
||||||
$this->addSql('CREATE INDEX IDX_44856726EF983E8 ON food_order (food_vendor_id)');
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__order_item AS SELECT id, name, extras, food_order_id, menu_item_id FROM order_item');
|
|
||||||
$this->addSql('DROP TABLE order_item');
|
|
||||||
$this->addSql('CREATE TABLE order_item (id BLOB NOT NULL, name VARCHAR(255) NOT NULL, extras VARCHAR(255) DEFAULT NULL, food_order_id BLOB DEFAULT NULL, menu_item_id BLOB NOT NULL, 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('INSERT INTO order_item (id, name, extras, food_order_id, menu_item_id) SELECT id, name, extras, food_order_id, menu_item_id FROM __temp__order_item');
|
|
||||||
$this->addSql('DROP TABLE __temp__order_item');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F09A5D24A7A ON order_item (food_order_id)');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F099AB44FE0 ON order_item (menu_item_id)');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,36 +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 Version20240815151510 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('ALTER TABLE menu_item ADD COLUMN deleted_at DATETIME DEFAULT NULL');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__menu_item AS SELECT id, name, food_vendor_id FROM menu_item');
|
|
||||||
$this->addSql('DROP TABLE menu_item');
|
|
||||||
$this->addSql('CREATE TABLE menu_item (id BLOB NOT NULL, name VARCHAR(255) NOT NULL, food_vendor_id BLOB NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_D754D5506EF983E8 FOREIGN KEY (food_vendor_id) REFERENCES food_vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('INSERT INTO menu_item (id, name, food_vendor_id) SELECT id, name, food_vendor_id FROM __temp__menu_item');
|
|
||||||
$this->addSql('DROP TABLE __temp__menu_item');
|
|
||||||
$this->addSql('CREATE INDEX IDX_D754D5506EF983E8 ON menu_item (food_vendor_id)');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +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 Version20240816193410 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('ALTER TABLE food_vendor ADD COLUMN menu_link VARCHAR(255) DEFAULT NULL');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__food_vendor AS SELECT name, id FROM food_vendor');
|
|
||||||
$this->addSql('DROP TABLE food_vendor');
|
|
||||||
$this->addSql('CREATE TABLE food_vendor (name VARCHAR(50) NOT NULL, id BLOB NOT NULL, PRIMARY KEY(id))');
|
|
||||||
$this->addSql('INSERT INTO food_vendor (name, id) SELECT name, id FROM __temp__food_vendor');
|
|
||||||
$this->addSql('DROP TABLE __temp__food_vendor');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,9 +6,7 @@
|
||||||
backupGlobals="false"
|
backupGlobals="false"
|
||||||
colors="true"
|
colors="true"
|
||||||
bootstrap="tests/bootstrap.php"
|
bootstrap="tests/bootstrap.php"
|
||||||
convertDeprecationsToExceptions="true"
|
convertDeprecationsToExceptions="false"
|
||||||
executionOrder="random"
|
|
||||||
resolveDependencies="true"
|
|
||||||
>
|
>
|
||||||
<php>
|
<php>
|
||||||
<ini name="display_errors" value="1" />
|
<ini name="display_errors" value="1" />
|
||||||
|
|
1
public/static/css/new.min.css
vendored
1
public/static/css/new.min.css
vendored
|
@ -1 +0,0 @@
|
||||||
blockquote,header{background:var(--nc-bg-2)}dt,summary,table caption{font-weight:700}img,pre,textarea{max-width:100%}: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;--nc-d-tx-1:#ffffff;--nc-d-tx-2:#eeeeee;--nc-d-bg-1:#000000;--nc-d-bg-2:#111111;--nc-d-bg-3:#222222;--nc-d-lk-1:#3291FF;--nc-d-lk-2:#0070F3;--nc-d-lk-tx:#FFFFFF;--nc-d-ac-1:#7928CA;--nc-d-ac-tx:#FFFFFF}@media (prefers-color-scheme:dark){:root{--nc-tx-1:var(--nc-d-tx-1);--nc-tx-2:var(--nc-d-tx-2);--nc-bg-1:var(--nc-d-bg-1);--nc-bg-2:var(--nc-d-bg-2);--nc-bg-3:var(--nc-d-bg-3);--nc-lk-1:var(--nc-d-lk-1);--nc-lk-2:var(--nc-d-lk-2);--nc-lk-tx:var(--nc--dlk-tx);--nc-ac-1:var(--nc-d-ac-1);--nc-ac-tx:var(--nc--dac-tx)}}*{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,abbr:hover{cursor:help}blockquote{padding:1.5rem;border-left:5px solid var(--nc-bg-3)}blockquote :last-child{padding-bottom:0;margin-bottom:0}header{border-bottom:1px solid var(--nc-bg-3);padding:2rem 1.5rem;margin:-2rem calc(50% - 50vw) 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}a img,details[open]>:last-child,header>:last-child,ol ol,ol ul,ul ol,ul ul{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]{opacity:.5;cursor:not-allowed}.button:enabled:hover,.button:focus,button:enabled:hover,button:focus,input[type=button]:enabled:hover,input[type=button]:focus,input[type=reset]:enabled:hover,input[type=reset]:focus,input[type=submit]:enabled:hover,input[type=submit]:focus{background:var(--nc-lk-2)}code,details,input,kbd,pre,samp,select,textarea,th,tr:nth-child(2n){background:var(--nc-bg-2)}code,kbd,pre,samp{font-family:var(--nc-font-mono);border:1px solid var(--nc-bg-3);border-radius:4px;padding:3px 6px;font-size:.9em}code pre,pre code{background:inherit;font-size:inherit;color:inherit;border:0;padding:0;margin:0}details,fieldset{border:1px solid var(--nc-bg-3)}kbd{border-bottom:3px solid var(--nc-bg-3)}pre{padding:1rem 1.4rem;overflow:auto}code pre{display:inline}details{padding:.6rem 1rem;border-radius:4px}summary{cursor:pointer}details[open]{padding-bottom:.75rem}details[open] summary{margin-bottom:6px}dd::before{content:'→ '}hr{border:0;border-bottom:1px solid var(--nc-bg-3);margin:1rem auto}fieldset{margin-top:1rem;padding:2rem;border-radius:4px}input,select,td,textarea,th{border:1px solid var(--nc-bg-3)}legend{padding:auto .5rem}table{border-collapse:collapse;width:100%}td,th{text-align:left;padding:.5rem}table caption{margin-bottom:.5rem}ol,ul{padding-left:2rem}li{margin-top:.4rem}mark{padding:3px 6px;background:var(--nc-ac-1);color:var(--nc-ac-tx)}input,select,textarea{padding:6px 12px;margin-bottom:.5rem;color:var(--nc-tx-2);border-radius:4px;box-shadow:none;box-sizing:border-box}
|
|
|
@ -1,13 +0,0 @@
|
||||||
<svg
|
|
||||||
enable-background="new 0 0 512 512"
|
|
||||||
viewBox="0 0 512 512"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<g
|
|
||||||
transform="rotate(30, 256, 256)"
|
|
||||||
>
|
|
||||||
<path d="m51.6 72.608 199.566-34.825 213.114 34.825c19.867 0 32.553 21.19 23.171 38.701l-206.224 384.92c-9.908 18.492-36.421 18.499-46.337.011l-206.455-384.92c-9.393-17.512 3.293-38.712 23.165-38.712z" fill="#fecb21"/>
|
|
||||||
<path d="m270.254 307.902c0 28.665-23.238 51.902-51.902 51.902s-51.902-23.237-51.902-51.902 23.237-51.902 51.902-51.902 51.902 23.237 51.902 51.902zm65.862 81.954c-25.323-13.433-56.74-3.794-70.173 21.528-13.433 25.323-3.794 56.74 21.528 70.173m48.645-342.08c-28.665 0-51.902 23.237-51.902 51.902s23.237 51.902 51.902 51.902 51.902-23.237 51.902-51.902-23.237-51.902-51.902-51.902zm-182.102-33.763c-28.665 0-51.902 23.237-51.902 51.902s23.237 51.902 51.902 51.902 51.902-23.237 51.902-51.902-23.237-51.902-51.902-51.902z" fill="#f43b22"/>
|
|
||||||
<path d="m41.204 130.519c-13.328.001-26.256-7.039-33.184-19.518-10.167-18.308-3.566-41.391 14.743-51.557 34.605-19.215 72.08-34.048 111.383-44.088 39.334-10.047 80.138-15.214 121.279-15.356 40.982-.14 81.845 4.711 121.369 14.423 40.306 9.904 78.8 24.757 114.412 44.147 18.393 10.014 25.184 33.041 15.17 51.433-10.014 18.391-33.043 25.185-51.433 15.169-29.887-16.273-62.269-28.757-96.246-37.105-33.046-8.12-67.199-12.236-101.53-12.236-.496 0-.986.001-1.481.002-34.903.121-69.481 4.494-102.772 12.998-33.009 8.432-64.412 20.851-93.338 36.912-5.829 3.239-12.145 4.776-18.372 4.776z" fill="#c4790c"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
35
src/Command/FakeDataCommand.php
Normal file
35
src/Command/FakeDataCommand.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Command;
|
||||||
|
|
||||||
|
use App\Service\FakeData;
|
||||||
|
use Override;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
#[AsCommand(
|
||||||
|
name: 'app:fake-data',
|
||||||
|
description: 'add some fake data to database',
|
||||||
|
)]
|
||||||
|
final class FakeDataCommand extends Command
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly FakeData $fakeData,
|
||||||
|
) {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Override]
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$this->fakeData->resetDb();
|
||||||
|
$this->fakeData->generate();
|
||||||
|
|
||||||
|
$io->success('Added some fake data to database');
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,49 +14,11 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||||
#[Route('/food/order')]
|
#[Route('/food/order')]
|
||||||
final class FoodOrderController extends AbstractController
|
final class FoodOrderController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route(
|
#[Route('/', name: 'app_food_order_index', methods: ['GET'])]
|
||||||
path: '/list',
|
|
||||||
name: 'app_food_order_index',
|
|
||||||
methods: ['GET']
|
|
||||||
)]
|
|
||||||
public function index(FoodOrderRepository $foodOrderRepository): Response
|
public function index(FoodOrderRepository $foodOrderRepository): Response
|
||||||
{
|
{
|
||||||
|
|
||||||
return $this->render('food_order/index.html.twig', [
|
return $this->render('food_order/index.html.twig', [
|
||||||
'food_orders' => $foodOrderRepository->findLatestEntries(days: 3),
|
'food_orders' => $foodOrderRepository->findLatestEntries(),
|
||||||
'current_page' => 0,
|
|
||||||
'next_page' => 0,
|
|
||||||
'prev_page' => 0,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route(
|
|
||||||
path: '/list/archive/{page}',
|
|
||||||
name: 'app_food_order_archive',
|
|
||||||
requirements: [
|
|
||||||
'page' => '\d+',
|
|
||||||
],
|
|
||||||
methods: ['GET']
|
|
||||||
)]
|
|
||||||
public function archive(FoodOrderRepository $foodOrderRepository, int $page = 1): Response
|
|
||||||
{
|
|
||||||
$nextPage = $page + 1;
|
|
||||||
$prevPage = $page - 1;
|
|
||||||
$itemsPerPage = 10;
|
|
||||||
$count = $foodOrderRepository->count();
|
|
||||||
if($count < $page * $itemsPerPage) {
|
|
||||||
$nextPage = $page;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->render('food_order/index.html.twig', [
|
|
||||||
'food_orders' => $foodOrderRepository->findLatestEntries(
|
|
||||||
page: $page,
|
|
||||||
pagesize: $itemsPerPage,
|
|
||||||
days: 0
|
|
||||||
),
|
|
||||||
'current_page' => $page,
|
|
||||||
'next_page' => $nextPage,
|
|
||||||
'prev_page' => $prevPage,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +26,6 @@ final class FoodOrderController extends AbstractController
|
||||||
public function new(Request $request, EntityManagerInterface $entityManager): Response
|
public function new(Request $request, EntityManagerInterface $entityManager): Response
|
||||||
{
|
{
|
||||||
$foodOrder = new FoodOrder;
|
$foodOrder = new FoodOrder;
|
||||||
$username = $request->cookies->get('username', 'nobody');
|
|
||||||
$foodOrder->setCreatedBy($username);
|
|
||||||
$form = $this->createForm(FoodOrderType::class, $foodOrder, [
|
$form = $this->createForm(FoodOrderType::class, $foodOrder, [
|
||||||
'action' => $this->generateUrl('app_food_order_new'),
|
'action' => $this->generateUrl('app_food_order_new'),
|
||||||
]);
|
]);
|
||||||
|
@ -95,8 +55,7 @@ final class FoodOrderController extends AbstractController
|
||||||
#[Route('/{id}/close', name: 'app_food_order_close', methods: ['GET'])]
|
#[Route('/{id}/close', name: 'app_food_order_close', methods: ['GET'])]
|
||||||
public function close(FoodOrder $foodOrder, FoodOrderRepository $repository): Response
|
public function close(FoodOrder $foodOrder, FoodOrderRepository $repository): Response
|
||||||
{
|
{
|
||||||
$foodOrder->close();
|
$repository->save($foodOrder->close());
|
||||||
$repository->save();
|
|
||||||
return $this->redirectToRoute('app_food_order_show', [
|
return $this->redirectToRoute('app_food_order_show', [
|
||||||
'id' => $foodOrder->getId(),
|
'id' => $foodOrder->getId(),
|
||||||
], Response::HTTP_SEE_OTHER);
|
], Response::HTTP_SEE_OTHER);
|
||||||
|
@ -105,8 +64,7 @@ final class FoodOrderController extends AbstractController
|
||||||
#[Route('/{id}/open', name: 'app_food_order_open', methods: ['GET'])]
|
#[Route('/{id}/open', name: 'app_food_order_open', methods: ['GET'])]
|
||||||
public function open(FoodOrder $foodOrder, FoodOrderRepository $repository): Response
|
public function open(FoodOrder $foodOrder, FoodOrderRepository $repository): Response
|
||||||
{
|
{
|
||||||
$foodOrder->open();
|
$repository->save($foodOrder->open());
|
||||||
$repository->save();
|
|
||||||
return $this->redirectToRoute('app_food_order_show', [
|
return $this->redirectToRoute('app_food_order_show', [
|
||||||
'id' => $foodOrder->getId(),
|
'id' => $foodOrder->getId(),
|
||||||
], Response::HTTP_SEE_OTHER);
|
], Response::HTTP_SEE_OTHER);
|
||||||
|
|
|
@ -2,46 +2,16 @@
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Form\UserNameFormType;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
||||||
use Symfony\Component\HttpFoundation\Cookie;
|
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
|
|
||||||
final class HomeController extends AbstractController
|
final class HomeController
|
||||||
{
|
{
|
||||||
public const string DEFAULT_USERNAME = 'nobody';
|
|
||||||
|
|
||||||
#[Route('/', name: 'home')]
|
#[Route('/', name: 'home')]
|
||||||
public function home(UrlGeneratorInterface $router): Response
|
public function home(UrlGeneratorInterface $router): Response
|
||||||
{
|
{
|
||||||
return new RedirectResponse($router->generate('app_food_order_index'));
|
return new RedirectResponse($router->generate('app_food_order_index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/username', name: 'username')]
|
|
||||||
public function usernameForm(Request $request, UrlGeneratorInterface $router): Response
|
|
||||||
{
|
|
||||||
$form = $this->createForm(UsernameFormType::class);
|
|
||||||
$form->handleRequest($request);
|
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
|
||||||
$username = $form->getData()['username'] ?? self::DEFAULT_USERNAME;
|
|
||||||
$response = new RedirectResponse($router->generate('app_food_order_index'));
|
|
||||||
if ($username === self::DEFAULT_USERNAME || $username === '') {
|
|
||||||
$response->headers->clearCookie('username');
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
$response->headers->setCookie(new Cookie('username', $username));
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
$username = $request->cookies->get('username', self::DEFAULT_USERNAME);
|
|
||||||
$form->setData([
|
|
||||||
'username' => $username,
|
|
||||||
]);
|
|
||||||
return $this->render('username.html.twig', [
|
|
||||||
'form' => $form,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Controller;
|
|
||||||
|
|
||||||
use App\Entity\MenuItem;
|
|
||||||
use App\Form\MenuItemType;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
|
||||||
|
|
||||||
#[Route('/menu/item')]
|
|
||||||
final class MenuItemController extends AbstractController
|
|
||||||
{
|
|
||||||
#[Route('/{id}', name: 'app_menu_item_show', methods: ['GET'])]
|
|
||||||
public function show(MenuItem $menuItem): Response
|
|
||||||
{
|
|
||||||
return $this->render('menu_item/show.html.twig', [
|
|
||||||
'menu_item' => $menuItem,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/{id}/edit', name: 'app_menu_item_edit', methods: ['GET', 'POST'])]
|
|
||||||
public function edit(Request $request, MenuItem $menuItem, EntityManagerInterface $entityManager): Response
|
|
||||||
{
|
|
||||||
$form = $this->createForm(MenuItemType::class, $menuItem);
|
|
||||||
$form->handleRequest($request);
|
|
||||||
|
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
|
||||||
$entityManager->flush();
|
|
||||||
|
|
||||||
return $this->redirectToRoute('app_menu_item_show', [
|
|
||||||
'id' => $menuItem->getId(),
|
|
||||||
], Response::HTTP_SEE_OTHER);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->render('menu_item/edit.html.twig', [
|
|
||||||
'menu_item' => $menuItem,
|
|
||||||
'form' => $form,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Route('/{id}', name: 'app_menu_item_delete', methods: ['POST'])]
|
|
||||||
public function delete(Request $request, MenuItem $menuItem, EntityManagerInterface $entityManager): Response
|
|
||||||
{
|
|
||||||
if ($this->isCsrfTokenValid('delete' . $menuItem->getId(), $request->getPayload()->getString('_token'))) {
|
|
||||||
$menuItem->delete();
|
|
||||||
$entityManager->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->redirectToRoute('app_food_vendor_show', [
|
|
||||||
'id' => $menuItem->getFoodVendor()
|
|
||||||
->getId(),
|
|
||||||
], Response::HTTP_SEE_OTHER);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,10 +3,8 @@
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\FoodOrder;
|
use App\Entity\FoodOrder;
|
||||||
use App\Entity\MenuItem;
|
|
||||||
use App\Entity\OrderItem;
|
use App\Entity\OrderItem;
|
||||||
use App\Form\OrderItemType;
|
use App\Form\OrderItemType;
|
||||||
use App\Repository\MenuItemRepository;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
@ -17,35 +15,18 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||||
final class OrderItemController extends AbstractController
|
final class OrderItemController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/new/{foodOrder}', name: 'app_order_item_new', methods: ['GET', 'POST'])]
|
#[Route('/new/{foodOrder}', name: 'app_order_item_new', methods: ['GET', 'POST'])]
|
||||||
public function new(Request $request, FoodOrder $foodOrder, EntityManagerInterface $entityManager, MenuItemRepository $menuItemRepository): Response
|
public function new(Request $request, FoodOrder $foodOrder, EntityManagerInterface $entityManager): Response
|
||||||
{
|
{
|
||||||
if ($foodOrder->isClosed()) {
|
if ($foodOrder->isClosed()) {
|
||||||
return $this->redirectToRoute('app_food_order_show', [
|
return $this->redirectToRoute('app_food_order_show', [
|
||||||
'id' => $foodOrder->getId(),
|
'id' => $foodOrder->getId(),
|
||||||
], Response::HTTP_SEE_OTHER);
|
], Response::HTTP_SEE_OTHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
$orderItem = new OrderItem;
|
$orderItem = new OrderItem;
|
||||||
$username = $request->cookies->get('username', 'nobody');
|
|
||||||
$orderItem->setCreatedBy($username);
|
|
||||||
|
|
||||||
$form = $this->createForm(OrderItemType::class, $orderItem);
|
$form = $this->createForm(OrderItemType::class, $orderItem);
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
$menuItem = $menuItemRepository->findOneBy([
|
|
||||||
'name' => $orderItem->getName(),
|
|
||||||
'foodVendor' => $foodOrder->getFoodVendor(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($menuItem === null) {
|
|
||||||
$menuItem = new MenuItem;
|
|
||||||
$menuItem->setName($orderItem->getName());
|
|
||||||
$menuItem->setFoodVendor($foodOrder->getFoodVendor());
|
|
||||||
$entityManager->persist($menuItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
$orderItem->setMenuItem($menuItem);
|
|
||||||
$orderItem->setFoodOrder($foodOrder);
|
$orderItem->setFoodOrder($foodOrder);
|
||||||
$entityManager->persist($orderItem);
|
$entityManager->persist($orderItem);
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
|
@ -54,16 +35,11 @@ final class OrderItemController extends AbstractController
|
||||||
'id' => $foodOrder->getId(),
|
'id' => $foodOrder->getId(),
|
||||||
], Response::HTTP_SEE_OTHER);
|
], Response::HTTP_SEE_OTHER);
|
||||||
}
|
}
|
||||||
$menuItems = $menuItemRepository->findBy([
|
|
||||||
'foodVendor' => $foodOrder->getFoodVendor(),
|
|
||||||
'deletedAt' => null,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $this->render('order_item/new.html.twig', [
|
return $this->render('order_item/new.html.twig', [
|
||||||
'order_item' => $orderItem,
|
'order_item' => $orderItem,
|
||||||
'food_order' => $foodOrder,
|
'food_order' => $foodOrder,
|
||||||
'form' => $form,
|
'form' => $form,
|
||||||
'menuItems' => $menuItems,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +56,6 @@ final class OrderItemController extends AbstractController
|
||||||
$newOrderItem->setFoodOrder($orderItem->getFoodOrder());
|
$newOrderItem->setFoodOrder($orderItem->getFoodOrder());
|
||||||
$newOrderItem->setName($orderItem->getName());
|
$newOrderItem->setName($orderItem->getName());
|
||||||
$newOrderItem->setExtras($orderItem->getExtras());
|
$newOrderItem->setExtras($orderItem->getExtras());
|
||||||
$newOrderItem->setMenuItem($orderItem->getMenuItem());
|
|
||||||
|
|
||||||
$entityManager->persist($newOrderItem);
|
$entityManager->persist($newOrderItem);
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
|
@ -91,39 +66,18 @@ final class OrderItemController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/{id}/edit', name: 'app_order_item_edit', methods: ['GET', 'POST'])]
|
#[Route('/{id}/edit', name: 'app_order_item_edit', methods: ['GET', 'POST'])]
|
||||||
public function edit(
|
public function edit(Request $request, OrderItem $orderItem, EntityManagerInterface $entityManager): Response
|
||||||
Request $request,
|
{
|
||||||
OrderItem $orderItem,
|
|
||||||
EntityManagerInterface $entityManager,
|
|
||||||
MenuItemRepository $menuItemRepository,
|
|
||||||
): Response {
|
|
||||||
$foodOrder = $orderItem->getFoodOrder();
|
$foodOrder = $orderItem->getFoodOrder();
|
||||||
if ($foodOrder->isClosed()) {
|
if ($foodOrder->isClosed()) {
|
||||||
return $this->redirectToRoute('app_food_order_show', [
|
return $this->redirectToRoute('app_food_order_show', [
|
||||||
'id' => $foodOrder->getId(),
|
'id' => $foodOrder->getId(),
|
||||||
], Response::HTTP_SEE_OTHER);
|
], Response::HTTP_SEE_OTHER);
|
||||||
}
|
}
|
||||||
$orderItem->setName($orderItem->getMenuItem()->getName());
|
|
||||||
$form = $this->createForm(OrderItemType::class, $orderItem);
|
$form = $this->createForm(OrderItemType::class, $orderItem);
|
||||||
$form->setData($orderItem);
|
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
|
||||||
if ($form->isSubmitted() && $form->isValid()) {
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
$menuItem = $menuItemRepository->findOneBy([
|
|
||||||
'name' => $orderItem->getName(),
|
|
||||||
'foodVendor' => $foodOrder->getFoodVendor(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($menuItem === null) {
|
|
||||||
$menuItem = new MenuItem;
|
|
||||||
$menuItem->setName($orderItem->getName());
|
|
||||||
$menuItem->setFoodVendor($foodOrder->getFoodVendor());
|
|
||||||
$entityManager->persist($menuItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
$orderItem->setMenuItem($menuItem);
|
|
||||||
$orderItem->setFoodOrder($foodOrder);
|
|
||||||
$entityManager->persist($orderItem);
|
|
||||||
$entityManager->flush();
|
$entityManager->flush();
|
||||||
|
|
||||||
return $this->redirectToRoute('app_food_order_show', [
|
return $this->redirectToRoute('app_food_order_show', [
|
||||||
|
|
|
@ -3,19 +3,23 @@
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
use App\Repository\FoodOrderRepository;
|
use App\Repository\FoodOrderRepository;
|
||||||
use DateInterval;
|
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
|
||||||
use Symfony\Bridge\Doctrine\Types\UlidType;
|
use Symfony\Bridge\Doctrine\Types\UlidType;
|
||||||
use Symfony\Component\Uid\Ulid;
|
use Symfony\Component\Uid\Ulid;
|
||||||
|
|
||||||
use function iterator_to_array;
|
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: FoodOrderRepository::class)]
|
#[ORM\Entity(repositoryClass: FoodOrderRepository::class)]
|
||||||
class FoodOrder
|
class FoodOrder
|
||||||
{
|
{
|
||||||
|
#[ORM\Id]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Column(type: UlidType::NAME, unique: true)]
|
||||||
|
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
|
||||||
|
private Ulid|null $id = null;
|
||||||
|
|
||||||
#[ORM\Column(nullable: true)]
|
#[ORM\Column(nullable: true)]
|
||||||
private DateTimeImmutable|null $closedAt = null;
|
private DateTimeImmutable|null $closedAt = null;
|
||||||
|
|
||||||
|
@ -29,18 +33,9 @@ class FoodOrder
|
||||||
#[ORM\OneToMany(targetEntity: OrderItem::class, mappedBy: 'foodOrder', orphanRemoval: true)]
|
#[ORM\OneToMany(targetEntity: OrderItem::class, mappedBy: 'foodOrder', orphanRemoval: true)]
|
||||||
private Collection $orderItems;
|
private Collection $orderItems;
|
||||||
|
|
||||||
#[ORM\Column(length: 255, options: [
|
public function __construct()
|
||||||
'default' => 'nobody',
|
{
|
||||||
])]
|
|
||||||
private string|null $createdBy = 'nobody';
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\Column(type: UlidType::NAME, unique: true)]
|
|
||||||
private Ulid|null $id = new Ulid
|
|
||||||
) {
|
|
||||||
$this->orderItems = new ArrayCollection;
|
$this->orderItems = new ArrayCollection;
|
||||||
$this->open();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): Ulid|null
|
public function getId(): Ulid|null
|
||||||
|
@ -58,7 +53,7 @@ class FoodOrder
|
||||||
return $this->closedAt;
|
return $this->closedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setClosedAt(DateTimeImmutable|null $closedAt = null): static
|
public function setClosedAt(DateTimeImmutable|null $closedAt): static
|
||||||
{
|
{
|
||||||
$this->closedAt = $closedAt;
|
$this->closedAt = $closedAt;
|
||||||
|
|
||||||
|
@ -67,10 +62,7 @@ class FoodOrder
|
||||||
|
|
||||||
public function isClosed(): bool
|
public function isClosed(): bool
|
||||||
{
|
{
|
||||||
if (! $this->closedAt instanceof DateTimeImmutable) {
|
return $this->closedAt instanceof DateTimeImmutable;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $this->closedAt < new DateTimeImmutable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function close(): static
|
public function close(): static
|
||||||
|
@ -80,8 +72,7 @@ class FoodOrder
|
||||||
|
|
||||||
public function open(): static
|
public function open(): static
|
||||||
{
|
{
|
||||||
$this->closedAt = (new DateTimeImmutable)->add(new DateInterval('PT1H'));
|
return $this->setClosedAt(null);
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFoodVendor(): FoodVendor|null
|
public function getFoodVendor(): FoodVendor|null
|
||||||
|
@ -104,23 +95,6 @@ class FoodOrder
|
||||||
return $this->orderItems;
|
return $this->orderItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection<int, OrderItem>
|
|
||||||
*/
|
|
||||||
public function getOrderItemsSortedByName(): Collection
|
|
||||||
{
|
|
||||||
$iterator = $this->getOrderItems()
|
|
||||||
->getIterator();
|
|
||||||
$iterator->uasort(
|
|
||||||
static fn(OrderItem $a, OrderItem $b): int => $a->getName() <=> $b->getName()
|
|
||||||
);
|
|
||||||
return new ArrayCollection(
|
|
||||||
iterator_to_array(
|
|
||||||
$iterator
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addOrderItem(OrderItem $orderItem): static
|
public function addOrderItem(OrderItem $orderItem): static
|
||||||
{
|
{
|
||||||
if (! $this->orderItems->contains($orderItem)) {
|
if (! $this->orderItems->contains($orderItem)) {
|
||||||
|
@ -134,22 +108,10 @@ class FoodOrder
|
||||||
public function removeOrderItem(OrderItem $orderItem): static
|
public function removeOrderItem(OrderItem $orderItem): static
|
||||||
{
|
{
|
||||||
// set the owning side to null (unless already changed)
|
// set the owning side to null (unless already changed)
|
||||||
if ($this->orderItems->removeElement($orderItem)) {
|
if ($this->orderItems->removeElement($orderItem) && $orderItem->getFoodOrder() === $this) {
|
||||||
$orderItem->setFoodOrder(null);
|
$orderItem->setFoodOrder(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCreatedBy(): string|null
|
|
||||||
{
|
|
||||||
return $this->createdBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCreatedBy(string $createdBy): static
|
|
||||||
{
|
|
||||||
$this->createdBy = $createdBy;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,12 @@ use Symfony\Component\Uid\Ulid;
|
||||||
#[ORM\Entity(repositoryClass: FoodVendorRepository::class)]
|
#[ORM\Entity(repositoryClass: FoodVendorRepository::class)]
|
||||||
class FoodVendor
|
class FoodVendor
|
||||||
{
|
{
|
||||||
|
#[ORM\Id]
|
||||||
|
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||||
|
#[ORM\Column(type: UlidType::NAME, unique: true)]
|
||||||
|
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
|
||||||
|
private Ulid|null $id = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 50)]
|
#[ORM\Column(length: 50)]
|
||||||
private string|null $name = null;
|
private string|null $name = null;
|
||||||
|
|
||||||
|
@ -22,24 +28,9 @@ class FoodVendor
|
||||||
#[ORM\OneToMany(targetEntity: FoodOrder::class, mappedBy: 'foodVendor', orphanRemoval: true)]
|
#[ORM\OneToMany(targetEntity: FoodOrder::class, mappedBy: 'foodVendor', orphanRemoval: true)]
|
||||||
private Collection $foodOrders;
|
private Collection $foodOrders;
|
||||||
|
|
||||||
/**
|
public function __construct()
|
||||||
* @var Collection<int, MenuItem>
|
{
|
||||||
*/
|
|
||||||
#[ORM\OneToMany(targetEntity: MenuItem::class, mappedBy: 'foodVendor', orphanRemoval: true)]
|
|
||||||
private Collection $menuItems;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
|
||||||
private string|null $menuLink = null;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\Column(type: UlidType::NAME, unique: true)]
|
|
||||||
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
|
|
||||||
private Ulid|null $id = new Ulid
|
|
||||||
) {
|
|
||||||
$this->foodOrders = new ArrayCollection;
|
$this->foodOrders = new ArrayCollection;
|
||||||
$this->menuItems = new ArrayCollection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): Ulid|null
|
public function getId(): Ulid|null
|
||||||
|
@ -80,55 +71,10 @@ class FoodVendor
|
||||||
public function removeFoodOrder(FoodOrder $foodOrder): static
|
public function removeFoodOrder(FoodOrder $foodOrder): static
|
||||||
{
|
{
|
||||||
// set the owning side to null (unless already changed)
|
// set the owning side to null (unless already changed)
|
||||||
if ($this->foodOrders->removeElement($foodOrder)) {
|
if ($this->foodOrders->removeElement($foodOrder) && $foodOrder->getFoodVendor() === $this) {
|
||||||
$foodOrder->setFoodVendor(null);
|
$foodOrder->setFoodVendor(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection<int, MenuItem>
|
|
||||||
*/
|
|
||||||
public function getMenuItems(bool $withDeleted = false): Collection
|
|
||||||
{
|
|
||||||
if ($withDeleted) {
|
|
||||||
return $this->menuItems;
|
|
||||||
}
|
|
||||||
return $this->menuItems->filter(
|
|
||||||
static fn(MenuItem $item): bool => $item->isDeleted() === false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addMenuItem(MenuItem $menuItem): static
|
|
||||||
{
|
|
||||||
if (! $this->menuItems->contains($menuItem)) {
|
|
||||||
$this->menuItems->add($menuItem);
|
|
||||||
$menuItem->setFoodVendor($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function removeMenuItem(MenuItem $menuItem): static
|
|
||||||
{
|
|
||||||
// set the owning side to null (unless already changed)
|
|
||||||
if ($this->menuItems->removeElement($menuItem)) {
|
|
||||||
$menuItem->setFoodVendor(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMenuLink(): string|null
|
|
||||||
{
|
|
||||||
return $this->menuLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setMenuLink(string|null $menuLink): static
|
|
||||||
{
|
|
||||||
$this->menuLink = $menuLink;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Entity;
|
|
||||||
|
|
||||||
use App\Repository\MenuItemRepository;
|
|
||||||
use DateTimeImmutable;
|
|
||||||
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\Column(length: 255)]
|
|
||||||
private string|null $name = null;
|
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'menuItems')]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
|
||||||
private FoodVendor|null $foodVendor = null;
|
|
||||||
|
|
||||||
#[ORM\Column(nullable: true)]
|
|
||||||
private DateTimeImmutable|null $deletedAt = null;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
|
||||||
#[ORM\Column(type: UlidType::NAME, unique: true)]
|
|
||||||
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
|
|
||||||
private Ulid|null $id = new Ulid
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public function getId(): Ulid|null
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName(): string|null
|
|
||||||
{
|
|
||||||
return $this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setName(string $name): static
|
|
||||||
{
|
|
||||||
$this->name = $name;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFoodVendor(): FoodVendor|null
|
|
||||||
{
|
|
||||||
return $this->foodVendor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setFoodVendor(FoodVendor|null $foodVendor): static
|
|
||||||
{
|
|
||||||
$this->foodVendor = $foodVendor;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isDeleted(): bool
|
|
||||||
{
|
|
||||||
return $this->getDeletedAt() instanceof DateTimeImmutable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function delete(): static
|
|
||||||
{
|
|
||||||
$this->setDeletedAt(new DateTimeImmutable);
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDeletedAt(): DateTimeImmutable|null
|
|
||||||
{
|
|
||||||
return $this->deletedAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setDeletedAt(DateTimeImmutable|null $deletedAt = new DateTimeImmutable): static
|
|
||||||
{
|
|
||||||
$this->deletedAt = $deletedAt;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,17 +24,8 @@ class OrderItem
|
||||||
private string|null $extras = null;
|
private string|null $extras = null;
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'orderItems')]
|
#[ORM\ManyToOne(inversedBy: 'orderItems')]
|
||||||
#[ORM\JoinColumn(nullable: true)]
|
|
||||||
private FoodOrder|null $foodOrder = null;
|
|
||||||
|
|
||||||
#[ORM\ManyToOne]
|
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
private MenuItem|null $menuItem = null;
|
private FoodOrder|null $foodOrder = null;
|
||||||
|
|
||||||
#[ORM\Column(length: 255, options: [
|
|
||||||
'default' => 'nobody',
|
|
||||||
])]
|
|
||||||
private string|null $createdBy = 'nobody';
|
|
||||||
|
|
||||||
public function getId(): Ulid|null
|
public function getId(): Ulid|null
|
||||||
{
|
{
|
||||||
|
@ -76,28 +67,4 @@ class OrderItem
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMenuItem(): MenuItem|null
|
|
||||||
{
|
|
||||||
return $this->menuItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setMenuItem(MenuItem|null $menuItem): static
|
|
||||||
{
|
|
||||||
$this->menuItem = $menuItem;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCreatedBy(): string|null
|
|
||||||
{
|
|
||||||
return $this->createdBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCreatedBy(string $createdBy): static
|
|
||||||
{
|
|
||||||
$this->createdBy = $createdBy;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
|
|
||||||
namespace App\Form;
|
namespace App\Form;
|
||||||
|
|
||||||
|
use App\Entity\FoodOrder;
|
||||||
use App\Entity\FoodVendor;
|
use App\Entity\FoodVendor;
|
||||||
use Override;
|
use Override;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
final class FoodOrderType extends AbstractType
|
final class FoodOrderType extends AbstractType
|
||||||
{
|
{
|
||||||
|
@ -19,14 +21,17 @@ final class FoodOrderType extends AbstractType
|
||||||
'class' => FoodVendor::class,
|
'class' => FoodVendor::class,
|
||||||
'choice_label' => 'name',
|
'choice_label' => 'name',
|
||||||
])
|
])
|
||||||
->add(child: 'closedAt', options: [
|
|
||||||
'label' => 'closes at',
|
|
||||||
'view_timezone' => 'Europe/Berlin',
|
|
||||||
])
|
|
||||||
->add(child: 'createdBy')
|
|
||||||
;
|
;
|
||||||
if ($action !== null) {
|
if ($action !== null) {
|
||||||
$builder->setAction($action);
|
$builder->setAction($action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Override]
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => FoodOrder::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ final class FoodVendorType extends AbstractType
|
||||||
{
|
{
|
||||||
$builder
|
$builder
|
||||||
->add('name')
|
->add('name')
|
||||||
->add('menuLink')
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +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\FormBuilderInterface;
|
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
||||||
|
|
||||||
final class MenuItemType 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' => MenuItem::class,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,13 +14,8 @@ final class OrderItemType extends AbstractType
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
{
|
{
|
||||||
$builder
|
$builder
|
||||||
->add(child: 'name', options: [
|
->add('name')
|
||||||
'label' => 'order item',
|
->add('extras')
|
||||||
])
|
|
||||||
->add(child: 'extras')
|
|
||||||
->add(child: 'createdBy', options: [
|
|
||||||
'label' => 'your name',
|
|
||||||
])
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Form;
|
|
||||||
|
|
||||||
use Override;
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
|
||||||
|
|
||||||
final class UserNameFormType extends AbstractType
|
|
||||||
{
|
|
||||||
#[Override]
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
|
||||||
{
|
|
||||||
$builder
|
|
||||||
->add(child: 'username')
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,10 +3,7 @@
|
||||||
namespace App\Repository;
|
namespace App\Repository;
|
||||||
|
|
||||||
use App\Entity\FoodOrder;
|
use App\Entity\FoodOrder;
|
||||||
use DateInterval;
|
|
||||||
use DateTimeImmutable;
|
|
||||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,8 +16,10 @@ final class FoodOrderRepository extends ServiceEntityRepository
|
||||||
parent::__construct($registry, FoodOrder::class);
|
parent::__construct($registry, FoodOrder::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save(): void
|
public function save(FoodOrder $order): void
|
||||||
{
|
{
|
||||||
|
$this->getEntityManager()
|
||||||
|
->persist($order);
|
||||||
$this->getEntityManager()
|
$this->getEntityManager()
|
||||||
->flush();
|
->flush();
|
||||||
}
|
}
|
||||||
|
@ -28,23 +27,15 @@ final class FoodOrderRepository extends ServiceEntityRepository
|
||||||
/**
|
/**
|
||||||
* @return FoodOrder[]
|
* @return FoodOrder[]
|
||||||
*/
|
*/
|
||||||
public function findLatestEntries(int $page = 1, int $pagesize = 10, int $days = 4): array
|
public function findLatestEntries(int $limit = 10): array
|
||||||
{
|
{
|
||||||
|
$qb = $this->createQueryBuilder('alias');
|
||||||
|
|
||||||
$result = $this->createQueryBuilder('alias')
|
$qb->orderBy('alias.id', 'DESC');
|
||||||
->orderBy('alias.id', 'DESC')
|
$qb->setMaxResults($limit);
|
||||||
->setFirstResult(($page - 1) * $pagesize)
|
|
||||||
->setMaxResults($pagesize)
|
|
||||||
->getQuery()
|
|
||||||
->getResult();
|
|
||||||
|
|
||||||
if ($days < 1) {
|
$query = $qb->getQuery();
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
$date = (new DateTimeImmutable)->sub(new DateInterval('P' . $days . 'D'));
|
return $query->getResult();
|
||||||
return (new ArrayCollection($result))
|
|
||||||
->filter(static fn(FoodOrder $order): bool => $order->getCreatedAt() >= $date)
|
|
||||||
->getValues();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +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>
|
|
||||||
*/
|
|
||||||
final 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()
|
|
||||||
// ;
|
|
||||||
// }
|
|
||||||
}
|
|
100
src/Service/FakeData.php
Normal file
100
src/Service/FakeData.php
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use App\Entity\FoodOrder;
|
||||||
|
use App\Entity\FoodVendor;
|
||||||
|
use App\Entity\OrderItem;
|
||||||
|
use App\Repository\FoodOrderRepository;
|
||||||
|
use App\Repository\FoodVendorRepository;
|
||||||
|
use App\Repository\OrderItemRepository;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
|
use function range;
|
||||||
|
|
||||||
|
final readonly class FakeData
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private EntityManagerInterface $entityManager,
|
||||||
|
private FoodVendorRepository $foodVendorRepository,
|
||||||
|
private FoodOrderRepository $foodOrderRepository,
|
||||||
|
private OrderItemRepository $orderItemRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function resetDb(): void
|
||||||
|
{
|
||||||
|
foreach ($this->orderItemRepository->findAll() as $item) {
|
||||||
|
$this->entityManager->remove($item);
|
||||||
|
}
|
||||||
|
foreach ($this->foodOrderRepository->findAll() as $item) {
|
||||||
|
$this->entityManager->remove($item);
|
||||||
|
}
|
||||||
|
foreach ($this->foodVendorRepository->findAll() as $item) {
|
||||||
|
$this->entityManager->remove($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generate(int $vendorAmount = 3, int $orderAmount = 4, int $itemAmount = 10): void
|
||||||
|
{
|
||||||
|
$vendors = $this->generateVendors($vendorAmount);
|
||||||
|
foreach ($vendors as $vendor) {
|
||||||
|
$orders = $this->generateOrdersForVendor($vendor, $orderAmount);
|
||||||
|
foreach ($orders as $order) {
|
||||||
|
$this->generateItemsForOrder($order, $itemAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->entityManager->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return FoodVendor[]
|
||||||
|
*/
|
||||||
|
public function generateVendors(int $amount = 10): array
|
||||||
|
{
|
||||||
|
$vendors = [];
|
||||||
|
foreach (range(1, $amount) as $i) {
|
||||||
|
$vendor = new FoodVendor;
|
||||||
|
$vendor->setName('Food Vendor ' . $i);
|
||||||
|
$this->entityManager->persist($vendor);
|
||||||
|
$vendors[] = $vendor;
|
||||||
|
}
|
||||||
|
return $vendors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return FoodOrder[]
|
||||||
|
*/
|
||||||
|
public function generateOrdersForVendor(FoodVendor $vendor, int $amount = 10): array
|
||||||
|
{
|
||||||
|
$orders = [];
|
||||||
|
foreach (range(1, $amount) as $i) {
|
||||||
|
$order = new FoodOrder;
|
||||||
|
$order->setFoodVendor($vendor);
|
||||||
|
if ($i % 2 === 0) {
|
||||||
|
$order->close();
|
||||||
|
}
|
||||||
|
$this->entityManager->persist($order);
|
||||||
|
$orders[] = $order;
|
||||||
|
}
|
||||||
|
return $orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return OrderItem[]
|
||||||
|
*/
|
||||||
|
public function generateItemsForOrder(FoodOrder $order, int $amount = 10): array
|
||||||
|
{
|
||||||
|
$items = [];
|
||||||
|
foreach (range(1, $amount) as $i) {
|
||||||
|
$item = new OrderItem;
|
||||||
|
$item->setName('Item ' . $i);
|
||||||
|
$item->setFoodOrder($order);
|
||||||
|
if ($i % 2 === 0) {
|
||||||
|
$item->setExtras('Extra ' . $i);
|
||||||
|
}
|
||||||
|
$this->entityManager->persist($item);
|
||||||
|
$items[] = $item;
|
||||||
|
}
|
||||||
|
return $items;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Service;
|
|
||||||
|
|
||||||
use Override;
|
|
||||||
use Stringable;
|
|
||||||
|
|
||||||
use function random_int;
|
|
||||||
|
|
||||||
final class Favicon implements Stringable
|
|
||||||
{
|
|
||||||
#[Override]
|
|
||||||
public function __toString(): string
|
|
||||||
{
|
|
||||||
$rotate = random_int(0, 380);
|
|
||||||
return "data:image/svg+xml, %3Csvg enable-background='new 0 0 512 512' viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg' %3E%3Cg transform='rotate({$rotate}, 256, 256)' %3E%3Cpath d='m51.6 72.608 199.566-34.825 213.114 34.825c19.867 0 32.553 21.19 23.171 38.701l-206.224 384.92c-9.908 18.492-36.421 18.499-46.337.011l-206.455-384.92c-9.393-17.512 3.293-38.712 23.165-38.712z' fill='%23fecb21'/%3E%3Cpath d='m270.254 307.902c0 28.665-23.238 51.902-51.902 51.902s-51.902-23.237-51.902-51.902 23.237-51.902 51.902-51.902 51.902 23.237 51.902 51.902zm65.862 81.954c-25.323-13.433-56.74-3.794-70.173 21.528-13.433 25.323-3.794 56.74 21.528 70.173m48.645-342.08c-28.665 0-51.902 23.237-51.902 51.902s23.237 51.902 51.902 51.902 51.902-23.237 51.902-51.902-23.237-51.902-51.902-51.902zm-182.102-33.763c-28.665 0-51.902 23.237-51.902 51.902s23.237 51.902 51.902 51.902 51.902-23.237 51.902-51.902-23.237-51.902-51.902-51.902z' fill='%23f43b22'/%3E%3Cpath d='m41.204 130.519c-13.328.001-26.256-7.039-33.184-19.518-10.167-18.308-3.566-41.391 14.743-51.557 34.605-19.215 72.08-34.048 111.383-44.088 39.334-10.047 80.138-15.214 121.279-15.356 40.982-.14 81.845 4.711 121.369 14.423 40.306 9.904 78.8 24.757 114.412 44.147 18.393 10.014 25.184 33.041 15.17 51.433-10.014 18.391-33.043 25.185-51.433 15.169-29.887-16.273-62.269-28.757-96.246-37.105-33.046-8.12-67.199-12.236-101.53-12.236-.496 0-.986.001-1.481.002-34.903.121-69.481 4.494-102.772 12.998-33.009 8.432-64.412 20.851-93.338 36.912-5.829 3.239-12.145 4.776-18.372 4.776z' fill='%23c4790c'/%3E%3C/g%3E%3C/svg%3E%0A";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,38 +3,24 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||||
<link rel="icon" type="image/svg+xml"
|
<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>">
|
||||||
href="{{ favicon }}" />
|
<link rel="stylesheet" href="/static/css/simple.min.css">
|
||||||
{% set currentDate = "now"|date("d") %}
|
|
||||||
{% if currentDate % 3 == 0 %}
|
|
||||||
<link rel="stylesheet" href="/static/css/new.min.css">
|
|
||||||
{% elseif currentDate % 3 == 1 %}
|
|
||||||
<link rel="stylesheet" href="/static/css/simple.min.css">
|
|
||||||
{% else %}
|
|
||||||
<link rel="stylesheet" href="/static/css/water.min.css">
|
|
||||||
{% endif %}
|
|
||||||
<style>
|
|
||||||
label{
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script src="/static/js/htmx.min.js"></script>
|
<script src="/static/js/htmx.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<p>Hello {{ app.request.cookies.get('username', 'nobody') }} - <a href="{{ path('username') }}">change name</a></p>
|
<nav>
|
||||||
<nav>
|
<a href="{{ path('app_food_order_index') }}">Orders</a>
|
||||||
<a href="{{ path('app_food_order_index') }}">Orders</a> /
|
<a href="{{ path('app_food_vendor_index') }}">Vendors</a>
|
||||||
<a href="{{ path('app_food_vendor_index') }}">Vendors</a> /
|
<a
|
||||||
<a
|
href="https://hannover.ccc.de/gitlab/lubiana/futtern/issues/new"
|
||||||
href="https://git.hannover.ccc.de/lubiana/futtern/issues/new"
|
target="_blank"
|
||||||
target="_blank"
|
>Create Issue</a>
|
||||||
>Create Issue</a>
|
</nav>
|
||||||
</nav>
|
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
{% block body %}{% endblock %}
|
{% block body %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,10 @@
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<h1>FoodOrder index</h1>
|
<h1>FoodOrder index</h1>
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
hx-get="{{ path('app_food_order_new') }}"
|
|
||||||
hx-trigger="click"
|
|
||||||
hx-target="closest div"
|
|
||||||
>Create new</button>
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>CreatedBy</th>
|
|
||||||
<th>Vendor</th>
|
<th>Vendor</th>
|
||||||
<th>CreatedAt</th>
|
<th>CreatedAt</th>
|
||||||
<th>ClosedAt</th>
|
<th>ClosedAt</th>
|
||||||
|
@ -25,21 +17,18 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for food_order in food_orders %}
|
{% for food_order in food_orders %}
|
||||||
{{ include('food_order/table_row.html.twig') }}
|
{{ include('food_order/table_row.html.twig') }}
|
||||||
{% endfor %}
|
{% else %}
|
||||||
{% if food_orders|length < 10 %}
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="5">
|
<td colspan="4">no records found</td>
|
||||||
check the <a href="{{ path('app_food_order_archive') }}">archive</a>
|
|
||||||
for older orders
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% if prev_page > 0 %}
|
<div>
|
||||||
<a href="{{ path('app_food_order_archive', {'page': prev_page}) }}">previous page</a> |
|
<button
|
||||||
{% endif %}
|
hx-get="{{ path('app_food_order_new') }}"
|
||||||
{% if next_page > current_page %}
|
hx-trigger="click"
|
||||||
<a href="{{ path('app_food_order_archive', {'page': next_page}) }}">next page</a>
|
hx-target="closest div"
|
||||||
{% endif %}
|
>Create new</button>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -11,17 +11,13 @@
|
||||||
<th>Vendor</th>
|
<th>Vendor</th>
|
||||||
<td>{{ food_order.foodVendor.name }}</td>
|
<td>{{ food_order.foodVendor.name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th>Created By</th>
|
|
||||||
<td>{{ food_order.createdBy }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>CreatedAt</th>
|
<th>CreatedAt</th>
|
||||||
<td>{{ food_order.createdAt ? food_order.createdAt|date('Y-m-d H:i:s', 'Europe/Berlin') : '' }}</td>
|
<td>{{ food_order.createdAt ? food_order.createdAt|date('Y-m-d H:i:s') : '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ClosedAt</th>
|
<th>ClosedAt</th>
|
||||||
<td>{{ food_order.closedAt ? food_order.closedAt|date('Y-m-d H:i:s', 'Europe/Berlin') : '' }}</td>
|
<td>{{ food_order.closedAt ? food_order.closedAt|date('Y-m-d H:i:s') : '' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -36,16 +32,14 @@
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>username</th>
|
|
||||||
<th>name</th>
|
<th>name</th>
|
||||||
<th>extras</th>
|
<th>extras</th>
|
||||||
<th>actions</th>
|
<th>actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in food_order.orderItemsSortedByName %}
|
{% for item in food_order.orderItems %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ item.createdBy }}</td>
|
|
||||||
<td>{{ item.name }}</td>
|
<td>{{ item.name }}</td>
|
||||||
<td>{{ item.extras }}</td>
|
<td>{{ item.extras }}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ food_order.createdBy }}</td>
|
|
||||||
<td>{{ food_order.foodVendor.name }}</td>
|
<td>{{ food_order.foodVendor.name }}</td>
|
||||||
<td>{{ food_order.createdAt ? food_order.createdAt|date('Y-m-d H:i:s', 'Europe/Berlin') : '' }}</td>
|
<td>{{ food_order.createdAt ? food_order.createdAt|date('Y-m-d H:i:s') : '' }}</td>
|
||||||
<td>{{ food_order.closedAt ? food_order.closedAt|date('Y-m-d H:i:s', 'Europe/Berlin') : '' }}</td>
|
<td>{{ food_order.closedAt ? food_order.closedAt|date('Y-m-d H:i:s') : '' }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ path('app_food_order_show', {'id': food_order.id}) }}">show</a>
|
<a href="{{ path('app_food_order_show', {'id': food_order.id}) }}">show</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>actions</th>
|
<th>actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for food_vendor in food_vendors %}
|
{% for food_vendor in food_vendors %}
|
||||||
<tr>
|
<tr>
|
||||||
|
<td>{{ food_vendor.id }}</td>
|
||||||
<td>{{ food_vendor.name }}</td>
|
<td>{{ food_vendor.name }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ path('app_food_vendor_show', {'id': food_vendor.id}) }}">show</a>
|
<a href="{{ path('app_food_vendor_show', {'id': food_vendor.id}) }}">show</a>
|
||||||
|
|
|
@ -7,30 +7,17 @@
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<td>{{ food_vendor.id }}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<td>{{ food_vendor.name }}</td>
|
<td>{{ food_vendor.name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th>Menu</th>
|
|
||||||
<td><a href="{{ food_vendor.menuLink }}" target="_blank">{{ food_vendor.menuLink }}</a></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<section>
|
|
||||||
<h2>known menuitems</h2>
|
|
||||||
<ul>
|
|
||||||
{% for item in food_vendor.menuItems %}
|
|
||||||
<li>
|
|
||||||
<a href="{{ path('app_menu_item_show', {'id': item.id}) }}">{{ item.name }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<a href="{{ path('app_food_vendor_index') }}">back to list</a>
|
<a href="{{ path('app_food_vendor_index') }}">back to list</a>
|
||||||
|
|
||||||
<a href="{{ path('app_food_vendor_edit', {'id': food_vendor.id}) }}">edit</a>
|
<a href="{{ path('app_food_vendor_edit', {'id': food_vendor.id}) }}">edit</a>
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<form method="post" action="{{ path('app_menu_item_delete', {'id': menu_item.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
|
|
||||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ menu_item.id) }}">
|
|
||||||
<button class="btn">Delete</button>
|
|
||||||
</form>
|
|
|
@ -1,4 +0,0 @@
|
||||||
{{ form_start(form) }}
|
|
||||||
{{ form_widget(form) }}
|
|
||||||
<button class="btn">{{ button_label|default('Save') }}</button>
|
|
||||||
{{ form_end(form) }}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}Edit MenuItem{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>Edit MenuItem</h1>
|
|
||||||
|
|
||||||
{{ include('menu_item/_form.html.twig', {'button_label': 'Update'}) }}
|
|
||||||
|
|
||||||
{{ include('menu_item/_delete_form.html.twig') }}
|
|
||||||
{% endblock %}
|
|
|
@ -1,35 +0,0 @@
|
||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}MenuItem index{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>MenuItem index</h1>
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Id</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for menu_item in menu_items %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ menu_item.id }}</td>
|
|
||||||
<td>{{ menu_item.name }}</td>
|
|
||||||
<td>
|
|
||||||
<a href="{{ path('app_menu_item_show', {'id': menu_item.id}) }}">show</a>
|
|
||||||
<a href="{{ path('app_menu_item_edit', {'id': menu_item.id}) }}">edit</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% else %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="3">no records found</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<a href="{{ path('app_menu_item_new') }}">Create new</a>
|
|
||||||
{% endblock %}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}New MenuItem{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>Create new MenuItem</h1>
|
|
||||||
|
|
||||||
{{ include('menu_item/_form.html.twig') }}
|
|
||||||
|
|
||||||
<a href="{{ path('app_menu_item_index') }}">back to list</a>
|
|
||||||
{% endblock %}
|
|
|
@ -1,26 +0,0 @@
|
||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}MenuItem{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>MenuItem</h1>
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th>Id</th>
|
|
||||||
<td>{{ menu_item.id }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<td>{{ menu_item.name }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<a href="{{ path('app_food_vendor_show', { 'id': menu_item.foodVendor.id}) }}">back to list</a>
|
|
||||||
|
|
||||||
<a href="{{ path('app_menu_item_edit', {'id': menu_item.id}) }}">edit</a>
|
|
||||||
|
|
||||||
{{ include('menu_item/_delete_form.html.twig') }}
|
|
||||||
{% endblock %}
|
|
|
@ -7,33 +7,5 @@
|
||||||
|
|
||||||
{{ include('order_item/_form.html.twig') }}
|
{{ include('order_item/_form.html.twig') }}
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
{% if food_order.foodVendor.menuLink != '' %}
|
|
||||||
<a href="{{ food_order.foodVendor.menuLink }}" target="_blank">
|
|
||||||
External link to Menu
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<b>click a button to select a given menuitem</b>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{% for menuItem in menuItems %}
|
|
||||||
<a href="#" data-menu-item>{{ menuItem.name }}</a>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<a class="button" href="{{ path('app_food_order_show', { 'id': food_order.id}) }}">back to list</a>
|
<a class="button" href="{{ path('app_food_order_show', { 'id': food_order.id}) }}">back to list</a>
|
||||||
|
|
||||||
<script>
|
|
||||||
document.querySelectorAll('[data-menu-item]').forEach(function(element) {
|
|
||||||
element.addEventListener('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
document.getElementById('order_item_name').value = e.target.textContent
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
{% extends 'base.html.twig' %}
|
|
||||||
|
|
||||||
{% block title %}Tell me your name{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>Tell me your name</h1>
|
|
||||||
<p>By submitting the form, you agree that your username will be stored as a cookie.</p>
|
|
||||||
{{ include('_form.html.twig') }}
|
|
||||||
{% endblock %}
|
|
|
@ -4,13 +4,10 @@ namespace App\Tests\Controller;
|
||||||
|
|
||||||
use App\Entity\FoodOrder;
|
use App\Entity\FoodOrder;
|
||||||
use App\Entity\FoodVendor;
|
use App\Entity\FoodVendor;
|
||||||
use App\Entity\MenuItem;
|
|
||||||
use App\Entity\OrderItem;
|
|
||||||
use App\Tests\DbWebTest;
|
use App\Tests\DbWebTest;
|
||||||
use Override;
|
use Override;
|
||||||
use Symfony\Component\DomCrawler\Crawler;
|
use Symfony\Component\DomCrawler\Crawler;
|
||||||
|
|
||||||
use function range;
|
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
|
|
||||||
final class FoodOrderControllerTest extends DbWebTest
|
final class FoodOrderControllerTest extends DbWebTest
|
||||||
|
@ -44,7 +41,7 @@ final class FoodOrderControllerTest extends DbWebTest
|
||||||
$this->manager->persist($this->vendor);
|
$this->manager->persist($this->vendor);
|
||||||
$this->manager->flush();
|
$this->manager->flush();
|
||||||
|
|
||||||
$crawler = $this->client->request('GET', "{$this->path}list");
|
$crawler = $this->client->request('GET', $this->path);
|
||||||
self::assertResponseStatusCodeSame(200);
|
self::assertResponseStatusCodeSame(200);
|
||||||
self::assertPageTitleContains('FoodOrder index');
|
self::assertPageTitleContains('FoodOrder index');
|
||||||
$this->assertCount(
|
$this->assertCount(
|
||||||
|
@ -54,120 +51,6 @@ final class FoodOrderControllerTest extends DbWebTest
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOrderedItems(): void
|
|
||||||
{
|
|
||||||
$order = new FoodOrder;
|
|
||||||
$order->setFoodVendor($this->vendor);
|
|
||||||
|
|
||||||
$this->manager->persist($order);
|
|
||||||
$this->manager->persist($this->vendor);
|
|
||||||
|
|
||||||
$menuItemA = new MenuItem;
|
|
||||||
$menuItemA->setName('A');
|
|
||||||
$menuItemA->setFoodVendor($this->vendor);
|
|
||||||
|
|
||||||
$this->manager->persist($menuItemA);
|
|
||||||
$itemA = new OrderItem;
|
|
||||||
$itemA->setMenuItem($menuItemA);
|
|
||||||
$itemA->setName($menuItemA->getName());
|
|
||||||
|
|
||||||
$order->addOrderItem($itemA);
|
|
||||||
$this->manager->persist($itemA);
|
|
||||||
|
|
||||||
$menuItemC = new MenuItem;
|
|
||||||
$menuItemC->setName('C');
|
|
||||||
$menuItemC->setFoodVendor($this->vendor);
|
|
||||||
|
|
||||||
$this->manager->persist($menuItemC);
|
|
||||||
$itemC = new OrderItem;
|
|
||||||
$itemC->setMenuItem($menuItemC);
|
|
||||||
$itemC->setName($menuItemC->getName());
|
|
||||||
|
|
||||||
$order->addOrderItem($itemC);
|
|
||||||
$this->manager->persist($itemC);
|
|
||||||
|
|
||||||
$menuItemB = new MenuItem;
|
|
||||||
$menuItemB->setName('B');
|
|
||||||
$menuItemB->setFoodVendor($this->vendor);
|
|
||||||
|
|
||||||
$this->manager->persist($menuItemB);
|
|
||||||
$itemB = new OrderItem;
|
|
||||||
$itemB->setMenuItem($menuItemB);
|
|
||||||
$itemB->setName($menuItemB->getName());
|
|
||||||
|
|
||||||
$order->addOrderItem($itemB);
|
|
||||||
$this->manager->persist($itemB);
|
|
||||||
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$crawler = $this->client->request('GET', "{$this->path}{$order->getId()}");
|
|
||||||
self::assertResponseIsSuccessful();
|
|
||||||
$tdContent = $crawler->filter(
|
|
||||||
'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(1) > td:nth-child(2)'
|
|
||||||
)->text();
|
|
||||||
$this->assertEquals('A', $tdContent);
|
|
||||||
$tdContent = $crawler->filter(
|
|
||||||
'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(2) > td:nth-child(2)'
|
|
||||||
)->text();
|
|
||||||
$this->assertEquals('B', $tdContent);
|
|
||||||
$tdContent = $crawler->filter(
|
|
||||||
'table.table:nth-child(6) > tbody:nth-child(2) > tr:nth-child(3) > td:nth-child(2)'
|
|
||||||
)->text();
|
|
||||||
$this->assertEquals('C', $tdContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testPaginatedIndex(): void
|
|
||||||
{
|
|
||||||
$this->generatePaginatedOrders();
|
|
||||||
$crawler = $this->client->request('GET', "{$this->path}list");
|
|
||||||
self::assertResponseStatusCodeSame(200);
|
|
||||||
self::assertPageTitleContains('FoodOrder index');
|
|
||||||
$this->assertElementContainsCount(
|
|
||||||
$crawler,
|
|
||||||
'td',
|
|
||||||
1,
|
|
||||||
'older orders'
|
|
||||||
);
|
|
||||||
$this->assertElementContainsCount(
|
|
||||||
$crawler,
|
|
||||||
'td',
|
|
||||||
0,
|
|
||||||
'next page'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @testWith [1, 0, 1]
|
|
||||||
* [2, 1, 1]
|
|
||||||
* [3, 1, 1]
|
|
||||||
* [4, 1, 0, 5]
|
|
||||||
*/
|
|
||||||
public function testPaginatedFirstPage(int $page, int $prevPage, int $nextPage, int $items = 10): void
|
|
||||||
{
|
|
||||||
$this->generatePaginatedOrders();
|
|
||||||
$crawler = $this->client->request('GET', "{$this->path}list/archive/{$page}");
|
|
||||||
self::assertResponseStatusCodeSame(200);
|
|
||||||
self::assertPageTitleContains('FoodOrder index');
|
|
||||||
$this->assertElementContainsCount(
|
|
||||||
$crawler,
|
|
||||||
'td',
|
|
||||||
$items,
|
|
||||||
'nobody'
|
|
||||||
);
|
|
||||||
$this->assertElementContainsCount(
|
|
||||||
$crawler,
|
|
||||||
'a',
|
|
||||||
$nextPage,
|
|
||||||
'next page'
|
|
||||||
);
|
|
||||||
$this->assertElementContainsCount(
|
|
||||||
$crawler,
|
|
||||||
'a',
|
|
||||||
$prevPage,
|
|
||||||
'previous page'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testNew(): void
|
public function testNew(): void
|
||||||
{
|
{
|
||||||
$this->client->request('GET', sprintf('%snew', $this->path));
|
$this->client->request('GET', sprintf('%snew', $this->path));
|
||||||
|
@ -178,51 +61,7 @@ final class FoodOrderControllerTest extends DbWebTest
|
||||||
'food_order[foodVendor]' => $this->vendor->getId(),
|
'food_order[foodVendor]' => $this->vendor->getId(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
self::assertResponseRedirects("{$this->path}list");
|
self::assertResponseRedirects($this->path);
|
||||||
self::assertSame(1, $this->repository->count([]));
|
self::assertSame(1, $this->repository->count([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOpen(): void
|
|
||||||
{
|
|
||||||
$order = new FoodOrder;
|
|
||||||
$order->setFoodVendor($this->vendor);
|
|
||||||
$order->close();
|
|
||||||
|
|
||||||
$this->assertTrue($order->isClosed());
|
|
||||||
$this->manager->persist($order);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$this->client->request('GET', sprintf('%s%s/open', $this->path, $order->getId()));
|
|
||||||
self::assertResponseRedirects("{$this->path}{$order->getId()}");
|
|
||||||
$openOrder = $this->repository->find($order->getId());
|
|
||||||
$this->assertFalse($openOrder->isClosed());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testClose(): void
|
|
||||||
{
|
|
||||||
$order = new FoodOrder;
|
|
||||||
$order->setClosedAt();
|
|
||||||
$order->setFoodVendor($this->vendor);
|
|
||||||
|
|
||||||
$this->assertFalse($order->isClosed());
|
|
||||||
$this->manager->persist($order);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$this->client->request('GET', sprintf('%s%s/close', $this->path, $order->getId()));
|
|
||||||
self::assertResponseRedirects("{$this->path}{$order->getId()}");
|
|
||||||
$openOrder = $this->repository->find($order->getId());
|
|
||||||
$this->assertTrue($openOrder->isClosed());
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generatePaginatedOrders(): void
|
|
||||||
{
|
|
||||||
foreach (range(1, 35) as $i) {
|
|
||||||
$order = new FoodOrder($this->generateOldUlid());
|
|
||||||
$order->setFoodVendor($this->vendor);
|
|
||||||
$order->close();
|
|
||||||
$this->manager->persist($order);
|
|
||||||
|
|
||||||
}
|
|
||||||
$this->manager->flush();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
namespace App\Tests\Controller;
|
namespace App\Tests\Controller;
|
||||||
|
|
||||||
use App\Entity\FoodVendor;
|
use App\Entity\FoodVendor;
|
||||||
use App\Entity\MenuItem;
|
|
||||||
use App\Tests\DbWebTest;
|
use App\Tests\DbWebTest;
|
||||||
use Override;
|
use Override;
|
||||||
|
|
||||||
|
@ -38,7 +37,6 @@ final class FoodVendorControllerTest extends DbWebTest
|
||||||
{
|
{
|
||||||
$fixture = new FoodVendor;
|
$fixture = new FoodVendor;
|
||||||
$fixture->setName('My Title');
|
$fixture->setName('My Title');
|
||||||
$fixture->setMenuLink('https://example.com/');
|
|
||||||
|
|
||||||
$this->manager->persist($fixture);
|
$this->manager->persist($fixture);
|
||||||
$this->manager->flush();
|
$this->manager->flush();
|
||||||
|
@ -46,68 +44,9 @@ final class FoodVendorControllerTest extends DbWebTest
|
||||||
$crawler = $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
|
$crawler = $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
|
||||||
|
|
||||||
$this->assertResponseIsSuccessful();
|
$this->assertResponseIsSuccessful();
|
||||||
|
|
||||||
$nameNode = $crawler->filter('td')
|
$nameNode = $crawler->filter('td')
|
||||||
->last();
|
->last();
|
||||||
$nameNode = $crawler->filter(
|
$this->assertSame('My Title', $nameNode->text());
|
||||||
'.table > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)'
|
|
||||||
)->text();
|
|
||||||
$menuLinkNode = $crawler->filter(
|
|
||||||
'.table > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2) > a:nth-child(1)'
|
|
||||||
)->text();
|
|
||||||
$this->assertSame('My Title', $nameNode);
|
|
||||||
$this->assertSame('https://example.com/', $menuLinkNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testShowMenuItems(): void
|
|
||||||
{
|
|
||||||
$fixture = new FoodVendor;
|
|
||||||
$fixture->setName('My Title');
|
|
||||||
|
|
||||||
$this->manager->persist($fixture);
|
|
||||||
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$itemOne = new MenuItem;
|
|
||||||
$itemOne->setName('Item One');
|
|
||||||
|
|
||||||
$fixture->addMenuItem($itemOne);
|
|
||||||
$this->manager->persist($itemOne);
|
|
||||||
|
|
||||||
$itemTwo = new MenuItem;
|
|
||||||
$itemTwo->setName('Item Two');
|
|
||||||
$itemTwo->setFoodVendor($fixture);
|
|
||||||
|
|
||||||
$fixture->addMenuItem($itemTwo);
|
|
||||||
$this->manager->persist($itemTwo);
|
|
||||||
|
|
||||||
$itemThree = new MenuItem;
|
|
||||||
$itemThree->setName('Item Three');
|
|
||||||
$itemThree->setFoodVendor($fixture);
|
|
||||||
|
|
||||||
$fixture->addMenuItem($itemThree);
|
|
||||||
$this->manager->persist($itemThree);
|
|
||||||
|
|
||||||
$itemFour = new MenuItem;
|
|
||||||
$itemFour->setName('Item Four');
|
|
||||||
$itemFour->setFoodVendor($fixture);
|
|
||||||
|
|
||||||
$fixture->addMenuItem($itemFour);
|
|
||||||
$this->manager->persist($itemFour);
|
|
||||||
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$crawler = $this->client->request('GET', sprintf('%s%s', $this->path, $fixture->getId()));
|
|
||||||
|
|
||||||
$this->assertResponseIsSuccessful();
|
|
||||||
$nameNode = $crawler->filter(
|
|
||||||
'.table > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)'
|
|
||||||
)->text();
|
|
||||||
$this->assertSame('My Title', $nameNode);
|
|
||||||
|
|
||||||
$itemNodes = $crawler->filter('li');
|
|
||||||
|
|
||||||
$this->assertCount(4, $itemNodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testEdit(): void
|
public function testEdit(): void
|
||||||
|
@ -118,17 +57,10 @@ final class FoodVendorControllerTest extends DbWebTest
|
||||||
$this->manager->persist($fixture);
|
$this->manager->persist($fixture);
|
||||||
$this->manager->flush();
|
$this->manager->flush();
|
||||||
|
|
||||||
$crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $fixture->getId()));
|
$this->client->request('GET', sprintf('%s%s/edit', $this->path, $fixture->getId()));
|
||||||
$this->assertSame(
|
|
||||||
$crawler->filter('#food_vendor_name')
|
|
||||||
->last()
|
|
||||||
->attr('value', ''),
|
|
||||||
'Value'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->client->submitForm('Update', [
|
$this->client->submitForm('Update', [
|
||||||
'food_vendor[name]' => 'Something New',
|
'food_vendor[name]' => 'Something New',
|
||||||
'food_vendor[menuLink]' => 'https://example.com/',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
self::assertResponseRedirects('/food/vendor/');
|
self::assertResponseRedirects('/food/vendor/');
|
||||||
|
@ -136,7 +68,6 @@ final class FoodVendorControllerTest extends DbWebTest
|
||||||
$fixture = $this->repository->findAll();
|
$fixture = $this->repository->findAll();
|
||||||
|
|
||||||
self::assertSame('Something New', $fixture[0]->getName());
|
self::assertSame('Something New', $fixture[0]->getName());
|
||||||
self::assertSame('https://example.com/', $fixture[0]->getMenuLink());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Override]
|
#[Override]
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Tests\Controller;
|
|
||||||
|
|
||||||
use App\Tests\DbWebTest;
|
|
||||||
use Override;
|
|
||||||
|
|
||||||
final class HomeControllerTest extends DbWebTest
|
|
||||||
{
|
|
||||||
public function testIndex(): void
|
|
||||||
{
|
|
||||||
$this->client->request(
|
|
||||||
'GET',
|
|
||||||
'/'
|
|
||||||
);
|
|
||||||
|
|
||||||
self::assertResponseStatusCodeSame(302);
|
|
||||||
self::assertResponseHeaderSame('Location', '/food/order/list');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSetUsername(): void
|
|
||||||
{
|
|
||||||
$this->client->request(
|
|
||||||
'GET',
|
|
||||||
'/username',
|
|
||||||
);
|
|
||||||
|
|
||||||
self::assertResponseStatusCodeSame(200);
|
|
||||||
|
|
||||||
$this->client->submitForm('Save', [
|
|
||||||
'user_name_form[username]' => 'Testing-1',
|
|
||||||
]);
|
|
||||||
self::assertResponseStatusCodeSame(302);
|
|
||||||
self::assertResponseHeaderSame('Location', '/food/order/list');
|
|
||||||
self::assertResponseCookieValueSame('username', 'Testing-1');
|
|
||||||
|
|
||||||
$crawler = $this->client->request(
|
|
||||||
'GET',
|
|
||||||
'/username',
|
|
||||||
);
|
|
||||||
|
|
||||||
self::assertResponseStatusCodeSame(200);
|
|
||||||
|
|
||||||
$this->assertSame(
|
|
||||||
$crawler->filter('#user_name_form_username')
|
|
||||||
->last()
|
|
||||||
->attr('value', ''),
|
|
||||||
'Testing-1'
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testRemoveUsername(): void
|
|
||||||
{
|
|
||||||
$this->client->request(
|
|
||||||
'GET',
|
|
||||||
'/username',
|
|
||||||
);
|
|
||||||
|
|
||||||
self::assertResponseStatusCodeSame(200);
|
|
||||||
|
|
||||||
$this->client->submitForm('Save', [
|
|
||||||
'user_name_form[username]' => '',
|
|
||||||
]);
|
|
||||||
self::assertResponseStatusCodeSame(302);
|
|
||||||
self::assertResponseHeaderSame('Location', '/food/order/list');
|
|
||||||
self::assertResponseCookieValueSame('username', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Override]
|
|
||||||
public function getEntityClass(): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Tests\Controller;
|
|
||||||
|
|
||||||
use App\Entity\FoodOrder;
|
|
||||||
use App\Entity\FoodVendor;
|
|
||||||
use App\Entity\MenuItem;
|
|
||||||
use App\Tests\DbWebTest;
|
|
||||||
use Override;
|
|
||||||
|
|
||||||
use function sprintf;
|
|
||||||
|
|
||||||
final class MenuItemControllerTest extends DbWebTest
|
|
||||||
{
|
|
||||||
private string $path = '/menu/item/';
|
|
||||||
private FoodVendor $vendor;
|
|
||||||
|
|
||||||
#[Override]
|
|
||||||
public function setUp(): void
|
|
||||||
{
|
|
||||||
parent::setUp();
|
|
||||||
$this->vendor = new FoodVendor;
|
|
||||||
$this->vendor->setName('Food Vendor');
|
|
||||||
|
|
||||||
$this->manager->persist($this->vendor);
|
|
||||||
$this->manager->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[Override]
|
|
||||||
public function getEntityClass(): string
|
|
||||||
{
|
|
||||||
return MenuItem::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testShow(): void
|
|
||||||
{
|
|
||||||
$menuItem = new MenuItem;
|
|
||||||
$menuItem->setName('Testing 1 2');
|
|
||||||
|
|
||||||
$this->vendor->addMenuItem($menuItem);
|
|
||||||
$this->manager->persist($this->vendor);
|
|
||||||
$this->manager->persist($menuItem);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$crawler = $this->client->request('GET', "{$this->path}{$menuItem->getId()}");
|
|
||||||
$idValue = $crawler->filter(
|
|
||||||
'.table > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(2)'
|
|
||||||
)->text();
|
|
||||||
$nameValue = $crawler->filter(
|
|
||||||
'.table > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(2)'
|
|
||||||
)->text();
|
|
||||||
self::assertResponseStatusCodeSame(200);
|
|
||||||
$this->assertEquals($idValue, $menuItem->getId());
|
|
||||||
$this->assertEquals($nameValue, $menuItem->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testEdit(): void
|
|
||||||
{
|
|
||||||
$menuItem = new MenuItem;
|
|
||||||
$menuItem->setName('Testing 1 2');
|
|
||||||
|
|
||||||
$this->vendor->addMenuItem($menuItem);
|
|
||||||
$this->manager->persist($this->vendor);
|
|
||||||
$this->manager->persist($menuItem);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $menuItem->getId()));
|
|
||||||
$nameElem = $crawler->filter('#menu_item_name');
|
|
||||||
$this->assertEquals(
|
|
||||||
'Testing 1 2',
|
|
||||||
$nameElem->attr('value')
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->client->submitForm('Update', [
|
|
||||||
'menu_item[name]' => 'Testing-1',
|
|
||||||
]);
|
|
||||||
|
|
||||||
self::assertResponseRedirects(sprintf('/menu/item/%s', $menuItem->getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testDelete(): void
|
|
||||||
{
|
|
||||||
$menuItem = new MenuItem;
|
|
||||||
$menuItem->setName('Testing 1 2');
|
|
||||||
|
|
||||||
$this->vendor->addMenuItem($menuItem);
|
|
||||||
$this->manager->persist($this->vendor);
|
|
||||||
$this->manager->persist($menuItem);
|
|
||||||
|
|
||||||
$order = new FoodOrder;
|
|
||||||
$order->setFoodVendor($this->vendor);
|
|
||||||
|
|
||||||
$this->manager->persist($order);
|
|
||||||
$this->manager->flush();
|
|
||||||
$this->assertFalse($menuItem->isDeleted());
|
|
||||||
|
|
||||||
$this->client->request('GET', "{$this->path}{$menuItem->getId()}");
|
|
||||||
$this->client->submitForm('Delete', []);
|
|
||||||
|
|
||||||
$menuItem = $this->repository->find($menuItem->getId());
|
|
||||||
|
|
||||||
$this->assertTrue($menuItem->isDeleted());
|
|
||||||
|
|
||||||
$crawler = $this->client->request('GET', '/order/item/new/' . $order->getId());
|
|
||||||
$count = $crawler->filter('body > main:nth-child(2) > div:nth-child(5)')
|
|
||||||
->children()
|
|
||||||
->count();
|
|
||||||
$this->assertSame(0, $count);
|
|
||||||
|
|
||||||
$this->assertResponseIsSuccessful();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,11 +4,8 @@ namespace App\Tests\Controller;
|
||||||
|
|
||||||
use App\Entity\FoodOrder;
|
use App\Entity\FoodOrder;
|
||||||
use App\Entity\FoodVendor;
|
use App\Entity\FoodVendor;
|
||||||
use App\Entity\MenuItem;
|
|
||||||
use App\Entity\OrderItem;
|
use App\Entity\OrderItem;
|
||||||
use App\Repository\MenuItemRepository;
|
|
||||||
use App\Tests\DbWebTest;
|
use App\Tests\DbWebTest;
|
||||||
use DateTimeImmutable;
|
|
||||||
use Override;
|
use Override;
|
||||||
|
|
||||||
use function sprintf;
|
use function sprintf;
|
||||||
|
@ -17,8 +14,6 @@ final class OrderItemControllerTest extends DbWebTest
|
||||||
{
|
{
|
||||||
public FoodVendor $vendor;
|
public FoodVendor $vendor;
|
||||||
public FoodOrder $order;
|
public FoodOrder $order;
|
||||||
public Menuitem $menuItem;
|
|
||||||
public MenuItemRepository $menuItemRepository;
|
|
||||||
private string $path = '/order/item/';
|
private string $path = '/order/item/';
|
||||||
|
|
||||||
#[Override]
|
#[Override]
|
||||||
|
@ -33,39 +28,16 @@ final class OrderItemControllerTest extends DbWebTest
|
||||||
$this->order->setFoodVendor($this->vendor);
|
$this->order->setFoodVendor($this->vendor);
|
||||||
|
|
||||||
$this->manager->persist($this->order);
|
$this->manager->persist($this->order);
|
||||||
|
|
||||||
$this->menuItem = new MenuItem;
|
|
||||||
$this->menuItem->setName('Testing');
|
|
||||||
$this->menuItem->setFoodVendor($this->vendor);
|
|
||||||
|
|
||||||
$vendor2 = new FoodVendor;
|
|
||||||
$vendor2->setName('Vendor 2');
|
|
||||||
|
|
||||||
$menuItem2 = new MenuItem;
|
|
||||||
$menuItem2->setName('Testing2');
|
|
||||||
$menuItem2->setFoodVendor($vendor2);
|
|
||||||
|
|
||||||
$this->manager->persist($vendor2);
|
|
||||||
$this->manager->persist($menuItem2);
|
|
||||||
|
|
||||||
$this->manager->persist($this->menuItem);
|
|
||||||
$this->manager->flush();
|
$this->manager->flush();
|
||||||
|
|
||||||
$this->menuItemRepository = static::getContainer()->get(MenuItemRepository::class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNew(): void
|
public function testNew(): void
|
||||||
{
|
{
|
||||||
$crawler = $this->client->request(
|
$this->client->request(
|
||||||
'GET',
|
'GET',
|
||||||
sprintf('%snew/%s', $this->path, $this->order->getId())
|
sprintf('%snew/%s', $this->path, $this->order->getId())
|
||||||
);
|
);
|
||||||
|
|
||||||
$children = $crawler->filter('body > main:nth-child(2) > div:nth-child(5)')
|
|
||||||
->children();
|
|
||||||
|
|
||||||
$this->assertCount(1, $children);
|
|
||||||
|
|
||||||
self::assertResponseStatusCodeSame(200);
|
self::assertResponseStatusCodeSame(200);
|
||||||
|
|
||||||
$this->client->submitForm('Save', [
|
$this->client->submitForm('Save', [
|
||||||
|
@ -76,55 +48,13 @@ final class OrderItemControllerTest extends DbWebTest
|
||||||
self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
|
self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
|
||||||
|
|
||||||
self::assertSame(1, $this->repository->count([]));
|
self::assertSame(1, $this->repository->count([]));
|
||||||
self::assertSame(1, $this->menuItemRepository->count([
|
|
||||||
'foodVendor' => $this->vendor->getId(),
|
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testNewOrderClosed(): void
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->order->setClosedAt(new DateTimeImmutable('-1 Hour'));
|
|
||||||
$this->manager->persist($this->order);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$this->client->request(
|
|
||||||
'GET',
|
|
||||||
sprintf('%snew/%s', $this->path, $this->order->getId())
|
|
||||||
);
|
|
||||||
|
|
||||||
self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
|
|
||||||
|
|
||||||
self::assertSame(0, $this->repository->count([]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testNewCreateMenuItem(): void
|
|
||||||
{
|
|
||||||
$this->client->request(
|
|
||||||
'GET',
|
|
||||||
sprintf('%snew/%s', $this->path, $this->order->getId())
|
|
||||||
);
|
|
||||||
|
|
||||||
self::assertResponseStatusCodeSame(200);
|
|
||||||
|
|
||||||
$this->client->submitForm('Save', [
|
|
||||||
'order_item[name]' => 'Testing-1',
|
|
||||||
'order_item[extras]' => 'Testing-1',
|
|
||||||
]);
|
|
||||||
|
|
||||||
self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
|
|
||||||
|
|
||||||
self::assertSame(1, $this->repository->count([]));
|
|
||||||
self::assertSame(3, $this->menuItemRepository->count([]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRemove(): void
|
public function testRemove(): void
|
||||||
{
|
{
|
||||||
$fixture = new OrderItem;
|
$fixture = new OrderItem;
|
||||||
$fixture->setName('Testing');
|
$fixture->setName('Value');
|
||||||
$fixture->setExtras('Value');
|
$fixture->setExtras('Value');
|
||||||
$fixture->setMenuItem($this->menuItem);
|
|
||||||
|
|
||||||
$fixture->setFoodOrder($this->order);
|
$fixture->setFoodOrder($this->order);
|
||||||
|
|
||||||
$this->manager->persist($fixture);
|
$this->manager->persist($fixture);
|
||||||
|
@ -136,87 +66,12 @@ final class OrderItemControllerTest extends DbWebTest
|
||||||
self::assertSame(0, $this->repository->count([]));
|
self::assertSame(0, $this->repository->count([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOrderClosed(): void
|
|
||||||
{
|
|
||||||
$fixture = new OrderItem;
|
|
||||||
$fixture->setName('Testing');
|
|
||||||
$fixture->setExtras('Value');
|
|
||||||
$fixture->setMenuItem($this->menuItem);
|
|
||||||
$fixture->setFoodOrder($this->order);
|
|
||||||
|
|
||||||
$this->order->close();
|
|
||||||
|
|
||||||
$this->manager->persist($this->order);
|
|
||||||
$this->manager->persist($fixture);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$this->client->request('GET', sprintf('%sdelete/%s', $this->path, $fixture->getId()));
|
|
||||||
|
|
||||||
self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
|
|
||||||
self::assertSame(1, $this->repository->count([]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testEdit(): void
|
|
||||||
{
|
|
||||||
$orderItem = new OrderItem;
|
|
||||||
$orderItem->setName('Testing');
|
|
||||||
$orderItem->setExtras('My Extra');
|
|
||||||
$orderItem->setFoodOrder($this->order);
|
|
||||||
$orderItem->setMenuItem($this->menuItem);
|
|
||||||
|
|
||||||
$this->manager->persist($orderItem);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$crawler = $this->client->request('GET', sprintf('%s%s/edit', $this->path, $orderItem->getId()));
|
|
||||||
$nameElem = $crawler->filter('#order_item_name');
|
|
||||||
$extrasElem = $crawler->filter('#order_item_extras');
|
|
||||||
$this->assertEquals(
|
|
||||||
'Testing',
|
|
||||||
$nameElem->attr('value')
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertEquals(
|
|
||||||
'My Extra',
|
|
||||||
$extrasElem->attr('value')
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->client->submitForm('Update', [
|
|
||||||
'order_item[name]' => 'Testing-1',
|
|
||||||
'order_item[extras]' => 'Testing-1',
|
|
||||||
]);
|
|
||||||
|
|
||||||
self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
|
|
||||||
|
|
||||||
self::assertSame(1, $this->repository->count([]));
|
|
||||||
self::assertSame(3, $this->menuItemRepository->count([]));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testEditOrderClosed(): void
|
|
||||||
{
|
|
||||||
$orderItem = new OrderItem;
|
|
||||||
$orderItem->setName('Testing');
|
|
||||||
$orderItem->setExtras('My Extra');
|
|
||||||
$orderItem->setFoodOrder($this->order);
|
|
||||||
$orderItem->setMenuItem($this->menuItem);
|
|
||||||
|
|
||||||
$this->order->close();
|
|
||||||
|
|
||||||
$this->manager->persist($orderItem);
|
|
||||||
$this->manager->persist($this->order);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$this->client->request('GET', sprintf('%s%s/edit', $this->path, $orderItem->getId()));
|
|
||||||
self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testCopy(): void
|
public function testCopy(): void
|
||||||
{
|
{
|
||||||
$orderItem = new OrderItem;
|
$orderItem = new OrderItem;
|
||||||
$orderItem->setName('My Title');
|
$orderItem->setName('My Title');
|
||||||
$orderItem->setExtras('My Title');
|
$orderItem->setExtras('My Title');
|
||||||
$orderItem->setFoodOrder($this->order);
|
$orderItem->setFoodOrder($this->order);
|
||||||
$orderItem->setMenuItem($this->menuItem);
|
|
||||||
|
|
||||||
$this->manager->persist($orderItem);
|
$this->manager->persist($orderItem);
|
||||||
$this->manager->flush();
|
$this->manager->flush();
|
||||||
|
@ -232,28 +87,7 @@ final class OrderItemControllerTest extends DbWebTest
|
||||||
$this->assertSame($orderItem->getName(), $item->getName());
|
$this->assertSame($orderItem->getName(), $item->getName());
|
||||||
$this->assertSame($orderItem->getExtras(), $item->getExtras());
|
$this->assertSame($orderItem->getExtras(), $item->getExtras());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public function testCopyOrderClosed(): void
|
|
||||||
{
|
|
||||||
$orderItem = new OrderItem;
|
|
||||||
$orderItem->setName('My Title');
|
|
||||||
$orderItem->setExtras('My Title');
|
|
||||||
$orderItem->setFoodOrder($this->order);
|
|
||||||
$orderItem->setMenuItem($this->menuItem);
|
|
||||||
|
|
||||||
$this->order->close();
|
|
||||||
$this->manager->persist($this->order);
|
|
||||||
$this->manager->persist($orderItem);
|
|
||||||
$this->manager->flush();
|
|
||||||
|
|
||||||
$this->client->request('GET', sprintf('%s%s/copy', $this->path, $orderItem->getId()));
|
|
||||||
self::assertResponseRedirects(sprintf('/food/order/%s', $this->order->getId()));
|
|
||||||
|
|
||||||
$result = $this->repository->findBy([
|
|
||||||
'foodOrder' => $this->order->getId(),
|
|
||||||
]);
|
|
||||||
$this->assertCount(1, $result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Override]
|
#[Override]
|
||||||
|
|
|
@ -2,18 +2,12 @@
|
||||||
|
|
||||||
namespace App\Tests;
|
namespace App\Tests;
|
||||||
|
|
||||||
use DateInterval;
|
|
||||||
use DateTimeImmutable;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
use Doctrine\ORM\Tools\SchemaTool;
|
use Doctrine\ORM\Tools\SchemaTool;
|
||||||
use Override;
|
use Override;
|
||||||
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
use Symfony\Bundle\FrameworkBundle\KernelBrowser;
|
||||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||||
use Symfony\Component\DomCrawler\Crawler;
|
|
||||||
use Symfony\Component\Uid\Ulid;
|
|
||||||
|
|
||||||
use function str_contains;
|
|
||||||
|
|
||||||
abstract class DbWebTest extends WebTestCase
|
abstract class DbWebTest extends WebTestCase
|
||||||
{
|
{
|
||||||
|
@ -31,29 +25,13 @@ abstract class DbWebTest extends WebTestCase
|
||||||
$schemaTool = new SchemaTool($this->manager);
|
$schemaTool = new SchemaTool($this->manager);
|
||||||
$metadata = $this->manager->getMetadataFactory()
|
$metadata = $this->manager->getMetadataFactory()
|
||||||
->getAllMetadata();
|
->getAllMetadata();
|
||||||
$schemaTool->dropDatabase();
|
|
||||||
$schemaTool->updateSchema($metadata);
|
$schemaTool->updateSchema($metadata);
|
||||||
|
|
||||||
if ($this->getEntityClass() !== '') {
|
$this->repository = $this->manager->getRepository($this->getEntityClass());
|
||||||
$this->repository = $this->manager->getRepository($this->getEntityClass());
|
foreach ($this->repository->findAll() as $object) {
|
||||||
|
$this->manager->remove($object);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected function generateOldUlid(int $daysToSubtract = 10): Ulid
|
$this->manager->flush();
|
||||||
{
|
|
||||||
$date = (new DateTimeImmutable)->sub(new DateInterval('P' . $daysToSubtract . 'D'));
|
|
||||||
$ulidString = Ulid::generate($date);
|
|
||||||
return Ulid::fromString($ulidString);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function assertElementContainsCount(Crawler $crawler, string $element, int $count, string $text): void
|
|
||||||
{
|
|
||||||
$this->assertCount(
|
|
||||||
$count,
|
|
||||||
$crawler->filter($element)
|
|
||||||
->reduce(
|
|
||||||
static fn(Crawler $node, $i): bool => str_contains($node->text(), $text),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Tests\Entity;
|
|
||||||
|
|
||||||
use App\Entity\FoodOrder;
|
|
||||||
use App\Entity\OrderItem;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
final class FoodOrderTest extends TestCase
|
|
||||||
{
|
|
||||||
public function testFoodOrder(): void
|
|
||||||
{
|
|
||||||
$order = new FoodOrder;
|
|
||||||
$orderItem = new OrderItem;
|
|
||||||
$this->assertCount(0, $order->getOrderItems());
|
|
||||||
$order->addOrderItem($orderItem);
|
|
||||||
$order->addOrderItem($orderItem);
|
|
||||||
$this->assertCount(1, $order->getOrderItems());
|
|
||||||
$this->assertSame($order, $orderItem->getFoodOrder());
|
|
||||||
$order->removeOrderItem($orderItem);
|
|
||||||
$this->assertCount(0, $order->getOrderItems());
|
|
||||||
$this->assertNull($orderItem->getFoodOrder());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Tests\Entity;
|
|
||||||
|
|
||||||
use App\Entity\FoodOrder;
|
|
||||||
use App\Entity\FoodVendor;
|
|
||||||
use App\Entity\MenuItem;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
use Symfony\Component\Uid\Ulid;
|
|
||||||
|
|
||||||
final class FoodVendorTest extends TestCase
|
|
||||||
{
|
|
||||||
public function testFoodVendor(): void
|
|
||||||
{
|
|
||||||
$vendor = new FoodVendor;
|
|
||||||
$vendor->setName('Test');
|
|
||||||
$this->assertEquals('Test', $vendor->getName());
|
|
||||||
$this->assertInstanceOf(Ulid::class, $vendor->getId());
|
|
||||||
|
|
||||||
$this->assertCount(0, $vendor->getFoodOrders());
|
|
||||||
$order1 = new FoodOrder;
|
|
||||||
$vendor->addFoodOrder($order1);
|
|
||||||
$vendor->addFoodOrder($order1);
|
|
||||||
$this->assertCount(1, $vendor->getFoodOrders());
|
|
||||||
$this->assertSame($vendor, $order1->getFoodVendor());
|
|
||||||
$vendor->removeFoodOrder($order1);
|
|
||||||
$this->assertCount(0, $vendor->getFoodOrders());
|
|
||||||
$this->assertNull($order1->getFoodVendor());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testMenuItem(): void
|
|
||||||
{
|
|
||||||
$vendor = new FoodVendor;
|
|
||||||
$menuItem1 = new MenuItem;
|
|
||||||
$menuItem2 = new MenuItem;
|
|
||||||
$this->assertCount(0, $vendor->getMenuItems());
|
|
||||||
$vendor->addMenuItem($menuItem1);
|
|
||||||
$vendor->addMenuItem($menuItem1);
|
|
||||||
$this->assertCount(1, $vendor->getMenuItems());
|
|
||||||
$vendor->removeMenuItem($menuItem1);
|
|
||||||
$this->assertCount(0, $vendor->getMenuItems());
|
|
||||||
$this->assertNull($menuItem1->getFoodVendor());
|
|
||||||
$vendor->addMenuItem($menuItem1);
|
|
||||||
$menuItem2->delete();
|
|
||||||
$vendor->addMenuItem($menuItem2);
|
|
||||||
$this->assertCount(1, $vendor->getMenuItems());
|
|
||||||
$this->assertCount(2, $vendor->getMenuItems(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testRemoveForeignMenuItem(): void
|
|
||||||
{
|
|
||||||
$vendor1 = new FoodVendor;
|
|
||||||
$vendor2 = new FoodVendor;
|
|
||||||
$item1 = new MenuItem;
|
|
||||||
|
|
||||||
$vendor1->addMenuItem($item1);
|
|
||||||
$this->assertCount(1, $vendor1->getMenuItems());
|
|
||||||
$vendor2->removeMenuItem($item1);
|
|
||||||
$this->assertCount(1, $vendor1->getMenuItems());
|
|
||||||
$this->assertSame($vendor1, $item1->getFoodVendor());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Tests\Entity;
|
|
||||||
|
|
||||||
use App\Entity\FoodVendor;
|
|
||||||
use App\Entity\MenuItem;
|
|
||||||
use DateTimeImmutable;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
final class MenuItemTest extends TestCase
|
|
||||||
{
|
|
||||||
public function testMenuItem(): void
|
|
||||||
{
|
|
||||||
$item = new MenuItem;
|
|
||||||
$item->setName('Test');
|
|
||||||
$this->assertEquals('Test', $item->getName());
|
|
||||||
|
|
||||||
$vendor = new FoodVendor;
|
|
||||||
$vendor->setName('Test');
|
|
||||||
|
|
||||||
$item->setFoodVendor($vendor);
|
|
||||||
$this->assertEquals($vendor, $item->getFoodVendor());
|
|
||||||
|
|
||||||
$this->assertFalse($item->isDeleted());
|
|
||||||
$this->assertNull($item->getDeletedAt());
|
|
||||||
$item->delete();
|
|
||||||
$this->assertTrue($item->isDeleted());
|
|
||||||
$this->assertInstanceOf(DateTimeImmutable::class, $item->getDeletedAt());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue